import { useEffect, useRef, useState, type RefObject } from "react"; import type { MediaParticleHandle } from "@/features/particles/media-particle-view"; import { useSuspendPlayback } from "@/hooks/use-suspend-playback"; import { selectIsPaused, usePlaybackPauseStore } from "@/stores/playback-pause-store"; import { isTypingTarget } from "@/lib/keyboard"; import { set } from "zod"; const SPACE_TAP_THRESHOLD_MS = 250; interface UsePlaybackKeysOptions { mediaRef: RefObject; } interface UsePlaybackKeysResult { fastPlayback: boolean; } /** * Hold-space to pause, hold-shift for 1.5x. Space is always handled (it * manages its own suspender via useSuspendPlayback); other keys bail when * playback is already paused for an external reason. */ export function usePlaybackKeys({ mediaRef }: UsePlaybackKeysOptions): UsePlaybackKeysResult { const [spaceHeld, setSpaceHeld] = useState(false); const [fastPlayback, setFastPlayback] = useState(false); const spaceStartRef = useRef(0); useSuspendPlayback(spaceHeld, "hold-space"); useEffect(() => { const isExternallyPaused = () => selectIsPaused(usePlaybackPauseStore.getState()) && !spaceHeld; const onKeyDown = (e: KeyboardEvent) => { if (isTypingTarget(e)) return; if (e.key === " ") { e.preventDefault(); if (!e.repeat) { if (spaceHeld) { setSpaceHeld(false); spaceStartRef.current = 0; } else { setSpaceHeld(true); spaceStartRef.current = Date.now(); } } return; } if (isExternallyPaused()) return; if (e.key === "Shift" && !e.repeat) { mediaRef.current?.setPlaybackRate(1.5); setFastPlayback(true); } }; const onKeyUp = (e: KeyboardEvent) => { if (isTypingTarget(e)) return; if (e.key === " ") { e.preventDefault(); // keep space-held if it was a quick tap, to allow for space-to-toggle behavior if (Date.now() - spaceStartRef.current < SPACE_TAP_THRESHOLD_MS) { return; } setSpaceHeld(false); spaceStartRef.current = 0; return; } if (isExternallyPaused()) return; if (e.key === "Shift") { mediaRef.current?.setPlaybackRate(1); setFastPlayback(false); } }; window.addEventListener("keydown", onKeyDown); window.addEventListener("keyup", onKeyUp); return () => { window.removeEventListener("keydown", onKeyDown); window.removeEventListener("keyup", onKeyUp); }; }, [mediaRef, spaceHeld]); return { fastPlayback }; }