Revised plan: focus on batch assignment and explore view assignment

Co-authored-by: Teagan42 <2989925+Teagan42@users.noreply.github.com>
This commit is contained in:
copilot-swe-agent[bot] 2026-02-19 08:08:10 +00:00
parent 8d0b4b8322
commit 9a41eaceb9

View File

@ -416,6 +416,86 @@ export default function FaceLibrary() {
</> </>
)} )}
</div> </div>
{pageToggle === "train" && (
<FaceSelectionDialog
faceNames={faces}
onTrainAttempt={(name) => {
// Batch train all selected faces
let successCount = 0;
let failCount = 0;
const totalCount = selectedFaces.length;
selectedFaces.forEach((filename, index) => {
axios
.post(`/faces/train/${name}/classify`, {
training_file: filename,
})
.then((resp) => {
if (resp.status == 200) {
successCount++;
} else {
failCount++;
}
// Show final toast after all requests complete
if (index === totalCount - 1) {
if (successCount === totalCount) {
toast.success(
t("toast.success.batchTrainedFaces", {
count: successCount,
}),
{
position: "top-center",
},
);
} else if (successCount > 0) {
toast.warning(
t("toast.warning.partialBatchTrained", {
success: successCount,
total: totalCount,
}),
{
position: "top-center",
},
);
} else {
toast.error(
t("toast.error.batchTrainFailed", {
count: totalCount,
}),
{
position: "top-center",
},
);
}
setSelectedFaces([]);
refreshFaces();
}
})
.catch(() => {
failCount++;
if (index === totalCount - 1) {
toast.error(
t("toast.error.batchTrainFailed", {
count: totalCount,
}),
{
position: "top-center",
},
);
setSelectedFaces([]);
refreshFaces();
}
});
});
}}
>
<Button className="flex gap-2">
<AddFaceIcon className="size-7 rounded-md p-1 text-secondary-foreground" />
{isDesktop && t("button.trainFaces")}
</Button>
</FaceSelectionDialog>
)}
<Button <Button
className="flex gap-2" className="flex gap-2"
onClick={() => onClick={() =>
@ -811,6 +891,7 @@ type FaceAttemptGroupProps = {
) => FaceLibraryData | undefined), ) => FaceLibraryData | undefined),
opts?: boolean | { revalidate?: boolean }, opts?: boolean | { revalidate?: boolean },
) => Promise<FaceLibraryData | undefined>; ) => Promise<FaceLibraryData | undefined>;
onClickEvent: (event: Event) => void;
}; };
function FaceAttemptGroup({ function FaceAttemptGroup({
config, config,
@ -820,6 +901,7 @@ function FaceAttemptGroup({
selectedFaces, selectedFaces,
onClickFaces, onClickFaces,
onRefresh, onRefresh,
onClickEvent,
}: FaceAttemptGroupProps) { }: FaceAttemptGroupProps) {
const { t } = useTranslation(["views/faceLibrary", "views/explore"]); const { t } = useTranslation(["views/faceLibrary", "views/explore"]);
@ -837,6 +919,10 @@ function FaceAttemptGroup({
const handleClickEvent = useCallback( const handleClickEvent = useCallback(
(meta: boolean) => { (meta: boolean) => {
if (!meta) { if (!meta) {
// Open detail view when clicking without meta key
if (event) {
onClickEvent(event);
}
return; return;
} else { } else {
const anySelected = const anySelected =
@ -861,7 +947,7 @@ function FaceAttemptGroup({
} }
} }
}, },
[group, selectedFaces, onClickFaces], [group, selectedFaces, onClickFaces, event, onClickEvent],
); );
// api calls // api calls