From 85ace6a6be5736b5d00ab94388adccf5100d0ebc Mon Sep 17 00:00:00 2001 From: Josh Hawkins <32435876+hawkeye217@users.noreply.github.com> Date: Thu, 2 Oct 2025 07:31:09 -0500 Subject: [PATCH] Add input focused boolean to face library keyboard listener (#20325) Because the "a" key is used by the keyboard listener for select all, this would prevent it from being used in the tracked object details pane. This change mimics what is already done in Explore. --- web/src/pages/FaceLibrary.tsx | 56 +++++++++++++++++++++-------------- 1 file changed, 34 insertions(+), 22 deletions(-) diff --git a/web/src/pages/FaceLibrary.tsx b/web/src/pages/FaceLibrary.tsx index f76237bba..919d26c86 100644 --- a/web/src/pages/FaceLibrary.tsx +++ b/web/src/pages/FaceLibrary.tsx @@ -109,6 +109,9 @@ export default function FaceLibrary() { const [upload, setUpload] = useState(false); const [addFace, setAddFace] = useState(false); + // input focus for keyboard shortcuts + const [inputFocused, setInputFocused] = useState(false); + const onUploadImage = useCallback( (file: File) => { const formData = new FormData(); @@ -260,28 +263,32 @@ export default function FaceLibrary() { // keyboard - useKeyboardListener(["a", "Escape"], (key, modifiers) => { - if (modifiers.repeat || !modifiers.down) { - return; - } + useKeyboardListener( + ["a", "Escape"], + (key, modifiers) => { + if (modifiers.repeat || !modifiers.down) { + return; + } - switch (key) { - case "a": - if (modifiers.ctrl) { - if (selectedFaces.length) { - setSelectedFaces([]); - } else { - setSelectedFaces([ - ...(pageToggle === "train" ? trainImages : faceImages), - ]); + switch (key) { + case "a": + if (modifiers.ctrl) { + if (selectedFaces.length) { + setSelectedFaces([]); + } else { + setSelectedFaces([ + ...(pageToggle === "train" ? trainImages : faceImages), + ]); + } } - } - break; - case "Escape": - setSelectedFaces([]); - break; - } - }); + break; + case "Escape": + setSelectedFaces([]); + break; + } + }, + !inputFocused, + ); useEffect(() => { setSelectedFaces([]); @@ -406,6 +413,7 @@ export default function FaceLibrary() { selectedFaces={selectedFaces} onClickFaces={onClickFaces} onRefresh={refreshFaces} + setInputFocused={setInputFocused} /> ) : ( void; onRefresh: () => void; + setInputFocused: React.Dispatch>; }; function TrainingGrid({ config, @@ -614,6 +623,7 @@ function TrainingGrid({ selectedFaces, onClickFaces, onRefresh, + setInputFocused, }: TrainingGridProps) { const { t } = useTranslation(["views/faceLibrary"]); @@ -688,7 +698,7 @@ function TrainingGrid({ setSimilarity={undefined} setSearchPage={setDialogTab} setSearch={(search) => setSelectedEvent(search as unknown as Event)} - setInputFocused={() => {}} + setInputFocused={setInputFocused} />
@@ -1042,6 +1052,8 @@ function FaceGrid({ onClickFaces, onDelete, }: FaceGridProps) { + const { t } = useTranslation(["views/faceLibrary"]); + const sortedFaces = useMemo( () => (faceImages || []).sort().reverse(), [faceImages], @@ -1051,7 +1063,7 @@ function FaceGrid({ return (
- (t("nofaces")) + {t("nofaces")}
); }