Add pomodoro, microbreaks, breathing guide, screen dimming, presentation mode, goals, multi-monitor, and activity manager

This commit is contained in:
2026-02-07 15:11:44 +02:00
parent ccfa03d8d2
commit adaf82d839
27 changed files with 3714 additions and 448 deletions

View File

@@ -26,6 +26,27 @@ export interface TimerSnapshot {
naturalBreakOccurred: boolean;
smartBreaksEnabled: boolean;
smartBreakThreshold: number;
// F1: Microbreaks
microbreakEnabled: boolean;
microbreakActive: boolean;
microbreakTimeRemaining: number;
microbreakTotalDuration: number;
microbreakCountdown: number;
microbreakFrequency: number;
// F3: Pomodoro
pomodoroEnabled: boolean;
pomodoroCyclePosition: number;
pomodoroTotalInCycle: number;
pomodoroIsLongBreak: boolean;
pomodoroNextIsLong: boolean;
// F5: Screen dimming
screenDimActive: boolean;
screenDimProgress: number;
// F2: Presentation mode
presentationModeActive: boolean;
deferredBreakPending: boolean;
// F10: Gamification
isLongBreak: boolean;
}
const defaultSnapshot: TimerSnapshot = {
@@ -50,6 +71,22 @@ const defaultSnapshot: TimerSnapshot = {
naturalBreakOccurred: false,
smartBreaksEnabled: true,
smartBreakThreshold: 300,
microbreakEnabled: false,
microbreakActive: false,
microbreakTimeRemaining: 0,
microbreakTotalDuration: 0,
microbreakCountdown: 0,
microbreakFrequency: 1200,
pomodoroEnabled: false,
pomodoroCyclePosition: 0,
pomodoroTotalInCycle: 4,
pomodoroIsLongBreak: false,
pomodoroNextIsLong: false,
screenDimActive: false,
screenDimProgress: 0,
presentationModeActive: false,
deferredBreakPending: false,
isLongBreak: false,
};
export const timer = writable<TimerSnapshot>(defaultSnapshot);
@@ -114,8 +151,43 @@ export async function initTimerStore() {
playSound(cfg.sound_preset as any, cfg.sound_volume * 0.5);
}
});
// F1: Microbreak events
await listen("microbreak-started", () => {
const cfg = get(config);
if (cfg.microbreak_sound_enabled && cfg.sound_enabled) {
playSound(cfg.sound_preset as any, cfg.sound_volume * 0.4);
}
});
await listen("microbreak-ended", () => {
const cfg = get(config);
if (cfg.microbreak_sound_enabled && cfg.sound_enabled) {
playBreakEndSound(cfg.sound_preset as any, cfg.sound_volume * 0.3);
}
});
// F10: Milestone and daily goal events
await listen<{ streak: number }>("milestone-reached", (event) => {
milestoneEvent.set(event.payload.streak);
setTimeout(() => milestoneEvent.set(null), 4000);
});
await listen("daily-goal-met", () => {
dailyGoalEvent.set(true);
setTimeout(() => dailyGoalEvent.set(false), 4000);
});
// F2: Break deferred
await listen("break-deferred", () => {
// Dashboard will show deferred status from snapshot
});
}
// F10: Gamification event stores
export const milestoneEvent = writable<number | null>(null);
export const dailyGoalEvent = writable<boolean>(false);
// Helper: format seconds as MM:SS
export function formatTime(secs: number): string {
const m = Math.floor(secs / 60);