diff options
| author | Solstice <solstice@local> | 2026-06-09 00:22:18 -0700 |
|---|---|---|
| committer | Solstice <solstice@local> | 2026-06-09 00:22:18 -0700 |
| commit | 6cb006cc136f1fc5c83537cc30c64d223d1755e4 (patch) | |
| tree | b12dfb4a8345c980dc8747657ce381016cdf3b34 /src/hooks/useTimerEvents.ts | |
| parent | 25e1dcf205cd14feafdd9b4cf6b7a66f253ba6d2 (diff) | |
feat: frontend view, state management, and user interface
Diffstat (limited to 'src/hooks/useTimerEvents.ts')
| -rw-r--r-- | src/hooks/useTimerEvents.ts | 78 |
1 files changed, 78 insertions, 0 deletions
diff --git a/src/hooks/useTimerEvents.ts b/src/hooks/useTimerEvents.ts new file mode 100644 index 0000000..2bc502d --- /dev/null +++ b/src/hooks/useTimerEvents.ts @@ -0,0 +1,78 @@ +import { useEffect } from 'react'; +import { listen } from '@tauri-apps/api/event'; +import { invoke } from '@tauri-apps/api/core'; +import { useTimerStore, TimerTickPayload } from '../store/timerStore'; +import { useTaskStore } from '../store/taskStore'; + +interface PhaseChangedPayload { + phase: TimerTickPayload['phase']; + session_count: number; +} + +interface CompletedPayload { + task_id: string | null; +} + +export function useTimerEvents( + onCompleted: (taskId: string | null) => void, +) { + const setTimerTick = useTimerStore((s) => s.setTimerTick); + const setRunning = useTimerStore((s) => s.setRunning); + const fetchTasks = useTaskStore((s) => s.fetchTasks); + + useEffect(() => { + // Bootstrap initial state from backend + invoke<{ + phase: TimerTickPayload['phase']; + remaining_secs: number; + total_secs: number; + running: boolean; + session_count: number; + current_task_id: string | null; + }>('get_timer_status') + .then((status) => { + setTimerTick({ + phase: status.phase, + remaining_secs: status.remaining_secs, + total_secs: status.total_secs, + session_count: status.session_count, + current_task_id: status.current_task_id, + }); + setRunning(status.running); + }) + .catch((e) => console.error('get_timer_status error:', e)); + + let unlistenTick: (() => void) | null = null; + let unlistenCompleted: (() => void) | null = null; + let unlistenPhaseChanged: (() => void) | null = null; + + listen<TimerTickPayload>('timer-tick', (event) => { + setTimerTick(event.payload); + setRunning(true); + }).then((fn) => { unlistenTick = fn; }); + + listen<CompletedPayload>('timer-completed', (event) => { + setRunning(false); + onCompleted(event.payload.task_id); + // Refresh tasks since remaining_sessions may have changed + fetchTasks(); + }).then((fn) => { unlistenCompleted = fn; }); + + listen<PhaseChangedPayload>('timer-phase-changed', (event) => { + setRunning(false); + setTimerTick({ + phase: event.payload.phase, + remaining_secs: useTimerStore.getState().remainingSecs, + total_secs: useTimerStore.getState().totalSecs, + session_count: event.payload.session_count, + current_task_id: useTimerStore.getState().currentTaskId, + }); + }).then((fn) => { unlistenPhaseChanged = fn; }); + + return () => { + unlistenTick?.(); + unlistenCompleted?.(); + unlistenPhaseChanged?.(); + }; + }, [setTimerTick, setRunning, fetchTasks, onCompleted]); +} |
