import { useRef, useEffect } from 'react'; import { FONT_MONO } from '../../styles/fonts'; import { useGearReplayStore } from '../../stores/gearReplayStore'; interface HistoryReplayControllerProps { onClose: () => void; } const HistoryReplayController = ({ onClose }: HistoryReplayControllerProps) => { // React selectors (infrequent changes) const isPlaying = useGearReplayStore(s => s.isPlaying); const snapshotRanges = useGearReplayStore(s => s.snapshotRanges); const frameCount = useGearReplayStore(s => s.historyFrames.length); // DOM refs for imperative updates const progressBarRef = useRef(null); const progressIndicatorRef = useRef(null); const timeDisplayRef = useRef(null); // Subscribe to currentTime for DOM updates (no React re-render) useEffect(() => { const unsub = useGearReplayStore.subscribe( s => s.currentTime, (currentTime) => { const { startTime, endTime } = useGearReplayStore.getState(); if (endTime <= startTime) return; const progress = (currentTime - startTime) / (endTime - startTime); if (progressBarRef.current) progressBarRef.current.value = String(Math.round(progress * 1000)); if (progressIndicatorRef.current) progressIndicatorRef.current.style.left = `${progress * 100}%`; if (timeDisplayRef.current) { timeDisplayRef.current.textContent = new Date(currentTime).toLocaleTimeString('ko-KR', { hour: '2-digit', minute: '2-digit' }); } }, ); return unsub; }, []); const store = useGearReplayStore; return (
{/* 프로그레스 바 — 갭 표시 */}
{snapshotRanges.map((pos, i) => (
))} {/* 현재 위치 인디케이터 (DOM ref로 업데이트) */}
{/* 컨트롤 행 */}
--:-- { const { startTime, endTime } = store.getState(); const progress = Number(e.target.value) / 1000; const seekTime = startTime + progress * (endTime - startTime); store.getState().pause(); store.getState().seek(seekTime); }} style={{ flex: 1, cursor: 'pointer', accentColor: '#fbbf24' }} title="히스토리 타임라인" aria-label="히스토리 타임라인" /> {frameCount}건
); }; export default HistoryReplayController;