From 695adddaff0c4e76278bffcb490eb9dfbc7dd860 Mon Sep 17 00:00:00 2001 From: talksik Date: Tue, 7 Apr 2026 16:32:51 -0700 Subject: [PATCH] feat: hold to pause stream playback --- js/src/features/particles/stream-view.tsx | 42 +++++++++++++++++------ 1 file changed, 31 insertions(+), 11 deletions(-) diff --git a/js/src/features/particles/stream-view.tsx b/js/src/features/particles/stream-view.tsx index 948d017..cf938e4 100644 --- a/js/src/features/particles/stream-view.tsx +++ b/js/src/features/particles/stream-view.tsx @@ -177,19 +177,20 @@ export function StreamView({ path, streamParticle }: StreamViewProps) { else resume(); }, [composeActive, pause, resume]); - // Playback keyboard: arrows, escape + // Playback keyboard: arrows, escape, hold-space-to-pause useEffect(() => { - const handleKeyDown = (e: KeyboardEvent) => { - if (composeActive) return; - + function isInputTarget(e: KeyboardEvent) { const target = e.target as HTMLElement; - if ( + return ( target.tagName === "INPUT" || target.tagName === "TEXTAREA" || target.isContentEditable - ) { - return; - } + ); + } + + const handleKeyDown = (e: KeyboardEvent) => { + if (composeActive) return; + if (isInputTarget(e)) return; switch (e.key) { case "ArrowRight": @@ -202,6 +203,10 @@ export function StreamView({ path, streamParticle }: StreamViewProps) { e.preventDefault(); prev(); break; + case " ": + e.preventDefault(); + if (!e.repeat) pause(); + break; case "Escape": e.preventDefault(); navigate(`/${networkId}`); @@ -215,11 +220,26 @@ export function StreamView({ path, streamParticle }: StreamViewProps) { break; } } - } + }; + + const handleKeyUp = (e: KeyboardEvent) => { + if (composeActive) return; + if (isInputTarget(e)) return; + + if (e.key === " ") { + e.preventDefault(); + resume(); + } + }; + window.addEventListener("keydown", handleKeyDown); - return () => window.removeEventListener("keydown", handleKeyDown); + window.addEventListener("keyup", handleKeyUp); + return () => { + window.removeEventListener("keydown", handleKeyDown); + window.removeEventListener("keyup", handleKeyUp); + }; }, - [composeActive, next, prev, navigate, networkId, streamParticle.id], + [composeActive, next, prev, pause, resume, navigate, networkId, streamParticle.id], ); // Click-to-navigate: left 30% = prev, right 70% = next