import { useCallback, useEffect, useRef, useState } from 'react'; import type { HudStatusLineItem, HudStatusLinePayload } from '@/shared/lib/useHudStatusLine'; import { useReducedMotion } from '@/shared/lib/useReducedMotion'; import { SpaceTimerHudWidget } from '@/widgets/space-timer-hud'; import { GoalCompleteSheet } from './GoalCompleteSheet'; import { GoalFlashOverlay } from './GoalFlashOverlay'; interface SpaceFocusHudWidgetProps { goal: string; timerLabel: string; visible: boolean; onGoalUpdate: (nextGoal: string) => void; statusLine: HudStatusLineItem | null; onStatusAction: () => void; onStatusMessage: (payload: HudStatusLinePayload) => void; } export const SpaceFocusHudWidget = ({ goal, timerLabel, visible, onGoalUpdate, statusLine, onStatusAction, onStatusMessage, }: SpaceFocusHudWidgetProps) => { const reducedMotion = useReducedMotion(); const [flashVisible, setFlashVisible] = useState(false); const [sheetOpen, setSheetOpen] = useState(false); const playbackStateRef = useRef<'running' | 'paused'>('running'); const flashTimerRef = useRef(null); const restReminderTimerRef = useRef(null); const triggerFlash = useCallback((durationMs: number) => { if (reducedMotion || !visible) { return; } setFlashVisible(true); if (flashTimerRef.current) { window.clearTimeout(flashTimerRef.current); } flashTimerRef.current = window.setTimeout(() => { setFlashVisible(false); flashTimerRef.current = null; }, durationMs); }, [reducedMotion, visible]); useEffect(() => { return () => { if (flashTimerRef.current) { window.clearTimeout(flashTimerRef.current); flashTimerRef.current = null; } if (restReminderTimerRef.current) { window.clearTimeout(restReminderTimerRef.current); restReminderTimerRef.current = null; } }; }, []); useEffect(() => { if (!visible || reducedMotion) { setFlashVisible(false); return; } triggerFlash(2000); }, [visible, reducedMotion, triggerFlash]); useEffect(() => { const ENABLE_PERIODIC_FLASH = false; if (!visible || reducedMotion || !ENABLE_PERIODIC_FLASH) { return; } const intervalId = window.setInterval(() => { triggerFlash(800); }, 10 * 60 * 1000); return () => { window.clearInterval(intervalId); }; }, [visible, reducedMotion, triggerFlash]); if (!visible) { return null; } const handleOpenCompleteSheet = () => { setSheetOpen(true); }; return ( <> { if (reducedMotion) { playbackStateRef.current = state; return; } if (playbackStateRef.current === 'paused' && state === 'running') { triggerFlash(1000); } playbackStateRef.current = state; }} /> setSheetOpen(false)} onRest={() => { setSheetOpen(false); if (restReminderTimerRef.current) { window.clearTimeout(restReminderTimerRef.current); } restReminderTimerRef.current = window.setTimeout(() => { onStatusMessage({ message: '5분이 지났어요. 다음 한 조각으로 돌아와요.' }); restReminderTimerRef.current = null; }, 5 * 60 * 1000); }} onConfirm={(nextGoal) => { onGoalUpdate(nextGoal); setSheetOpen(false); triggerFlash(1200); }} /> ); };