daily-focus 1.2.0-dev.7 → 1.2.0-dev.9

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/public/app.js CHANGED
@@ -69,9 +69,9 @@ function H() {
69
69
  }
70
70
  }
71
71
  function L(n3, l5, u4, t4, i4, r4, o4, e4, f4, c4, a4) {
72
- var s4, h5, p5, v4, y4, _5, g4 = t4 && t4.__k || w, m4 = l5.length;
73
- for (f4 = T(u4, l5, g4, f4, m4), s4 = 0; s4 < m4; s4++) null != (p5 = u4.__k[s4]) && (h5 = -1 != p5.__i && g4[p5.__i] || d, p5.__i = s4, _5 = q(n3, p5, h5, i4, r4, o4, e4, f4, c4, a4), v4 = p5.__e, p5.ref && h5.ref != p5.ref && (h5.ref && J(h5.ref, null, p5), a4.push(p5.ref, p5.__c || v4, p5)), null == y4 && null != v4 && (y4 = v4), 4 & p5.__u ? (f4 = j(p5, f4, n3), h5.__e && (h5.__e = null)) : "function" == typeof p5.type && void 0 !== _5 ? f4 = _5 : v4 && (f4 = v4.nextSibling), p5.__u &= -7);
74
- return u4.__e = y4, f4;
72
+ var s4, h5, p5, v4, y5, _5, g4 = t4 && t4.__k || w, m4 = l5.length;
73
+ for (f4 = T(u4, l5, g4, f4, m4), s4 = 0; s4 < m4; s4++) null != (p5 = u4.__k[s4]) && (h5 = -1 != p5.__i && g4[p5.__i] || d, p5.__i = s4, _5 = q(n3, p5, h5, i4, r4, o4, e4, f4, c4, a4), v4 = p5.__e, p5.ref && h5.ref != p5.ref && (h5.ref && J(h5.ref, null, p5), a4.push(p5.ref, p5.__c || v4, p5)), null == y5 && null != v4 && (y5 = v4), 4 & p5.__u ? (f4 = j(p5, f4, n3), h5.__e && (h5.__e = null)) : "function" == typeof p5.type && void 0 !== _5 ? f4 = _5 : v4 && (f4 = v4.nextSibling), p5.__u &= -7);
74
+ return u4.__e = y5, f4;
75
75
  }
76
76
  function T(n3, l5, u4, t4, i4) {
77
77
  var r4, o4, e4, f4, c4, a4 = u4.length, s4 = a4, h5 = 0;
@@ -131,29 +131,29 @@ function V(n3) {
131
131
  };
132
132
  }
133
133
  function q(n3, u4, t4, i4, r4, o4, e4, f4, c4, a4) {
134
- var s4, h5, p5, v4, y4, d4, _5, k3, x4, M, I2, P2, A3, H2, T4, j4, F2 = u4.type;
134
+ var s4, h5, p5, v4, y5, d5, _5, k3, x4, M, I2, P2, A3, H2, T4, j4, F2 = u4.type;
135
135
  if (void 0 !== u4.constructor) return null;
136
136
  128 & t4.__u && (c4 = !!(32 & t4.__u), o4 = [f4 = u4.__e = t4.__e]), (s4 = l.__b) && s4(u4);
137
137
  n: if ("function" == typeof F2) {
138
138
  h5 = e4.length;
139
139
  try {
140
- if (x4 = u4.props, M = F2.prototype && F2.prototype.render, I2 = (s4 = F2.contextType) && i4[s4.__c], P2 = s4 ? I2 ? I2.props.value : s4.__ : i4, t4.__c ? k3 = (p5 = u4.__c = t4.__c).__ = p5.__E : (M ? u4.__c = p5 = new F2(x4, P2) : (u4.__c = p5 = new C(x4, P2), p5.constructor = F2, p5.render = Q), I2 && I2.sub(p5), p5.state || (p5.state = {}), p5.__n = i4, v4 = p5.__d = true, p5.__h = [], p5._sb = []), M && null == p5.__s && (p5.__s = p5.state), M && null != F2.getDerivedStateFromProps && (p5.__s == p5.state && (p5.__s = m({}, p5.__s)), m(p5.__s, F2.getDerivedStateFromProps(x4, p5.__s))), y4 = p5.props, d4 = p5.state, p5.__v = u4, v4) M && null == F2.getDerivedStateFromProps && null != p5.componentWillMount && p5.componentWillMount(), M && null != p5.componentDidMount && p5.__h.push(p5.componentDidMount);
140
+ if (x4 = u4.props, M = F2.prototype && F2.prototype.render, I2 = (s4 = F2.contextType) && i4[s4.__c], P2 = s4 ? I2 ? I2.props.value : s4.__ : i4, t4.__c ? k3 = (p5 = u4.__c = t4.__c).__ = p5.__E : (M ? u4.__c = p5 = new F2(x4, P2) : (u4.__c = p5 = new C(x4, P2), p5.constructor = F2, p5.render = Q), I2 && I2.sub(p5), p5.state || (p5.state = {}), p5.__n = i4, v4 = p5.__d = true, p5.__h = [], p5._sb = []), M && null == p5.__s && (p5.__s = p5.state), M && null != F2.getDerivedStateFromProps && (p5.__s == p5.state && (p5.__s = m({}, p5.__s)), m(p5.__s, F2.getDerivedStateFromProps(x4, p5.__s))), y5 = p5.props, d5 = p5.state, p5.__v = u4, v4) M && null == F2.getDerivedStateFromProps && null != p5.componentWillMount && p5.componentWillMount(), M && null != p5.componentDidMount && p5.__h.push(p5.componentDidMount);
141
141
  else {
142
- if (M && null == F2.getDerivedStateFromProps && x4 !== y4 && null != p5.componentWillReceiveProps && p5.componentWillReceiveProps(x4, P2), u4.__v == t4.__v || !p5.__e && null != p5.shouldComponentUpdate && false === p5.shouldComponentUpdate(x4, p5.__s, P2)) {
142
+ if (M && null == F2.getDerivedStateFromProps && x4 !== y5 && null != p5.componentWillReceiveProps && p5.componentWillReceiveProps(x4, P2), u4.__v == t4.__v || !p5.__e && null != p5.shouldComponentUpdate && false === p5.shouldComponentUpdate(x4, p5.__s, P2)) {
143
143
  u4.__v != t4.__v && (p5.props = x4, p5.state = p5.__s, p5.__d = false), u4.__e = t4.__e, u4.__k = t4.__k, u4.__k.some(function(n4) {
144
144
  n4 && (n4.__ = u4);
145
145
  }), w.push.apply(p5.__h, p5._sb), p5._sb = [], p5.__h.length && e4.push(p5), f4 = $(t4);
146
146
  break n;
147
147
  }
148
148
  null != p5.componentWillUpdate && p5.componentWillUpdate(x4, p5.__s, P2), M && null != p5.componentDidUpdate && p5.__h.push(function() {
149
- p5.componentDidUpdate(y4, d4, _5);
149
+ p5.componentDidUpdate(y5, d5, _5);
150
150
  });
151
151
  }
152
152
  if (p5.context = P2, p5.props = x4, p5.__P = n3, p5.__e = false, A3 = l.__r, H2 = 0, M) p5.state = p5.__s, p5.__d = false, A3 && A3(u4), s4 = p5.render(p5.props, p5.state, p5.context), w.push.apply(p5.__h, p5._sb), p5._sb = [];
153
153
  else do {
154
154
  p5.__d = false, A3 && A3(u4), s4 = p5.render(p5.props, p5.state, p5.context), p5.state = p5.__s;
155
155
  } while (p5.__d && ++H2 < 25);
156
- p5.state = p5.__s, null != p5.getChildContext && (i4 = m(m({}, i4), p5.getChildContext())), M && !v4 && null != p5.getSnapshotBeforeUpdate && (_5 = p5.getSnapshotBeforeUpdate(y4, d4)), T4 = null != s4 && s4.type === S && null == s4.key ? E(s4.props.children) : s4, f4 = L(n3, g(T4) ? T4 : [T4], u4, t4, i4, r4, o4, e4, f4, c4, a4), p5.base = u4.__e, u4.__u &= -161, p5.__h.length && e4.push(p5), k3 && (p5.__E = p5.__ = null);
156
+ p5.state = p5.__s, null != p5.getChildContext && (i4 = m(m({}, i4), p5.getChildContext())), M && !v4 && null != p5.getSnapshotBeforeUpdate && (_5 = p5.getSnapshotBeforeUpdate(y5, d5)), T4 = null != s4 && s4.type === S && null == s4.key ? E(s4.props.children) : s4, f4 = L(n3, g(T4) ? T4 : [T4], u4, t4, i4, r4, o4, e4, f4, c4, a4), p5.base = u4.__e, u4.__u &= -161, p5.__h.length && e4.push(p5), k3 && (p5.__E = p5.__ = null);
157
157
  } catch (n4) {
158
158
  if (e4.length = h5, u4.__v = null, c4 || null != o4) {
159
159
  if (n4.then) {
@@ -185,10 +185,10 @@ function E(n3) {
185
185
  return "object" != typeof n3 || null == n3 || n3.__b > 0 ? n3 : g(n3) ? n3.map(E) : void 0 !== n3.constructor ? null : m({}, n3);
186
186
  }
187
187
  function G(u4, t4, i4, r4, o4, e4, f4, c4, a4) {
188
- var s4, h5, p5, v4, y4, w5, _5, m4 = i4.props || d, k3 = t4.props, x4 = t4.type;
188
+ var s4, h5, p5, v4, y5, w5, _5, m4 = i4.props || d, k3 = t4.props, x4 = t4.type;
189
189
  if ("svg" == x4 ? o4 = "http://www.w3.org/2000/svg" : "math" == x4 ? o4 = "http://www.w3.org/1998/Math/MathML" : o4 || (o4 = "http://www.w3.org/1999/xhtml"), null != e4) {
190
- for (s4 = 0; s4 < e4.length; s4++) if ((y4 = e4[s4]) && "setAttribute" in y4 == !!x4 && (x4 ? y4.localName == x4 : 3 == y4.nodeType)) {
191
- u4 = y4, e4[s4] = null;
190
+ for (s4 = 0; s4 < e4.length; s4++) if ((y5 = e4[s4]) && "setAttribute" in y5 == !!x4 && (x4 ? y5.localName == x4 : 3 == y5.nodeType)) {
191
+ u4 = y5, e4[s4] = null;
192
192
  break;
193
193
  }
194
194
  }
@@ -198,9 +198,9 @@ function G(u4, t4, i4, r4, o4, e4, f4, c4, a4) {
198
198
  }
199
199
  if (null == x4) m4 === k3 || c4 && u4.data == k3 || (u4.data = k3);
200
200
  else {
201
- if (e4 = "textarea" == x4 && null != k3.defaultValue ? null : e4 && n.call(u4.childNodes), !c4 && null != e4) for (m4 = {}, s4 = 0; s4 < u4.attributes.length; s4++) m4[(y4 = u4.attributes[s4]).name] = y4.value;
202
- for (s4 in m4) y4 = m4[s4], "dangerouslySetInnerHTML" == s4 ? p5 = y4 : "children" == s4 || s4 in k3 || "value" == s4 && "defaultValue" in k3 || "checked" == s4 && "defaultChecked" in k3 || N(u4, s4, null, y4, o4);
203
- for (s4 in k3) y4 = k3[s4], "children" == s4 ? v4 = y4 : "dangerouslySetInnerHTML" == s4 ? h5 = y4 : "value" == s4 ? w5 = y4 : "checked" == s4 ? _5 = y4 : c4 && "function" != typeof y4 || m4[s4] === y4 || N(u4, s4, y4, m4[s4], o4);
201
+ if (e4 = "textarea" == x4 && null != k3.defaultValue ? null : e4 && n.call(u4.childNodes), !c4 && null != e4) for (m4 = {}, s4 = 0; s4 < u4.attributes.length; s4++) m4[(y5 = u4.attributes[s4]).name] = y5.value;
202
+ for (s4 in m4) y5 = m4[s4], "dangerouslySetInnerHTML" == s4 ? p5 = y5 : "children" == s4 || s4 in k3 || "value" == s4 && "defaultValue" in k3 || "checked" == s4 && "defaultChecked" in k3 || N(u4, s4, null, y5, o4);
203
+ for (s4 in k3) y5 = k3[s4], "children" == s4 ? v4 = y5 : "dangerouslySetInnerHTML" == s4 ? h5 = y5 : "value" == s4 ? w5 = y5 : "checked" == s4 ? _5 = y5 : c4 && "function" != typeof y5 || m4[s4] === y5 || N(u4, s4, y5, m4[s4], o4);
204
204
  if (h5) c4 || p5 && (h5.__html == p5.__html || h5.__html == u4.innerHTML) || (u4.innerHTML = h5.__html), t4.__k = [];
205
205
  else if (p5 && (u4.innerHTML = ""), L("template" == t4.type ? u4.content : u4, g(v4) ? v4 : [v4], t4, i4, r4, "foreignObject" == x4 ? "http://www.w3.org/1999/xhtml" : o4, e4, f4, e4 ? e4[0] : i4.__k && $(i4, 0), c4, a4), null != e4) for (s4 = e4.length; s4--; ) b(e4[s4]);
206
206
  c4 && "textarea" != x4 || (s4 = "value", "progress" == x4 && null == w5 ? u4.removeAttribute("value") : null != w5 && (w5 !== u4[s4] || "progress" == x4 && !w5 || "option" == x4 && w5 != m4[s4]) && N(u4, s4, w5, m4[s4], o4), s4 = "checked", null != _5 && _5 != u4[s4] && N(u4, s4, _5, m4[s4], o4));
@@ -274,6 +274,42 @@ function s2(n3, t4) {
274
274
  var u4 = r2.__H || (r2.__H = { __: [], __h: [] });
275
275
  return n3 >= u4.__.length && u4.__.push({}), u4.__[n3];
276
276
  }
277
+ function d2(n3) {
278
+ return o2 = 1, y2(D2, n3);
279
+ }
280
+ function y2(n3, u4, i4) {
281
+ var o4 = s2(t2++, 2);
282
+ if (o4.t = n3, !o4.__c && (o4.__ = [i4 ? i4(u4) : D2(void 0, u4), function(n4) {
283
+ var t4 = o4.__N ? o4.__N[0] : o4.__[0], r4 = o4.t(t4, n4);
284
+ t4 !== r4 && (o4.__N = [r4, o4.__[1]], o4.__c.setState({}));
285
+ }], o4.__c = r2, !r2.__f)) {
286
+ var f4 = function(n4, t4, r4) {
287
+ if (!o4.__c.__H) return true;
288
+ var u5 = false, i5 = o4.__c.props !== n4;
289
+ if (o4.__c.__H.__.some(function(n5) {
290
+ if (n5.__N) {
291
+ u5 = true;
292
+ var t5 = n5.__[0];
293
+ n5.__ = n5.__N, n5.__N = void 0, t5 !== n5.__[0] && (i5 = true);
294
+ }
295
+ }), c4) {
296
+ var f5 = c4.call(this, n4, t4, r4);
297
+ return u5 ? f5 || i5 : f5;
298
+ }
299
+ return !u5 || i5;
300
+ };
301
+ r2.__f = true;
302
+ var c4 = r2.shouldComponentUpdate, e4 = r2.componentWillUpdate;
303
+ r2.componentWillUpdate = function(n4, t4, r4) {
304
+ if (this.__e) {
305
+ var u5 = c4;
306
+ c4 = void 0, f4(n4, t4, r4), c4 = u5;
307
+ }
308
+ e4 && e4.call(this, n4, t4, r4);
309
+ }, r2.shouldComponentUpdate = f4;
310
+ }
311
+ return o4.__N || o4.__;
312
+ }
277
313
  function h2(n3, u4) {
278
314
  var i4 = s2(t2++, 3);
279
315
  !c2.__s && C2(i4.__H, u4) && (i4.__ = n3, i4.u = u4, r2.__H.__h.push(i4));
@@ -360,6 +396,9 @@ function C2(n3, t4) {
360
396
  return t5 !== n3[r4];
361
397
  });
362
398
  }
399
+ function D2(n3, t4) {
400
+ return "function" == typeof t4 ? t4(n3) : t4;
401
+ }
363
402
 
364
403
  // node_modules/@preact/signals-core/dist/signals-core.module.js
365
404
  var i3 = /* @__PURE__ */ Symbol.for("preact-signals");
@@ -430,7 +469,7 @@ var s3 = 0;
430
469
  var u3 = 0;
431
470
  var e3 = 0;
432
471
  var c3 = void 0;
433
- var d2 = 0;
472
+ var d3 = 0;
434
473
  function a3(i4) {
435
474
  if (void 0 !== o3) {
436
475
  var t4 = i4.n;
@@ -543,7 +582,7 @@ Object.defineProperty(l3.prototype, "value", { get: function() {
543
582
  })(this);
544
583
  this.v = i4;
545
584
  this.i++;
546
- d2++;
585
+ d3++;
547
586
  v3++;
548
587
  try {
549
588
  for (var n3 = this.t; void 0 !== n3; n3 = n3.x) n3.t.N();
@@ -552,7 +591,7 @@ Object.defineProperty(l3.prototype, "value", { get: function() {
552
591
  }
553
592
  }
554
593
  } });
555
- function y2(i4, t4) {
594
+ function y3(i4, t4) {
556
595
  return new l3(i4, t4);
557
596
  }
558
597
  function w3(i4) {
@@ -590,7 +629,7 @@ function p3(i4, t4) {
590
629
  l3.call(this, void 0, t4);
591
630
  this.x = i4;
592
631
  this.s = void 0;
593
- this.g = d2 - 1;
632
+ this.g = d3 - 1;
594
633
  this.f = 4;
595
634
  }
596
635
  p3.prototype = new l3();
@@ -599,8 +638,8 @@ p3.prototype.h = function() {
599
638
  if (1 & this.f) return false;
600
639
  if (32 == (36 & this.f)) return true;
601
640
  this.f &= -5;
602
- if (this.g === d2) return true;
603
- this.g = d2;
641
+ if (this.g === d3) return true;
642
+ this.g = d3;
604
643
  this.f |= 1;
605
644
  if (this.i > 0 && !w3(this)) {
606
645
  this.f &= -2;
@@ -754,7 +793,7 @@ function j3(i4, t4) {
754
793
  // node_modules/@preact/signals/dist/signals.module.js
755
794
  var l4;
756
795
  var h4;
757
- var d3;
796
+ var d4;
758
797
  var p4 = "undefined" != typeof window && !!window.__PREACT_SIGNALS_DEVTOOLS__;
759
798
  var _4 = [];
760
799
  j3(function() {
@@ -765,14 +804,14 @@ function g3(i4, r4) {
765
804
  });
766
805
  }
767
806
  function b3(i4) {
768
- if (d3) {
769
- var n3 = d3;
770
- d3 = void 0;
807
+ if (d4) {
808
+ var n3 = d4;
809
+ d4 = void 0;
771
810
  n3();
772
811
  }
773
- d3 = i4 && i4.S();
812
+ d4 = i4 && i4.S();
774
813
  }
775
- function y3(i4) {
814
+ function y4(i4) {
776
815
  var n3 = this, t4 = i4.data, f4 = useSignal(t4);
777
816
  f4.name = "ReactiveDom";
778
817
  f4.value = t4;
@@ -802,8 +841,8 @@ function y3(i4) {
802
841
  }, []), a4 = e4[0], v4 = e4[1];
803
842
  return a4.value ? v4.peek() : v4.value;
804
843
  }
805
- y3.displayName = "ReactiveTextNode";
806
- Object.defineProperties(l3.prototype, { constructor: { configurable: true, value: void 0 }, type: { configurable: true, value: y3 }, props: { configurable: true, get: function() {
844
+ y4.displayName = "ReactiveTextNode";
845
+ Object.defineProperties(l3.prototype, { constructor: { configurable: true, value: void 0 }, type: { configurable: true, value: y4 }, props: { configurable: true, get: function() {
807
846
  var i4 = this;
808
847
  return { data: { get value() {
809
848
  return i4.value;
@@ -887,7 +926,7 @@ g3("diffed", function(i4, n3) {
887
926
  i4(n3);
888
927
  });
889
928
  function w4(i4, n3, r4, t4) {
890
- var o4 = n3 in i4 && void 0 === i4.ownerSVGElement, f4 = y2(r4);
929
+ var o4 = n3 in i4 && void 0 === i4.ownerSVGElement, f4 = y3(r4);
891
930
  return { o: function(i5, n4) {
892
931
  f4.value = i5;
893
932
  t4 = n4;
@@ -955,7 +994,7 @@ C.prototype.shouldComponentUpdate = function(i4, n3) {
955
994
  };
956
995
  function useSignal(i4, n3) {
957
996
  return T2(function() {
958
- return y2(i4, n3);
997
+ return y3(i4, n3);
959
998
  }, []);
960
999
  }
961
1000
  var q2 = function(i4) {
@@ -1013,9 +1052,6 @@ function subscribe(onState, onError) {
1013
1052
  function postTimeZone(timeZone) {
1014
1053
  return post("/api/timezone", { timeZone });
1015
1054
  }
1016
- function postSession(body) {
1017
- return post("/api/session", body);
1018
- }
1019
1055
  function postBoardRefresh() {
1020
1056
  return post("/api/board/refresh");
1021
1057
  }
@@ -1080,40 +1116,35 @@ var VIEWS = ["today", "board", "tickets", "settings"];
1080
1116
  var RUN_PREFIX = "run:";
1081
1117
  var PANEL_PREFIX = "panel:";
1082
1118
  var VIEW_KEY = "daily-focus:view";
1083
- var UNATTENDED_SEEN_KEY = "daily-focus:unattended-seen";
1084
1119
  var AGENT_RUN_SEEN_KEY = "daily-focus:agent-run-seen";
1085
- var FOCUS_MODE_KEY = "daily-focus:focus-mode";
1086
1120
  var DETAIL_KEY = "daily-focus:detail-for";
1087
- var state = y2(null);
1121
+ var state = y3(null);
1088
1122
  function createUi(initial = {}) {
1089
1123
  return {
1090
- selectedId: y2(initial.selectedId ?? null),
1091
- clickedId: y2(initial.clickedId ?? null),
1092
- pending: y2(initial.pending ?? /* @__PURE__ */ new Set()),
1093
- menuFor: y2(initial.menuFor ?? null),
1094
- statusFor: y2(initial.statusFor ?? null),
1095
- detailFor: y2(initial.detailFor ?? null),
1096
- noteDraft: y2(initial.noteDraft ?? ""),
1097
- assistantDraft: y2(initial.assistantDraft ?? ""),
1098
- focusField: y2(initial.focusField ?? null),
1099
- openDrawers: y2(initial.openDrawers ?? /* @__PURE__ */ new Set()),
1100
- ticketMode: y2(initial.ticketMode ?? "sync"),
1101
- unattendedSeen: y2(initial.unattendedSeen ?? null),
1102
- agentReportSeen: y2(initial.agentReportSeen ?? null),
1103
- messageOpen: y2(initial.messageOpen ?? /* @__PURE__ */ new Map()),
1104
- view: y2(initial.view ?? "today"),
1105
- focusMode: y2(initial.focusMode ?? false),
1106
- theme: y2(initial.theme ?? "system"),
1107
- toast: y2(initial.toast ?? null),
1108
- connectionError: y2(initial.connectionError ?? null),
1109
- clock: y2(initial.clock ?? Date.now()),
1110
- settingsReturn: y2(initial.settingsReturn ?? "today"),
1111
- settings: y2(initial.settings ?? null),
1112
- settingsDraft: y2(initial.settingsDraft ?? /* @__PURE__ */ new Map()),
1113
- settingsError: y2(initial.settingsError ?? null),
1114
- settingsSaving: y2(initial.settingsSaving ?? false),
1115
- texts: y2(initial.texts ?? {}),
1116
- calendars: y2(initial.calendars ?? null)
1124
+ selectedId: y3(initial.selectedId ?? null),
1125
+ clickedId: y3(initial.clickedId ?? null),
1126
+ pending: y3(initial.pending ?? /* @__PURE__ */ new Set()),
1127
+ menuFor: y3(initial.menuFor ?? null),
1128
+ statusFor: y3(initial.statusFor ?? null),
1129
+ detailFor: y3(initial.detailFor ?? null),
1130
+ noteDraft: y3(initial.noteDraft ?? ""),
1131
+ assistantDraft: y3(initial.assistantDraft ?? ""),
1132
+ focusField: y3(initial.focusField ?? null),
1133
+ openDrawers: y3(initial.openDrawers ?? /* @__PURE__ */ new Set()),
1134
+ ticketMode: y3(initial.ticketMode ?? "sync"),
1135
+ agentReportSeen: y3(initial.agentReportSeen ?? null),
1136
+ messageOpen: y3(initial.messageOpen ?? /* @__PURE__ */ new Map()),
1137
+ view: y3(initial.view ?? "today"),
1138
+ theme: y3(initial.theme ?? "system"),
1139
+ toast: y3(initial.toast ?? null),
1140
+ connectionError: y3(initial.connectionError ?? null),
1141
+ settingsReturn: y3(initial.settingsReturn ?? "today"),
1142
+ settings: y3(initial.settings ?? null),
1143
+ settingsDraft: y3(initial.settingsDraft ?? /* @__PURE__ */ new Map()),
1144
+ settingsError: y3(initial.settingsError ?? null),
1145
+ settingsSaving: y3(initial.settingsSaving ?? false),
1146
+ texts: y3(initial.texts ?? {}),
1147
+ calendars: y3(initial.calendars ?? null)
1117
1148
  };
1118
1149
  }
1119
1150
  function isView(value) {
@@ -1125,9 +1156,7 @@ function remembered() {
1125
1156
  return {
1126
1157
  // Settings is a page to visit, so a reload returns to the view underneath.
1127
1158
  view: isView(view) && view !== "settings" ? view : "today",
1128
- unattendedSeen: localStorage.getItem(UNATTENDED_SEEN_KEY),
1129
1159
  agentReportSeen: localStorage.getItem(AGENT_RUN_SEEN_KEY),
1130
- focusMode: localStorage.getItem(FOCUS_MODE_KEY) === "1",
1131
1160
  detailFor: sessionStorage.getItem(DETAIL_KEY)
1132
1161
  };
1133
1162
  } catch {
@@ -1295,208 +1324,6 @@ function ThemeToggle({ ui: ui2, handlers: handlers2 }) {
1295
1324
  );
1296
1325
  }
1297
1326
 
1298
- // client/format.ts
1299
- var DAY_FORMAT = {
1300
- weekday: "long",
1301
- day: "numeric",
1302
- month: "long"
1303
- };
1304
- function formatters(timeZone) {
1305
- return {
1306
- time: new Intl.DateTimeFormat(void 0, { timeZone, hour: "2-digit", minute: "2-digit" }),
1307
- day: new Intl.DateTimeFormat(void 0, { timeZone, ...DAY_FORMAT }),
1308
- shortDay: new Intl.DateTimeFormat(void 0, { timeZone, day: "numeric", month: "short" }),
1309
- shortDayYear: new Intl.DateTimeFormat(void 0, { timeZone, day: "numeric", month: "short", year: "numeric" }),
1310
- weekday: new Intl.DateTimeFormat(void 0, { timeZone, weekday: "long" })
1311
- };
1312
- }
1313
- var clockFormats = formatters();
1314
- var dateFormats = formatters("UTC");
1315
- var DATE_ONLY = /^\d{4}-\d{2}-\d{2}$/;
1316
- function formatted(value, kind) {
1317
- const bare = typeof value === "string" && DATE_ONLY.test(value);
1318
- const d4 = bare ? /* @__PURE__ */ new Date(`${value}T00:00:00Z`) : parseDate(value);
1319
- return d4 && !Number.isNaN(d4.getTime()) ? (bare ? dateFormats : clockFormats)[kind].format(d4) : "";
1320
- }
1321
- function parseDate(value) {
1322
- if (typeof value !== "string" || value === "") return null;
1323
- const dateOnly = /^(\d{4})-(\d{2})-(\d{2})$/.exec(value);
1324
- if (dateOnly) return new Date(+dateOnly[1], +dateOnly[2] - 1, +dateOnly[3]);
1325
- const d4 = new Date(value);
1326
- return Number.isNaN(d4.getTime()) ? null : d4;
1327
- }
1328
- function formatTime(value) {
1329
- return formatted(value, "time");
1330
- }
1331
- function formatDay(value) {
1332
- return formatted(value, "day");
1333
- }
1334
- function formatShortDay(value) {
1335
- return formatted(value, "shortDay");
1336
- }
1337
- function formatWeekday(value) {
1338
- return formatted(value, "weekday");
1339
- }
1340
- var dayKeyFmt = null;
1341
- var calendarZone;
1342
- function setCalendarZone(timeZone) {
1343
- if (timeZone === calendarZone) return;
1344
- calendarZone = timeZone;
1345
- try {
1346
- clockFormats = formatters(timeZone);
1347
- dayKeyFmt = timeZone ? new Intl.DateTimeFormat("en-US", { timeZone, year: "numeric", month: "2-digit", day: "2-digit" }) : null;
1348
- } catch {
1349
- dayKeyFmt = null;
1350
- clockFormats = formatters();
1351
- }
1352
- }
1353
- function dayKey(d4) {
1354
- if (dayKeyFmt) {
1355
- const parts = dayKeyFmt.formatToParts(d4);
1356
- const part = (type) => parts.find((p5) => p5.type === type)?.value ?? "";
1357
- return `${part("year")}-${part("month")}-${part("day")}`;
1358
- }
1359
- const m4 = String(d4.getMonth() + 1).padStart(2, "0");
1360
- const day = String(d4.getDate()).padStart(2, "0");
1361
- return `${d4.getFullYear()}-${m4}-${day}`;
1362
- }
1363
- function splitKey(key) {
1364
- const [y4, m4, d4] = key.split("-").map(Number);
1365
- return [y4, m4 - 1, d4];
1366
- }
1367
- function keyAt(ms) {
1368
- return new Date(ms).toISOString().slice(0, 10);
1369
- }
1370
- function addDays(key, days) {
1371
- const [y4, m4, d4] = splitKey(key);
1372
- return keyAt(Date.UTC(y4, m4, d4 + days));
1373
- }
1374
- function addMonths(key, months) {
1375
- const [y4, m4, d4] = splitKey(key);
1376
- const lastDay = new Date(Date.UTC(y4, m4 + months + 1, 0)).getUTCDate();
1377
- return keyAt(Date.UTC(y4, m4 + months, Math.min(d4, lastDay)));
1378
- }
1379
- function daysFromToday(value, now = /* @__PURE__ */ new Date()) {
1380
- if (typeof value === "string" && /^\d{4}-\d{2}-\d{2}$/.test(value)) {
1381
- const [y4, m4, d4] = splitKey(value);
1382
- const [ty, tm, td] = splitKey(dayKey(now));
1383
- return Math.round((Date.UTC(y4, m4, d4) - Date.UTC(ty, tm, td)) / 864e5);
1384
- }
1385
- const target = parseDate(value);
1386
- if (!target) return null;
1387
- const a4 = Date.UTC(...splitKey(dayKey(now)));
1388
- const b4 = Date.UTC(...splitKey(dayKey(target)));
1389
- return Math.round((b4 - a4) / 864e5);
1390
- }
1391
- function relativeDay(value, now = /* @__PURE__ */ new Date()) {
1392
- const diff = daysFromToday(value, now);
1393
- if (diff === null) return "";
1394
- if (diff === 0) return "today";
1395
- if (diff === 1) return "tomorrow";
1396
- if (diff === -1) return "yesterday";
1397
- if (diff > 1 && diff <= 7) return `in ${diff} days`;
1398
- if (diff < -1 && diff >= -7) return `${Math.abs(diff)} days ago`;
1399
- return formatShortDay(value);
1400
- }
1401
- function formatDuration(minutes) {
1402
- const h5 = Math.floor(minutes / 60);
1403
- const m4 = minutes % 60;
1404
- if (h5 === 0) return `${m4} min`;
1405
- if (m4 === 0) return `${h5} h`;
1406
- return `${h5} h ${m4} min`;
1407
- }
1408
- function relativeTime(value, now = /* @__PURE__ */ new Date()) {
1409
- const d4 = parseDate(value);
1410
- if (!d4) return "";
1411
- const seconds = Math.round((now.getTime() - d4.getTime()) / 1e3);
1412
- if (seconds < 60) return "just now";
1413
- const minutes = Math.round(seconds / 60);
1414
- if (minutes < 60) return `${minutes} min ago`;
1415
- const hours = Math.round(minutes / 60);
1416
- if (hours < 48) return `${hours} h ago`;
1417
- const days = Math.round(hours / 24);
1418
- if (days <= 30) return `${days} days ago`;
1419
- return dayKey(d4).slice(0, 4) === dayKey(now).slice(0, 4) ? formatShortDay(value) : formatted(value, "shortDayYear");
1420
- }
1421
- function firstLine(text) {
1422
- const line = String(text).split("\n").find((l5) => l5.trim() !== "") ?? "";
1423
- return line.replace(/^[#>*\-\s]+/, "").replace(/[*_`]/g, "").trim();
1424
- }
1425
-
1426
- // client/timer.ts
1427
- function clock(seconds) {
1428
- const total = Math.abs(seconds);
1429
- const mm = Math.floor(total / 60);
1430
- const ss = Math.floor(total % 60);
1431
- return `${seconds < 0 ? "+" : ""}${mm}:${String(ss).padStart(2, "0")}`;
1432
- }
1433
- function remainingSeconds(active, nowMs) {
1434
- return Math.round((new Date(active.endsAt).getTime() - nowMs) / 1e3);
1435
- }
1436
- function unattendedNotice(closed, handlers2) {
1437
- const stoppedAt = formatTime(closed.endedAt);
1438
- const headline = closed.reason === "away" ? `Timer stopped at ${stoppedAt} \u2014 nothing had touched the machine since.` : `Timer stopped at ${stoppedAt} \u2014 it had been left running.`;
1439
- return el(
1440
- "div",
1441
- { class: "timer__away", role: "status" },
1442
- el(
1443
- "span",
1444
- { class: "timer__away-body" },
1445
- el("span", { class: "timer__away-text" }, headline),
1446
- el(
1447
- "span",
1448
- { class: "timer__away-detail" },
1449
- `${formatDuration(closed.actualMinutes)} logged on \u201C${closed.title}\u201D. `,
1450
- closed.reason === "away" ? "The time you were away is not in the record." : "Treat that as an upper bound, not a measurement."
1451
- )
1452
- ),
1453
- el("button", { type: "button", class: "button", onClick: () => handlers2.startSession(closed.id) }, "Pick it back up"),
1454
- el(
1455
- "button",
1456
- {
1457
- type: "button",
1458
- class: "icon-button",
1459
- "aria-label": "Dismiss",
1460
- onClick: () => handlers2.dismissUnattended(closed.endedAt)
1461
- },
1462
- "\u2715"
1463
- )
1464
- );
1465
- }
1466
- function Timer({ state: state2, ui: ui2, handlers: handlers2 }) {
1467
- const { active, completedToday, minutesToday, unattendedClose } = state2.session;
1468
- const closed = unattendedClose && ui2.unattendedSeen.value !== unattendedClose.endedAt ? unattendedClose : null;
1469
- if (!active && completedToday === 0 && !closed) {
1470
- return el("div", { class: "timer", id: "timer", hidden: true });
1471
- }
1472
- const tally = completedToday > 0 ? `${completedToday} session${completedToday === 1 ? "" : "s"} today \xB7 ${formatDuration(minutesToday)}` : null;
1473
- if (!active) {
1474
- return el(
1475
- "div",
1476
- { class: "timer", id: "timer", hidden: false, "data-state": closed ? "stopped" : "idle" },
1477
- closed ? unattendedNotice(closed, handlers2) : null,
1478
- tally ? el("span", { class: "timer__tally" }, tally) : null
1479
- );
1480
- }
1481
- const remaining = remainingSeconds(active, ui2.clock.value);
1482
- const overrun = remaining < 0;
1483
- return el(
1484
- "div",
1485
- { class: "timer", id: "timer", hidden: false, "data-state": overrun ? "overrun" : "running" },
1486
- el("span", { class: "timer__clock" }, clock(remaining)),
1487
- el(
1488
- "span",
1489
- { class: "timer__title" },
1490
- active.title,
1491
- overrun ? el("span", { class: "timer__note" }, ` \xB7 ${active.minutes} min in, still counting`) : null,
1492
- // The one thing a kitchen timer can't tell you.
1493
- active.collidesWithNextEvent && !overrun ? el("span", { class: "timer__note timer__note--warn" }, ` \xB7 runs into ${formatTime(active.nextEventAt)}`) : null
1494
- ),
1495
- tally ? el("span", { class: "timer__tally" }, tally) : null,
1496
- el("button", { type: "button", class: "button", onClick: () => handlers2.stopSession() }, "Stop")
1497
- );
1498
- }
1499
-
1500
1327
  // client/actions.ts
1501
1328
  function afterRender(fn) {
1502
1329
  if (typeof requestAnimationFrame === "function") requestAnimationFrame(fn);
@@ -1550,7 +1377,6 @@ function adoptState(next) {
1550
1377
  state.value = next;
1551
1378
  ui.connectionError.value = null;
1552
1379
  });
1553
- startLocalTick();
1554
1380
  checkStore(next.storeId);
1555
1381
  checkAssetVersion(next.assetVersion);
1556
1382
  }
@@ -1714,6 +1540,27 @@ async function stopAssistant(id) {
1714
1540
  showToast(`Could not stop: ${err.message}`);
1715
1541
  }
1716
1542
  }
1543
+ async function copy(text) {
1544
+ try {
1545
+ if (navigator.clipboard && window.isSecureContext) {
1546
+ await navigator.clipboard.writeText(text);
1547
+ } else {
1548
+ const field = document.createElement("textarea");
1549
+ field.value = text;
1550
+ field.setAttribute("readonly", "");
1551
+ field.style.position = "fixed";
1552
+ field.style.opacity = "0";
1553
+ document.body.append(field);
1554
+ field.select();
1555
+ const copied = document.execCommand("copy");
1556
+ field.remove();
1557
+ if (!copied) throw new Error("the browser would not copy");
1558
+ }
1559
+ showToast("Copied");
1560
+ } catch (err) {
1561
+ showToast(`Could not copy: ${err.message}`);
1562
+ }
1563
+ }
1717
1564
  async function runAgent() {
1718
1565
  if (!state.value?.agentRun?.enabled || state.value.agentRun.last?.status === "running") return;
1719
1566
  const ok = window.confirm(
@@ -1742,53 +1589,6 @@ async function askAgent(run, text) {
1742
1589
  showToast(`Could not ask the morning agent: ${err.message}`);
1743
1590
  }
1744
1591
  }
1745
- async function changeSession(body) {
1746
- if (body.action === "start" && "Notification" in window && Notification.permission === "default") {
1747
- void Notification.requestPermission();
1748
- }
1749
- try {
1750
- state.value = await postSession(body);
1751
- startLocalTick();
1752
- } catch (err) {
1753
- showToast(`Could not change the timer: ${err.message}`);
1754
- }
1755
- }
1756
- var tickTimer = null;
1757
- var announcedOverrunFor = null;
1758
- function startLocalTick() {
1759
- if (tickTimer) clearInterval(tickTimer);
1760
- tickTimer = setInterval(tick, 1e3);
1761
- tick();
1762
- }
1763
- function tick() {
1764
- const active = state.value?.session.active;
1765
- if (!active) {
1766
- document.title = "Daily Focus";
1767
- if (tickTimer) clearInterval(tickTimer);
1768
- tickTimer = null;
1769
- return;
1770
- }
1771
- const nowMs = Date.now();
1772
- ui.clock.value = nowMs;
1773
- const remaining = remainingSeconds(active, nowMs);
1774
- const mm = Math.floor(Math.abs(remaining) / 60);
1775
- const ss = String(Math.floor(Math.abs(remaining) % 60)).padStart(2, "0");
1776
- document.title = `${remaining < 0 ? "+" : ""}${mm}:${ss} \xB7 ${active.title}`;
1777
- if (remaining <= 0 && announcedOverrunFor !== active.startedAt) {
1778
- announcedOverrunFor = active.startedAt;
1779
- announceSessionEnd(active);
1780
- }
1781
- }
1782
- function announceSessionEnd(active) {
1783
- const label = active.minutes === 1 ? "1 minute" : `${active.minutes} minutes`;
1784
- showToast(`${label} in \u2014 still on "${active.title}"?`, null);
1785
- if ("Notification" in window && Notification.permission === "granted") {
1786
- new Notification("Still on this?", {
1787
- body: `${label} in on ${active.title}. Keep going, or stop and log it.`,
1788
- tag: "daily-focus-session"
1789
- });
1790
- }
1791
- }
1792
1592
  function showView(view) {
1793
1593
  if (ui.view.value === view) return;
1794
1594
  if (state.value && !availableViews(state.value).includes(view)) return;
@@ -1837,10 +1637,6 @@ function setTicketMode(mode) {
1837
1637
  closeMenus();
1838
1638
  });
1839
1639
  }
1840
- function setFocusMode(on) {
1841
- ui.focusMode.value = on;
1842
- remember(FOCUS_MODE_KEY, on ? "1" : null);
1843
- }
1844
1640
  function restartToast(page) {
1845
1641
  if (page.restart === "manual") showToast("Saved. Restart the dashboard to apply it.");
1846
1642
  else if (page.restart === "waiting" && state.value?.agentRun?.last?.status === "running") {
@@ -2063,12 +1859,6 @@ var handlers = {
2063
1859
  () => document.querySelector('#tickets .item[data-selected="true"]')?.scrollIntoView({ block: "center", behavior: "smooth" })
2064
1860
  );
2065
1861
  },
2066
- startSession: (id) => void changeSession({ action: "start", id }),
2067
- stopSession: () => void changeSession({ action: "stop" }),
2068
- dismissUnattended: (endedAt) => {
2069
- ui.unattendedSeen.value = endedAt;
2070
- remember(UNATTENDED_SEEN_KEY, endedAt);
2071
- },
2072
1862
  // A nudge on Slack is invisible to GitHub, so it's recorded: the board's nudge
2073
1863
  // timer starts over from it, and the agent reads that the user asked.
2074
1864
  nudge: (id) => void applyAction(id, "nudge"),
@@ -2078,6 +1868,7 @@ var handlers = {
2078
1868
  refreshCalendar: () => void refreshCalendar(),
2079
1869
  ask: (id, body) => void ask(id, body),
2080
1870
  stopAssistant: (id) => void stopAssistant(id),
1871
+ copy: (text) => void copy(text),
2081
1872
  runAgent: () => void runAgent(),
2082
1873
  stopAgent: () => void stopAgent(),
2083
1874
  askAgent: (run, text) => void askAgent(run, text),
@@ -2096,7 +1887,6 @@ var handlers = {
2096
1887
  applyTheme(mode);
2097
1888
  ui.theme.value = mode;
2098
1889
  },
2099
- setFocusMode,
2100
1890
  openHelp: () => document.getElementById("help")?.showModal(),
2101
1891
  hideToast,
2102
1892
  openSettings,
@@ -2117,6 +1907,145 @@ var handlers = {
2117
1907
  listCalendars: () => void listCalendars()
2118
1908
  };
2119
1909
 
1910
+ // client/format.ts
1911
+ var DAY_FORMAT = {
1912
+ weekday: "long",
1913
+ day: "numeric",
1914
+ month: "long"
1915
+ };
1916
+ function formatters(timeZone) {
1917
+ return {
1918
+ time: new Intl.DateTimeFormat(void 0, { timeZone, hour: "2-digit", minute: "2-digit" }),
1919
+ day: new Intl.DateTimeFormat(void 0, { timeZone, ...DAY_FORMAT }),
1920
+ shortDay: new Intl.DateTimeFormat(void 0, { timeZone, day: "numeric", month: "short" }),
1921
+ shortDayYear: new Intl.DateTimeFormat(void 0, { timeZone, day: "numeric", month: "short", year: "numeric" }),
1922
+ weekday: new Intl.DateTimeFormat(void 0, { timeZone, weekday: "long" })
1923
+ };
1924
+ }
1925
+ var clockFormats = formatters();
1926
+ var dateFormats = formatters("UTC");
1927
+ var DATE_ONLY = /^\d{4}-\d{2}-\d{2}$/;
1928
+ function formatted(value, kind) {
1929
+ const bare = typeof value === "string" && DATE_ONLY.test(value);
1930
+ const d5 = bare ? /* @__PURE__ */ new Date(`${value}T00:00:00Z`) : parseDate(value);
1931
+ return d5 && !Number.isNaN(d5.getTime()) ? (bare ? dateFormats : clockFormats)[kind].format(d5) : "";
1932
+ }
1933
+ function parseDate(value) {
1934
+ if (typeof value !== "string" || value === "") return null;
1935
+ const dateOnly = /^(\d{4})-(\d{2})-(\d{2})$/.exec(value);
1936
+ if (dateOnly) return new Date(+dateOnly[1], +dateOnly[2] - 1, +dateOnly[3]);
1937
+ const d5 = new Date(value);
1938
+ return Number.isNaN(d5.getTime()) ? null : d5;
1939
+ }
1940
+ function formatTime(value) {
1941
+ return formatted(value, "time");
1942
+ }
1943
+ function formatDay(value) {
1944
+ return formatted(value, "day");
1945
+ }
1946
+ function formatShortDay(value) {
1947
+ return formatted(value, "shortDay");
1948
+ }
1949
+ function formatWeekday(value) {
1950
+ return formatted(value, "weekday");
1951
+ }
1952
+ var dayKeyFmt = null;
1953
+ var calendarZone;
1954
+ function setCalendarZone(timeZone) {
1955
+ if (timeZone === calendarZone) return;
1956
+ calendarZone = timeZone;
1957
+ try {
1958
+ clockFormats = formatters(timeZone);
1959
+ dayKeyFmt = timeZone ? new Intl.DateTimeFormat("en-US", { timeZone, year: "numeric", month: "2-digit", day: "2-digit" }) : null;
1960
+ } catch {
1961
+ dayKeyFmt = null;
1962
+ clockFormats = formatters();
1963
+ }
1964
+ }
1965
+ function dayKey(d5) {
1966
+ if (dayKeyFmt) {
1967
+ const parts = dayKeyFmt.formatToParts(d5);
1968
+ const part = (type) => parts.find((p5) => p5.type === type)?.value ?? "";
1969
+ return `${part("year")}-${part("month")}-${part("day")}`;
1970
+ }
1971
+ const m4 = String(d5.getMonth() + 1).padStart(2, "0");
1972
+ const day = String(d5.getDate()).padStart(2, "0");
1973
+ return `${d5.getFullYear()}-${m4}-${day}`;
1974
+ }
1975
+ function splitKey(key) {
1976
+ const [y5, m4, d5] = key.split("-").map(Number);
1977
+ return [y5, m4 - 1, d5];
1978
+ }
1979
+ function keyAt(ms) {
1980
+ return new Date(ms).toISOString().slice(0, 10);
1981
+ }
1982
+ function addDays(key, days) {
1983
+ const [y5, m4, d5] = splitKey(key);
1984
+ return keyAt(Date.UTC(y5, m4, d5 + days));
1985
+ }
1986
+ function addMonths(key, months) {
1987
+ const [y5, m4, d5] = splitKey(key);
1988
+ const lastDay = new Date(Date.UTC(y5, m4 + months + 1, 0)).getUTCDate();
1989
+ return keyAt(Date.UTC(y5, m4 + months, Math.min(d5, lastDay)));
1990
+ }
1991
+ function daysFromToday(value, now = /* @__PURE__ */ new Date()) {
1992
+ if (typeof value === "string" && /^\d{4}-\d{2}-\d{2}$/.test(value)) {
1993
+ const [y5, m4, d5] = splitKey(value);
1994
+ const [ty, tm, td] = splitKey(dayKey(now));
1995
+ return Math.round((Date.UTC(y5, m4, d5) - Date.UTC(ty, tm, td)) / 864e5);
1996
+ }
1997
+ const target = parseDate(value);
1998
+ if (!target) return null;
1999
+ const a4 = Date.UTC(...splitKey(dayKey(now)));
2000
+ const b4 = Date.UTC(...splitKey(dayKey(target)));
2001
+ return Math.round((b4 - a4) / 864e5);
2002
+ }
2003
+ function relativeDay(value, now = /* @__PURE__ */ new Date()) {
2004
+ const diff = daysFromToday(value, now);
2005
+ if (diff === null) return "";
2006
+ if (diff === 0) return "today";
2007
+ if (diff === 1) return "tomorrow";
2008
+ if (diff === -1) return "yesterday";
2009
+ if (diff > 1 && diff <= 7) return `in ${diff} days`;
2010
+ if (diff < -1 && diff >= -7) return `${Math.abs(diff)} days ago`;
2011
+ return formatShortDay(value);
2012
+ }
2013
+ function formatDuration(minutes) {
2014
+ const h5 = Math.floor(minutes / 60);
2015
+ const m4 = minutes % 60;
2016
+ if (h5 === 0) return `${m4} min`;
2017
+ if (m4 === 0) return `${h5} h`;
2018
+ return `${h5} h ${m4} min`;
2019
+ }
2020
+ function relativeTime(value, now = /* @__PURE__ */ new Date()) {
2021
+ const d5 = parseDate(value);
2022
+ if (!d5) return "";
2023
+ const seconds = Math.round((now.getTime() - d5.getTime()) / 1e3);
2024
+ if (seconds < 60) return "just now";
2025
+ const minutes = Math.round(seconds / 60);
2026
+ if (minutes < 60) return `${minutes} min ago`;
2027
+ const hours = Math.round(minutes / 60);
2028
+ if (hours < 48) return `${hours} h ago`;
2029
+ const days = Math.round(hours / 24);
2030
+ if (days <= 30) return `${days} days ago`;
2031
+ return dayKey(d5).slice(0, 4) === dayKey(now).slice(0, 4) ? formatShortDay(value) : formatted(value, "shortDayYear");
2032
+ }
2033
+ function durationBetween(start, end) {
2034
+ const from = parseDate(start);
2035
+ const to = parseDate(end);
2036
+ if (!from || !to || to < from) return "";
2037
+ const seconds = Math.round((to.getTime() - from.getTime()) / 1e3);
2038
+ return seconds < 60 ? `${seconds} s` : formatDuration(Math.round(seconds / 60));
2039
+ }
2040
+ function formatClock(seconds) {
2041
+ const whole = Math.max(0, Math.floor(seconds));
2042
+ return `${Math.floor(whole / 60)}:${String(whole % 60).padStart(2, "0")}`;
2043
+ }
2044
+ function firstLine(text) {
2045
+ const line = String(text).split("\n").find((l5) => l5.trim() !== "") ?? "";
2046
+ return line.replace(/^[#>*\-\s]+/, "").replace(/[*_`]/g, "").trim();
2047
+ }
2048
+
2120
2049
  // client/failure.ts
2121
2050
  function failureNotice(failure, { fold, className, icon, lastGood, now, onRetry }, ui2, handlers2) {
2122
2051
  return el(
@@ -2310,7 +2239,7 @@ function renderMarkdown(value) {
2310
2239
  function anchor(href, label) {
2311
2240
  return el("a", { href: /^https?:\/\//i.test(href) ? href : "#", target: "_blank", rel: "noopener noreferrer" }, label);
2312
2241
  }
2313
- function renderMarkdownBlocks(value) {
2242
+ function renderMarkdownBlocks(value, options = {}) {
2314
2243
  const out = [];
2315
2244
  const lines = String(value).replace(/\r\n/g, "\n").split("\n");
2316
2245
  let i4 = 0;
@@ -2321,7 +2250,16 @@ function renderMarkdownBlocks(value) {
2321
2250
  i4++;
2322
2251
  while (i4 < lines.length && !/^\s*```/.test(lines[i4])) code.push(lines[i4++]);
2323
2252
  i4++;
2324
- out.push(el("pre", null, code.join("\n")));
2253
+ const text = code.join("\n");
2254
+ const { onCopy } = options;
2255
+ out.push(
2256
+ onCopy ? el(
2257
+ "div",
2258
+ { class: "code-block" },
2259
+ el("pre", null, text),
2260
+ el("button", { type: "button", class: "code-block__copy", title: "Copy to the clipboard", onClick: () => onCopy(text) }, "Copy")
2261
+ ) : el("pre", null, text)
2262
+ );
2325
2263
  continue;
2326
2264
  }
2327
2265
  if (line.trim() === "") {
@@ -2331,7 +2269,7 @@ function renderMarkdownBlocks(value) {
2331
2269
  if (/^\s*>/.test(line)) {
2332
2270
  const quoted = [];
2333
2271
  while (i4 < lines.length && /^\s*>/.test(lines[i4])) quoted.push(lines[i4++].replace(/^\s*>\s?/, ""));
2334
- out.push(el("blockquote", null, renderMarkdownBlocks(quoted.join("\n"))));
2272
+ out.push(el("blockquote", null, renderMarkdownBlocks(quoted.join("\n"), options)));
2335
2273
  continue;
2336
2274
  }
2337
2275
  if (/^\s*(?:-{3,}|\*{3,}|_{3,})\s*$/.test(line)) {
@@ -2575,9 +2513,6 @@ function renderItem(item, state2, ui2, handlers2) {
2575
2513
  function ItemRow({ item, state: state2, ui: ui2, handlers: handlers2 }) {
2576
2514
  const now = new Date(state2.now);
2577
2515
  const selected = ui2.selectedId.value === item.id;
2578
- const active = state2.session?.active ?? null;
2579
- const running = active !== null && active.id === item.id;
2580
- const overrun = running && remainingSeconds(active, ui2.clock.value) < 0;
2581
2516
  const repo = githubRepo(item);
2582
2517
  const title = item.url ? el(
2583
2518
  "a",
@@ -2595,8 +2530,6 @@ function ItemRow({ item, state: state2, ui: ui2, handlers: handlers2 }) {
2595
2530
  "data-selected": String(selected),
2596
2531
  "data-priority": String(item.priority !== void 0 && item.status === "open"),
2597
2532
  "data-pending": String(ui2.pending.value.has(item.id)),
2598
- "data-running": String(running),
2599
- "data-overrun": String(overrun),
2600
2533
  "data-detail": String(ui2.detailFor.value === item.id),
2601
2534
  // A click on the card opens the panel on it: one way in, and the whole card is it.
2602
2535
  onClick: (event) => {
@@ -2616,31 +2549,20 @@ function ItemRow({ item, state: state2, ui: ui2, handlers: handlers2 }) {
2616
2549
  "div",
2617
2550
  { class: "item__body" },
2618
2551
  el("p", { class: "item__title" }, title),
2619
- renderMeta(item, state2, ui2, now),
2552
+ renderMeta(item, state2, now),
2620
2553
  item.detail ? el("p", { class: "item__detail" }, renderMarkdown(item.detail)) : null
2621
2554
  ),
2622
- renderActions(item, state2, ui2, handlers2),
2555
+ renderActions(item, ui2, handlers2),
2623
2556
  ui2.menuFor.value === item.id ? renderSnoozeMenu(item, now, handlers2) : null
2624
2557
  );
2625
2558
  }
2626
- function renderMeta(item, state2, ui2, now) {
2559
+ function renderMeta(item, state2, now) {
2627
2560
  const pills = [];
2628
2561
  const said = /* @__PURE__ */ new Set();
2629
2562
  const pill = (cls, text) => {
2630
2563
  pills.push(el("span", { class: cls }, text));
2631
2564
  said.add(text.trim().toLowerCase());
2632
2565
  };
2633
- const active = state2.session?.active ?? null;
2634
- if (active && active.id === item.id) {
2635
- pills.push(
2636
- el(
2637
- "span",
2638
- { class: "pill pill--running" },
2639
- el("span", { class: "item__running-clock" }, clock(remainingSeconds(active, ui2.clock.value))),
2640
- " focusing"
2641
- )
2642
- );
2643
- }
2644
2566
  if (item.priority !== void 0 && item.status === "open") {
2645
2567
  pill("pill pill--priority", `#${item.priority}`);
2646
2568
  }
@@ -2692,24 +2614,11 @@ function rowPillTexts(row, state2) {
2692
2614
  function rowPills(row, state2) {
2693
2615
  return rowPillTexts(row, state2).map(([cls, text]) => el("span", { class: cls }, text));
2694
2616
  }
2695
- function renderActions(item, state2, ui2, handlers2) {
2617
+ function renderActions(item, ui2, handlers2) {
2696
2618
  const buttons = [];
2697
2619
  const act = (id, action) => () => handlers2.onAction(id, action);
2698
- const running = state2.session?.active?.id === item.id;
2699
2620
  if (item.status === "open") {
2700
2621
  if (item.kind === "task") {
2701
- buttons.push(
2702
- el(
2703
- "button",
2704
- {
2705
- type: "button",
2706
- class: running ? "button button--primary" : "button",
2707
- title: running ? "Stop the focus session" : "Start a focus session on this",
2708
- onClick: () => running ? handlers2.stopSession() : handlers2.startSession(item.id)
2709
- },
2710
- running ? "Stop" : "Focus"
2711
- )
2712
- );
2713
2622
  buttons.push(el("button", { type: "button", class: "button", onClick: act(item.id, "done") }, "Done"));
2714
2623
  buttons.push(
2715
2624
  el(
@@ -3776,8 +3685,6 @@ var SHORTCUTS = [
3776
3685
  [["Esc"], "Close the menu, then the panel"],
3777
3686
  [["o"], "Open the source link"],
3778
3687
  [["u"], "Undo the last action"],
3779
- [["f"], "Focus mode \u2014 hide all but the top item"],
3780
- [["p"], "Start a focus session on the selected item"],
3781
3688
  [["r"], "Refresh whichever board you are on"],
3782
3689
  [["w"], "Jira tickets: switch between out of sync and working on"],
3783
3690
  [[","], "Settings: your objective, where the agent looks, and the rest"],
@@ -3971,11 +3878,7 @@ function runStatus(run, now, handlers2) {
3971
3878
  );
3972
3879
  }
3973
3880
  function runDuration(run) {
3974
- const from = parseDate(run.startedAt);
3975
- const to = parseDate(run.endedAt);
3976
- if (!from || !to || to < from) return "";
3977
- const seconds = Math.round((to.getTime() - from.getTime()) / 1e3);
3978
- return seconds < 60 ? `${seconds} s` : formatDuration(Math.round(seconds / 60));
3881
+ return durationBetween(run.startedAt, run.endedAt);
3979
3882
  }
3980
3883
  function runConversation(run, busy, answering, enabled, ui2, handlers2, inputRef) {
3981
3884
  const turns = run.turns.length ? el(
@@ -4131,8 +4034,9 @@ function RowPanel({ row, state: state2, ui: ui2, handlers: handlers2 }) {
4131
4034
  ) : el("p", { class: "flyout__empty" }, "Nothing noted yet. A note goes to the morning agent as free text."),
4132
4035
  k(NoteForm, { row, title: facts.title, ui: ui2, handlers: handlers2, inputRef: noteInput })
4133
4036
  ),
4134
- enabled ? renderAssistantSection(row, facts, state2, entry, ui2, handlers2, askInput) : entry.turns.length ? renderAssistantHistory(state2, entry) : null
4135
- )
4037
+ entry.turns.length ? renderAssistantSection(state2, entry, enabled, handlers2) : null
4038
+ ),
4039
+ enabled ? renderAssistantFooter(facts, state2, entry, ui2, handlers2, askInput, row) : null
4136
4040
  ];
4137
4041
  }
4138
4042
  function describeRow(row) {
@@ -4233,21 +4137,27 @@ function NoteForm({
4233
4137
  el("button", { type: "submit", class: "button button--primary flyout__submit" }, "Save")
4234
4138
  );
4235
4139
  }
4236
- function renderAssistantSection(row, facts, state2, entry, ui2, handlers2, inputRef) {
4237
- const source = "source" in row ? row.source : "github";
4238
- const actions = (state2.assistant?.quickActions ?? []).filter(
4239
- (action) => action.sources === null || action.sources.includes(source)
4240
- );
4140
+ function renderAssistantSection(state2, entry, enabled, handlers2) {
4241
4141
  const label = new Map((state2.assistant?.quickActions ?? []).map((action) => [action.id, action]));
4242
4142
  return el(
4243
4143
  "section",
4244
4144
  { class: "flyout__section assistant", "data-running": String(entry.running) },
4245
4145
  el("h3", { class: "flyout__label" }, "Assistant"),
4246
- entry.turns.length ? el(
4146
+ el(
4247
4147
  "div",
4248
4148
  { class: "assistant__turns" },
4249
- entry.turns.map((turn) => renderAssistantTurn(turn, label))
4250
- ) : null,
4149
+ entry.turns.map((turn) => renderAssistantTurn(turn, label, handlers2))
4150
+ ),
4151
+ enabled ? null : el("p", { class: "flyout__empty" }, "The assistant is switched off (DAILY_FOCUS_ASSISTANT), so nothing more can be asked here.")
4152
+ );
4153
+ }
4154
+ function renderAssistantFooter(facts, state2, entry, ui2, handlers2, inputRef, row) {
4155
+ const actions = (state2.assistant?.quickActions ?? []).filter(
4156
+ (action) => action.sources === null || action.sources.includes(facts.source)
4157
+ );
4158
+ return el(
4159
+ "div",
4160
+ { class: "flyout__footer" },
4251
4161
  entry.running ? null : el(
4252
4162
  "div",
4253
4163
  { class: "assistant__quick" },
@@ -4267,20 +4177,6 @@ function renderAssistantSection(row, facts, state2, entry, ui2, handlers2, input
4267
4177
  k(AssistantComposer, { row, title: facts.title, entry, ui: ui2, handlers: handlers2, inputRef })
4268
4178
  );
4269
4179
  }
4270
- function renderAssistantHistory(state2, entry) {
4271
- const label = new Map((state2.assistant?.quickActions ?? []).map((action) => [action.id, action]));
4272
- return el(
4273
- "section",
4274
- { class: "flyout__section assistant", "data-running": "false" },
4275
- el("h3", { class: "flyout__label" }, "Assistant"),
4276
- el(
4277
- "div",
4278
- { class: "assistant__turns" },
4279
- entry.turns.map((turn) => renderAssistantTurn(turn, label))
4280
- ),
4281
- el("p", { class: "flyout__empty" }, "The assistant is switched off (DAILY_FOCUS_ASSISTANT), so nothing more can be asked here.")
4282
- );
4283
- }
4284
4180
  function AssistantComposer({
4285
4181
  row,
4286
4182
  title,
@@ -4309,7 +4205,7 @@ function AssistantComposer({
4309
4205
  rows: 2,
4310
4206
  ref: inputRef,
4311
4207
  value: ui2.assistantDraft.value,
4312
- placeholder: entry.turns.length ? "Follow up\u2026" : "What do you need help with?",
4208
+ placeholder: entry.turns.length ? "Follow up\u2026" : "Ask the assistant about this\u2026",
4313
4209
  "aria-label": `Ask the assistant about ${title}`,
4314
4210
  disabled: entry.running,
4315
4211
  onInput: (event) => {
@@ -4325,19 +4221,83 @@ function AssistantComposer({
4325
4221
  entry.running ? el("button", { type: "button", class: "button flyout__submit", onClick: () => handlers2.stopAssistant(row.id) }, "Stop") : el("button", { type: "submit", class: "button button--primary flyout__submit" }, "Send")
4326
4222
  );
4327
4223
  }
4328
- function renderAssistantTurn(turn, label) {
4224
+ function renderAssistantTurn(turn, label, handlers2) {
4329
4225
  const action = turn.action ? label.get(turn.action) : null;
4330
4226
  const extra = action && turn.request.startsWith(action.request) ? turn.request.slice(action.request.length).trim() : null;
4331
4227
  const asked = action ? [el("strong", null, action.label), extra ? ` \u2014 ${extra}` : ""] : [turn.request];
4332
- const status = turn.status === "running" ? el("p", { class: "assistant__status" }, "Working\u2026") : turn.status === "failed" ? el("p", { class: "assistant__status assistant__status--bad" }, `Failed: ${turn.error}`) : turn.status === "aborted" ? el("p", { class: "assistant__status" }, `Stopped: ${turn.error}`) : null;
4228
+ const { body, created } = turn.status === "done" ? splitCreated(turn.reply) : { body: turn.reply, created: [] };
4229
+ const status = turn.status === "failed" ? el("p", { class: "assistant__status assistant__status--bad" }, `Failed: ${turn.error}`) : turn.status === "aborted" ? el("p", { class: "assistant__status" }, `Stopped: ${turn.error}`) : null;
4333
4230
  return el(
4334
4231
  "div",
4335
- { class: "assistant__turn", "data-status": turn.status },
4232
+ { key: turn.id, class: "assistant__turn", "data-status": turn.status },
4336
4233
  el("p", { class: "assistant__request" }, asked),
4337
- turn.reply ? el("div", { class: "assistant__reply" }, renderMarkdownBlocks(turn.reply)) : null,
4338
- status
4234
+ renderWork(turn),
4235
+ body ? el("div", { class: "assistant__reply" }, renderMarkdownBlocks(body, { onCopy: (text) => handlers2.copy(text) })) : null,
4236
+ status,
4237
+ turn.status === "done" && (body || created.length) ? el(
4238
+ "div",
4239
+ { class: "assistant__after" },
4240
+ created.map(
4241
+ (link) => el("a", { class: "button", href: link.url, target: "_blank", rel: "noopener noreferrer", title: link.url }, `${link.label} \u2197`)
4242
+ ),
4243
+ body ? el("button", { type: "button", class: "button", onClick: () => handlers2.copy(body) }, "Copy reply") : null
4244
+ ) : null
4245
+ );
4246
+ }
4247
+ function renderWork(turn) {
4248
+ const steps = turn.steps ?? [];
4249
+ if (turn.status === "running") {
4250
+ return el(
4251
+ "div",
4252
+ { class: "assistant__work" },
4253
+ el("p", { class: "assistant__status assistant__status--working" }, "Working \xB7 ", k(Elapsed, { since: turn.startedAt })),
4254
+ steps.length ? renderSteps(steps) : null
4255
+ );
4256
+ }
4257
+ const took = durationBetween(turn.startedAt, turn.endedAt);
4258
+ if (!steps.length) return took ? el("p", { class: "assistant__took" }, `Answered in ${took}`) : null;
4259
+ const failed = steps.filter((step2) => step2.state === "failed").length;
4260
+ const summary = [
4261
+ took ? `${turn.status === "done" ? "Worked" : "Ran"} for ${took}` : null,
4262
+ `${steps.length} ${steps.length === 1 ? "step" : "steps"}`,
4263
+ failed ? `${failed} failed` : null
4264
+ ].filter(Boolean).join(" \xB7 ");
4265
+ return el("details", { class: "assistant__work", open: turn.status === "failed" }, el("summary", null, summary), renderSteps(steps));
4266
+ }
4267
+ function renderSteps(steps) {
4268
+ return el(
4269
+ "ol",
4270
+ { class: "assistant__steps" },
4271
+ steps.map(
4272
+ (step2, index) => step2.kind === "message" ? el("li", { key: index, class: "assistant__step assistant__step--message" }, renderMarkdown(step2.text.trim())) : el(
4273
+ "li",
4274
+ { key: index, class: "assistant__step", "data-state": step2.state },
4275
+ el("span", { class: "assistant__step-text" }, step2.text),
4276
+ step2.detail ? el("code", { class: "assistant__step-detail", title: step2.detail }, step2.detail) : null
4277
+ )
4278
+ )
4339
4279
  );
4340
4280
  }
4281
+ function Elapsed({ since }) {
4282
+ const [now, setNow] = d2(() => Date.now());
4283
+ h2(() => {
4284
+ const timer = setInterval(() => setNow(Date.now()), 1e3);
4285
+ return () => clearInterval(timer);
4286
+ }, []);
4287
+ const start = parseDate(since)?.getTime() ?? now;
4288
+ return el("span", { class: "assistant__clock" }, formatClock((now - start) / 1e3));
4289
+ }
4290
+ var CREATED = /^\s*(?:[-*]\s+)?Created:\s*\[([^\]]+)\]\((https?:\/\/[^\s)]+)\)\s*\.?\s*$/i;
4291
+ function splitCreated(reply) {
4292
+ const created = [];
4293
+ const kept = [];
4294
+ for (const line of reply.split("\n")) {
4295
+ const match = CREATED.exec(line);
4296
+ if (match) created.push({ label: match[1].trim(), url: match[2] });
4297
+ else kept.push(line);
4298
+ }
4299
+ return { body: created.length ? kept.join("\n").trim() : reply, created };
4300
+ }
4341
4301
 
4342
4302
  // client/settings.ts
4343
4303
  var VIEW_NAME = {
@@ -4873,14 +4833,8 @@ function boardRow(name, health, text, action) {
4873
4833
 
4874
4834
  // client/today.ts
4875
4835
  function TodayView({ state: state2, ui: ui2, handlers: handlers2 }) {
4876
- const focusBar = el(
4877
- "p",
4878
- { class: "focus-bar", id: "focus-bar", hidden: !ui2.focusMode.value },
4879
- "Focus mode \u2014 everything but the top item is hidden. ",
4880
- el("button", { type: "button", class: "button", id: "focus-exit", onClick: () => handlers2.setFocusMode(false) }, "Show everything")
4881
- );
4882
- if (state2.setup?.needed) return [focusBar, k(SetupCard, { state: state2, ui: ui2, handlers: handlers2 })];
4883
- return [focusBar, renderObjective(state2, handlers2), renderStats(state2), renderHeadline(state2), renderSections(state2, ui2, handlers2)];
4836
+ if (state2.setup?.needed) return [k(SetupCard, { state: state2, ui: ui2, handlers: handlers2 })];
4837
+ return [renderObjective(state2, handlers2), renderStats(state2), renderHeadline(state2), renderSections(state2, ui2, handlers2)];
4884
4838
  }
4885
4839
  function renderObjective(state2, handlers2 = null) {
4886
4840
  const focus = state2.focus;
@@ -5003,7 +4957,6 @@ function App({ ui: ui2, handlers: handlers2 }) {
5003
4957
  el("a", { class: "skip-link", href: "#main" }, "Skip to content"),
5004
4958
  k(Header, { state: current, ui: ui2, handlers: handlers2 }),
5005
4959
  k(Tabs, { state: current, ui: ui2, handlers: handlers2 }),
5006
- current ? k(Timer, { state: current, ui: ui2, handlers: handlers2 }) : el("div", { class: "timer", id: "timer", hidden: true }),
5007
4960
  el("div", { id: "banners", class: "banners" }, current ? renderBanners(current, ui2, handlers2) : null),
5008
4961
  el(
5009
4962
  "main",
@@ -5121,11 +5074,6 @@ function installKeyboard(handlers2) {
5121
5074
  event.preventDefault();
5122
5075
  moveSelection(-1);
5123
5076
  return;
5124
- case "f":
5125
- if (ui.view.value !== "today") return;
5126
- event.preventDefault();
5127
- handlers2.setFocusMode(!ui.focusMode.value);
5128
- return;
5129
5077
  case "1":
5130
5078
  event.preventDefault();
5131
5079
  handlers2.setView("today");
@@ -5170,7 +5118,6 @@ function installKeyboard(handlers2) {
5170
5118
  if (!item) return;
5171
5119
  const boardRow2 = ui.view.value !== "today";
5172
5120
  const status = "status" in item ? item.status : null;
5173
- const kind = "kind" in item ? item.kind : null;
5174
5121
  switch (event.key) {
5175
5122
  case "e":
5176
5123
  event.preventDefault();
@@ -5193,12 +5140,6 @@ function installKeyboard(handlers2) {
5193
5140
  event.preventDefault();
5194
5141
  handlers2.openDetail(item.id, "assistant");
5195
5142
  break;
5196
- case "p":
5197
- event.preventDefault();
5198
- if (boardRow2) break;
5199
- if (state.value?.session.active?.id === item.id) handlers2.stopSession();
5200
- else if (status === "open" && kind === "task") handlers2.startSession(item.id);
5201
- break;
5202
5143
  case "o":
5203
5144
  if (item.url) {
5204
5145
  event.preventDefault();
@@ -5218,15 +5159,9 @@ R(k(App, { ui, handlers }), root);
5218
5159
  j3(() => {
5219
5160
  document.body.dataset.view = ui.view.value;
5220
5161
  });
5221
- j3(() => {
5222
- document.body.dataset.focusMode = String(ui.focusMode.value);
5223
- });
5224
5162
  j3(() => {
5225
5163
  document.body.dataset.offline = String(ui.connectionError.value !== null);
5226
5164
  });
5227
- j3(() => {
5228
- document.body.dataset.sessionActive = String(state.value?.session.active != null);
5229
- });
5230
5165
  j3(() => {
5231
5166
  const current = state.value;
5232
5167
  const open = current !== null && (detailRun(current, ui) !== null || detailRow(current, ui) !== null);
@@ -5253,7 +5188,6 @@ j3(() => {
5253
5188
  });
5254
5189
  installKeyboard(handlers);
5255
5190
  await refresh();
5256
- startLocalTick();
5257
5191
  var zone = watchZone({
5258
5192
  browserZone,
5259
5193
  dashboardZone: () => state.value?.timeZone,