diff --git a/web/public/locales/en/views/faceLibrary.json b/web/public/locales/en/views/faceLibrary.json
index ea3210eee..48bc6401c 100644
--- a/web/public/locales/en/views/faceLibrary.json
+++ b/web/public/locales/en/views/faceLibrary.json
@@ -40,12 +40,17 @@
"title": "Delete Name",
"desc": "Are you sure you want to delete the collection {{name}}? This will permanently delete all associated faces."
},
+ "deleteFaceAttempts": {
+ "title": "Delete Faces",
+ "desc_one": "Are you sure you want to delete {{count}} face? This action cannot be undone.",
+ "desc_other": "Are you sure you want to delete {{count}} faces? This action cannot be undone."
+ },
"renameFace": {
"title": "Rename Face",
"desc": "Enter a new name for {{name}}"
},
"button": {
- "deleteFaceAttempts": "Delete Face Attempts",
+ "deleteFaceAttempts": "Delete Faces",
"addFace": "Add Face",
"renameFace": "Rename Face",
"deleteFace": "Delete Face",
diff --git a/web/src/pages/FaceLibrary.tsx b/web/src/pages/FaceLibrary.tsx
index 3a33cb204..d5ba4c26e 100644
--- a/web/src/pages/FaceLibrary.tsx
+++ b/web/src/pages/FaceLibrary.tsx
@@ -6,7 +6,17 @@ import CreateFaceWizardDialog from "@/components/overlay/detail/FaceCreateWizard
import TextEntryDialog from "@/components/overlay/dialog/TextEntryDialog";
import UploadImageDialog from "@/components/overlay/dialog/UploadImageDialog";
import FaceSelectionDialog from "@/components/overlay/FaceSelectionDialog";
-import { Button } from "@/components/ui/button";
+import { Button, buttonVariants } from "@/components/ui/button";
+import {
+ AlertDialog,
+ AlertDialogAction,
+ AlertDialogCancel,
+ AlertDialogContent,
+ AlertDialogDescription,
+ AlertDialogFooter,
+ AlertDialogHeader,
+ AlertDialogTitle,
+} from "@/components/ui/alert-dialog";
import {
Dialog,
DialogContent,
@@ -44,7 +54,7 @@ import { TooltipPortal } from "@radix-ui/react-tooltip";
import axios from "axios";
import { useCallback, useEffect, useMemo, useRef, useState } from "react";
import { isDesktop, isMobile } from "react-device-detect";
-import { useTranslation } from "react-i18next";
+import { Trans, useTranslation } from "react-i18next";
import {
LuFolderCheck,
LuImagePlus,
@@ -165,6 +175,11 @@ export default function FaceLibrary() {
[selectedFaces, setSelectedFaces],
);
+ const [deleteDialogOpen, setDeleteDialogOpen] = useState<{
+ name: string;
+ ids: string[];
+ } | null>(null);
+
const onDelete = useCallback(
(name: string, ids: string[], isName: boolean = false) => {
axios
@@ -191,7 +206,7 @@ export default function FaceLibrary() {
if (faceImages.length == 1) {
// face has been deleted
- setPageToggle("");
+ setPageToggle("train");
}
refreshFaces();
@@ -244,29 +259,32 @@ export default function FaceLibrary() {
// keyboard
- useKeyboardListener(
- page === "train" ? ["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([...trainImages]);
- }
+ 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;
+ }
+ });
+
+ useEffect(() => {
+ setSelectedFaces([]);
+ }, [pageToggle]);
if (!config) {
return