efficient-shell 4.127.0 → 4.132.0
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/README.md +938 -5
- package/dist/{Browser-F5TKMP4K.js → Browser-XPVJ2K7B.js} +13 -10
- package/dist/Browser-XPVJ2K7B.js.map +1 -0
- package/dist/{Calculator-T3XG7S73.js → Calculator-ZXJPXG7F.js} +12 -9
- package/dist/Calculator-ZXJPXG7F.js.map +1 -0
- package/dist/ConfirmDialog-MTC7QMUJ.js +4 -0
- package/dist/{ConfirmDialog-LJXMB45A.js.map → ConfirmDialog-MTC7QMUJ.js.map} +1 -1
- package/dist/{CurrencyConverter-CASQMKLO.js → CurrencyConverter-WSJ2BBSX.js} +12 -9
- package/dist/CurrencyConverter-WSJ2BBSX.js.map +1 -0
- package/dist/{Documents-YX67YTZS.js → Documents-ONGSXUJI.js} +14 -11
- package/dist/Documents-ONGSXUJI.js.map +1 -0
- package/dist/{Files-QB63GO6J.js → Files-GQZMFWXQ.js} +17 -14
- package/dist/Files-GQZMFWXQ.js.map +1 -0
- package/dist/{Notepad-3SUD5XUE.js → Notepad-HM73XAM4.js} +15 -12
- package/dist/Notepad-HM73XAM4.js.map +1 -0
- package/dist/PdfViewer-M2YGZIYX.js +5 -0
- package/dist/{PdfViewer-LSP3YNFC.js.map → PdfViewer-M2YGZIYX.js.map} +1 -1
- package/dist/{PomodoroTimer-4EHD2QC4.js → PomodoroTimer-DG3LI5CX.js} +14 -11
- package/dist/PomodoroTimer-DG3LI5CX.js.map +1 -0
- package/dist/{Preview-4ZHR4SKP.js → Preview-TUSV4UMO.js} +16 -13
- package/dist/Preview-TUSV4UMO.js.map +1 -0
- package/dist/{Sidebar-J76PV4QF.js → Sidebar-BPU7RCZP.js} +5 -4
- package/dist/Sidebar-BPU7RCZP.js.map +1 -0
- package/dist/{Spreadsheet-G3SC7XJ5.js → Spreadsheet-3WTXCHYQ.js} +14 -11
- package/dist/Spreadsheet-3WTXCHYQ.js.map +1 -0
- package/dist/{Stock-TLT4VN2R.js → Stock-YMPOMUAW.js} +12 -9
- package/dist/Stock-YMPOMUAW.js.map +1 -0
- package/dist/{Weather-FRKX3DAK.js → Weather-NZO3CWLH.js} +12 -9
- package/dist/Weather-NZO3CWLH.js.map +1 -0
- package/dist/{WorldClock-GKCITO3M.js → WorldClock-HUC6D3AD.js} +12 -9
- package/dist/WorldClock-HUC6D3AD.js.map +1 -0
- package/dist/apps/index.js +26 -22
- package/dist/apps/index.js.map +1 -1
- package/dist/brand.css +1 -1
- package/dist/chunk-7IN7YZAL.js +547 -0
- package/dist/chunk-7IN7YZAL.js.map +1 -0
- package/dist/{chunk-YNGPTOL6.js → chunk-7MA5XBWD.js} +3 -3
- package/dist/{chunk-YNGPTOL6.js.map → chunk-7MA5XBWD.js.map} +1 -1
- package/dist/{chunk-WK7FV7VV.js → chunk-BJ34QOR3.js} +827 -625
- package/dist/chunk-BJ34QOR3.js.map +1 -0
- package/dist/{chunk-HNH7FOYB.js → chunk-CGXMWHQW.js} +7 -6
- package/dist/chunk-CGXMWHQW.js.map +1 -0
- package/dist/{chunk-XUCIYMN7.js → chunk-CJYO4RVV.js} +4 -4
- package/dist/{chunk-XUCIYMN7.js.map → chunk-CJYO4RVV.js.map} +1 -1
- package/dist/{chunk-N3CG5HG5.js → chunk-CLGNTGC5.js} +12 -11
- package/dist/chunk-CLGNTGC5.js.map +1 -0
- package/dist/chunk-D276EMXS.js +57 -0
- package/dist/chunk-D276EMXS.js.map +1 -0
- package/dist/{chunk-7KIOEKHS.js → chunk-E3TWIN7Z.js} +21 -135
- package/dist/chunk-E3TWIN7Z.js.map +1 -0
- package/dist/{chunk-2VM2FRZJ.js → chunk-EENVXIVU.js} +47 -67
- package/dist/chunk-EENVXIVU.js.map +1 -0
- package/dist/{chunk-YG45DAUT.js → chunk-FONEQRBH.js} +17 -11
- package/dist/chunk-FONEQRBH.js.map +1 -0
- package/dist/chunk-IPXN646P.js +14 -0
- package/dist/chunk-IPXN646P.js.map +1 -0
- package/dist/chunk-IRWSRJ4K.js +48 -0
- package/dist/chunk-IRWSRJ4K.js.map +1 -0
- package/dist/chunk-JMKYYPOF.js +7 -0
- package/dist/{chunk-CJZXR7MG.js.map → chunk-JMKYYPOF.js.map} +1 -1
- package/dist/{chunk-JFQGPY7W.js → chunk-KWEX4ZAF.js} +20 -17
- package/dist/chunk-KWEX4ZAF.js.map +1 -0
- package/dist/{chunk-OKEFO6TI.js → chunk-LQTVTOSY.js} +10 -10
- package/dist/chunk-LQTVTOSY.js.map +1 -0
- package/dist/{chunk-G4KA3SAX.js → chunk-MQPX6ERJ.js} +4 -4
- package/dist/{chunk-G4KA3SAX.js.map → chunk-MQPX6ERJ.js.map} +1 -1
- package/dist/{chunk-FQB24B42.js → chunk-SEWF4O3H.js} +3 -3
- package/dist/{chunk-FQB24B42.js.map → chunk-SEWF4O3H.js.map} +1 -1
- package/dist/{chunk-AXWC3332.js → chunk-TFXJRHJV.js} +3 -3
- package/dist/{chunk-AXWC3332.js.map → chunk-TFXJRHJV.js.map} +1 -1
- package/dist/{chunk-G3HQLQYZ.js → chunk-TQURTLK2.js} +59 -34
- package/dist/chunk-TQURTLK2.js.map +1 -0
- package/dist/{chunk-6XQHH7D2.js → chunk-TRCWINHF.js} +5 -5
- package/dist/{chunk-6XQHH7D2.js.map → chunk-TRCWINHF.js.map} +1 -1
- package/dist/{chunk-NPJCMM6V.js → chunk-VWZIGZFF.js} +4 -4
- package/dist/{chunk-NPJCMM6V.js.map → chunk-VWZIGZFF.js.map} +1 -1
- package/dist/{chunk-HYZ5QMVO.js → chunk-XH3ELPQZ.js} +22 -19
- package/dist/chunk-XH3ELPQZ.js.map +1 -0
- package/dist/{chunk-PPUZJFCI.js → chunk-ZKHD4J73.js} +8 -7
- package/dist/chunk-ZKHD4J73.js.map +1 -0
- package/dist/file-intake/index.js +3 -1
- package/dist/file-intake/index.js.map +1 -1
- package/dist/{index-dQia6NpB.d.ts → index-COwksV6G.d.ts} +699 -199
- package/dist/index.d.ts +2 -2
- package/dist/index.js +37 -32
- package/dist/index.js.map +1 -1
- package/dist/map/index.js +5 -3
- package/dist/map/index.js.map +1 -1
- package/dist/markdown/index.js +4 -3
- package/dist/markdown/index.js.map +1 -1
- package/dist/page-tabs/index.js +12 -8
- package/dist/page-tabs/index.js.map +1 -1
- package/dist/shell.css +17 -17
- package/dist/themes.css +15 -0
- package/dist/ui/index.d.ts +1 -1
- package/dist/ui/index.js +17 -13
- package/dist/ui/index.js.map +1 -1
- package/dist/ui.css +691 -283
- package/package.json +1 -1
- package/dist/Browser-F5TKMP4K.js.map +0 -1
- package/dist/Calculator-T3XG7S73.js.map +0 -1
- package/dist/ConfirmDialog-LJXMB45A.js +0 -3
- package/dist/CurrencyConverter-CASQMKLO.js.map +0 -1
- package/dist/Documents-YX67YTZS.js.map +0 -1
- package/dist/Files-QB63GO6J.js.map +0 -1
- package/dist/Notepad-3SUD5XUE.js.map +0 -1
- package/dist/PdfViewer-LSP3YNFC.js +0 -4
- package/dist/PomodoroTimer-4EHD2QC4.js.map +0 -1
- package/dist/Preview-4ZHR4SKP.js.map +0 -1
- package/dist/Sidebar-J76PV4QF.js.map +0 -1
- package/dist/Spreadsheet-G3SC7XJ5.js.map +0 -1
- package/dist/Stock-TLT4VN2R.js.map +0 -1
- package/dist/Weather-FRKX3DAK.js.map +0 -1
- package/dist/WorldClock-GKCITO3M.js.map +0 -1
- package/dist/chunk-2VM2FRZJ.js.map +0 -1
- package/dist/chunk-3CUSBZWG.js +0 -59
- package/dist/chunk-3CUSBZWG.js.map +0 -1
- package/dist/chunk-7KIOEKHS.js.map +0 -1
- package/dist/chunk-CJZXR7MG.js +0 -7
- package/dist/chunk-G3HQLQYZ.js.map +0 -1
- package/dist/chunk-HNH7FOYB.js.map +0 -1
- package/dist/chunk-HYZ5QMVO.js.map +0 -1
- package/dist/chunk-JFQGPY7W.js.map +0 -1
- package/dist/chunk-N3CG5HG5.js.map +0 -1
- package/dist/chunk-OKEFO6TI.js.map +0 -1
- package/dist/chunk-PPUZJFCI.js.map +0 -1
- package/dist/chunk-WK7FV7VV.js.map +0 -1
- package/dist/chunk-YG45DAUT.js.map +0 -1
|
@@ -1,7 +1,8 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { useShellStrings } from './chunk-7IN7YZAL.js';
|
|
2
|
+
import { useHydrated, useBrowserState } from './chunk-IRWSRJ4K.js';
|
|
3
|
+
import { createContext, useSyncExternalStore, useCallback, useContext, useMemo } from 'react';
|
|
2
4
|
import { jsxs, jsx } from 'react/jsx-runtime';
|
|
3
5
|
|
|
4
|
-
// src/shell/useIsMobile.ts
|
|
5
6
|
var QUERY = "(max-width: 767px), (pointer: coarse)";
|
|
6
7
|
function getSnapshot() {
|
|
7
8
|
if (typeof window === "undefined" || !window.matchMedia) return false;
|
|
@@ -42,9 +43,9 @@ var TONE_CLASS = {
|
|
|
42
43
|
info: "text-blue-600 bg-blue-100"
|
|
43
44
|
};
|
|
44
45
|
var DEFAULT_TITLE = {
|
|
45
|
-
404:
|
|
46
|
-
403:
|
|
47
|
-
500:
|
|
46
|
+
404: (errors) => errors.notFound,
|
|
47
|
+
403: (errors) => errors.noAccess,
|
|
48
|
+
500: (errors) => errors.serverError
|
|
48
49
|
};
|
|
49
50
|
function StatusIcon({ tone }) {
|
|
50
51
|
const common = { className: "h-6 w-6", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", strokeWidth: 1.5, "aria-hidden": true };
|
|
@@ -69,6 +70,7 @@ function Result({
|
|
|
69
70
|
className = ""
|
|
70
71
|
}) {
|
|
71
72
|
const tone = STATUS_TONE[status];
|
|
73
|
+
const errors = useShellStrings().errors;
|
|
72
74
|
const announces = tone === "error";
|
|
73
75
|
return /* @__PURE__ */ jsxs(
|
|
74
76
|
"div",
|
|
@@ -77,7 +79,7 @@ function Result({
|
|
|
77
79
|
className: `flex flex-col items-center justify-center px-6 py-12 text-center ${className}`.trim(),
|
|
78
80
|
children: [
|
|
79
81
|
/* @__PURE__ */ jsx("div", { className: `flex h-14 w-14 items-center justify-center rounded-full ${TONE_CLASS[tone]}`, children: icon ?? /* @__PURE__ */ jsx(StatusIcon, { tone }) }),
|
|
80
|
-
/* @__PURE__ */ jsx("h2", { className: "mt-4 text-lg font-semibold text-gray-900", children: title ?? DEFAULT_TITLE[status] ?? "" }),
|
|
82
|
+
/* @__PURE__ */ jsx("h2", { className: "mt-4 text-lg font-semibold text-gray-900", children: title ?? DEFAULT_TITLE[status]?.(errors) ?? "" }),
|
|
81
83
|
subTitle && /* @__PURE__ */ jsx("p", { className: "mt-1 max-w-md text-sm text-gray-500", children: subTitle }),
|
|
82
84
|
children && /* @__PURE__ */ jsx("div", { className: "mt-4 w-full max-w-md text-left", children }),
|
|
83
85
|
extra && /* @__PURE__ */ jsx("div", { className: "mt-6 flex flex-wrap items-center justify-center gap-3", children: extra })
|
|
@@ -96,6 +98,52 @@ function LoadingSpinner({ size = "md", padding = "py-12", label, className = ""
|
|
|
96
98
|
/* @__PURE__ */ jsx("p", { className: "text-sm text-gray-500", children: label })
|
|
97
99
|
] });
|
|
98
100
|
}
|
|
101
|
+
var isMac = typeof window !== "undefined" && typeof navigator !== "undefined" && /Mac|iPhone|iPad/.test(navigator.platform || navigator.userAgent);
|
|
102
|
+
var FORMS = {
|
|
103
|
+
MOD: ["\u2318", "Ctrl"],
|
|
104
|
+
ALT: ["\u2325", "Alt"],
|
|
105
|
+
CMD_ENTER: ["\u2318\u23CE", "Ctrl\u23CE"],
|
|
106
|
+
CMD_S: ["\u2318S", "Ctrl+S"],
|
|
107
|
+
CMD_K: ["\u2318K", "Ctrl+K"],
|
|
108
|
+
CMD_DOT: ["\u2318.", "Ctrl+."],
|
|
109
|
+
CMD_A: ["\u2318A", "Ctrl+A"],
|
|
110
|
+
CMD_Z: ["\u2318Z", "Ctrl+Z"],
|
|
111
|
+
CMD_SHIFT_Z: ["\u2318\u21E7Z", "Ctrl+Shift+Z"],
|
|
112
|
+
ALT_SHIFT_D: ["\u2325\u21E7D", "Alt+Shift+D"],
|
|
113
|
+
ALT_SHIFT_E: ["\u2325\u21E7E", "Alt+Shift+E"],
|
|
114
|
+
ALT_SHIFT_N: ["\u2325\u21E7N", "Alt+Shift+N"]
|
|
115
|
+
};
|
|
116
|
+
var HERE = isMac ? 0 : 1;
|
|
117
|
+
var MOD = FORMS.MOD[HERE];
|
|
118
|
+
var ALT = FORMS.ALT[HERE];
|
|
119
|
+
var SHIFT = "\u21E7";
|
|
120
|
+
var ENTER = "\u23CE";
|
|
121
|
+
var CMD_ENTER = FORMS.CMD_ENTER[HERE];
|
|
122
|
+
var CMD_S = FORMS.CMD_S[HERE];
|
|
123
|
+
var CMD_K = FORMS.CMD_K[HERE];
|
|
124
|
+
var CMD_DOT = FORMS.CMD_DOT[HERE];
|
|
125
|
+
var CMD_A = FORMS.CMD_A[HERE];
|
|
126
|
+
var CMD_Z = FORMS.CMD_Z[HERE];
|
|
127
|
+
var CMD_SHIFT_Z = FORMS.CMD_SHIFT_Z[HERE];
|
|
128
|
+
var ALT_SHIFT_D = FORMS.ALT_SHIFT_D[HERE];
|
|
129
|
+
var ALT_SHIFT_E = FORMS.ALT_SHIFT_E[HERE];
|
|
130
|
+
var ALT_SHIFT_N = FORMS.ALT_SHIFT_N[HERE];
|
|
131
|
+
var AS_ON_SERVER = new Map(
|
|
132
|
+
isMac ? Object.values(FORMS).map(([mac, other]) => [mac, other]) : []
|
|
133
|
+
);
|
|
134
|
+
function useShortcutLabel(keys) {
|
|
135
|
+
const hydrated = useHydrated();
|
|
136
|
+
return hydrated ? keys : AS_ON_SERVER.get(keys) ?? keys;
|
|
137
|
+
}
|
|
138
|
+
var KBD_BASE = "inline-flex items-center justify-center rounded border border-gray-200 bg-gray-50 font-medium text-gray-500";
|
|
139
|
+
var KBD_SIZES = {
|
|
140
|
+
sm: "px-1 py-0.5 text-[10px]",
|
|
141
|
+
md: "px-1.5 py-0.5 text-[11px]"
|
|
142
|
+
};
|
|
143
|
+
function Kbd({ keys, size = "md", className = "" }) {
|
|
144
|
+
const label = useShortcutLabel(keys);
|
|
145
|
+
return /* @__PURE__ */ jsx("kbd", { className: [KBD_BASE, KBD_SIZES[size], className].filter(Boolean).join(" "), children: label });
|
|
146
|
+
}
|
|
99
147
|
var ShellPrefsContext = createContext(null);
|
|
100
148
|
function ShellPrefsProvider({
|
|
101
149
|
value,
|
|
@@ -104,14 +152,14 @@ function ShellPrefsProvider({
|
|
|
104
152
|
return /* @__PURE__ */ jsx(ShellPrefsContext.Provider, { value, children });
|
|
105
153
|
}
|
|
106
154
|
function useLocalStoragePrefs(storageKey = "react-os-shell:prefs", defaults) {
|
|
107
|
-
const [prefs, setPrefs] =
|
|
155
|
+
const [prefs, setPrefs] = useBrowserState(() => {
|
|
108
156
|
try {
|
|
109
157
|
const stored = JSON.parse(localStorage.getItem(storageKey) || "{}");
|
|
110
158
|
return { ...defaults ?? {}, ...stored };
|
|
111
159
|
} catch {
|
|
112
160
|
return { ...defaults ?? {} };
|
|
113
161
|
}
|
|
114
|
-
});
|
|
162
|
+
}, { ...defaults ?? {} });
|
|
115
163
|
const save = useCallback((patch) => {
|
|
116
164
|
setPrefs((prev) => {
|
|
117
165
|
const next = { ...prev, ...patch };
|
|
@@ -262,30 +310,7 @@ function installStaleChunkReload(options = {}) {
|
|
|
262
310
|
if (onChunkError) window.removeEventListener("error", onChunkError, true);
|
|
263
311
|
};
|
|
264
312
|
}
|
|
265
|
-
var isMac = typeof navigator !== "undefined" && /Mac|iPhone|iPad/.test(navigator.platform || navigator.userAgent);
|
|
266
|
-
var MOD = isMac ? "\u2318" : "Ctrl";
|
|
267
|
-
var ALT = isMac ? "\u2325" : "Alt";
|
|
268
|
-
var SHIFT = "\u21E7";
|
|
269
|
-
var ENTER = "\u23CE";
|
|
270
|
-
var CMD_ENTER = isMac ? "\u2318\u23CE" : "Ctrl\u23CE";
|
|
271
|
-
var CMD_S = isMac ? "\u2318S" : "Ctrl+S";
|
|
272
|
-
var CMD_K = isMac ? "\u2318K" : "Ctrl+K";
|
|
273
|
-
var CMD_DOT = isMac ? "\u2318." : "Ctrl+.";
|
|
274
|
-
var CMD_A = isMac ? "\u2318A" : "Ctrl+A";
|
|
275
|
-
var CMD_Z = isMac ? "\u2318Z" : "Ctrl+Z";
|
|
276
|
-
var CMD_SHIFT_Z = isMac ? "\u2318\u21E7Z" : "Ctrl+Shift+Z";
|
|
277
|
-
var ALT_SHIFT_D = isMac ? "\u2325\u21E7D" : "Alt+Shift+D";
|
|
278
|
-
var ALT_SHIFT_E = isMac ? "\u2325\u21E7E" : "Alt+Shift+E";
|
|
279
|
-
var ALT_SHIFT_N = isMac ? "\u2325\u21E7N" : "Alt+Shift+N";
|
|
280
|
-
var KBD_BASE = "inline-flex items-center justify-center rounded border border-gray-200 bg-gray-50 font-medium text-gray-500";
|
|
281
|
-
var KBD_SIZES = {
|
|
282
|
-
sm: "px-1 py-0.5 text-[10px]",
|
|
283
|
-
md: "px-1.5 py-0.5 text-[11px]"
|
|
284
|
-
};
|
|
285
|
-
function Kbd({ keys, size = "md", className = "" }) {
|
|
286
|
-
return /* @__PURE__ */ jsx("kbd", { className: [KBD_BASE, KBD_SIZES[size], className].filter(Boolean).join(" "), children: keys });
|
|
287
|
-
}
|
|
288
313
|
|
|
289
|
-
export { ALT, ALT_SHIFT_D, ALT_SHIFT_E, ALT_SHIFT_N, CMD_A, CMD_DOT, CMD_ENTER, CMD_K, CMD_S, CMD_SHIFT_Z, CMD_Z, ENTER, Kbd, LoadingSpinner, MOD, NEXT_CHUNK_PATH_PREFIX, Result, SHIFT, STALE_CHUNK_RELOAD_COOLDOWN_MS, STALE_CHUNK_RELOAD_KEY, ShellPrefsProvider, VITE_PRELOAD_ERROR_EVENT, installStaleChunkReload, isMac, isStaleChunkError, useIsMobile, useLocalStoragePrefs, useShellPrefs, useShellPrefsAdapter };
|
|
290
|
-
//# sourceMappingURL=chunk-
|
|
291
|
-
//# sourceMappingURL=chunk-
|
|
314
|
+
export { ALT, ALT_SHIFT_D, ALT_SHIFT_E, ALT_SHIFT_N, CMD_A, CMD_DOT, CMD_ENTER, CMD_K, CMD_S, CMD_SHIFT_Z, CMD_Z, ENTER, Kbd, LoadingSpinner, MOD, NEXT_CHUNK_PATH_PREFIX, Result, SHIFT, STALE_CHUNK_RELOAD_COOLDOWN_MS, STALE_CHUNK_RELOAD_KEY, ShellPrefsProvider, VITE_PRELOAD_ERROR_EVENT, installStaleChunkReload, isMac, isStaleChunkError, useIsMobile, useLocalStoragePrefs, useShellPrefs, useShellPrefsAdapter, useShortcutLabel };
|
|
315
|
+
//# sourceMappingURL=chunk-TQURTLK2.js.map
|
|
316
|
+
//# sourceMappingURL=chunk-TQURTLK2.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/shell/useIsMobile.ts","../src/shell/Result.tsx","../src/shell/Spinner.tsx","../src/shell/Kbd.tsx","../src/shell/ShellPrefs.tsx","../src/shell/staleChunk.ts"],"names":["jsx","jsxs"],"mappings":"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","file":"chunk-TQURTLK2.js","sourcesContent":["/**\n * Mobile breakpoint hook — single source of truth for \"is this a phone/tablet\n * portrait viewport?\" Drives whether <Layout> renders the desktop chrome\n * (windows / taskbar / start menu sidebar) or the <MobileAppLanding> screen\n * that points the user at the consumer-wired mobile app. A handful of\n * primitives (Modal, ResizableTable) also read it to adapt touch behaviour.\n *\n * Locked at 768 px so iPad portrait counts as mobile. Also OR's with\n * `pointer: coarse` so touch-only devices that happen to be wider (e.g. an\n * Android tablet in landscape) still get touch-appropriate UI.\n */\nimport { useSyncExternalStore } from 'react';\n\nconst QUERY = '(max-width: 767px), (pointer: coarse)';\n\nfunction getSnapshot(): boolean {\n if (typeof window === 'undefined' || !window.matchMedia) return false;\n return window.matchMedia(QUERY).matches;\n}\n\nfunction getServerSnapshot(): boolean {\n return false;\n}\n\nfunction subscribe(cb: () => void): () => void {\n if (typeof window === 'undefined' || !window.matchMedia) return () => {};\n const mql = window.matchMedia(QUERY);\n // Older Safari uses addListener; modern browsers use addEventListener.\n if (mql.addEventListener) {\n mql.addEventListener('change', cb);\n return () => mql.removeEventListener('change', cb);\n }\n mql.addListener(cb);\n return () => mql.removeListener(cb);\n}\n\nexport function useIsMobile(): boolean {\n return useSyncExternalStore(subscribe, getSnapshot, getServerSnapshot);\n}\n","/**\n * Result — the full-page outcome state: a 404, a 403, a crashed boundary, a\n * completed checkout.\n *\n * `EmptyState` is the neighbour to know about. That one means \"this list has\n * nothing in it yet\", which is normal and usually actionable. This one means\n * something ENDED — succeeded, failed, or was refused — and it is the whole\n * page rather than a region of one. `ErrorPage` is this component wrapped in a\n * full-screen frame.\n */\nimport { type ReactNode } from 'react';\nimport { useShellStrings, type ShellStrings } from './strings';\n\nexport type ResultStatus = 'success' | 'error' | 'warning' | 'info' | '404' | '403' | '500';\n\nexport interface ResultProps {\n status?: ResultStatus;\n title?: ReactNode;\n subTitle?: ReactNode;\n /** Actions — usually one primary route out. Always give the user one. */\n extra?: ReactNode;\n /** Replace the status glyph entirely. */\n icon?: ReactNode;\n children?: ReactNode;\n className?: string;\n}\n\ntype Tone = 'success' | 'error' | 'warning' | 'info';\n\nconst STATUS_TONE: Record<ResultStatus, Tone> = {\n success: 'success', error: 'error', warning: 'warning', info: 'info',\n // A missing page is not an error the user made, and colouring it red says it\n // was. Refused and broken are genuinely different from not-found.\n 404: 'info', 403: 'warning', 500: 'error',\n};\n\nconst TONE_CLASS: Record<Tone, string> = {\n success: 'text-green-600 bg-green-100',\n error: 'text-red-600 bg-red-100',\n warning: 'text-amber-600 bg-amber-100',\n info: 'text-blue-600 bg-blue-100',\n};\n\n/** Default copy, so the common cases need only `status` — the catalog's\n * `errors` words, picked at render so a translation reaches them. */\nconst DEFAULT_TITLE: Partial<Record<ResultStatus, (errors: ShellStrings['errors']) => string>> = {\n 404: errors => errors.notFound,\n 403: errors => errors.noAccess,\n 500: errors => errors.serverError,\n};\n\nfunction StatusIcon({ tone }: { tone: Tone }) {\n const common = { className: 'h-6 w-6', fill: 'none', viewBox: '0 0 24 24', stroke: 'currentColor', strokeWidth: 1.5, 'aria-hidden': true } as const;\n switch (tone) {\n case 'success':\n return <svg {...common}><path strokeLinecap=\"round\" strokeLinejoin=\"round\" d=\"M4.5 12.75l6 6 9-13.5\" /></svg>;\n case 'error':\n return <svg {...common}><path strokeLinecap=\"round\" strokeLinejoin=\"round\" d=\"M6 18L18 6M6 6l12 12\" /></svg>;\n case 'warning':\n return <svg {...common}><path strokeLinecap=\"round\" strokeLinejoin=\"round\" d=\"M12 9v3.75m9-.75a9 9 0 11-18 0 9 9 0 0118 0zm-9 3.75h.008v.008H12v-.008z\" /></svg>;\n default:\n return <svg {...common}><path strokeLinecap=\"round\" strokeLinejoin=\"round\" d=\"M11.25 11.25l.041-.02a.75.75 0 011.063.852l-.708 2.836a.75.75 0 001.063.853l.041-.021M21 12a9 9 0 11-18 0 9 9 0 0118 0zm-9-3.75h.008v.008H12V8.25z\" /></svg>;\n }\n}\n\nexport default function Result({\n status = 'info', title, subTitle, extra, icon, children, className = '',\n}: ResultProps) {\n const tone = STATUS_TONE[status];\n const errors = useShellStrings().errors;\n // WCAG 4.1.3. A Result that reports a failure is a status message: it appears\n // without the user moving focus, so a screen-reader user is told nothing\n // unless it announces itself. `alert` is assertive, which is right for a\n // failure and wrong for everything else — an outcome someone asked for\n // (a completed checkout) or a neutral one (an empty cart) would interrupt\n // whatever they were reading to say something they already expected.\n const announces = tone === 'error';\n return (\n <div\n role={announces ? 'alert' : undefined}\n className={`flex flex-col items-center justify-center px-6 py-12 text-center ${className}`.trim()}\n >\n <div className={`flex h-14 w-14 items-center justify-center rounded-full ${TONE_CLASS[tone]}`}>\n {icon ?? <StatusIcon tone={tone} />}\n </div>\n <h2 className=\"mt-4 text-lg font-semibold text-gray-900\">\n {title ?? DEFAULT_TITLE[status]?.(errors) ?? ''}\n </h2>\n {subTitle && <p className=\"mt-1 max-w-md text-sm text-gray-500\">{subTitle}</p>}\n {children && <div className=\"mt-4 w-full max-w-md text-left\">{children}</div>}\n {extra && <div className=\"mt-6 flex flex-wrap items-center justify-center gap-3\">{extra}</div>}\n </div>\n );\n}\n","import { type ReactNode } from 'react';\n\nexport interface LoadingSpinnerProps {\n /** Ring diameter: `sm` = 20px, `md` = 32px (default), `lg` = 48px. */\n size?: 'sm' | 'md' | 'lg';\n /** Wrapper padding utility (default `py-12`). Pass `''` to remove. */\n padding?: string;\n /**\n * Caption under the ring, e.g. \"Signing in…\". Naming what is happening beats\n * a bare ring on a full-screen wait, where there is nothing else on the page\n * to infer it from. Adds `role=\"status\"` so it is announced.\n */\n label?: ReactNode;\n /** Extra classes on the centering wrapper. */\n className?: string;\n}\n\n/**\n * LoadingSpinner — a centered animated ring for pending/loading regions.\n * (Distinct from the shell's internal \"Loading…\" text used inside data grids.)\n */\nexport default function LoadingSpinner({ size = 'md', padding = 'py-12', label, className = '' }: LoadingSpinnerProps) {\n const dim = size === 'sm' ? 'h-5 w-5' : size === 'lg' ? 'h-12 w-12' : 'h-8 w-8';\n const ring = <div className={`${dim} animate-spin rounded-full border-2 border-gray-200 border-t-blue-600`} />;\n // Without a label the markup is exactly what it has always been — including\n // no `role`, which would otherwise have changed the a11y tree for every\n // existing caller. A labelled spinner is a status; a bare ring is decoration.\n if (label == null) {\n return <div className={`flex items-center justify-center ${padding} ${className}`}>{ring}</div>;\n }\n return (\n <div role=\"status\" className={`flex flex-col items-center justify-center gap-3 ${padding} ${className}`}>\n {ring}\n <p className=\"text-sm text-gray-500\">{label}</p>\n </div>\n );\n}\n","/**\n * Keyboard shortcuts: the platform-aware STRINGS a shortcut is written with,\n * and the badge that renders one.\n *\n * Both live here because they are one concept — a shortcut nobody can see is\n * not a shortcut — and because the strings came first: the constants have\n * shipped for years and the badge around them was left to each consumer, which\n * is how the admin portal ended up with 109 hand-written `<kbd>` elements\n * across 80 files in two different sizes.\n */\nimport { useHydrated } from './hydration';\n\n/**\n * Whether the READER is on a Mac. Fixed when the module loads, and `false` on a\n * server whatever the server runs on: Node has had a global `navigator` since\n * 21, and its `platform` is the machine's own — a guard on `navigator` alone\n * let a Mac server write \\u2318 into HTML for every reader it served.\n */\nexport const isMac = typeof window !== 'undefined' && typeof navigator !== 'undefined'\n && /Mac|iPhone|iPad/.test(navigator.platform || navigator.userAgent);\n\n/**\n * Every platform-aware label, as [Mac, everywhere else]. One table, so the\n * badge can tell what a constant was written as on the server from what it is\n * written as here.\n */\nconst FORMS = {\n MOD: ['\\u2318', 'Ctrl'],\n ALT: ['\\u2325', 'Alt'],\n CMD_ENTER: ['\\u2318\\u23CE', 'Ctrl\\u23CE'],\n CMD_S: ['\\u2318S', 'Ctrl+S'],\n CMD_K: ['\\u2318K', 'Ctrl+K'],\n CMD_DOT: ['\\u2318.', 'Ctrl+.'],\n CMD_A: ['\\u2318A', 'Ctrl+A'],\n CMD_Z: ['\\u2318Z', 'Ctrl+Z'],\n CMD_SHIFT_Z: ['\\u2318\\u21e7Z', 'Ctrl+Shift+Z'],\n ALT_SHIFT_D: ['\\u2325\\u21E7D', 'Alt+Shift+D'],\n ALT_SHIFT_E: ['\\u2325\\u21E7E', 'Alt+Shift+E'],\n ALT_SHIFT_N: ['\\u2325\\u21E7N', 'Alt+Shift+N'],\n} as const;\nconst HERE = isMac ? 0 : 1;\n\n/** Platform-aware modifier symbols */\nexport const MOD = FORMS.MOD[HERE];\nexport const ALT = FORMS.ALT[HERE];\nexport const SHIFT = '\\u21E7';\nexport const ENTER = '\\u23CE';\n\n/** Common shortcut labels */\nexport const CMD_ENTER = FORMS.CMD_ENTER[HERE];\nexport const CMD_S = FORMS.CMD_S[HERE];\nexport const CMD_K = FORMS.CMD_K[HERE];\nexport const CMD_DOT = FORMS.CMD_DOT[HERE];\nexport const CMD_A = FORMS.CMD_A[HERE];\nexport const CMD_Z = FORMS.CMD_Z[HERE];\n/** Redo. Mac has no \\u2318Y convention, so it is the shifted undo there. */\nexport const CMD_SHIFT_Z = FORMS.CMD_SHIFT_Z[HERE];\nexport const ALT_SHIFT_D = FORMS.ALT_SHIFT_D[HERE];\nexport const ALT_SHIFT_E = FORMS.ALT_SHIFT_E[HERE];\nexport const ALT_SHIFT_N = FORMS.ALT_SHIFT_N[HERE];\n\n/**\n * What each constant said on the server, keyed by what it says on this Mac.\n * Empty everywhere else, because a server and a non-Mac reader write every\n * constant the same way and there is nothing to translate.\n */\nconst AS_ON_SERVER: ReadonlyMap<string, string> = new Map(\n isMac ? Object.values(FORMS).map(([mac, other]) => [mac, other] as [string, string]) : [],\n);\n\n/**\n * A shortcut label as it can be shown NOW.\n *\n * The constants are fixed when the module loads, so on a server they are the\n * non-Mac forms and in a Mac reader's browser the \\u2318 forms — and a page\n * hydrating `Ctrl+S` into `\\u2318S` is a mismatch. While hydrating, this hands\n * back the form the server wrote; one render later, the reader's own. A root\n * that was never server-rendered gets the reader's form on its first render,\n * as it always did.\n *\n * Only the constants are recognised. A string written out by hand — `'\\u2318K'`\n * rather than `CMD_K` — cannot be told apart from the Mac constant, so on a\n * server-rendered page write shortcuts with the constants.\n */\nexport function useShortcutLabel(keys: string): string {\n const hydrated = useHydrated();\n return hydrated ? keys : (AS_ON_SERVER.get(keys) ?? keys);\n}\n\nexport type KbdSize = 'sm' | 'md';\n\nexport interface KbdProps {\n /**\n * The shortcut, already written \\u2014 one of the constants above, or any string\n * (`'Esc'`, `'\\u2190'`). This component does NOT assemble a shortcut from\n * modifier flags: which symbol a platform uses is what the constants are\n * for, and two answers to that question is one too many.\n */\n keys: string;\n /**\n * `sm` is the quiet badge that rides inside another control's label \\u2014 the\n * `\\u2325\\u21E7E` on an Edit button. `md` (the default) is the one beside a\n * primary action, where it has to be readable at a glance.\n */\n size?: KbdSize;\n /**\n * Layered on, not replacing: a consumer that themes the badge (the admin\n * portal tints the submit one with its accent) adds its own class here and\n * keeps the shape.\n */\n className?: string;\n}\n\nconst KBD_BASE =\n 'inline-flex items-center justify-center rounded border border-gray-200 bg-gray-50 font-medium text-gray-500';\n\n// A Record keyed by the union, so a new rung without an entry is a compile\n// error rather than an undefined class string.\nconst KBD_SIZES: Record<KbdSize, string> = {\n sm: 'px-1 py-0.5 text-[10px]',\n md: 'px-1.5 py-0.5 text-[11px]',\n};\n\n/**\n * The shortcut badge: a real `<kbd>`, which is what tells a screen reader that\n * `\\u2318\\u23CE` is a key combination and not two pieces of punctuation.\n *\n * It renders the shortcut and nothing else \\u2014 no `aria-label` naming it \"Command\n * Enter\", because the badge is almost always INSIDE the control it belongs to\n * (\"Save \\u2318\\u23CE\") and a second name there would be read as part of the\n * button's own.\n */\nexport function Kbd({ keys, size = 'md', className = '' }: KbdProps) {\n const label = useShortcutLabel(keys);\n return <kbd className={[KBD_BASE, KBD_SIZES[size], className].filter(Boolean).join(' ')}>{label}</kbd>;\n}\n","/**\n * Shell-side user-preferences surface — the package never owns where prefs\n * live. The consumer supplies a hook returning the current prefs object plus\n * a save callback; the shell reads keys it knows about (theme,\n * taskbar_position, taskbar_size, world_clocks, favorite_documents,\n * desktop_folders, desktop_snap, notepad_notes, …) and patches them.\n *\n * When no provider is mounted, the shell falls back to localStorage scoped\n * by `storageKey` — so the package works out of the box for a backend-less\n * consumer.\n */\nimport { createContext, useContext, useCallback, useMemo, type ReactNode } from 'react';\nimport { useBrowserState } from './hydration';\n\nexport interface ShellPrefsAdapter {\n /** The current prefs object. The shell reads its known keys directly off\n * this; consumer-private keys are ignored. */\n prefs: Record<string, any>;\n /** Patch a subset of prefs. The shell calls this with shallow diffs. */\n save: (patch: Record<string, any>) => Promise<void> | void;\n}\n\nconst ShellPrefsContext = createContext<ShellPrefsAdapter | null>(null);\n\nexport function ShellPrefsProvider({\n value,\n children,\n}: { value: ShellPrefsAdapter; children: ReactNode }) {\n return <ShellPrefsContext.Provider value={value}>{children}</ShellPrefsContext.Provider>;\n}\n\n/** Default localStorage-backed adapter — useful when the consumer doesn't\n * ship a backend. Pass the result into <ShellPrefsProvider value={…}>.\n *\n * `defaults` are merged behind whatever's already stored, so they only\n * apply for keys the user hasn't set yet. Useful for opting out of bundled\n * features (e.g. `{ restore_windows: false }`). Note this is the only way to\n * turn a default-ON feature off up front; a default-OFF one like\n * `show_desktop_version` is already off until someone ticks its box. */\nexport function useLocalStoragePrefs(\n storageKey = 'react-os-shell:prefs',\n defaults?: Record<string, any>,\n): ShellPrefsAdapter {\n // Stored prefs are the reader's, so a server renders the defaults and\n // hydration agrees with it; the stored ones land the moment hydration ends.\n // A save that arrives before that — a child's mount effect — is merged into\n // what is STORED, never into the defaults (see `useBrowserState`).\n const [prefs, setPrefs] = useBrowserState<Record<string, any>>(() => {\n try {\n const stored = JSON.parse(localStorage.getItem(storageKey) || '{}');\n return { ...(defaults ?? {}), ...stored };\n } catch { return { ...(defaults ?? {}) }; }\n }, { ...(defaults ?? {}) });\n const save = useCallback((patch: Record<string, any>) => {\n setPrefs(prev => {\n const next = { ...prev, ...patch };\n try { localStorage.setItem(storageKey, JSON.stringify(next)); } catch {}\n return next;\n });\n }, [storageKey]);\n return { prefs, save };\n}\n\n/** Stable no-provider adapter: reads as empty, drops saves. One instance, so\n * a component with no provider above it is not handed a new `save` (and a new\n * effect dependency) on every render. */\nconst NO_PROVIDER: ShellPrefsAdapter = { prefs: {}, save: () => {} };\n\n/** The adapter exactly as the consumer supplied it — its `save` MAY reject.\n *\n * A consumer whose adapter reports a failed write is how the shell knows a\n * write did not land, which is what lets `SessionWindowRestore` retry one\n * rather than record a lost write as saved. That component is the only caller\n * that wants this; everything else wants `useShellPrefs`. Exported from the\n * module for it and for the spec, not from the package index. */\nexport function useShellPrefsAdapter(): ShellPrefsAdapter {\n return useContext(ShellPrefsContext) ?? NO_PROVIDER;\n}\n\n/** Returns the active prefs adapter. When no provider is mounted, reads as\n * empty and silently drops saves — components still render, but persistence\n * is a no-op.\n *\n * `save` here NEVER REJECTS. Nearly every caller fires and forgets —\n * `save({ desktop_bg: bg })` inside an onChange, with the result discarded —\n * and an adapter that reports a failed write turns each of those into an\n * unhandled rejection, one per failed PATCH, across the shell and every\n * consumer. So the rejection is swallowed once here rather than at a dozen\n * call sites that would each have to remember. `await save(…)` still works;\n * it just resolves whether or not the write landed.\n *\n * A caller that must know reads `useShellPrefsAdapter` instead. */\nexport function useShellPrefs(): ShellPrefsAdapter {\n const { prefs, save: rawSave } = useShellPrefsAdapter();\n const save = useCallback((patch: Record<string, any>) => {\n const result = rawSave(patch);\n // Stay thenable for `await save(…)`, but settled either way. Duck-typed:\n // an adapter may hand back any thenable, not a native Promise.\n return result && typeof (result as Promise<void>).then === 'function'\n ? (result as Promise<void>).catch(() => {})\n : result;\n }, [rawSave]);\n return useMemo(() => ({ prefs, save }), [prefs, save]);\n}\n","/**\n * Stale-chunk recovery — reload once when a lazy chunk the running page asks\n * for is no longer on the server.\n *\n * A build names every lazy chunk by its content hash, and a deploy replaces\n * the whole set. A tab opened before the deploy still runs the old entry, and\n * the first lazy window it opens asks for a chunk the server no longer has.\n * The SPA fallback answers with `index.html`, which is not the script the\n * page asked for, and the import fails. Nothing inside the page can satisfy\n * that import — only a fresh document, which names the new chunks, can — so\n * an error boundary's \"try again\" remounts into the same failure, and the\n * only recovery that works is a reload.\n *\n * Two bundlers, two ways to hear it:\n *\n * - **Vite** dispatches `vite:preloadError` on `window` (cancelable;\n * `preventDefault()` swallows the throw), and the import rejects with\n * \"Failed to fetch dynamically imported module\".\n * - **Next.js (Turbopack) and webpack** load a chunk by appending a `<script>`\n * or a stylesheet `<link>`, and a failed one rejects the import with an\n * Error named `ChunkLoadError`. There is no bundler event, but one capture\n * listener on `window`, matching the build's chunk path (`/_next/static/`\n * by default), hears every chunk — the app's lazy pages, the shell's lazy\n * apps, CSS — in one of two ways:\n * - the element's own `error`: a 404, or `index.html` refused under\n * `X-Content-Type-Options: nosniff`. A resource error does not bubble,\n * but it does pass `window` in the capture phase.\n * - without `nosniff` the browser RUNS `index.html` as the script, and a\n * `SyntaxError` whose `filename` is the chunk reaches `window`. Nothing\n * else ever would: Turbopack's loader waits for the chunk to register\n * itself, so the import neither resolves nor rejects.\n *\n * Neither proves a deploy. A dropped connection fails the element too, and\n * Turbopack retries a failed chunk once before it gives up. So before\n * reloading, a `HEAD` request (`no-store`) asks the server whether the file\n * is gone: a 404 or 410, or HTML where a chunk should be (the SPA\n * fallback). A chunk that is still there, a 5xx, or no answer at all\n * (offline) is left to the loader's retry and the crash fallback — a reload\n * would throw the page away for nothing, or land on the browser's offline\n * page.\n *\n * `installStaleChunkReload` listens for both and reloads the page — once per\n * cooldown, remembered in `sessionStorage` under one key whichever signal\n * fired, so a chunk that is STILL missing after the reload (a broken deploy)\n * surfaces as the crash it is rather than as a reload loop that eats the\n * user's open windows.\n *\n * Kit-safe: imports nothing. Call it once, before the app mounts.\n */\n\n/** sessionStorage key holding the epoch-ms of the last reload this made. */\nexport const STALE_CHUNK_RELOAD_KEY = 'react-os-shell:stale-chunk-reload-at';\n\n/**\n * How soon after a reload a second missing chunk is allowed to crash instead\n * of reloading again. A reload plus the shell restoring its windows takes a\n * few seconds; anything under this is the same failure, not a new deploy.\n */\nexport const STALE_CHUNK_RELOAD_COOLDOWN_MS = 30_000;\n\n/** The event name Vite's preload helper dispatches. */\nexport const VITE_PRELOAD_ERROR_EVENT = 'vite:preloadError';\n\n/** Where Next.js serves a build's hashed chunks, under Turbopack or webpack. */\nexport const NEXT_CHUNK_PATH_PREFIX = '/_next/static/';\n\nexport interface StaleChunkReloadOptions {\n /** Defaults to {@link STALE_CHUNK_RELOAD_COOLDOWN_MS}. */\n cooldownMs?: number;\n /** Replaced in tests; the default is `window.location.reload()`. */\n reload?: () => void;\n /**\n * Where the last-reload timestamp is kept. Defaults to `sessionStorage`\n * (guarded — a browser that throws on access, such as a private window\n * with storage disabled, degrades to \"always reload\"). `null` disables the\n * cooldown outright.\n */\n storage?: Pick<Storage, 'getItem' | 'setItem'> | null;\n /** Clock, for tests. */\n now?: () => number;\n /**\n * Where the build serves its chunks: a `<script>` or stylesheet `<link>`\n * under it that fails to load — and that the server confirms is gone —\n * reloads the page. A path, resolved from this page's origin, or a full URL\n * for chunks on another host (Next's `assetPrefix` on a CDN, which must then\n * allow the cross-origin `HEAD` that confirms it). End it with `/`: it is a\n * plain prefix match. Defaults to {@link NEXT_CHUNK_PATH_PREFIX}; a\n * `basePath` app passes `'/<basePath>/_next/static/'`, a webpack app its\n * `output.publicPath`. `null` listens for Vite's event only.\n *\n * Never point it at Vite's `/assets/`: Vite's own event already covers\n * those chunks, and hearing the same failure twice would spend the\n * cooldown on the first and let Vite throw on the second.\n */\n chunkPathPrefix?: string | null;\n}\n\n/**\n * The messages the three engines produce for a dynamic `import()` whose\n * module the server did not return, plus Vite's own line for a CSS chunk it\n * could not preload. Used by the shell's crash fallback to offer \"Reload\n * page\" instead of a remount that cannot succeed.\n */\nconst STALE_CHUNK_MESSAGE =\n /Failed to fetch dynamically imported module|error loading dynamically imported module|Importing a module script failed|Unable to preload CSS/i;\n\n/**\n * The name Turbopack and webpack give the Error a failed chunk rejects with\n * (\"Failed to load chunk /_next/static/chunks/… from module …\", \"Loading\n * chunk 42 failed.\").\n */\nconst CHUNK_LOAD_ERROR_NAME = 'ChunkLoadError';\n\n/** True when `error` is a lazy chunk the server no longer serves. */\nexport function isStaleChunkError(error: unknown): boolean {\n if (error instanceof Error && error.name === CHUNK_LOAD_ERROR_NAME) return true;\n const message =\n error instanceof Error ? error.message : typeof error === 'string' ? error : '';\n return STALE_CHUNK_MESSAGE.test(message);\n}\n\n/**\n * Whether a failed `<link>` was loading code or styles the page needs now: a\n * stylesheet, a module preload, or a preload of a script or a style. A\n * prefetch is speculative — for a page the user may never open — and a font,\n * an image or an icon is not a chunk; reloading for any of those would throw\n * away what the user is doing for nothing. `rel` is matched without regard\n * to case, as the browser matches it.\n */\nfunction linkLoadsChunk(link: HTMLLinkElement): boolean {\n const rels = link.rel.toLowerCase().split(/\\s+/);\n if (rels.includes('stylesheet') || rels.includes('modulepreload')) return true;\n const as = (link.getAttribute('as') ?? '').toLowerCase();\n return rels.includes('preload') && (as === 'script' || as === 'style');\n}\n\n/**\n * The address of the chunk an `error` on `window` is about, when it is one of\n * the build's chunks under `prefix`: a failed `<script>` or chunk `<link>`,\n * or a `SyntaxError` thrown by running a chunk that came back as HTML. Null\n * for anything else — an image, a third party, a runtime error in the app.\n * The constructors are read off `window`, so a document without them as bare\n * globals (a test DOM) or an element from another frame cannot throw here.\n */\nfunction failedChunkUrl(event: Event, prefix: string): string | null {\n const target = event.target;\n let src = '';\n if (target instanceof window.HTMLScriptElement) src = target.src;\n else if (target instanceof window.HTMLLinkElement && linkLoadsChunk(target)) src = target.href;\n else if (event instanceof window.ErrorEvent && (event.error as { name?: unknown } | null)?.name === 'SyntaxError') {\n src = event.filename;\n }\n if (!src) return null;\n try {\n // A path prefix lands on this origin, from its root; a full-URL prefix\n // stays where it points. Then one comparison serves both.\n const base = new URL(prefix, window.location.origin).href;\n const url = new URL(src, window.location.href).href;\n return url.startsWith(base) ? url : null;\n } catch {\n return null;\n }\n}\n\n/**\n * Whether the server no longer has `url`: a 404 or 410, or the SPA fallback's\n * HTML where a chunk should be. Anything else — the file is there, a 5xx, no\n * answer at all — means the load failed for a reason a reload would not fix.\n * `no-store`, so a cached copy cannot answer for the server.\n */\nasync function isGoneFromServer(url: string): Promise<boolean> {\n try {\n const response = await fetch(url, { method: 'HEAD', cache: 'no-store' });\n if (response.status === 404 || response.status === 410) return true;\n return response.ok && /\\btext\\/html\\b/i.test(response.headers.get('content-type') ?? '');\n } catch {\n return false;\n }\n}\n\nfunction defaultStorage(): Pick<Storage, 'getItem' | 'setItem'> | null {\n try {\n const s = window.sessionStorage;\n // Touch it: some browsers expose the object and throw on first use.\n s.getItem(STALE_CHUNK_RELOAD_KEY);\n return s;\n } catch {\n return null;\n }\n}\n\nfunction readLastReload(storage: Pick<Storage, 'getItem' | 'setItem'> | null): number | null {\n if (!storage) return null;\n try {\n const raw = storage.getItem(STALE_CHUNK_RELOAD_KEY);\n const at = raw === null ? NaN : Number(raw);\n return Number.isFinite(at) ? at : null;\n } catch {\n return null;\n }\n}\n\nfunction writeLastReload(storage: Pick<Storage, 'getItem' | 'setItem'> | null, at: number): void {\n if (!storage) return;\n try {\n storage.setItem(STALE_CHUNK_RELOAD_KEY, String(at));\n } catch {\n /* storage full or disabled — the reload still happens, just without the cooldown */\n }\n}\n\n/**\n * Reload the page the first time a lazy chunk fails to load, and let the\n * failure through on a repeat within the cooldown.\n *\n * Returns the uninstaller. Server-side (no `window`) it installs nothing.\n */\nexport function installStaleChunkReload(options: StaleChunkReloadOptions = {}): () => void {\n if (typeof window === 'undefined') return () => {};\n\n const cooldownMs = options.cooldownMs ?? STALE_CHUNK_RELOAD_COOLDOWN_MS;\n const reload = options.reload ?? (() => window.location.reload());\n const now = options.now ?? Date.now;\n const storage = options.storage === undefined ? defaultStorage() : options.storage;\n const chunkPathPrefix =\n options.chunkPathPrefix === undefined ? NEXT_CHUNK_PATH_PREFIX : options.chunkPathPrefix;\n\n /**\n * Whether to reload for this missing chunk — false inside the cooldown.\n * Claims the cooldown when it says yes. Both listeners ask here, so they\n * share one record.\n */\n const claimReload = (chunk: unknown): boolean => {\n const at = now();\n const last = readLastReload(storage);\n if (last !== null && at - last < cooldownMs) {\n // Reloaded moments ago and the chunk is still gone: this is not a\n // deploy the page missed, it is a server that cannot serve the build.\n // Let the import fail, so the boundary shows what is wrong.\n console.error(\n '[react-os-shell] a lazy chunk is still missing after a reload; letting the failure through:',\n chunk,\n );\n return false;\n }\n writeLastReload(storage, at);\n console.warn(\n '[react-os-shell] a lazy chunk is no longer on the server (new deploy?); reloading onto the current build:',\n chunk,\n );\n return true;\n };\n\n const onPreloadError = (event: Event) => {\n const payload = (event as Event & { payload?: unknown }).payload;\n // Vite dispatches this for ANY rejected dynamic import it wraps, not only\n // a missing chunk — an optional peer probed by its bare package name\n // rejects the same way, and its caller already catches that.\n // Reloading on that threw the whole portal away on every DXF preview.\n if (!isStaleChunkError(payload) || !claimReload(payload)) return;\n event.preventDefault();\n reload();\n };\n\n // The chunk listener asks the server before it reloads, so its decision is\n // async. One question per chunk at a time (Turbopack's retry fails the same\n // file again while the first is out), none once a reload has started (the\n // page is going), and none acted on after uninstall.\n let active = true;\n let reloading = false;\n const asking = new Set<string>();\n\n // Capture phase: a resource error does not bubble.\n const onChunkError = chunkPathPrefix === null ? null : (event: Event) => {\n const chunk = failedChunkUrl(event, chunkPathPrefix);\n if (!chunk || reloading || asking.has(chunk)) return;\n asking.add(chunk);\n void isGoneFromServer(chunk).then((gone) => {\n asking.delete(chunk);\n if (!gone || !active || reloading || !claimReload(chunk)) return;\n reloading = true;\n reload();\n });\n };\n\n window.addEventListener(VITE_PRELOAD_ERROR_EVENT, onPreloadError);\n if (onChunkError) window.addEventListener('error', onChunkError, true);\n return () => {\n active = false;\n window.removeEventListener(VITE_PRELOAD_ERROR_EVENT, onPreloadError);\n if (onChunkError) window.removeEventListener('error', onChunkError, true);\n };\n}\n"]}
|
|
@@ -17,9 +17,9 @@ function resolveBrandMarkTreatment(hasAlpha, isLight, surface) {
|
|
|
17
17
|
return surface === "dark" ? "plate-light" : "bare";
|
|
18
18
|
}
|
|
19
19
|
var TREATMENT_CLASS = {
|
|
20
|
-
"plate-light": "bg-white shadow-[
|
|
21
|
-
"plate-dark": "bg-neutral-900 shadow-[
|
|
22
|
-
framed: "border border-black/10 shadow-[
|
|
20
|
+
"plate-light": "bg-white shadow-[0_2px_12px_var(--rosh-mark-plate-shadow)]",
|
|
21
|
+
"plate-dark": "bg-neutral-900 shadow-[0_2px_12px_var(--rosh-mark-plate-shadow-strong)]",
|
|
22
|
+
framed: "border border-black/10 shadow-[0_2px_12px_var(--rosh-mark-plate-shadow)]",
|
|
23
23
|
bare: ""
|
|
24
24
|
};
|
|
25
25
|
function treatmentStyle(treatment, radius, padding) {
|
|
@@ -101,5 +101,5 @@ function BrandMark({
|
|
|
101
101
|
}
|
|
102
102
|
|
|
103
103
|
export { BrandMark, resolveBrandMarkTreatment };
|
|
104
|
-
//# sourceMappingURL=chunk-
|
|
105
|
-
//# sourceMappingURL=chunk-
|
|
104
|
+
//# sourceMappingURL=chunk-TRCWINHF.js.map
|
|
105
|
+
//# sourceMappingURL=chunk-TRCWINHF.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/forms/BrandMark.tsx"],"names":[],"mappings":";;;;AAqCA,IAAM,UAAA,GAA4C;AAAA,EAChD,OAAA,EAAS,SAAA;AAAA,EACT,OAAA,EAAS,WAAA;AAAA,EACT,QAAA,EAAU;AACZ,CAAA;AAEA,SAAS,SAAS,GAAA,EAAa;AAC7B,EAAA,OAAO,IAAI,IAAA,EAAK,CAAE,OAAO,CAAC,CAAA,CAAE,mBAAkB,IAAK,MAAA;AACrD;AAQO,SAAS,yBAAA,CACd,QAAA,EACA,OAAA,EACA,OAAA,EACoB;AACpB,EAAA,IAAI,QAAA,KAAa,OAAO,OAAO,QAAA;AAC/B,EAAA,IAAI,QAAA,IAAY,IAAA,IAAQ,OAAA,IAAW,IAAA,EAAM,OAAO,aAAA;AAChD,EAAA,IAAI,OAAA,EAAS,OAAO,OAAA,KAAY,OAAA,GAAU,YAAA,GAAe,MAAA;AACzD,EAAA,OAAO,OAAA,KAAY,SAAS,aAAA,GAAgB,MAAA;AAC9C;
|
|
1
|
+
{"version":3,"sources":["../src/forms/BrandMark.tsx"],"names":[],"mappings":"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","file":"chunk-TRCWINHF.js","sourcesContent":["import { useEffect, useState, type CSSProperties } from 'react';\n\nexport type BrandMarkSlot = 'favicon' | 'compact' | 'wordmark';\nexport type BrandMarkSurface = 'light' | 'dark';\nexport type BrandMarkTreatment = 'plate-light' | 'plate-dark' | 'framed' | 'bare';\n\nexport interface BrandMarkProps {\n src?: string | null;\n fallbackSrc?: string | null;\n fallbackHasAlpha?: boolean | null;\n fallbackIsLight?: boolean | null;\n fallbackAdaptive?: boolean;\n alt: string;\n slot?: BrandMarkSlot;\n surface?: BrandMarkSurface;\n /** Override the square slot size in pixels for compact shell chrome. */\n size?: number;\n /** Override a natural-aspect slot width without forcing square dimensions. */\n width?: number | string;\n /** Override a natural-aspect slot height without forcing square dimensions. */\n height?: number | string;\n /** Mark the image decorative when the adjacent text already names it. */\n decorative?: boolean;\n /** Hide the slot after load failure when surrounding UI owns the fallback. */\n fallbackMode?: 'monogram' | 'none';\n /** Keep an arbitrary tenant mark readable without recolouring the artwork. */\n adaptive?: boolean;\n /** Server-detected transparency hint for the selected asset. */\n hasAlpha?: boolean | null;\n /** Server-detected tone hint for the selected asset. */\n isLight?: boolean | null;\n treatmentPadding?: number | string;\n treatmentRadius?: number;\n className?: string;\n style?: CSSProperties;\n}\n\nconst SLOT_CLASS: Record<BrandMarkSlot, string> = {\n favicon: 'h-8 w-8',\n compact: 'h-10 w-10',\n wordmark: 'h-10 w-40',\n};\n\nfunction monogram(alt: string) {\n return alt.trim().charAt(0).toLocaleUpperCase() || '·';\n}\n\n/**\n * Chooses the smallest backing needed to preserve contrast. Opaque artwork\n * carries its own background; transparent artwork only needs a plate when its\n * tone would disappear into the current surface. Unknown artwork gets the\n * conservative light plate used by every portal.\n */\nexport function resolveBrandMarkTreatment(\n hasAlpha: boolean | null,\n isLight: boolean | null,\n surface: BrandMarkSurface,\n): BrandMarkTreatment {\n if (hasAlpha === false) return 'framed';\n if (hasAlpha == null || isLight == null) return 'plate-light';\n if (isLight) return surface === 'light' ? 'plate-dark' : 'bare';\n return surface === 'dark' ? 'plate-light' : 'bare';\n}\n\n/** The plate's colour and border are classes, so they follow the theme like\n * the rest of the file; only the caller-tunable radius and padding are\n * inline, because those arrive as numbers. The shadow's geometry is in the\n * class and its colour is a token (`--rosh-mark-plate-shadow`, and the\n * `-strong` one under the dark plate), so a host restyling depth reaches it. */\nconst TREATMENT_CLASS: Record<BrandMarkTreatment, string> = {\n 'plate-light': 'bg-white shadow-[0_2px_12px_var(--rosh-mark-plate-shadow)]',\n 'plate-dark': 'bg-neutral-900 shadow-[0_2px_12px_var(--rosh-mark-plate-shadow-strong)]',\n framed: 'border border-black/10 shadow-[0_2px_12px_var(--rosh-mark-plate-shadow)]',\n bare: '',\n};\n\nfunction treatmentStyle(\n treatment: BrandMarkTreatment,\n radius: number,\n padding: number | string,\n): CSSProperties {\n if (treatment === 'bare') return {};\n return treatment === 'framed'\n ? { borderRadius: radius }\n : { borderRadius: radius, padding };\n}\n\n/**\n * Renders a brand asset inside a stable portal slot without ever cropping or\n * stretching the source. Raster normalisation belongs to the server; this\n * component owns only the presentation contract shared by portal surfaces.\n */\nexport default function BrandMark({\n src,\n fallbackSrc,\n fallbackHasAlpha = null,\n fallbackIsLight = null,\n fallbackAdaptive,\n alt,\n slot = 'compact',\n surface = 'light',\n size,\n width,\n height,\n decorative = false,\n fallbackMode = 'monogram',\n adaptive = false,\n hasAlpha = null,\n isLight = null,\n treatmentPadding = 4,\n treatmentRadius = 8,\n className = '',\n style,\n}: BrandMarkProps) {\n const [activeSrc, setActiveSrc] = useState(src || fallbackSrc || '');\n\n useEffect(() => {\n setActiveSrc(src || fallbackSrc || '');\n }, [src, fallbackSrc]);\n\n const usingFallback = Boolean(\n fallbackSrc && activeSrc === fallbackSrc && activeSrc !== src,\n );\n const activeAdaptive = usingFallback ? fallbackAdaptive ?? adaptive : adaptive;\n const activeHasAlpha = usingFallback ? fallbackHasAlpha : hasAlpha;\n const activeIsLight = usingFallback ? fallbackIsLight : isLight;\n const treatment = activeAdaptive\n ? resolveBrandMarkTreatment(activeHasAlpha, activeIsLight, surface)\n : 'bare';\n const frameClass = [\n 'inline-flex shrink-0 items-center justify-center overflow-hidden',\n size == null && width == null && height == null ? SLOT_CLASS[slot] : '',\n surface === 'dark' ? 'text-white' : 'text-gray-700',\n TREATMENT_CLASS[treatment],\n className,\n ].filter(Boolean).join(' ');\n const frameStyle: CSSProperties = {\n ...treatmentStyle(treatment, treatmentRadius, treatmentPadding),\n ...(size == null ? { width, height } : { width: size, height: size }),\n ...style,\n };\n\n if (!activeSrc) {\n if (fallbackMode === 'none') return null;\n return (\n <span\n data-brand-fallback\n data-brand-slot={slot}\n aria-label={decorative ? undefined : alt}\n aria-hidden={decorative || undefined}\n role={decorative ? undefined : 'img'}\n className={`${frameClass} rounded-md bg-gray-100 font-semibold`}\n style={frameStyle}\n >\n {decorative ? null : monogram(alt)}\n </span>\n );\n }\n\n return (\n <span className={frameClass} data-brand-treatment={treatment} style={frameStyle}>\n <img\n src={activeSrc}\n alt={decorative ? '' : alt}\n data-brand-slot={slot}\n className=\"block max-h-full max-w-full\"\n style={{ objectFit: 'contain' }}\n onError={() => setActiveSrc(current => (\n fallbackSrc && current !== fallbackSrc ? fallbackSrc : ''\n ))}\n />\n </span>\n );\n}\n"]}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { toast_default } from './chunk-
|
|
2
|
-
import { useShellPrefs } from './chunk-
|
|
1
|
+
import { toast_default } from './chunk-EENVXIVU.js';
|
|
2
|
+
import { useShellPrefs } from './chunk-TQURTLK2.js';
|
|
3
3
|
import { useSyncExternalStore, useCallback, useMemo } from 'react';
|
|
4
4
|
|
|
5
5
|
// src/shell/pomodoroStore.ts
|
|
@@ -545,5 +545,5 @@ function migratePomodoroTasksOnce(currentTasks, setAllTasks) {
|
|
|
545
545
|
}
|
|
546
546
|
|
|
547
547
|
export { ALARM_OPTIONS, FOCUS_SOUND_OPTIONS, getPomoSnapshot, migratePomodoroTasksOnce, playAlarm, pomoPause, pomoStart, pomoSwitchMode, previewFocusSound, setPomoAlarm, setPomoAlarmConfig, setPomoBehaviour, setPomoDurations, setPomoFocusSound, setShellTodoProvider, subscribePomo, useTodoTasks };
|
|
548
|
-
//# sourceMappingURL=chunk-
|
|
549
|
-
//# sourceMappingURL=chunk-
|
|
548
|
+
//# sourceMappingURL=chunk-VWZIGZFF.js.map
|
|
549
|
+
//# sourceMappingURL=chunk-VWZIGZFF.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/shell/pomodoroStore.ts","../src/apps/_todoStore.ts"],"names":[],"mappings":"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","file":"chunk-NPJCMM6V.js","sourcesContent":["/**\n * Pomodoro store — module-level singleton that owns the timer state and\n * tick loop. Lifting the state above the widget means:\n *\n * 1. The taskbar indicator (`TaskbarPomodoro`) can subscribe even when\n * the widget itself is closed.\n * 2. The timer keeps running if the user closes / reopens the widget;\n * no progress is lost mid-session.\n *\n * The widget acts as a pure controller: it reads the snapshot via\n * `useSyncExternalStore` and calls the action functions below to drive\n * state transitions.\n *\n * The alarm sound on session-end is synthesised through the WebAudio API\n * (no audio file assets to bundle / license). All the presets are tuned\n * to be soft — gentle decay, low peak gain — so they don't startle. The\n * focus-time ambient sound (white / pink / brown noise) is synthesised\n * the same way and looped through an AudioBufferSourceNode.\n */\n\nimport toast from './toast';\n\nexport type Mode = 'focus' | 'short' | 'long';\nexport type AlarmSound = 'bell' | 'chime' | 'bowl' | 'wind-chimes' | 'off';\nexport type FocusSound =\n | 'none'\n | 'white' | 'pink' | 'brown'\n | 'tick-fast' | 'tick-slow'\n | 'rain' | 'fireplace';\n\nexport interface PomoDurations {\n /** Focus block, in seconds. */\n focus: number;\n /** Short break, in seconds. */\n short: number;\n /** Long break, in seconds. Triggered every Nth focus where N is\n * `longBreakInterval` from `setPomoBehaviour`. */\n long: number;\n}\n\nexport interface PomoBehaviour {\n /** When a focus block ends, automatically start the break. */\n autoStartBreaks: boolean;\n /** When a break ends, automatically start the next focus block. */\n autoStartPomodoros: boolean;\n /** Long break is taken after every Nth focus block. Default 4. */\n longBreakInterval: number;\n}\n\nexport interface PomoSnapshot {\n running: boolean;\n /** Seconds remaining in the current block. */\n remaining: number;\n mode: Mode;\n /** Seconds in the full current block — used for progress %. */\n total: number;\n /** Pomodoros completed since the page loaded. */\n streak: number;\n /** Today's lifetime count (persisted to localStorage). */\n count: number;\n}\n\nexport const ALARM_OPTIONS: { id: AlarmSound; label: string; description: string }[] = [\n { id: 'bell', label: 'Bell', description: 'Soft bell with one harmonic' },\n { id: 'chime', label: 'Chime', description: 'Two-note ascending chime' },\n { id: 'bowl', label: 'Singing Bowl', description: 'Long-decay meditation tone' },\n { id: 'wind-chimes', label: 'Wind Chimes', description: 'Four soft tones in succession' },\n { id: 'off', label: 'Off (silent)', description: 'No sound — only desktop notification' },\n];\n\nexport const FOCUS_SOUND_OPTIONS: { id: FocusSound; label: string }[] = [\n { id: 'none', label: 'None' },\n { id: 'tick-fast', label: 'Ticking Fast' },\n { id: 'tick-slow', label: 'Ticking Slow' },\n { id: 'rain', label: 'Rain' },\n { id: 'fireplace', label: 'Fireplace' },\n { id: 'white', label: 'White Noise' },\n { id: 'pink', label: 'Pink Noise' },\n { id: 'brown', label: 'Brown Noise' },\n];\n\nconst todayKey = () => `pomodoro-${new Date().toISOString().slice(0, 10)}`;\nconst loadCount = () => {\n try { return parseInt(localStorage.getItem(todayKey()) || '0', 10) || 0; } catch { return 0; }\n};\nconst saveCount = (n: number) => {\n try { localStorage.setItem(todayKey(), String(n)); } catch {}\n};\n\nlet _durations: PomoDurations = { focus: 25 * 60, short: 5 * 60, long: 15 * 60 };\nlet _alarm: AlarmSound = 'bell';\nlet _alarmVolume = 100; // 0–100\nlet _alarmRepeat = 1; // 1–5\nlet _focusSoundType: FocusSound = 'none';\nlet _focusVolume = 50; // 0–100\nlet _behaviour: PomoBehaviour = { autoStartBreaks: false, autoStartPomodoros: false, longBreakInterval: 4 };\n\nlet _state: PomoSnapshot = {\n running: false,\n remaining: _durations.focus,\n mode: 'focus',\n total: _durations.focus,\n streak: 0,\n count: typeof localStorage !== 'undefined' ? loadCount() : 0,\n};\n\nlet _intervalId: ReturnType<typeof setInterval> | null = null;\nconst _listeners = new Set<() => void>();\n\nconst _notify = () => _listeners.forEach(l => l());\nconst _set = (s: Partial<PomoSnapshot>) => { _state = { ..._state, ...s }; _notify(); };\n\nexport function getPomoSnapshot(): PomoSnapshot { return _state; }\nexport function subscribePomo(l: () => void) { _listeners.add(l); return () => { _listeners.delete(l); }; }\n\nexport function setPomoDurations(d: PomoDurations) {\n _durations = d;\n // If the user changed durations while not running and at the start of the\n // block, sync the visible time to the new value.\n if (!_state.running && _state.remaining === _state.total) {\n _set({ remaining: d[_state.mode], total: d[_state.mode] });\n }\n}\nexport function getPomoDurations(): PomoDurations { return _durations; }\n\nexport function setPomoAlarm(a: AlarmSound) { _alarm = a; }\nexport function getPomoAlarm(): AlarmSound { return _alarm; }\n\n/** Configure the alarm playback volume (0–100) and repeat count (1–5).\n * Used at session-end. The standalone `playAlarm()` preview button can\n * still pass overrides. */\nexport function setPomoAlarmConfig(volume: number, repeat: number) {\n _alarmVolume = Math.max(0, Math.min(100, Math.round(volume)));\n _alarmRepeat = Math.max(1, Math.min(5, Math.round(repeat)));\n}\nexport function getPomoAlarmConfig() { return { volume: _alarmVolume, repeat: _alarmRepeat }; }\n\nexport function setPomoBehaviour(b: PomoBehaviour) {\n _behaviour = {\n autoStartBreaks: !!b.autoStartBreaks,\n autoStartPomodoros: !!b.autoStartPomodoros,\n longBreakInterval: Math.max(1, Math.min(20, Math.round(b.longBreakInterval || 4))),\n };\n}\nexport function getPomoBehaviour(): PomoBehaviour { return _behaviour; }\n\n/** Configure the ambient focus-time sound. If a focus block is currently\n * running the audio is hot-swapped to the new settings. */\nexport function setPomoFocusSound(type: FocusSound, volume: number) {\n _focusSoundType = type;\n _focusVolume = Math.max(0, Math.min(100, Math.round(volume)));\n // Hot-swap if focus mode is currently running.\n if (_state.running && _state.mode === 'focus') {\n stopFocusAudio();\n startFocusAudio();\n } else if (type === 'none' || _focusVolume === 0) {\n stopFocusAudio();\n }\n}\nexport function getPomoFocusSound() { return { type: _focusSoundType, volume: _focusVolume }; }\n\nexport function pomoStart() {\n if (_state.running) return;\n _set({ running: true });\n _intervalId = setInterval(_tick, 1000);\n if (_state.mode === 'focus') startFocusAudio();\n}\nexport function pomoPause() {\n if (!_state.running && _intervalId === null) return;\n if (_intervalId !== null) { clearInterval(_intervalId); _intervalId = null; }\n _set({ running: false });\n stopFocusAudio();\n}\nexport function pomoReset() {\n pomoPause();\n _set({ remaining: _durations[_state.mode], total: _durations[_state.mode] });\n}\nexport function pomoSwitchMode(m: Mode) {\n pomoPause();\n _set({ mode: m, remaining: _durations[m], total: _durations[m] });\n}\n\nfunction _tick() {\n if (_state.remaining <= 1) {\n _onSessionEnd();\n return;\n }\n _set({ remaining: _state.remaining - 1 });\n}\n\nfunction _onSessionEnd() {\n if (_intervalId !== null) { clearInterval(_intervalId); _intervalId = null; }\n stopFocusAudio();\n playAlarm(_alarm, { volume: _alarmVolume, repeat: _alarmRepeat });\n\n // Notify the user three ways so they don't miss it:\n // 1. The alarm sound (already fired above).\n // 2. A native OS notification — fires even when the tab is in the\n // background, but only if the user granted permission.\n // 3. The in-app toast — guaranteed to render whenever the page is\n // open, regardless of OS permission state.\n const justFinishedFocus = _state.mode === 'focus';\n const headline = justFinishedFocus ? 'Pomodoro complete — time for a break! 🍅' : 'Break\\'s over — back to work!';\n if (typeof Notification !== 'undefined' && Notification.permission === 'granted') {\n try { new Notification(headline); } catch {}\n }\n try { toast.info(headline); } catch {}\n\n if (_state.mode === 'focus') {\n const nextStreak = _state.streak + 1;\n const newCount = _state.count + 1;\n saveCount(newCount);\n const nextMode: Mode = nextStreak % _behaviour.longBreakInterval === 0 ? 'long' : 'short';\n _set({\n running: false,\n streak: nextStreak,\n count: newCount,\n mode: nextMode,\n remaining: _durations[nextMode],\n total: _durations[nextMode],\n });\n if (_behaviour.autoStartBreaks) setTimeout(() => pomoStart(), 50);\n } else {\n _set({\n running: false,\n mode: 'focus',\n remaining: _durations.focus,\n total: _durations.focus,\n });\n if (_behaviour.autoStartPomodoros) setTimeout(() => pomoStart(), 50);\n }\n}\n\n/** Synthesise the chosen alarm via WebAudio. All presets are tuned soft —\n * exponential decay to near-silence, peak gain ≤ 0.22. The `volume`\n * option scales the peak (0-100). The `repeat` option plays the cue\n * several times with a 2.5 s gap between starts. */\nexport function playAlarm(kind: AlarmSound = _alarm, opts: { volume?: number; repeat?: number } = {}) {\n if (kind === 'off') return;\n const volScale = Math.max(0, Math.min(100, opts.volume ?? 100)) / 100;\n if (volScale === 0) return;\n const repeat = Math.max(1, Math.min(5, opts.repeat ?? 1));\n for (let i = 0; i < repeat; i++) {\n setTimeout(() => _playAlarmOnce(kind, volScale), i * 2500);\n }\n}\n\nfunction _playAlarmOnce(kind: AlarmSound, volScale: number) {\n try {\n const Ctor: typeof AudioContext = (window as any).AudioContext || (window as any).webkitAudioContext;\n if (!Ctor) return;\n const ctx = new Ctor();\n const playNote = (freq: number, start: number, duration: number, vol = 0.22, type: OscillatorType = 'sine') => {\n const osc = ctx.createOscillator();\n const gain = ctx.createGain();\n osc.connect(gain); gain.connect(ctx.destination);\n osc.type = type;\n osc.frequency.value = freq;\n const t0 = ctx.currentTime + start;\n gain.gain.setValueAtTime(0, t0);\n gain.gain.linearRampToValueAtTime(vol * volScale, t0 + 0.03);\n gain.gain.exponentialRampToValueAtTime(0.0001, t0 + duration);\n osc.start(t0);\n osc.stop(t0 + duration);\n };\n let totalDuration = 2;\n if (kind === 'bell') {\n playNote(880, 0, 1.8);\n playNote(1320, 0, 1.4, 0.10);\n totalDuration = 2;\n } else if (kind === 'chime') {\n playNote(659.25, 0, 0.7); // E5\n playNote(880, 0.20, 1.3); // A5\n totalDuration = 2;\n } else if (kind === 'bowl') {\n playNote(440, 0, 3.4, 0.22);\n playNote(660, 0, 3.0, 0.08);\n playNote(880, 0.05, 2.8, 0.05);\n totalDuration = 4;\n } else if (kind === 'wind-chimes') {\n playNote(1175, 0, 1.1, 0.16); // D6\n playNote(880, 0.15, 1.3, 0.16); // A5\n playNote(1318, 0.30, 1.5, 0.16); // E6\n playNote(1047, 0.50, 1.7, 0.13); // C6\n totalDuration = 3;\n }\n setTimeout(() => { try { ctx.close(); } catch {} }, totalDuration * 1000 + 500);\n } catch {}\n}\n\n// ── Ambient focus-time sound ──\nlet _focusAudio: { ctx: AudioContext; src: AudioBufferSourceNode; gain: GainNode } | null = null;\n\n/** Per-type volume cap. Sparse signals (ticking, fireplace pops) need a\n * higher gain to perceive at the same loudness as a continuous noise\n * texture. The user-facing slider always shows 0–100; this multiplier\n * is the headroom mapping. */\nconst FOCUS_VOL_CAP: Record<FocusSound, number> = {\n none: 0,\n white: 0.30,\n pink: 0.30,\n brown: 0.30,\n 'tick-fast': 0.60,\n 'tick-slow': 0.60,\n rain: 0.40,\n fireplace: 0.50,\n};\n\nfunction _makeNoiseBuffer(ctx: AudioContext, type: FocusSound): AudioBuffer | null {\n if (type === 'none') return null;\n const sr = ctx.sampleRate;\n // Noise textures use a 2 s loop. Ticking, rain, and fireplace use 4 s\n // so multiple ticks / pops fit in one cycle and the loop seam is masked\n // by the texture itself.\n const dur = (type === 'white' || type === 'pink' || type === 'brown') ? 2 : 4;\n const len = sr * dur;\n const buffer = ctx.createBuffer(1, len, sr);\n const data = buffer.getChannelData(0);\n\n if (type === 'white') {\n for (let i = 0; i < len; i++) data[i] = (Math.random() * 2 - 1) * 0.5;\n\n } else if (type === 'pink') {\n // Paul Kellet's filter — cheap pink-noise approximation.\n let b0 = 0, b1 = 0, b2 = 0, b3 = 0, b4 = 0, b5 = 0, b6 = 0;\n for (let i = 0; i < len; i++) {\n const w = Math.random() * 2 - 1;\n b0 = 0.99886 * b0 + w * 0.0555179;\n b1 = 0.99332 * b1 + w * 0.0750759;\n b2 = 0.96900 * b2 + w * 0.1538520;\n b3 = 0.86650 * b3 + w * 0.3104856;\n b4 = 0.55000 * b4 + w * 0.5329522;\n b5 = -0.7616 * b5 - w * 0.0168980;\n data[i] = (b0 + b1 + b2 + b3 + b4 + b5 + b6 + w * 0.5362) * 0.11 * 0.55;\n b6 = w * 0.115926;\n }\n\n } else if (type === 'brown') {\n // 1/f² — leaky integrator on white noise.\n let last = 0;\n for (let i = 0; i < len; i++) {\n const w = Math.random() * 2 - 1;\n last = (last + 0.02 * w) / 1.02;\n data[i] = last * 3.5 * 0.5;\n }\n\n } else if (type === 'tick-fast' || type === 'tick-slow') {\n // Wall-clock tick: brief noise burst with a sharp exponential decay.\n // Two intervals are even divisors of the 4 s buffer, so the loop is\n // perfectly seamless.\n const intervalSec = type === 'tick-fast' ? 0.5 : 1.0;\n const tickSamples = Math.floor(sr * 0.045);\n for (let t = 0; t < dur; t += intervalSec) {\n const start = Math.floor(t * sr);\n for (let i = 0; i < tickSamples && start + i < len; i++) {\n const env = Math.exp(-i / sr * 180); // ~5 ms attack, ~25 ms decay tail\n const noise = Math.random() * 2 - 1;\n // Mix sharp click (filtered noise) with a faint sine to add body.\n const tone = Math.sin(2 * Math.PI * 1100 * (i / sr));\n data[start + i] += (noise * 0.7 + tone * 0.25) * env * 0.55;\n }\n }\n\n } else if (type === 'rain') {\n // High-pass filtered white noise (the \"patter\") plus a slow tremolo\n // for occasional gusts.\n let prev = 0;\n for (let i = 0; i < len; i++) {\n const w = Math.random() * 2 - 1;\n const filtered = w - prev * 0.93; // high-pass\n prev = w;\n const gust = 0.7 + 0.3 * Math.sin((i / sr) * 2 * Math.PI * 0.25);\n data[i] = filtered * gust * 0.4;\n }\n\n } else if (type === 'fireplace') {\n // Brown-noise rumble underneath, plus randomly-spaced \"pops\" (short\n // noise transients with sharp decay) for the crackle.\n let last = 0;\n for (let i = 0; i < len; i++) {\n const w = Math.random() * 2 - 1;\n last = (last + 0.02 * w) / 1.02;\n data[i] = last * 1.6;\n }\n let next = Math.random() * 0.4 * sr;\n while (next < len) {\n const popLen = Math.floor((0.012 + Math.random() * 0.05) * sr);\n const popVol = 0.35 + Math.random() * 0.45;\n const popPos = Math.floor(next);\n for (let i = 0; i < popLen && popPos + i < len; i++) {\n const env = Math.exp(-i / sr * 90);\n data[popPos + i] += (Math.random() * 2 - 1) * env * popVol;\n }\n // Next pop somewhere between 80 ms and 700 ms later.\n next += (0.08 + Math.random() * 0.62) * sr;\n }\n }\n\n return buffer;\n}\n\nfunction startFocusAudio() {\n if (_focusAudio) return;\n if (_focusSoundType === 'none' || _focusVolume === 0) return;\n try {\n const Ctor: typeof AudioContext = (window as any).AudioContext || (window as any).webkitAudioContext;\n if (!Ctor) return;\n const ctx = new Ctor();\n const buffer = _makeNoiseBuffer(ctx, _focusSoundType);\n if (!buffer) { try { ctx.close(); } catch {} return; }\n const src = ctx.createBufferSource();\n src.buffer = buffer;\n src.loop = true;\n const gain = ctx.createGain();\n gain.gain.value = (_focusVolume / 100) * FOCUS_VOL_CAP[_focusSoundType];\n src.connect(gain).connect(ctx.destination);\n src.start();\n _focusAudio = { ctx, src, gain };\n } catch {}\n}\n\nfunction stopFocusAudio() {\n if (!_focusAudio) return;\n try { _focusAudio.src.stop(); } catch {}\n try { _focusAudio.ctx.close(); } catch {}\n _focusAudio = null;\n}\n\n/** Play the configured ambient focus sound for ~3 s as a preview. Used by\n * the Settings UI when the user adjusts the dropdown / volume slider. */\nexport function previewFocusSound(type: FocusSound, volume: number) {\n if (type === 'none' || volume === 0) return;\n try {\n const Ctor: typeof AudioContext = (window as any).AudioContext || (window as any).webkitAudioContext;\n if (!Ctor) return;\n const ctx = new Ctor();\n const buffer = _makeNoiseBuffer(ctx, type);\n if (!buffer) { try { ctx.close(); } catch {} return; }\n const src = ctx.createBufferSource();\n src.buffer = buffer;\n src.loop = true;\n const gain = ctx.createGain();\n gain.gain.value = (volume / 100) * FOCUS_VOL_CAP[type];\n src.connect(gain).connect(ctx.destination);\n src.start();\n setTimeout(() => {\n try { src.stop(); } catch {}\n try { ctx.close(); } catch {}\n }, 3000);\n } catch {}\n}\n","/**\n * Shared task store for the Todo List app and the Pomodoro widget — both\n * read/write the same list via `useTodoTasks()`.\n *\n * Two backends:\n * • Default: `useShellPrefs()` → `prefs.todo_tasks` (per-user prefs blob).\n * • Opt-in: a consumer-supplied `TodoProvider` registered with\n * `setShellTodoProvider(...)`. When set, the three apps read/write through\n * it instead — letting an ERP make the shell's tasks the SAME records as\n * its own task table, and tag each with a `contextLabel` badge (e.g.\n * \"Deal: Acme\"). Mirrors `setShellApiClient`.\n *\n * `migratePomodoroTasksOnce()` folds legacy `localStorage.pomodoro_tasks`\n * into the prefs store on first Pomodoro mount (no-op in provider mode).\n */\nimport { useCallback, useMemo, useSyncExternalStore } from 'react';\nimport { useShellPrefs } from '../shell/ShellPrefs';\nimport type { TodoTask } from './_todoTypes';\n\nconst POMODORO_LEGACY_KEY = 'pomodoro_tasks';\nconst POMODORO_LEGACY_MIGRATED_FLAG = 'pomodoro_tasks_migrated';\n\nfunction uid(): string {\n return Math.random().toString(36).slice(2, 11);\n}\n\nfunction nowIso(): string {\n return new Date().toISOString();\n}\n\nexport interface UseTodoTasks {\n tasks: TodoTask[];\n /** Add a new task. Returns the id of the freshly-added task. */\n addTask: (input: Partial<Omit<TodoTask, 'id' | 'createdAt' | 'updatedAt'>> & { name: string }) => string;\n /** Patch any subset of fields on a task by id. `updatedAt` is auto-bumped. */\n updateTask: (id: string, patch: Partial<TodoTask>) => void;\n /** Remove a task by id. Used by both Pomodoro's kebab menu and TodoList's delete action. */\n removeTask: (id: string) => void;\n /** Flip `done`. Same as `updateTask(id, { done: !done })` but faster to type at call sites. */\n toggleDone: (id: string) => void;\n /** Replace the entire list. Used by Google Tasks sync after a pull. */\n setAllTasks: (tasks: TodoTask[]) => void;\n}\n\n/**\n * A consumer-supplied task backend. Registering one (opt-in) routes every\n * shell task surface through it instead of the prefs blob. Methods map to/from\n * the shell's `TodoTask` shape, including the optional `source`/`contextLabel`.\n */\nexport interface TodoProvider {\n list(): Promise<TodoTask[]>;\n create(input: Partial<Omit<TodoTask, 'id' | 'createdAt' | 'updatedAt'>> & { name: string }): Promise<TodoTask>;\n update(id: string, patch: Partial<TodoTask>): Promise<TodoTask>;\n remove(id: string): Promise<void>;\n}\n\n// ── Module-level provider store (shared across all consumers) ──\nlet provider: TodoProvider | null = null;\nlet cache: TodoTask[] = [];\nlet loaded = false;\nlet inflight: Promise<void> | null = null;\nconst listeners = new Set<() => void>();\n\nfunction emit(): void {\n for (const l of listeners) l();\n}\n\nfunction setCache(next: TodoTask[]): void {\n cache = next;\n emit();\n}\n\nfunction refresh(): Promise<void> {\n const p = provider;\n if (!p) {\n cache = [];\n loaded = true;\n emit();\n return Promise.resolve();\n }\n inflight = p\n .list()\n .then(rows => {\n if (provider === p) {\n cache = rows;\n loaded = true;\n emit();\n }\n })\n .catch(() => {\n if (provider === p) {\n loaded = true;\n emit();\n }\n })\n .finally(() => {\n inflight = null;\n });\n return inflight;\n}\n\n/** Register (or clear with `null`) the backend task provider. Opt-in. */\nexport function setShellTodoProvider(next: TodoProvider | null): void {\n provider = next;\n cache = [];\n loaded = false;\n if (next) refresh();\n else emit();\n}\n\nexport function hasShellTodoProvider(): boolean {\n return provider !== null;\n}\n\nfunction subscribe(cb: () => void): () => void {\n listeners.add(cb);\n if (provider && !loaded && !inflight) refresh();\n return () => {\n listeners.delete(cb);\n };\n}\n\nfunction getSnapshot(): TodoTask[] {\n return cache;\n}\n\n// ── Prefs-backed implementation (default / fallback) ──\nfunction usePrefsTodoTasks(): UseTodoTasks {\n const { prefs, save } = useShellPrefs();\n const tasks: TodoTask[] = useMemo(() => {\n const raw = prefs.todo_tasks;\n return Array.isArray(raw) ? (raw as TodoTask[]) : [];\n }, [prefs.todo_tasks]);\n\n const writeTasks = useCallback((next: TodoTask[]) => {\n save({ todo_tasks: next });\n }, [save]);\n\n const addTask = useCallback<UseTodoTasks['addTask']>((input) => {\n const id = uid();\n const ts = nowIso();\n const task: TodoTask = { done: false, ...input, name: input.name.trim(), id, createdAt: ts, updatedAt: ts };\n writeTasks([...tasks, task]);\n return id;\n }, [tasks, writeTasks]);\n\n const updateTask = useCallback<UseTodoTasks['updateTask']>((id, patch) => {\n writeTasks(tasks.map(t => (t.id === id ? { ...t, ...patch, id: t.id, updatedAt: nowIso() } : t)));\n }, [tasks, writeTasks]);\n\n const removeTask = useCallback<UseTodoTasks['removeTask']>((id) => {\n writeTasks(tasks.filter(t => t.id !== id));\n }, [tasks, writeTasks]);\n\n const toggleDone = useCallback<UseTodoTasks['toggleDone']>((id) => {\n const target = tasks.find(t => t.id === id);\n if (target) updateTask(id, { done: !target.done });\n }, [tasks, updateTask]);\n\n return { tasks, addTask, updateTask, removeTask, toggleDone, setAllTasks: writeTasks };\n}\n\n// ── Public hook (provider-aware) ──\nexport function useTodoTasks(): UseTodoTasks {\n // Both hooks always run (rules of hooks); the active impl is chosen below.\n const prefsImpl = usePrefsTodoTasks();\n const providerTasks = useSyncExternalStore(subscribe, getSnapshot, getSnapshot);\n\n const addTask = useCallback<UseTodoTasks['addTask']>((input) => {\n const p = provider;\n if (!p) return prefsImpl.addTask(input);\n const tempId = 'tmp-' + uid();\n const ts = nowIso();\n const optimistic: TodoTask = { done: false, ...input, name: input.name.trim(), id: tempId, createdAt: ts, updatedAt: ts };\n setCache([...cache, optimistic]);\n p.create({ ...input, name: input.name.trim() })\n // Merge so server-owned fields win but client-only fields (estimated/\n // completed/notes the backend may not persist) survive the round-trip.\n .then(saved => setCache(cache.map(t => (t.id === tempId ? { ...optimistic, ...saved } : t))))\n .catch(() => setCache(cache.filter(t => t.id !== tempId)));\n return tempId;\n }, [prefsImpl]);\n\n const updateTask = useCallback<UseTodoTasks['updateTask']>((id, patch) => {\n const p = provider;\n if (!p) return prefsImpl.updateTask(id, patch);\n setCache(cache.map(t => (t.id === id ? { ...t, ...patch, id, updatedAt: nowIso() } : t)));\n p.update(id, patch).catch(() => { refresh(); });\n }, [prefsImpl]);\n\n const removeTask = useCallback<UseTodoTasks['removeTask']>((id) => {\n const p = provider;\n if (!p) return prefsImpl.removeTask(id);\n const prev = cache;\n setCache(cache.filter(t => t.id !== id));\n p.remove(id).catch(() => setCache(prev));\n }, [prefsImpl]);\n\n const toggleDone = useCallback<UseTodoTasks['toggleDone']>((id) => {\n if (!provider) return prefsImpl.toggleDone(id);\n const target = cache.find(t => t.id === id);\n if (target) updateTask(id, { done: !target.done });\n }, [prefsImpl, updateTask]);\n\n const setAllTasks = useCallback<UseTodoTasks['setAllTasks']>((next) => {\n // Provider owns persistence — bulk replace (Google Tasks sync) is a no-op there.\n if (!provider) prefsImpl.setAllTasks(next);\n }, [prefsImpl]);\n\n if (!hasShellTodoProvider()) return prefsImpl;\n return { tasks: providerTasks, addTask, updateTask, removeTask, toggleDone, setAllTasks };\n}\n\n/**\n * One-time migration: pull any tasks the Pomodoro widget previously\n * persisted to `localStorage.pomodoro_tasks` into the shared store.\n * No-op when a provider is registered (the provider owns persistence).\n */\nexport function migratePomodoroTasksOnce(\n currentTasks: TodoTask[],\n setAllTasks: (next: TodoTask[]) => void,\n): void {\n try {\n if (localStorage.getItem(POMODORO_LEGACY_MIGRATED_FLAG)) return;\n const raw = localStorage.getItem(POMODORO_LEGACY_KEY);\n if (!raw) {\n localStorage.setItem(POMODORO_LEGACY_MIGRATED_FLAG, '1');\n return;\n }\n const legacy: Array<{ id?: string; name?: string; estimated?: number; completed?: number; done?: boolean }>\n = JSON.parse(raw);\n if (!Array.isArray(legacy) || legacy.length === 0) {\n localStorage.removeItem(POMODORO_LEGACY_KEY);\n localStorage.setItem(POMODORO_LEGACY_MIGRATED_FLAG, '1');\n return;\n }\n const ts = nowIso();\n const migrated: TodoTask[] = legacy\n .filter(t => typeof t?.name === 'string')\n .map(t => ({\n id: t.id || uid(),\n name: String(t.name),\n done: !!t.done,\n estimated: typeof t.estimated === 'number' ? t.estimated : undefined,\n completed: typeof t.completed === 'number' ? t.completed : undefined,\n createdAt: ts,\n updatedAt: ts,\n }));\n const existingIds = new Set(currentTasks.map(t => t.id));\n const additions = migrated.filter(t => !existingIds.has(t.id));\n setAllTasks([...additions, ...currentTasks]);\n localStorage.removeItem(POMODORO_LEGACY_KEY);\n localStorage.setItem(POMODORO_LEGACY_MIGRATED_FLAG, '1');\n } catch {\n try { localStorage.setItem(POMODORO_LEGACY_MIGRATED_FLAG, '1'); } catch {}\n }\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/shell/pomodoroStore.ts","../src/apps/_todoStore.ts"],"names":[],"mappings":"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","file":"chunk-VWZIGZFF.js","sourcesContent":["/**\n * Pomodoro store — module-level singleton that owns the timer state and\n * tick loop. Lifting the state above the widget means:\n *\n * 1. The taskbar indicator (`TaskbarPomodoro`) can subscribe even when\n * the widget itself is closed.\n * 2. The timer keeps running if the user closes / reopens the widget;\n * no progress is lost mid-session.\n *\n * The widget acts as a pure controller: it reads the snapshot via\n * `useSyncExternalStore` and calls the action functions below to drive\n * state transitions.\n *\n * The alarm sound on session-end is synthesised through the WebAudio API\n * (no audio file assets to bundle / license). All the presets are tuned\n * to be soft — gentle decay, low peak gain — so they don't startle. The\n * focus-time ambient sound (white / pink / brown noise) is synthesised\n * the same way and looped through an AudioBufferSourceNode.\n */\n\nimport toast from './toast';\n\nexport type Mode = 'focus' | 'short' | 'long';\nexport type AlarmSound = 'bell' | 'chime' | 'bowl' | 'wind-chimes' | 'off';\nexport type FocusSound =\n | 'none'\n | 'white' | 'pink' | 'brown'\n | 'tick-fast' | 'tick-slow'\n | 'rain' | 'fireplace';\n\nexport interface PomoDurations {\n /** Focus block, in seconds. */\n focus: number;\n /** Short break, in seconds. */\n short: number;\n /** Long break, in seconds. Triggered every Nth focus where N is\n * `longBreakInterval` from `setPomoBehaviour`. */\n long: number;\n}\n\nexport interface PomoBehaviour {\n /** When a focus block ends, automatically start the break. */\n autoStartBreaks: boolean;\n /** When a break ends, automatically start the next focus block. */\n autoStartPomodoros: boolean;\n /** Long break is taken after every Nth focus block. Default 4. */\n longBreakInterval: number;\n}\n\nexport interface PomoSnapshot {\n running: boolean;\n /** Seconds remaining in the current block. */\n remaining: number;\n mode: Mode;\n /** Seconds in the full current block — used for progress %. */\n total: number;\n /** Pomodoros completed since the page loaded. */\n streak: number;\n /** Today's lifetime count (persisted to localStorage). */\n count: number;\n}\n\nexport const ALARM_OPTIONS: { id: AlarmSound; label: string; description: string }[] = [\n { id: 'bell', label: 'Bell', description: 'Soft bell with one harmonic' },\n { id: 'chime', label: 'Chime', description: 'Two-note ascending chime' },\n { id: 'bowl', label: 'Singing Bowl', description: 'Long-decay meditation tone' },\n { id: 'wind-chimes', label: 'Wind Chimes', description: 'Four soft tones in succession' },\n { id: 'off', label: 'Off (silent)', description: 'No sound — only desktop notification' },\n];\n\nexport const FOCUS_SOUND_OPTIONS: { id: FocusSound; label: string }[] = [\n { id: 'none', label: 'None' },\n { id: 'tick-fast', label: 'Ticking Fast' },\n { id: 'tick-slow', label: 'Ticking Slow' },\n { id: 'rain', label: 'Rain' },\n { id: 'fireplace', label: 'Fireplace' },\n { id: 'white', label: 'White Noise' },\n { id: 'pink', label: 'Pink Noise' },\n { id: 'brown', label: 'Brown Noise' },\n];\n\nconst todayKey = () => `pomodoro-${new Date().toISOString().slice(0, 10)}`;\nconst loadCount = () => {\n try { return parseInt(localStorage.getItem(todayKey()) || '0', 10) || 0; } catch { return 0; }\n};\nconst saveCount = (n: number) => {\n try { localStorage.setItem(todayKey(), String(n)); } catch {}\n};\n\nlet _durations: PomoDurations = { focus: 25 * 60, short: 5 * 60, long: 15 * 60 };\nlet _alarm: AlarmSound = 'bell';\nlet _alarmVolume = 100; // 0–100\nlet _alarmRepeat = 1; // 1–5\nlet _focusSoundType: FocusSound = 'none';\nlet _focusVolume = 50; // 0–100\nlet _behaviour: PomoBehaviour = { autoStartBreaks: false, autoStartPomodoros: false, longBreakInterval: 4 };\n\nlet _state: PomoSnapshot = {\n running: false,\n remaining: _durations.focus,\n mode: 'focus',\n total: _durations.focus,\n streak: 0,\n count: typeof localStorage !== 'undefined' ? loadCount() : 0,\n};\n\nlet _intervalId: ReturnType<typeof setInterval> | null = null;\nconst _listeners = new Set<() => void>();\n\nconst _notify = () => _listeners.forEach(l => l());\nconst _set = (s: Partial<PomoSnapshot>) => { _state = { ..._state, ...s }; _notify(); };\n\nexport function getPomoSnapshot(): PomoSnapshot { return _state; }\nexport function subscribePomo(l: () => void) { _listeners.add(l); return () => { _listeners.delete(l); }; }\n\nexport function setPomoDurations(d: PomoDurations) {\n _durations = d;\n // If the user changed durations while not running and at the start of the\n // block, sync the visible time to the new value.\n if (!_state.running && _state.remaining === _state.total) {\n _set({ remaining: d[_state.mode], total: d[_state.mode] });\n }\n}\nexport function getPomoDurations(): PomoDurations { return _durations; }\n\nexport function setPomoAlarm(a: AlarmSound) { _alarm = a; }\nexport function getPomoAlarm(): AlarmSound { return _alarm; }\n\n/** Configure the alarm playback volume (0–100) and repeat count (1–5).\n * Used at session-end. The standalone `playAlarm()` preview button can\n * still pass overrides. */\nexport function setPomoAlarmConfig(volume: number, repeat: number) {\n _alarmVolume = Math.max(0, Math.min(100, Math.round(volume)));\n _alarmRepeat = Math.max(1, Math.min(5, Math.round(repeat)));\n}\nexport function getPomoAlarmConfig() { return { volume: _alarmVolume, repeat: _alarmRepeat }; }\n\nexport function setPomoBehaviour(b: PomoBehaviour) {\n _behaviour = {\n autoStartBreaks: !!b.autoStartBreaks,\n autoStartPomodoros: !!b.autoStartPomodoros,\n longBreakInterval: Math.max(1, Math.min(20, Math.round(b.longBreakInterval || 4))),\n };\n}\nexport function getPomoBehaviour(): PomoBehaviour { return _behaviour; }\n\n/** Configure the ambient focus-time sound. If a focus block is currently\n * running the audio is hot-swapped to the new settings. */\nexport function setPomoFocusSound(type: FocusSound, volume: number) {\n _focusSoundType = type;\n _focusVolume = Math.max(0, Math.min(100, Math.round(volume)));\n // Hot-swap if focus mode is currently running.\n if (_state.running && _state.mode === 'focus') {\n stopFocusAudio();\n startFocusAudio();\n } else if (type === 'none' || _focusVolume === 0) {\n stopFocusAudio();\n }\n}\nexport function getPomoFocusSound() { return { type: _focusSoundType, volume: _focusVolume }; }\n\nexport function pomoStart() {\n if (_state.running) return;\n _set({ running: true });\n _intervalId = setInterval(_tick, 1000);\n if (_state.mode === 'focus') startFocusAudio();\n}\nexport function pomoPause() {\n if (!_state.running && _intervalId === null) return;\n if (_intervalId !== null) { clearInterval(_intervalId); _intervalId = null; }\n _set({ running: false });\n stopFocusAudio();\n}\nexport function pomoReset() {\n pomoPause();\n _set({ remaining: _durations[_state.mode], total: _durations[_state.mode] });\n}\nexport function pomoSwitchMode(m: Mode) {\n pomoPause();\n _set({ mode: m, remaining: _durations[m], total: _durations[m] });\n}\n\nfunction _tick() {\n if (_state.remaining <= 1) {\n _onSessionEnd();\n return;\n }\n _set({ remaining: _state.remaining - 1 });\n}\n\nfunction _onSessionEnd() {\n if (_intervalId !== null) { clearInterval(_intervalId); _intervalId = null; }\n stopFocusAudio();\n playAlarm(_alarm, { volume: _alarmVolume, repeat: _alarmRepeat });\n\n // Notify the user three ways so they don't miss it:\n // 1. The alarm sound (already fired above).\n // 2. A native OS notification — fires even when the tab is in the\n // background, but only if the user granted permission.\n // 3. The in-app toast — guaranteed to render whenever the page is\n // open, regardless of OS permission state.\n const justFinishedFocus = _state.mode === 'focus';\n const headline = justFinishedFocus ? 'Pomodoro complete — time for a break! 🍅' : 'Break\\'s over — back to work!';\n if (typeof Notification !== 'undefined' && Notification.permission === 'granted') {\n try { new Notification(headline); } catch {}\n }\n try { toast.info(headline); } catch {}\n\n if (_state.mode === 'focus') {\n const nextStreak = _state.streak + 1;\n const newCount = _state.count + 1;\n saveCount(newCount);\n const nextMode: Mode = nextStreak % _behaviour.longBreakInterval === 0 ? 'long' : 'short';\n _set({\n running: false,\n streak: nextStreak,\n count: newCount,\n mode: nextMode,\n remaining: _durations[nextMode],\n total: _durations[nextMode],\n });\n if (_behaviour.autoStartBreaks) setTimeout(() => pomoStart(), 50);\n } else {\n _set({\n running: false,\n mode: 'focus',\n remaining: _durations.focus,\n total: _durations.focus,\n });\n if (_behaviour.autoStartPomodoros) setTimeout(() => pomoStart(), 50);\n }\n}\n\n/** Synthesise the chosen alarm via WebAudio. All presets are tuned soft —\n * exponential decay to near-silence, peak gain ≤ 0.22. The `volume`\n * option scales the peak (0-100). The `repeat` option plays the cue\n * several times with a 2.5 s gap between starts. */\nexport function playAlarm(kind: AlarmSound = _alarm, opts: { volume?: number; repeat?: number } = {}) {\n if (kind === 'off') return;\n const volScale = Math.max(0, Math.min(100, opts.volume ?? 100)) / 100;\n if (volScale === 0) return;\n const repeat = Math.max(1, Math.min(5, opts.repeat ?? 1));\n for (let i = 0; i < repeat; i++) {\n setTimeout(() => _playAlarmOnce(kind, volScale), i * 2500);\n }\n}\n\nfunction _playAlarmOnce(kind: AlarmSound, volScale: number) {\n try {\n const Ctor: typeof AudioContext = (window as any).AudioContext || (window as any).webkitAudioContext;\n if (!Ctor) return;\n const ctx = new Ctor();\n const playNote = (freq: number, start: number, duration: number, vol = 0.22, type: OscillatorType = 'sine') => {\n const osc = ctx.createOscillator();\n const gain = ctx.createGain();\n osc.connect(gain); gain.connect(ctx.destination);\n osc.type = type;\n osc.frequency.value = freq;\n const t0 = ctx.currentTime + start;\n gain.gain.setValueAtTime(0, t0);\n gain.gain.linearRampToValueAtTime(vol * volScale, t0 + 0.03);\n gain.gain.exponentialRampToValueAtTime(0.0001, t0 + duration);\n osc.start(t0);\n osc.stop(t0 + duration);\n };\n let totalDuration = 2;\n if (kind === 'bell') {\n playNote(880, 0, 1.8);\n playNote(1320, 0, 1.4, 0.10);\n totalDuration = 2;\n } else if (kind === 'chime') {\n playNote(659.25, 0, 0.7); // E5\n playNote(880, 0.20, 1.3); // A5\n totalDuration = 2;\n } else if (kind === 'bowl') {\n playNote(440, 0, 3.4, 0.22);\n playNote(660, 0, 3.0, 0.08);\n playNote(880, 0.05, 2.8, 0.05);\n totalDuration = 4;\n } else if (kind === 'wind-chimes') {\n playNote(1175, 0, 1.1, 0.16); // D6\n playNote(880, 0.15, 1.3, 0.16); // A5\n playNote(1318, 0.30, 1.5, 0.16); // E6\n playNote(1047, 0.50, 1.7, 0.13); // C6\n totalDuration = 3;\n }\n setTimeout(() => { try { ctx.close(); } catch {} }, totalDuration * 1000 + 500);\n } catch {}\n}\n\n// ── Ambient focus-time sound ──\nlet _focusAudio: { ctx: AudioContext; src: AudioBufferSourceNode; gain: GainNode } | null = null;\n\n/** Per-type volume cap. Sparse signals (ticking, fireplace pops) need a\n * higher gain to perceive at the same loudness as a continuous noise\n * texture. The user-facing slider always shows 0–100; this multiplier\n * is the headroom mapping. */\nconst FOCUS_VOL_CAP: Record<FocusSound, number> = {\n none: 0,\n white: 0.30,\n pink: 0.30,\n brown: 0.30,\n 'tick-fast': 0.60,\n 'tick-slow': 0.60,\n rain: 0.40,\n fireplace: 0.50,\n};\n\nfunction _makeNoiseBuffer(ctx: AudioContext, type: FocusSound): AudioBuffer | null {\n if (type === 'none') return null;\n const sr = ctx.sampleRate;\n // Noise textures use a 2 s loop. Ticking, rain, and fireplace use 4 s\n // so multiple ticks / pops fit in one cycle and the loop seam is masked\n // by the texture itself.\n const dur = (type === 'white' || type === 'pink' || type === 'brown') ? 2 : 4;\n const len = sr * dur;\n const buffer = ctx.createBuffer(1, len, sr);\n const data = buffer.getChannelData(0);\n\n if (type === 'white') {\n for (let i = 0; i < len; i++) data[i] = (Math.random() * 2 - 1) * 0.5;\n\n } else if (type === 'pink') {\n // Paul Kellet's filter — cheap pink-noise approximation.\n let b0 = 0, b1 = 0, b2 = 0, b3 = 0, b4 = 0, b5 = 0, b6 = 0;\n for (let i = 0; i < len; i++) {\n const w = Math.random() * 2 - 1;\n b0 = 0.99886 * b0 + w * 0.0555179;\n b1 = 0.99332 * b1 + w * 0.0750759;\n b2 = 0.96900 * b2 + w * 0.1538520;\n b3 = 0.86650 * b3 + w * 0.3104856;\n b4 = 0.55000 * b4 + w * 0.5329522;\n b5 = -0.7616 * b5 - w * 0.0168980;\n data[i] = (b0 + b1 + b2 + b3 + b4 + b5 + b6 + w * 0.5362) * 0.11 * 0.55;\n b6 = w * 0.115926;\n }\n\n } else if (type === 'brown') {\n // 1/f² — leaky integrator on white noise.\n let last = 0;\n for (let i = 0; i < len; i++) {\n const w = Math.random() * 2 - 1;\n last = (last + 0.02 * w) / 1.02;\n data[i] = last * 3.5 * 0.5;\n }\n\n } else if (type === 'tick-fast' || type === 'tick-slow') {\n // Wall-clock tick: brief noise burst with a sharp exponential decay.\n // Two intervals are even divisors of the 4 s buffer, so the loop is\n // perfectly seamless.\n const intervalSec = type === 'tick-fast' ? 0.5 : 1.0;\n const tickSamples = Math.floor(sr * 0.045);\n for (let t = 0; t < dur; t += intervalSec) {\n const start = Math.floor(t * sr);\n for (let i = 0; i < tickSamples && start + i < len; i++) {\n const env = Math.exp(-i / sr * 180); // ~5 ms attack, ~25 ms decay tail\n const noise = Math.random() * 2 - 1;\n // Mix sharp click (filtered noise) with a faint sine to add body.\n const tone = Math.sin(2 * Math.PI * 1100 * (i / sr));\n data[start + i] += (noise * 0.7 + tone * 0.25) * env * 0.55;\n }\n }\n\n } else if (type === 'rain') {\n // High-pass filtered white noise (the \"patter\") plus a slow tremolo\n // for occasional gusts.\n let prev = 0;\n for (let i = 0; i < len; i++) {\n const w = Math.random() * 2 - 1;\n const filtered = w - prev * 0.93; // high-pass\n prev = w;\n const gust = 0.7 + 0.3 * Math.sin((i / sr) * 2 * Math.PI * 0.25);\n data[i] = filtered * gust * 0.4;\n }\n\n } else if (type === 'fireplace') {\n // Brown-noise rumble underneath, plus randomly-spaced \"pops\" (short\n // noise transients with sharp decay) for the crackle.\n let last = 0;\n for (let i = 0; i < len; i++) {\n const w = Math.random() * 2 - 1;\n last = (last + 0.02 * w) / 1.02;\n data[i] = last * 1.6;\n }\n let next = Math.random() * 0.4 * sr;\n while (next < len) {\n const popLen = Math.floor((0.012 + Math.random() * 0.05) * sr);\n const popVol = 0.35 + Math.random() * 0.45;\n const popPos = Math.floor(next);\n for (let i = 0; i < popLen && popPos + i < len; i++) {\n const env = Math.exp(-i / sr * 90);\n data[popPos + i] += (Math.random() * 2 - 1) * env * popVol;\n }\n // Next pop somewhere between 80 ms and 700 ms later.\n next += (0.08 + Math.random() * 0.62) * sr;\n }\n }\n\n return buffer;\n}\n\nfunction startFocusAudio() {\n if (_focusAudio) return;\n if (_focusSoundType === 'none' || _focusVolume === 0) return;\n try {\n const Ctor: typeof AudioContext = (window as any).AudioContext || (window as any).webkitAudioContext;\n if (!Ctor) return;\n const ctx = new Ctor();\n const buffer = _makeNoiseBuffer(ctx, _focusSoundType);\n if (!buffer) { try { ctx.close(); } catch {} return; }\n const src = ctx.createBufferSource();\n src.buffer = buffer;\n src.loop = true;\n const gain = ctx.createGain();\n gain.gain.value = (_focusVolume / 100) * FOCUS_VOL_CAP[_focusSoundType];\n src.connect(gain).connect(ctx.destination);\n src.start();\n _focusAudio = { ctx, src, gain };\n } catch {}\n}\n\nfunction stopFocusAudio() {\n if (!_focusAudio) return;\n try { _focusAudio.src.stop(); } catch {}\n try { _focusAudio.ctx.close(); } catch {}\n _focusAudio = null;\n}\n\n/** Play the configured ambient focus sound for ~3 s as a preview. Used by\n * the Settings UI when the user adjusts the dropdown / volume slider. */\nexport function previewFocusSound(type: FocusSound, volume: number) {\n if (type === 'none' || volume === 0) return;\n try {\n const Ctor: typeof AudioContext = (window as any).AudioContext || (window as any).webkitAudioContext;\n if (!Ctor) return;\n const ctx = new Ctor();\n const buffer = _makeNoiseBuffer(ctx, type);\n if (!buffer) { try { ctx.close(); } catch {} return; }\n const src = ctx.createBufferSource();\n src.buffer = buffer;\n src.loop = true;\n const gain = ctx.createGain();\n gain.gain.value = (volume / 100) * FOCUS_VOL_CAP[type];\n src.connect(gain).connect(ctx.destination);\n src.start();\n setTimeout(() => {\n try { src.stop(); } catch {}\n try { ctx.close(); } catch {}\n }, 3000);\n } catch {}\n}\n","/**\n * Shared task store for the Todo List app and the Pomodoro widget — both\n * read/write the same list via `useTodoTasks()`.\n *\n * Two backends:\n * • Default: `useShellPrefs()` → `prefs.todo_tasks` (per-user prefs blob).\n * • Opt-in: a consumer-supplied `TodoProvider` registered with\n * `setShellTodoProvider(...)`. When set, the three apps read/write through\n * it instead — letting an ERP make the shell's tasks the SAME records as\n * its own task table, and tag each with a `contextLabel` badge (e.g.\n * \"Deal: Acme\"). Mirrors `setShellApiClient`.\n *\n * `migratePomodoroTasksOnce()` folds legacy `localStorage.pomodoro_tasks`\n * into the prefs store on first Pomodoro mount (no-op in provider mode).\n */\nimport { useCallback, useMemo, useSyncExternalStore } from 'react';\nimport { useShellPrefs } from '../shell/ShellPrefs';\nimport type { TodoTask } from './_todoTypes';\n\nconst POMODORO_LEGACY_KEY = 'pomodoro_tasks';\nconst POMODORO_LEGACY_MIGRATED_FLAG = 'pomodoro_tasks_migrated';\n\nfunction uid(): string {\n return Math.random().toString(36).slice(2, 11);\n}\n\nfunction nowIso(): string {\n return new Date().toISOString();\n}\n\nexport interface UseTodoTasks {\n tasks: TodoTask[];\n /** Add a new task. Returns the id of the freshly-added task. */\n addTask: (input: Partial<Omit<TodoTask, 'id' | 'createdAt' | 'updatedAt'>> & { name: string }) => string;\n /** Patch any subset of fields on a task by id. `updatedAt` is auto-bumped. */\n updateTask: (id: string, patch: Partial<TodoTask>) => void;\n /** Remove a task by id. Used by both Pomodoro's kebab menu and TodoList's delete action. */\n removeTask: (id: string) => void;\n /** Flip `done`. Same as `updateTask(id, { done: !done })` but faster to type at call sites. */\n toggleDone: (id: string) => void;\n /** Replace the entire list. Used by Google Tasks sync after a pull. */\n setAllTasks: (tasks: TodoTask[]) => void;\n}\n\n/**\n * A consumer-supplied task backend. Registering one (opt-in) routes every\n * shell task surface through it instead of the prefs blob. Methods map to/from\n * the shell's `TodoTask` shape, including the optional `source`/`contextLabel`.\n */\nexport interface TodoProvider {\n list(): Promise<TodoTask[]>;\n create(input: Partial<Omit<TodoTask, 'id' | 'createdAt' | 'updatedAt'>> & { name: string }): Promise<TodoTask>;\n update(id: string, patch: Partial<TodoTask>): Promise<TodoTask>;\n remove(id: string): Promise<void>;\n}\n\n// ── Module-level provider store (shared across all consumers) ──\nlet provider: TodoProvider | null = null;\nlet cache: TodoTask[] = [];\nlet loaded = false;\nlet inflight: Promise<void> | null = null;\nconst listeners = new Set<() => void>();\n\nfunction emit(): void {\n for (const l of listeners) l();\n}\n\nfunction setCache(next: TodoTask[]): void {\n cache = next;\n emit();\n}\n\nfunction refresh(): Promise<void> {\n const p = provider;\n if (!p) {\n cache = [];\n loaded = true;\n emit();\n return Promise.resolve();\n }\n inflight = p\n .list()\n .then(rows => {\n if (provider === p) {\n cache = rows;\n loaded = true;\n emit();\n }\n })\n .catch(() => {\n if (provider === p) {\n loaded = true;\n emit();\n }\n })\n .finally(() => {\n inflight = null;\n });\n return inflight;\n}\n\n/** Register (or clear with `null`) the backend task provider. Opt-in. */\nexport function setShellTodoProvider(next: TodoProvider | null): void {\n provider = next;\n cache = [];\n loaded = false;\n if (next) refresh();\n else emit();\n}\n\nexport function hasShellTodoProvider(): boolean {\n return provider !== null;\n}\n\nfunction subscribe(cb: () => void): () => void {\n listeners.add(cb);\n if (provider && !loaded && !inflight) refresh();\n return () => {\n listeners.delete(cb);\n };\n}\n\nfunction getSnapshot(): TodoTask[] {\n return cache;\n}\n\n// ── Prefs-backed implementation (default / fallback) ──\nfunction usePrefsTodoTasks(): UseTodoTasks {\n const { prefs, save } = useShellPrefs();\n const tasks: TodoTask[] = useMemo(() => {\n const raw = prefs.todo_tasks;\n return Array.isArray(raw) ? (raw as TodoTask[]) : [];\n }, [prefs.todo_tasks]);\n\n const writeTasks = useCallback((next: TodoTask[]) => {\n save({ todo_tasks: next });\n }, [save]);\n\n const addTask = useCallback<UseTodoTasks['addTask']>((input) => {\n const id = uid();\n const ts = nowIso();\n const task: TodoTask = { done: false, ...input, name: input.name.trim(), id, createdAt: ts, updatedAt: ts };\n writeTasks([...tasks, task]);\n return id;\n }, [tasks, writeTasks]);\n\n const updateTask = useCallback<UseTodoTasks['updateTask']>((id, patch) => {\n writeTasks(tasks.map(t => (t.id === id ? { ...t, ...patch, id: t.id, updatedAt: nowIso() } : t)));\n }, [tasks, writeTasks]);\n\n const removeTask = useCallback<UseTodoTasks['removeTask']>((id) => {\n writeTasks(tasks.filter(t => t.id !== id));\n }, [tasks, writeTasks]);\n\n const toggleDone = useCallback<UseTodoTasks['toggleDone']>((id) => {\n const target = tasks.find(t => t.id === id);\n if (target) updateTask(id, { done: !target.done });\n }, [tasks, updateTask]);\n\n return { tasks, addTask, updateTask, removeTask, toggleDone, setAllTasks: writeTasks };\n}\n\n// ── Public hook (provider-aware) ──\nexport function useTodoTasks(): UseTodoTasks {\n // Both hooks always run (rules of hooks); the active impl is chosen below.\n const prefsImpl = usePrefsTodoTasks();\n const providerTasks = useSyncExternalStore(subscribe, getSnapshot, getSnapshot);\n\n const addTask = useCallback<UseTodoTasks['addTask']>((input) => {\n const p = provider;\n if (!p) return prefsImpl.addTask(input);\n const tempId = 'tmp-' + uid();\n const ts = nowIso();\n const optimistic: TodoTask = { done: false, ...input, name: input.name.trim(), id: tempId, createdAt: ts, updatedAt: ts };\n setCache([...cache, optimistic]);\n p.create({ ...input, name: input.name.trim() })\n // Merge so server-owned fields win but client-only fields (estimated/\n // completed/notes the backend may not persist) survive the round-trip.\n .then(saved => setCache(cache.map(t => (t.id === tempId ? { ...optimistic, ...saved } : t))))\n .catch(() => setCache(cache.filter(t => t.id !== tempId)));\n return tempId;\n }, [prefsImpl]);\n\n const updateTask = useCallback<UseTodoTasks['updateTask']>((id, patch) => {\n const p = provider;\n if (!p) return prefsImpl.updateTask(id, patch);\n setCache(cache.map(t => (t.id === id ? { ...t, ...patch, id, updatedAt: nowIso() } : t)));\n p.update(id, patch).catch(() => { refresh(); });\n }, [prefsImpl]);\n\n const removeTask = useCallback<UseTodoTasks['removeTask']>((id) => {\n const p = provider;\n if (!p) return prefsImpl.removeTask(id);\n const prev = cache;\n setCache(cache.filter(t => t.id !== id));\n p.remove(id).catch(() => setCache(prev));\n }, [prefsImpl]);\n\n const toggleDone = useCallback<UseTodoTasks['toggleDone']>((id) => {\n if (!provider) return prefsImpl.toggleDone(id);\n const target = cache.find(t => t.id === id);\n if (target) updateTask(id, { done: !target.done });\n }, [prefsImpl, updateTask]);\n\n const setAllTasks = useCallback<UseTodoTasks['setAllTasks']>((next) => {\n // Provider owns persistence — bulk replace (Google Tasks sync) is a no-op there.\n if (!provider) prefsImpl.setAllTasks(next);\n }, [prefsImpl]);\n\n if (!hasShellTodoProvider()) return prefsImpl;\n return { tasks: providerTasks, addTask, updateTask, removeTask, toggleDone, setAllTasks };\n}\n\n/**\n * One-time migration: pull any tasks the Pomodoro widget previously\n * persisted to `localStorage.pomodoro_tasks` into the shared store.\n * No-op when a provider is registered (the provider owns persistence).\n */\nexport function migratePomodoroTasksOnce(\n currentTasks: TodoTask[],\n setAllTasks: (next: TodoTask[]) => void,\n): void {\n try {\n if (localStorage.getItem(POMODORO_LEGACY_MIGRATED_FLAG)) return;\n const raw = localStorage.getItem(POMODORO_LEGACY_KEY);\n if (!raw) {\n localStorage.setItem(POMODORO_LEGACY_MIGRATED_FLAG, '1');\n return;\n }\n const legacy: Array<{ id?: string; name?: string; estimated?: number; completed?: number; done?: boolean }>\n = JSON.parse(raw);\n if (!Array.isArray(legacy) || legacy.length === 0) {\n localStorage.removeItem(POMODORO_LEGACY_KEY);\n localStorage.setItem(POMODORO_LEGACY_MIGRATED_FLAG, '1');\n return;\n }\n const ts = nowIso();\n const migrated: TodoTask[] = legacy\n .filter(t => typeof t?.name === 'string')\n .map(t => ({\n id: t.id || uid(),\n name: String(t.name),\n done: !!t.done,\n estimated: typeof t.estimated === 'number' ? t.estimated : undefined,\n completed: typeof t.completed === 'number' ? t.completed : undefined,\n createdAt: ts,\n updatedAt: ts,\n }));\n const existingIds = new Set(currentTasks.map(t => t.id));\n const additions = migrated.filter(t => !existingIds.has(t.id));\n setAllTasks([...additions, ...currentTasks]);\n localStorage.removeItem(POMODORO_LEGACY_KEY);\n localStorage.setItem(POMODORO_LEGACY_MIGRATED_FLAG, '1');\n } catch {\n try { localStorage.setItem(POMODORO_LEGACY_MIGRATED_FLAG, '1'); } catch {}\n }\n}\n"]}
|