feat(review): fast keyboard-first Stacks & Duplicates resolve queue
Both tabs get a resolve-and-advance queue instead of independent click-to-focus cards: ↑/↓ or j/k rove between groups, resolving a group removes it optimistically and auto-advances focus, and a sticky header tracks reclaimable bytes + a running "resolved this session" tally. ⌘Z undoes via a new sidecar restore endpoint (gridKeyNav — the usual ⌘Z owner — isn't mounted on these tabs, so DuplicatesView wires its own). Sidecar (handlers_dups.go, fs.go, main.go): - POST /duplicates/restore — inverse of /duplicates/archive, moves quarantined files back to their original path with the same BasePath guards and async reindex-with-cleanup. - Scan results now include each file's mtime so the UI can label older/newer copies. Stack losers now go through the same sidecar quarantine as cross-folder duplicates (setPrimary + archiveDuplicatePaths) instead of a hard PhotoPrism DELETE, so both tabs share one recoverable, undoable resolution path (services/duplicateActions.svelte.ts). StackGroupCard: comparison-first — fact rows highlight the best size/resolution per file, a "Suggested" badge appears when one file wins outright, and Space opens a fullscreen CompareLightbox that flips between candidates while preserving zoom/pan (extracted the zoom/pan gesture handling from PreviewPane into a shared lib/actions/zoomPan.ts action so both consumers share one implementation). CrossFolderGroupCard: since every copy is byte-identical, the old grid of N identical thumbnails told the user nothing — replaced with one thumbnail plus a path list that highlights the differing folder segment and flags the indexed/newest copy. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
@@ -8,6 +8,7 @@ import (
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
// sanitizeFilename trims a user-supplied filename and rejects anything
|
||||
@@ -168,6 +169,7 @@ type fileEntry struct {
|
||||
RelPath string
|
||||
AbsPath string
|
||||
Size int64
|
||||
ModTime time.Time
|
||||
}
|
||||
|
||||
// supportedExts mirrors the Node prototype's whitelist. PhotoPrism
|
||||
@@ -222,6 +224,7 @@ func walkFiles(root string) ([]fileEntry, error) {
|
||||
RelPath: rel,
|
||||
AbsPath: p,
|
||||
Size: info.Size(),
|
||||
ModTime: info.ModTime(),
|
||||
})
|
||||
return nil
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user