import React, { useEffect, useMemo, useState } from 'react'; import { ipcChannels } from '../../shared/ipc/contracts'; import { DEFAULT_SESSION_TIMER_DURATION_MS, formatSessionTimerMs, getSessionTimerRemainingMs, parseSessionTimerDurationInput, } from '../../shared/types/sessionTimer'; import { useEditorI18n } from '../editor/i18n/EditorI18nContext'; import { getDndApi } from '../shared/dndApi'; import { useSessionTimerState } from '../shared/sessionTimer/useSessionTimerState'; import { Button, Input } from '../shared/ui/controls'; import styles from './TimerApp.module.css'; const PRESETS_MS = [60_000, 5 * 60_000, 10 * 60_000] as const; function durationInputFromMs(ms: number): string { return formatSessionTimerMs(ms); } export function TimerApp() { const { t } = useEditorI18n(); const api = getDndApi(); const [state, timerApi] = useSessionTimerState(); const [now, setNow] = useState(() => Date.now()); const [durationDraft, setDurationDraft] = useState(durationInputFromMs(DEFAULT_SESSION_TIMER_DURATION_MS)); useEffect(() => { if (!state || state.running) return; setDurationDraft(durationInputFromMs(state.durationMs)); }, [state]); useEffect(() => { if (!state?.running) return; const id = window.setInterval(() => setNow(Date.now()), 200); return () => window.clearInterval(id); }, [state?.running]); useEffect(() => { const onKey = (e: KeyboardEvent) => { if (e.key === 'Escape') { void api.invoke(ipcChannels.windows.closeTimer, {}); } }; window.addEventListener('keydown', onKey); return () => window.removeEventListener('keydown', onKey); }, [api]); const remainingMs = useMemo(() => { if (!state) return DEFAULT_SESSION_TIMER_DURATION_MS; return getSessionTimerRemainingMs(state, now); }, [now, state]); useEffect(() => { if (!state?.running) return; if (remainingMs > 0) return; void timerApi.dispatch({ kind: 'pause' }); }, [remainingMs, state?.running, timerApi]); if (!state) { return
; } const applyDurationDraft = async () => { const parsed = parseSessionTimerDurationInput(durationDraft); if (parsed == null) { setDurationDraft(durationInputFromMs(state.durationMs)); return; } await timerApi.dispatch({ kind: 'setDuration', durationMs: parsed }); }; return (