diff --git a/frontend/src/components/timeline/Timeline.tsx b/frontend/src/components/timeline/Timeline.tsx index 26ba45e..2dd6d36 100644 --- a/frontend/src/components/timeline/Timeline.tsx +++ b/frontend/src/components/timeline/Timeline.tsx @@ -178,6 +178,7 @@ export function Timeline() { const sortBy = useFilterStore((s) => s.sortBy) const groupBy = useFilterStore((s) => s.groupBy) + const viewMode = usePhotoStore((s) => s.viewMode) // Calculate number of columns based on container width. const columns = useMemo(() => { @@ -322,7 +323,14 @@ export function Timeline() { // Handle keyboard shortcuts for photo navigation. Operates on the // grouped grid the user sees, so a half-full last row of a group // doesn't make ArrowDown skip into the wrong place. + // + // Inert in preview mode — PreviewView mounts its own arrow handlers, + // and a window-level grid handler firing alongside them used to race + // against PreviewView's setActivePhoto, landing the user on the wrong + // photo. The grid handler stays attached so it can re-engage the + // moment the user closes preview. useEffect(() => { + if (viewMode !== 'grid') return const handleKeyDown = (e: KeyboardEvent) => { if (photoRows.length === 0) return const target = e.target as HTMLElement | null @@ -413,7 +421,7 @@ export function Timeline() { window.addEventListener('keydown', handleKeyDown) return () => window.removeEventListener('keydown', handleKeyDown) // eslint-disable-next-line react-hooks/exhaustive-deps - }, [photoRows, photos, selectedPhotos, activePhotoId]) + }, [viewMode, photoRows, photos, selectedPhotos, activePhotoId]) if (isLoading) { return (