From b78e11bfb0f9dce78a12882a69feacb7a6067fa0 Mon Sep 17 00:00:00 2001 From: ilia Date: Tue, 4 Aug 2026 21:39:10 -0400 Subject: [PATCH] Sprint C#12: arrow-key prev/next on Identify face queue. --- admin-frontend/src/pages/Identify.tsx | 39 ++++++++++++++++++++++++--- 1 file changed, 35 insertions(+), 4 deletions(-) diff --git a/admin-frontend/src/pages/Identify.tsx b/admin-frontend/src/pages/Identify.tsx index 48ef9e0..65b21b7 100644 --- a/admin-frontend/src/pages/Identify.tsx +++ b/admin-frontend/src/pages/Identify.tsx @@ -851,6 +851,36 @@ export default function Identify() { return `Face ${currentIdx + 1} of ${faces.length}` }, [currentFace, currentIdx, faces.length]) + const goToPrevFace = useCallback(() => { + setCurrentIdx((i) => Math.max(0, i - 1)) + }, []) + + const goToNextFace = useCallback(() => { + setCurrentIdx((i) => Math.min(faces.length - 1, i + 1)) + }, [faces.length]) + + useEffect(() => { + if (activeTab !== 'faces' || faces.length === 0) return + + const onKeyDown = (e: globalThis.KeyboardEvent) => { + if (e.key !== 'ArrowLeft' && e.key !== 'ArrowRight') return + if (e.altKey || e.ctrlKey || e.metaKey) return + + const el = e.target as HTMLElement | null + if (!el) return + const tag = el.tagName + if (tag === 'INPUT' || tag === 'TEXTAREA' || tag === 'SELECT' || tag === 'BUTTON') return + if (el.isContentEditable) return + + e.preventDefault() + if (e.key === 'ArrowLeft') goToPrevFace() + else goToNextFace() + } + + window.addEventListener('keydown', onKeyDown) + return () => window.removeEventListener('keydown', onKeyDown) + }, [activeTab, faces.length, goToPrevFace, goToNextFace]) + const handleNextPage = () => { if (loadingFaces) return const nextPage = page + 1 @@ -1336,8 +1366,9 @@ export default function Identify() { )}
- - + + + ← → keys - - + +