react-os-shell 0.2.42 → 0.2.44
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/dist/{Browser-5ZCLRIRU.js → Browser-LSJORULM.js} +3 -3
- package/dist/{Browser-5ZCLRIRU.js.map → Browser-LSJORULM.js.map} +1 -1
- package/dist/{Calculator-OHL2AZ52.js → Calculator-ZKEH53OV.js} +4 -4
- package/dist/{Calculator-OHL2AZ52.js.map → Calculator-ZKEH53OV.js.map} +1 -1
- package/dist/{Calendar-6AHL3UJY.js → Calendar-4UQDQ3NT.js} +3 -3
- package/dist/{Calendar-6AHL3UJY.js.map → Calendar-4UQDQ3NT.js.map} +1 -1
- package/dist/{CurrencyConverter-XZVZ7XOF.js → CurrencyConverter-TXBFDFG2.js} +56 -50
- package/dist/CurrencyConverter-TXBFDFG2.js.map +1 -0
- package/dist/{Documents-IPVZ47JX.js → Documents-CQVIIFZV.js} +3 -3
- package/dist/{Documents-IPVZ47JX.js.map → Documents-CQVIIFZV.js.map} +1 -1
- package/dist/{Email-Z7FDKAFD.js → Email-HRBZUWPY.js} +3 -3
- package/dist/{Email-Z7FDKAFD.js.map → Email-HRBZUWPY.js.map} +1 -1
- package/dist/Files-ITIKVHIE.js +8 -0
- package/dist/{Files-KEHRZ2UY.js.map → Files-ITIKVHIE.js.map} +1 -1
- package/dist/{Minesweeper-NGN4O6C4.js → Minesweeper-QGUPDVRS.js} +3 -3
- package/dist/{Minesweeper-NGN4O6C4.js.map → Minesweeper-QGUPDVRS.js.map} +1 -1
- package/dist/{Notepad-W3YYZ3GS.js → Notepad-74CQPZCV.js} +3 -3
- package/dist/{Notepad-W3YYZ3GS.js.map → Notepad-74CQPZCV.js.map} +1 -1
- package/dist/PomodoroTimer-PRP5CZ3S.js +627 -0
- package/dist/PomodoroTimer-PRP5CZ3S.js.map +1 -0
- package/dist/Preview-4MBQI66Q.js +7 -0
- package/dist/{Preview-4354N46U.js.map → Preview-4MBQI66Q.js.map} +1 -1
- package/dist/{Spreadsheet-FCFII6DW.js → Spreadsheet-MKXPPSKV.js} +3 -3
- package/dist/{Spreadsheet-FCFII6DW.js.map → Spreadsheet-MKXPPSKV.js.map} +1 -1
- package/dist/Weather-YXSCSPQT.js +424 -0
- package/dist/Weather-YXSCSPQT.js.map +1 -0
- package/dist/WorldClock-QO5PVJQQ.js +250 -0
- package/dist/WorldClock-QO5PVJQQ.js.map +1 -0
- package/dist/apps/index.d.ts +6 -4
- package/dist/apps/index.js +18 -18
- package/dist/apps/index.js.map +1 -1
- package/dist/chunk-7CCHEEYC.js +94 -0
- package/dist/chunk-7CCHEEYC.js.map +1 -0
- package/dist/{chunk-T2NQXP2J.js → chunk-7M3BBAHQ.js} +10 -4
- package/dist/chunk-7M3BBAHQ.js.map +1 -0
- package/dist/{chunk-IY7JJVHR.js → chunk-DUUANLLE.js} +3 -3
- package/dist/{chunk-IY7JJVHR.js.map → chunk-DUUANLLE.js.map} +1 -1
- package/dist/chunk-MK3HLUO4.js +380 -0
- package/dist/chunk-MK3HLUO4.js.map +1 -0
- package/dist/{chunk-2SRU4BYH.js → chunk-MTLVXT2C.js} +4 -4
- package/dist/{chunk-2SRU4BYH.js.map → chunk-MTLVXT2C.js.map} +1 -1
- package/dist/{chunk-TVOBLSSV.js → chunk-UK2AA3J6.js} +3 -3
- package/dist/{chunk-TVOBLSSV.js.map → chunk-UK2AA3J6.js.map} +1 -1
- package/dist/index.d.ts +16 -1
- package/dist/index.js +4089 -11
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/dist/CurrencyConverter-XZVZ7XOF.js.map +0 -1
- package/dist/Files-KEHRZ2UY.js +0 -8
- package/dist/PomodoroTimer-T2J5NDJR.js +0 -196
- package/dist/PomodoroTimer-T2J5NDJR.js.map +0 -1
- package/dist/Preview-4354N46U.js +0 -7
- package/dist/Weather-XTADR7Z3.js +0 -266
- package/dist/Weather-XTADR7Z3.js.map +0 -1
- package/dist/WorldClock-GCN4NKQT.js +0 -114
- package/dist/WorldClock-GCN4NKQT.js.map +0 -1
- package/dist/chunk-T2NQXP2J.js.map +0 -1
- package/dist/chunk-WAMARCOS.js +0 -4144
- package/dist/chunk-WAMARCOS.js.map +0 -1
|
@@ -0,0 +1,380 @@
|
|
|
1
|
+
import { toast_default } from './chunk-WIJ45SYD.js';
|
|
2
|
+
|
|
3
|
+
// src/shell/pomodoroStore.ts
|
|
4
|
+
var ALARM_OPTIONS = [
|
|
5
|
+
{ id: "bell", label: "Bell", description: "Soft bell with one harmonic" },
|
|
6
|
+
{ id: "chime", label: "Chime", description: "Two-note ascending chime" },
|
|
7
|
+
{ id: "bowl", label: "Singing Bowl", description: "Long-decay meditation tone" },
|
|
8
|
+
{ id: "wind-chimes", label: "Wind Chimes", description: "Four soft tones in succession" },
|
|
9
|
+
{ id: "off", label: "Off (silent)", description: "No sound \u2014 only desktop notification" }
|
|
10
|
+
];
|
|
11
|
+
var FOCUS_SOUND_OPTIONS = [
|
|
12
|
+
{ id: "none", label: "None" },
|
|
13
|
+
{ id: "tick-fast", label: "Ticking Fast" },
|
|
14
|
+
{ id: "tick-slow", label: "Ticking Slow" },
|
|
15
|
+
{ id: "rain", label: "Rain" },
|
|
16
|
+
{ id: "fireplace", label: "Fireplace" },
|
|
17
|
+
{ id: "white", label: "White Noise" },
|
|
18
|
+
{ id: "pink", label: "Pink Noise" },
|
|
19
|
+
{ id: "brown", label: "Brown Noise" }
|
|
20
|
+
];
|
|
21
|
+
var todayKey = () => `pomodoro-${(/* @__PURE__ */ new Date()).toISOString().slice(0, 10)}`;
|
|
22
|
+
var loadCount = () => {
|
|
23
|
+
try {
|
|
24
|
+
return parseInt(localStorage.getItem(todayKey()) || "0", 10) || 0;
|
|
25
|
+
} catch {
|
|
26
|
+
return 0;
|
|
27
|
+
}
|
|
28
|
+
};
|
|
29
|
+
var saveCount = (n) => {
|
|
30
|
+
try {
|
|
31
|
+
localStorage.setItem(todayKey(), String(n));
|
|
32
|
+
} catch {
|
|
33
|
+
}
|
|
34
|
+
};
|
|
35
|
+
var _durations = { focus: 25 * 60, short: 5 * 60, long: 15 * 60 };
|
|
36
|
+
var _alarm = "bell";
|
|
37
|
+
var _alarmVolume = 100;
|
|
38
|
+
var _alarmRepeat = 1;
|
|
39
|
+
var _focusSoundType = "none";
|
|
40
|
+
var _focusVolume = 50;
|
|
41
|
+
var _behaviour = { autoStartBreaks: false, autoStartPomodoros: false, longBreakInterval: 4 };
|
|
42
|
+
var _state = {
|
|
43
|
+
running: false,
|
|
44
|
+
remaining: _durations.focus,
|
|
45
|
+
mode: "focus",
|
|
46
|
+
total: _durations.focus,
|
|
47
|
+
streak: 0,
|
|
48
|
+
count: typeof localStorage !== "undefined" ? loadCount() : 0
|
|
49
|
+
};
|
|
50
|
+
var _intervalId = null;
|
|
51
|
+
var _listeners = /* @__PURE__ */ new Set();
|
|
52
|
+
var _notify = () => _listeners.forEach((l) => l());
|
|
53
|
+
var _set = (s) => {
|
|
54
|
+
_state = { ..._state, ...s };
|
|
55
|
+
_notify();
|
|
56
|
+
};
|
|
57
|
+
function getPomoSnapshot() {
|
|
58
|
+
return _state;
|
|
59
|
+
}
|
|
60
|
+
function subscribePomo(l) {
|
|
61
|
+
_listeners.add(l);
|
|
62
|
+
return () => {
|
|
63
|
+
_listeners.delete(l);
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
function setPomoDurations(d) {
|
|
67
|
+
_durations = d;
|
|
68
|
+
if (!_state.running && _state.remaining === _state.total) {
|
|
69
|
+
_set({ remaining: d[_state.mode], total: d[_state.mode] });
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
function setPomoAlarm(a) {
|
|
73
|
+
_alarm = a;
|
|
74
|
+
}
|
|
75
|
+
function setPomoAlarmConfig(volume, repeat) {
|
|
76
|
+
_alarmVolume = Math.max(0, Math.min(100, Math.round(volume)));
|
|
77
|
+
_alarmRepeat = Math.max(1, Math.min(5, Math.round(repeat)));
|
|
78
|
+
}
|
|
79
|
+
function setPomoBehaviour(b) {
|
|
80
|
+
_behaviour = {
|
|
81
|
+
autoStartBreaks: !!b.autoStartBreaks,
|
|
82
|
+
autoStartPomodoros: !!b.autoStartPomodoros,
|
|
83
|
+
longBreakInterval: Math.max(1, Math.min(20, Math.round(b.longBreakInterval || 4)))
|
|
84
|
+
};
|
|
85
|
+
}
|
|
86
|
+
function setPomoFocusSound(type, volume) {
|
|
87
|
+
_focusSoundType = type;
|
|
88
|
+
_focusVolume = Math.max(0, Math.min(100, Math.round(volume)));
|
|
89
|
+
if (_state.running && _state.mode === "focus") {
|
|
90
|
+
stopFocusAudio();
|
|
91
|
+
startFocusAudio();
|
|
92
|
+
} else if (type === "none" || _focusVolume === 0) {
|
|
93
|
+
stopFocusAudio();
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
function pomoStart() {
|
|
97
|
+
if (_state.running) return;
|
|
98
|
+
_set({ running: true });
|
|
99
|
+
_intervalId = setInterval(_tick, 1e3);
|
|
100
|
+
if (_state.mode === "focus") startFocusAudio();
|
|
101
|
+
}
|
|
102
|
+
function pomoPause() {
|
|
103
|
+
if (!_state.running && _intervalId === null) return;
|
|
104
|
+
if (_intervalId !== null) {
|
|
105
|
+
clearInterval(_intervalId);
|
|
106
|
+
_intervalId = null;
|
|
107
|
+
}
|
|
108
|
+
_set({ running: false });
|
|
109
|
+
stopFocusAudio();
|
|
110
|
+
}
|
|
111
|
+
function pomoSwitchMode(m) {
|
|
112
|
+
pomoPause();
|
|
113
|
+
_set({ mode: m, remaining: _durations[m], total: _durations[m] });
|
|
114
|
+
}
|
|
115
|
+
function _tick() {
|
|
116
|
+
if (_state.remaining <= 1) {
|
|
117
|
+
_onSessionEnd();
|
|
118
|
+
return;
|
|
119
|
+
}
|
|
120
|
+
_set({ remaining: _state.remaining - 1 });
|
|
121
|
+
}
|
|
122
|
+
function _onSessionEnd() {
|
|
123
|
+
if (_intervalId !== null) {
|
|
124
|
+
clearInterval(_intervalId);
|
|
125
|
+
_intervalId = null;
|
|
126
|
+
}
|
|
127
|
+
stopFocusAudio();
|
|
128
|
+
playAlarm(_alarm, { volume: _alarmVolume, repeat: _alarmRepeat });
|
|
129
|
+
const justFinishedFocus = _state.mode === "focus";
|
|
130
|
+
const headline = justFinishedFocus ? "Pomodoro complete \u2014 time for a break! \u{1F345}" : "Break's over \u2014 back to work!";
|
|
131
|
+
if (typeof Notification !== "undefined" && Notification.permission === "granted") {
|
|
132
|
+
try {
|
|
133
|
+
new Notification(headline);
|
|
134
|
+
} catch {
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
try {
|
|
138
|
+
toast_default.info(headline);
|
|
139
|
+
} catch {
|
|
140
|
+
}
|
|
141
|
+
if (_state.mode === "focus") {
|
|
142
|
+
const nextStreak = _state.streak + 1;
|
|
143
|
+
const newCount = _state.count + 1;
|
|
144
|
+
saveCount(newCount);
|
|
145
|
+
const nextMode = nextStreak % _behaviour.longBreakInterval === 0 ? "long" : "short";
|
|
146
|
+
_set({
|
|
147
|
+
running: false,
|
|
148
|
+
streak: nextStreak,
|
|
149
|
+
count: newCount,
|
|
150
|
+
mode: nextMode,
|
|
151
|
+
remaining: _durations[nextMode],
|
|
152
|
+
total: _durations[nextMode]
|
|
153
|
+
});
|
|
154
|
+
if (_behaviour.autoStartBreaks) setTimeout(() => pomoStart(), 50);
|
|
155
|
+
} else {
|
|
156
|
+
_set({
|
|
157
|
+
running: false,
|
|
158
|
+
mode: "focus",
|
|
159
|
+
remaining: _durations.focus,
|
|
160
|
+
total: _durations.focus
|
|
161
|
+
});
|
|
162
|
+
if (_behaviour.autoStartPomodoros) setTimeout(() => pomoStart(), 50);
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
function playAlarm(kind = _alarm, opts = {}) {
|
|
166
|
+
if (kind === "off") return;
|
|
167
|
+
const volScale = Math.max(0, Math.min(100, opts.volume ?? 100)) / 100;
|
|
168
|
+
if (volScale === 0) return;
|
|
169
|
+
const repeat = Math.max(1, Math.min(5, opts.repeat ?? 1));
|
|
170
|
+
for (let i = 0; i < repeat; i++) {
|
|
171
|
+
setTimeout(() => _playAlarmOnce(kind, volScale), i * 2500);
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
function _playAlarmOnce(kind, volScale) {
|
|
175
|
+
try {
|
|
176
|
+
const Ctor = window.AudioContext || window.webkitAudioContext;
|
|
177
|
+
if (!Ctor) return;
|
|
178
|
+
const ctx = new Ctor();
|
|
179
|
+
const playNote = (freq, start, duration, vol = 0.22, type = "sine") => {
|
|
180
|
+
const osc = ctx.createOscillator();
|
|
181
|
+
const gain = ctx.createGain();
|
|
182
|
+
osc.connect(gain);
|
|
183
|
+
gain.connect(ctx.destination);
|
|
184
|
+
osc.type = type;
|
|
185
|
+
osc.frequency.value = freq;
|
|
186
|
+
const t0 = ctx.currentTime + start;
|
|
187
|
+
gain.gain.setValueAtTime(0, t0);
|
|
188
|
+
gain.gain.linearRampToValueAtTime(vol * volScale, t0 + 0.03);
|
|
189
|
+
gain.gain.exponentialRampToValueAtTime(1e-4, t0 + duration);
|
|
190
|
+
osc.start(t0);
|
|
191
|
+
osc.stop(t0 + duration);
|
|
192
|
+
};
|
|
193
|
+
let totalDuration = 2;
|
|
194
|
+
if (kind === "bell") {
|
|
195
|
+
playNote(880, 0, 1.8);
|
|
196
|
+
playNote(1320, 0, 1.4, 0.1);
|
|
197
|
+
totalDuration = 2;
|
|
198
|
+
} else if (kind === "chime") {
|
|
199
|
+
playNote(659.25, 0, 0.7);
|
|
200
|
+
playNote(880, 0.2, 1.3);
|
|
201
|
+
totalDuration = 2;
|
|
202
|
+
} else if (kind === "bowl") {
|
|
203
|
+
playNote(440, 0, 3.4, 0.22);
|
|
204
|
+
playNote(660, 0, 3, 0.08);
|
|
205
|
+
playNote(880, 0.05, 2.8, 0.05);
|
|
206
|
+
totalDuration = 4;
|
|
207
|
+
} else if (kind === "wind-chimes") {
|
|
208
|
+
playNote(1175, 0, 1.1, 0.16);
|
|
209
|
+
playNote(880, 0.15, 1.3, 0.16);
|
|
210
|
+
playNote(1318, 0.3, 1.5, 0.16);
|
|
211
|
+
playNote(1047, 0.5, 1.7, 0.13);
|
|
212
|
+
totalDuration = 3;
|
|
213
|
+
}
|
|
214
|
+
setTimeout(() => {
|
|
215
|
+
try {
|
|
216
|
+
ctx.close();
|
|
217
|
+
} catch {
|
|
218
|
+
}
|
|
219
|
+
}, totalDuration * 1e3 + 500);
|
|
220
|
+
} catch {
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
var _focusAudio = null;
|
|
224
|
+
var FOCUS_VOL_CAP = {
|
|
225
|
+
none: 0,
|
|
226
|
+
white: 0.3,
|
|
227
|
+
pink: 0.3,
|
|
228
|
+
brown: 0.3,
|
|
229
|
+
"tick-fast": 0.6,
|
|
230
|
+
"tick-slow": 0.6,
|
|
231
|
+
rain: 0.4,
|
|
232
|
+
fireplace: 0.5
|
|
233
|
+
};
|
|
234
|
+
function _makeNoiseBuffer(ctx, type) {
|
|
235
|
+
if (type === "none") return null;
|
|
236
|
+
const sr = ctx.sampleRate;
|
|
237
|
+
const dur = type === "white" || type === "pink" || type === "brown" ? 2 : 4;
|
|
238
|
+
const len = sr * dur;
|
|
239
|
+
const buffer = ctx.createBuffer(1, len, sr);
|
|
240
|
+
const data = buffer.getChannelData(0);
|
|
241
|
+
if (type === "white") {
|
|
242
|
+
for (let i = 0; i < len; i++) data[i] = (Math.random() * 2 - 1) * 0.5;
|
|
243
|
+
} else if (type === "pink") {
|
|
244
|
+
let b0 = 0, b1 = 0, b2 = 0, b3 = 0, b4 = 0, b5 = 0, b6 = 0;
|
|
245
|
+
for (let i = 0; i < len; i++) {
|
|
246
|
+
const w = Math.random() * 2 - 1;
|
|
247
|
+
b0 = 0.99886 * b0 + w * 0.0555179;
|
|
248
|
+
b1 = 0.99332 * b1 + w * 0.0750759;
|
|
249
|
+
b2 = 0.969 * b2 + w * 0.153852;
|
|
250
|
+
b3 = 0.8665 * b3 + w * 0.3104856;
|
|
251
|
+
b4 = 0.55 * b4 + w * 0.5329522;
|
|
252
|
+
b5 = -0.7616 * b5 - w * 0.016898;
|
|
253
|
+
data[i] = (b0 + b1 + b2 + b3 + b4 + b5 + b6 + w * 0.5362) * 0.11 * 0.55;
|
|
254
|
+
b6 = w * 0.115926;
|
|
255
|
+
}
|
|
256
|
+
} else if (type === "brown") {
|
|
257
|
+
let last = 0;
|
|
258
|
+
for (let i = 0; i < len; i++) {
|
|
259
|
+
const w = Math.random() * 2 - 1;
|
|
260
|
+
last = (last + 0.02 * w) / 1.02;
|
|
261
|
+
data[i] = last * 3.5 * 0.5;
|
|
262
|
+
}
|
|
263
|
+
} else if (type === "tick-fast" || type === "tick-slow") {
|
|
264
|
+
const intervalSec = type === "tick-fast" ? 0.5 : 1;
|
|
265
|
+
const tickSamples = Math.floor(sr * 0.045);
|
|
266
|
+
for (let t = 0; t < dur; t += intervalSec) {
|
|
267
|
+
const start = Math.floor(t * sr);
|
|
268
|
+
for (let i = 0; i < tickSamples && start + i < len; i++) {
|
|
269
|
+
const env = Math.exp(-i / sr * 180);
|
|
270
|
+
const noise = Math.random() * 2 - 1;
|
|
271
|
+
const tone = Math.sin(2 * Math.PI * 1100 * (i / sr));
|
|
272
|
+
data[start + i] += (noise * 0.7 + tone * 0.25) * env * 0.55;
|
|
273
|
+
}
|
|
274
|
+
}
|
|
275
|
+
} else if (type === "rain") {
|
|
276
|
+
let prev = 0;
|
|
277
|
+
for (let i = 0; i < len; i++) {
|
|
278
|
+
const w = Math.random() * 2 - 1;
|
|
279
|
+
const filtered = w - prev * 0.93;
|
|
280
|
+
prev = w;
|
|
281
|
+
const gust = 0.7 + 0.3 * Math.sin(i / sr * 2 * Math.PI * 0.25);
|
|
282
|
+
data[i] = filtered * gust * 0.4;
|
|
283
|
+
}
|
|
284
|
+
} else if (type === "fireplace") {
|
|
285
|
+
let last = 0;
|
|
286
|
+
for (let i = 0; i < len; i++) {
|
|
287
|
+
const w = Math.random() * 2 - 1;
|
|
288
|
+
last = (last + 0.02 * w) / 1.02;
|
|
289
|
+
data[i] = last * 1.6;
|
|
290
|
+
}
|
|
291
|
+
let next = Math.random() * 0.4 * sr;
|
|
292
|
+
while (next < len) {
|
|
293
|
+
const popLen = Math.floor((0.012 + Math.random() * 0.05) * sr);
|
|
294
|
+
const popVol = 0.35 + Math.random() * 0.45;
|
|
295
|
+
const popPos = Math.floor(next);
|
|
296
|
+
for (let i = 0; i < popLen && popPos + i < len; i++) {
|
|
297
|
+
const env = Math.exp(-i / sr * 90);
|
|
298
|
+
data[popPos + i] += (Math.random() * 2 - 1) * env * popVol;
|
|
299
|
+
}
|
|
300
|
+
next += (0.08 + Math.random() * 0.62) * sr;
|
|
301
|
+
}
|
|
302
|
+
}
|
|
303
|
+
return buffer;
|
|
304
|
+
}
|
|
305
|
+
function startFocusAudio() {
|
|
306
|
+
if (_focusAudio) return;
|
|
307
|
+
if (_focusSoundType === "none" || _focusVolume === 0) return;
|
|
308
|
+
try {
|
|
309
|
+
const Ctor = window.AudioContext || window.webkitAudioContext;
|
|
310
|
+
if (!Ctor) return;
|
|
311
|
+
const ctx = new Ctor();
|
|
312
|
+
const buffer = _makeNoiseBuffer(ctx, _focusSoundType);
|
|
313
|
+
if (!buffer) {
|
|
314
|
+
try {
|
|
315
|
+
ctx.close();
|
|
316
|
+
} catch {
|
|
317
|
+
}
|
|
318
|
+
return;
|
|
319
|
+
}
|
|
320
|
+
const src = ctx.createBufferSource();
|
|
321
|
+
src.buffer = buffer;
|
|
322
|
+
src.loop = true;
|
|
323
|
+
const gain = ctx.createGain();
|
|
324
|
+
gain.gain.value = _focusVolume / 100 * FOCUS_VOL_CAP[_focusSoundType];
|
|
325
|
+
src.connect(gain).connect(ctx.destination);
|
|
326
|
+
src.start();
|
|
327
|
+
_focusAudio = { ctx, src, gain };
|
|
328
|
+
} catch {
|
|
329
|
+
}
|
|
330
|
+
}
|
|
331
|
+
function stopFocusAudio() {
|
|
332
|
+
if (!_focusAudio) return;
|
|
333
|
+
try {
|
|
334
|
+
_focusAudio.src.stop();
|
|
335
|
+
} catch {
|
|
336
|
+
}
|
|
337
|
+
try {
|
|
338
|
+
_focusAudio.ctx.close();
|
|
339
|
+
} catch {
|
|
340
|
+
}
|
|
341
|
+
_focusAudio = null;
|
|
342
|
+
}
|
|
343
|
+
function previewFocusSound(type, volume) {
|
|
344
|
+
if (type === "none" || volume === 0) return;
|
|
345
|
+
try {
|
|
346
|
+
const Ctor = window.AudioContext || window.webkitAudioContext;
|
|
347
|
+
if (!Ctor) return;
|
|
348
|
+
const ctx = new Ctor();
|
|
349
|
+
const buffer = _makeNoiseBuffer(ctx, type);
|
|
350
|
+
if (!buffer) {
|
|
351
|
+
try {
|
|
352
|
+
ctx.close();
|
|
353
|
+
} catch {
|
|
354
|
+
}
|
|
355
|
+
return;
|
|
356
|
+
}
|
|
357
|
+
const src = ctx.createBufferSource();
|
|
358
|
+
src.buffer = buffer;
|
|
359
|
+
src.loop = true;
|
|
360
|
+
const gain = ctx.createGain();
|
|
361
|
+
gain.gain.value = volume / 100 * FOCUS_VOL_CAP[type];
|
|
362
|
+
src.connect(gain).connect(ctx.destination);
|
|
363
|
+
src.start();
|
|
364
|
+
setTimeout(() => {
|
|
365
|
+
try {
|
|
366
|
+
src.stop();
|
|
367
|
+
} catch {
|
|
368
|
+
}
|
|
369
|
+
try {
|
|
370
|
+
ctx.close();
|
|
371
|
+
} catch {
|
|
372
|
+
}
|
|
373
|
+
}, 3e3);
|
|
374
|
+
} catch {
|
|
375
|
+
}
|
|
376
|
+
}
|
|
377
|
+
|
|
378
|
+
export { ALARM_OPTIONS, FOCUS_SOUND_OPTIONS, getPomoSnapshot, playAlarm, pomoPause, pomoStart, pomoSwitchMode, previewFocusSound, setPomoAlarm, setPomoAlarmConfig, setPomoBehaviour, setPomoDurations, setPomoFocusSound, subscribePomo };
|
|
379
|
+
//# sourceMappingURL=chunk-MK3HLUO4.js.map
|
|
380
|
+
//# sourceMappingURL=chunk-MK3HLUO4.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/shell/pomodoroStore.ts"],"names":[],"mappings":"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","file":"chunk-MK3HLUO4.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"]}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { setPdfPreview } from './chunk-
|
|
1
|
+
import { setPdfPreview } from './chunk-DUUANLLE.js';
|
|
2
2
|
import { toast_default } from './chunk-WIJ45SYD.js';
|
|
3
|
-
import { useWindowManager, WindowTitle } from './chunk-
|
|
3
|
+
import { useWindowManager, WindowTitle } from './chunk-7M3BBAHQ.js';
|
|
4
4
|
import { confirm, prompt } from './chunk-PLGHQ7QW.js';
|
|
5
5
|
import { useState, useEffect, useRef, useCallback } from 'react';
|
|
6
6
|
import { jsxs, jsx, Fragment } from 'react/jsx-runtime';
|
|
@@ -609,5 +609,5 @@ function Files() {
|
|
|
609
609
|
}
|
|
610
610
|
|
|
611
611
|
export { Files, openFilesInTrashMode };
|
|
612
|
-
//# sourceMappingURL=chunk-
|
|
613
|
-
//# sourceMappingURL=chunk-
|
|
612
|
+
//# sourceMappingURL=chunk-MTLVXT2C.js.map
|
|
613
|
+
//# sourceMappingURL=chunk-MTLVXT2C.js.map
|