095b9876f9
* first attempt at stream sidebar, tasks, and events * fix folder from root * cleanup folders and events, and condense changes * cleanup and add toggle for sidebar * cleanup * fix nits
81 lines
2.1 KiB
TypeScript
81 lines
2.1 KiB
TypeScript
import { useEffect, type RefObject } from 'react';
|
|
import type { MediaParticleHandle } from '@/features/particles/media-particle-view';
|
|
import { isTypingTarget } from '@/lib/keyboard';
|
|
|
|
const SEEK_DELTA_SEC = 5;
|
|
|
|
interface UseStreamNavigationKeysOptions {
|
|
next: () => void;
|
|
prev: () => void;
|
|
currentIndex: number;
|
|
childrenLength: number;
|
|
mediaRef: RefObject<MediaParticleHandle | null>;
|
|
onExit: () => void;
|
|
onToggleViewMode: () => void;
|
|
}
|
|
|
|
/**
|
|
* Arrow keys (with shift+arrow seek), Escape. Skipped while playback is
|
|
* paused for any reason (overlay, hold-space, compose).
|
|
*/
|
|
export function useStreamNavigationKeys({
|
|
next,
|
|
prev,
|
|
currentIndex,
|
|
childrenLength,
|
|
mediaRef,
|
|
onExit,
|
|
onToggleViewMode,
|
|
}: UseStreamNavigationKeysOptions) {
|
|
useEffect(() => {
|
|
const onKeyDown = (e: KeyboardEvent) => {
|
|
if (isTypingTarget(e)) return;
|
|
|
|
const hasNext = currentIndex >= 0 && currentIndex < childrenLength - 1;
|
|
|
|
switch (e.key) {
|
|
case 'ArrowRight':
|
|
e.preventDefault();
|
|
if (!e.shiftKey || !mediaRef.current?.seek(SEEK_DELTA_SEC)) {
|
|
if (hasNext) next();
|
|
}
|
|
break;
|
|
case 'ArrowDown':
|
|
e.preventDefault();
|
|
if (hasNext) next();
|
|
break;
|
|
case 'ArrowLeft':
|
|
e.preventDefault();
|
|
if (!e.shiftKey || !mediaRef.current?.seek(-SEEK_DELTA_SEC)) prev();
|
|
break;
|
|
case 'ArrowUp':
|
|
e.preventDefault();
|
|
prev();
|
|
break;
|
|
case 'Escape':
|
|
e.preventDefault();
|
|
onExit();
|
|
break;
|
|
case 'l':
|
|
case 'L':
|
|
// Registered here (not in action keys) because the toggle must work
|
|
// in list mode, where playback is suspended and action keys bail.
|
|
e.preventDefault();
|
|
onToggleViewMode();
|
|
break;
|
|
}
|
|
};
|
|
|
|
window.addEventListener('keydown', onKeyDown);
|
|
return () => window.removeEventListener('keydown', onKeyDown);
|
|
}, [
|
|
next,
|
|
prev,
|
|
currentIndex,
|
|
childrenLength,
|
|
mediaRef,
|
|
onExit,
|
|
onToggleViewMode,
|
|
]);
|
|
}
|