diff --git a/src/components/DuplicateFinder.tsx b/src/components/DuplicateFinder.tsx index a6b546d..c0c2ad6 100644 --- a/src/components/DuplicateFinder.tsx +++ b/src/components/DuplicateFinder.tsx @@ -1,120 +1,10 @@ import { useRef, useState } from "react"; import { useVirtualizer } from "@tanstack/react-virtual"; -import { DuplicateGroup, useGalleryStore } from "../store"; -import { FolderScopeDropdown } from "./FolderScopeDropdown"; -import { mediaSrc } from "../lib/mediaSrc"; -import { Tooltip } from "./Tooltip"; -import { WarningIcon } from "./icons"; - -function formatBytes(bytes: number): string { - if (bytes >= 1_073_741_824) return `${(bytes / 1_073_741_824).toFixed(1)} GB`; - if (bytes >= 1_048_576) return `${(bytes / 1_048_576).toFixed(1)} MB`; - if (bytes >= 1024) return `${(bytes / 1024).toFixed(0)} KB`; - return `${bytes} B`; -} - -function DuplicateGroupCard({ group }: { group: DuplicateGroup }) { - const selectedIds = useGalleryStore((state) => state.duplicateSelectedIds); - const toggleDuplicateSelected = useGalleryStore((state) => state.toggleDuplicateSelected); - const selectAllDuplicates = useGalleryStore((state) => state.selectAllDuplicates); - const groupSelectedCount = group.images.filter((img) => selectedIds.has(img.id)).length; - const noneSelected = groupSelectedCount === 0; - - // "Keep all but the first" — a common quick action - const handleKeepFirst = () => { - const toDelete = group.images.slice(1).map((img) => img.id); - // Clear any selection for this group first, then add the ones to delete - for (const img of group.images) { - if (selectedIds.has(img.id)) toggleDuplicateSelected(img.id); - } - selectAllDuplicates(toDelete); - }; - - return ( -
- {duplicateScanning - ? duplicateScanProgress - ? `${progressLabel}… ${duplicateScanProgress.processed.toLocaleString()} / ${duplicateScanProgress.total.toLocaleString()}${duplicateScanProgress.skipped > 0 ? ` · ${duplicateScanProgress.skipped.toLocaleString()} skipped` : ""}` - : "Starting scan…" - : hasResults - ? `${duplicateGroups.length} group${duplicateGroups.length === 1 ? "" : "s"} · ${formatBytes(totalWasted)} reclaimable` - : duplicateLastScanned !== null - ? "No duplicates found" - : "Scan your library for identical files"} -
- {!duplicateScanning && duplicateLastScanned !== null && ( -- Last scanned {formatRelativeTime(duplicateLastScanned)} -
- )} -Delete from disk
-- Permanently delete {selectedCount} file{selectedCount === 1 ? "" : "s"} from your computer. - This removes the actual file{selectedCount === 1 ? "" : "s"} from disk and cannot be undone. -
-{duplicateScanError}
- ) : null} - {duplicateScanWarning ? ( -{duplicateScanWarning}
- ) : null} - {deleteResult ? ( -{deleteResult}
- ) : null} -- Finds files with identical content regardless of filename or location. - Click Scan for duplicates to begin. -
-- Large libraries may take a minute — files are hashed from disk. -
-No duplicate files found.
-+ Finds files with identical content regardless of filename or location. + Click Scan for duplicates to begin. +
++ Large libraries may take a minute — files are hashed from disk. +
+No duplicate files found.
++ {duplicateScanning + ? duplicateScanProgress + ? `${progressLabel}… ${duplicateScanProgress.processed.toLocaleString()} / ${duplicateScanProgress.total.toLocaleString()}${duplicateScanProgress.skipped > 0 ? ` · ${duplicateScanProgress.skipped.toLocaleString()} skipped` : ""}` + : "Starting scan…" + : hasResults + ? `${duplicateGroups.length} group${duplicateGroups.length === 1 ? "" : "s"} · ${formatBytes(totalWasted)} reclaimable` + : duplicateLastScanned !== null + ? "No duplicates found" + : "Scan your library for identical files"} +
+ {!duplicateScanning && duplicateLastScanned !== null ? ( ++ Last scanned {formatRelativeTime(duplicateLastScanned)} +
+ ) : null} +Delete from disk
++ Permanently delete {selectedCount} file{selectedCount === 1 ? "" : "s"} from your computer. + This removes the actual file{selectedCount === 1 ? "" : "s"} from disk and cannot be undone. +
+{duplicateScanError}
+ ) : null} + {duplicateScanWarning ? ( +{duplicateScanWarning}
+ ) : null} + {deleteResult ? ( +{deleteResult}
+ ) : null} +