Product Requirements Document (PRD)
1) Summary
A macOS desktop app for rapid photo triage. Users browse a folder tree (parent/children), enter Cleanup Mode to preview photos one-by-one, and use swipe gestures:
-
Swipe Left → move photo to a staging folder named “ToDelete”.
-
Swipe Right → keep photo, advance to next.
Keyboard shortcuts mirror gestures. Users can later review or permanently delete staged photos.
2) Goals & Non-Goals
Goals
-
Fast, low-friction review of photos in any filesystem folder.
-
Reliable, reversible “stage for deletion” workflow.
-
Smooth navigation among parent and child folders.
Non-Goals
-
Editing photos (crop, color, etc.).
-
Managing Photos app library (this release is filesystem-only).
-
Cloud sync logic (beyond what Finder/OS already does).
3) Assumptions
-
Sandboxed app; user grants access via folder picker. Use security-scoped bookmarks to persist access.
-
Photos are regular files in the filesystem (JPEG, PNG, HEIC, GIF, TIFF, RAW variants).
-
“ToDelete” is a sibling of the current folder by default (configurable).
4) User Stories
-
US-01: As a user, I can select a root folder to review.
-
US-02: I can navigate up to parent or down into children quickly.
-
US-03: I can enter Cleanup Mode and preview photos full-screen or in a focused pane.
-
US-04: Swiping left sends the current photo to “ToDelete” and shows the next photo.
-
US-05: Swiping right skips the photo and shows the next photo.
-
US-06: I can use keyboard shortcuts instead of gestures.
-
US-07: I can undo the last action(s).
-
US-08: I can review the “ToDelete” folder and restore items.
-
US-09: I can permanently delete staged items (to macOS Trash) with a confirmation.
-
US-10: I can configure where “ToDelete” is created and how images are sorted.
5) UX & Interaction Model
Navigation
-
Left sidebar: folder tree (current folder highlighted).
-
Breadcrumb at top for quick jump to ancestors.
-
Toggle to switch among Parent / Current / Children (or a three-segment control).
Cleanup Mode
-
Enters a focused viewer.
-
HUD: file name, index (e.g., 14/238), resolution, creation date.
-
Controls: Exit Cleanup, Undo, “Open in Finder”, “Reveal in Finder”, “View in ToDelete”.
-
Gestures:
-
Trackpad swipe left → stage to delete, auto-advance.
-
Trackpad swipe right → keep, advance.
-
-
Shortcuts:
-
← / D = Stage to delete.
-
→ / K = Keep/Next.
-
U / ⌘Z = Undo.
-
Space = Toggle quick zoom.
-
Esc = Exit Cleanup Mode.
-
Staging
-
On first stage action, app creates ToDelete if missing.
-
Name collisions resolved by appending “ (1)”, “ (2)”, etc.
-
Across volumes: perform copy+delete (with progress), preserving metadata.
Settings
-
Sort order: Date created | Date modified | Name | Size (asc/desc).
-
Include subfolders in Cleanup Mode: On/Off.
-
“ToDelete” location: sibling folder (default) | fixed app-level staging folder | custom.
-
Preview quality: Auto (default) | High | Low.
-
Confirm permanent deletion: On (default) | Off.
-
Skip files larger than N MB without warning: On/Off.
6) Functional Requirements
-
FR-01 Folder Access: User chooses one or more root folders; app stores security-scoped bookmarks.
-
FR-02 Folder Navigation: Display parent and children; jumping between them must be O(1) visible action with lazy loading of large trees.
-
FR-03 Media Discovery: Filter visible items to supported image types (configurable).
-
FR-04 Sorting & Filtering: Apply user’s sort preferences consistently across navigation and Cleanup Mode.
-
FR-05 Preview Engine: Generate fast thumbnails and quick-look previews (respect EXIF orientation). Preload next/previous image.
-
FR-06 Cleanup Mode State: Linear traversal of the filtered set; resume where left off per folder.
-
FR-07 Stage Left (Delete): Move file to “ToDelete” (atomic when possible). Advance immediately. Log action to an in-memory and on-disk session history for undo.
-
FR-08 Skip Right (Keep): Advance without moving file.
-
FR-09 Undo/Redo: Undo last N actions in session; supports restoring a moved file to its original path (or warn if path unavailable).
-
FR-10 “ToDelete” Review: Dedicated view to browse, restore, or permanently delete items.
-
FR-11 Permanent Delete: Send to macOS Trash (not immediate unlink) with count summary and confirmation dialog.
-
FR-12 Cross-Volume Handling: If “ToDelete” is on a different volume, copy+delete with progress UI; on failure, rollback.
-
FR-13 Conflicts: If a same-name file exists in “ToDelete”, auto-rename deterministically.
-
FR-14 Persistence: Store settings and per-folder progress in user defaults / app support.
-
FR-15 Accessibility: Full keyboard operation, VoiceOver labels, large hit-targets.
-
FR-16 Localization-Ready: Strings externalized.
-
FR-17 Telemetry (optional toggle): Count of staged/kept per session (no file names/paths).
-
FR-18 Error Handling: Friendly toasts for permission errors, missing files, iCloud download in progress, etc.
-
FR-19 Performance:
-
First preview < 300 ms p95 after assets indexed.
-
Next/prev transition < 120 ms p95.
-
Memory footprint < 500 MB when paging high-res photos (release decoded bitmaps).
-
7) Non-Functional Requirements
-
NFR-01 Platform: Current and last two major macOS versions. Universal build (Apple Silicon + Intel if required).
-
NFR-02 Privacy: All processing local; no network I/O by default.
-
NFR-03 Reliability: No data loss on interruption; operations are transactional where feasible.
-
NFR-04 Security: Respect sandbox; only user-granted folders accessible.
-
NFR-05 Observability: Lightweight logs (rotated), crash reports opt-in.
8) Data & Technical Notes
-
Use security-scoped bookmarks for persistent folder access.
-
Use file coordination for moves; preserve EXIF and extended attributes.
-
Use thumbnail APIs / CGImageSource for efficient previews; cache adjacent images.
-
Keep a session action log:
{timestamp, originalPath, stagedPath, actionType}
to power undo/redo and recovery after crash.
9) Out of Scope (v1)
-
Videos, Live Photos, and RAW sidecar pairing rules (treat as files for now).
-
Duplicate detection, fuzzy grouping, or AI.
Test Plan
A) Strategy
-
Unit Tests: file operations, name collision resolver, sort, state machine.
-
Integration Tests: security-scoped bookmark flow, cross-volume move, Trash deletion, EXIF orientation.
-
UI Tests (XCUITest): navigation, Cleanup Mode gestures/shortcuts, undo/redo.
-
Performance Tests: preview latency & memory under load.
-
Accessibility Tests: keyboard-only flows, VoiceOver labels.
-
Manual Exploratory: weird filenames, iCloud placeholders, external drives.
B) Test Environment
-
macOS latest and two prior majors; Apple Silicon primary.
-
File systems: APFS local; APFS external; network share (read/write).
-
Folder sets:
-
Small (≤100 photos), Medium (~5k), Large (≥50k, mixed formats).
-
Include HEIC, large JPEG (>25 MB), PNG, TIFF, common RAWs (CR2/NEF/ARW/DNG).
-
C) Acceptance Criteria (sample, traceable to FR-IDs)
-
AC-01 (FR-07): Swiping left moves file into “ToDelete” within 500 ms and advances to the next item.
-
AC-02 (FR-09): ⌘Z restores the last staged file to its original path even after folder change.
-
AC-03 (FR-11): “Delete staged” sends all items to macOS Trash and reduces “ToDelete” count to 0.
-
AC-04 (FR-05): Portrait photos show correctly oriented previews.
-
AC-05 (FR-02): Parent/children toggle switches views in ≤150 ms and preserves scroll and selection.
-
AC-06 (FR-12): Cross-volume stage shows progress and leaves no partials on failure.
-
AC-07 (FR-15): All primary actions are reachable by keyboard and announced by VoiceOver.
D) Core Test Cases
ID | Precondition | Steps | Expected Result |
---|---|---|---|
TC-01 | App fresh install | Launch → Choose Folder | Permission prompt shown; folder appears in sidebar; bookmark persisted. |
TC-02 | Folder with 500 JPEGs | Enter Cleanup Mode → Swipe Right 5× | Index increments; no files moved; HUD updates (6/500). |
TC-03 | Same as TC-02 | Swipe Left 1× | Current file appears in ToDelete; viewer advances; toast “Moved to ToDelete”. |
TC-04 | After TC-03 | Press ⌘Z | File restored to original path; index decrements; toast “Undo move”. |
TC-05 | “ToDelete” already has a file named IMG_0001.jpg |
Stage another IMG_0001.jpg |
New file saved as IMG_0001 (1).jpg (or next available). |
TC-06 | Large HEIC (30MB) | Enter Cleanup → View file | Preview < 300 ms p95 after first load; memory does not exceed cap. |
TC-07 | Mixed orientations | Browse 10 photos | All previews respect EXIF orientation (no sideways images). |
TC-08 | External APFS drive as “ToDelete” target | Stage 50 files | Progress UI shown; files appear on external; originals removed from source. |
TC-09 | iCloud Drive folder with placeholders | Stage a placeholder | App prompts/waits for download; on success, move proceeds; on failure, user gets actionable error. |
TC-10 | No write permission to target | Stage file | Clear error; action is rolled back; viewer remains consistent. |
TC-11 | Very long filename / unicode | Stage & Undo | Name preserved; no encoding issues; undo restores exact name. |
TC-12 | Settings: Sort by Date Created desc | Enter Cleanup | Order matches Finder’s equivalent sort; consistent across sessions. |
TC-13 | “Include subfolders” enabled | Enter Cleanup on parent | Traversal includes children; counter reflects combined count. |
TC-14 | ToDelete contains 100 items | Click “Delete staged” | System confirmation → items moved to Trash; counts zero; undo is not available for permanent delete. |
TC-15 | VoiceOver on | Navigate & stage item | All controls have labels; VoiceOver announces actions and counts. |
TC-16 | Keyboard-only | Use ← / → / U keys | Actions work without trackpad; focus ring visible. |
TC-17 | App crash simulated during move | Relaunch app | No orphan temp files; session log replays safely; user notified if any items could not be restored. |
TC-18 | Very large library (50k) | Open folder tree, enter Cleanup | UI remains responsive; lazy loading verified; no freezes >100 ms on main thread. |
TC-19 | Two windows | Stage in Window A, navigate in Window B | State is isolated per window; “ToDelete” reflects global filesystem state. |
TC-20 | Different volume for “ToDelete” | Stage RAW + Sidecar | Both files moved; pairing preserved if enabled; otherwise each handled independently. |
E) Performance Tests
-
PT-01 Preview Latency: Measure time to first frame and next/prev transitions across formats; must meet FR-19 thresholds.
-
PT-02 Memory: Scroll 1,000 photos; verify decoded image cache evicts correctly; memory plateau < 500 MB.
-
PT-03 Bulk Stage: Stage 2,000 photos cross-volume; mean throughput and no UI jank.
F) Accessibility Tests
-
Full keyboard path for: select folder, enter Cleanup, stage, undo, open ToDelete, delete staged.
-
VoiceOver reads: file name, index, action result.
-
Contrast & hit size meet macOS HIG.
G) Edge Cases
-
Files disappearing mid-session (external change): app skips with notice.
-
Read-only media (SD card switch): error & guidance.
-
Path length / unicode normalization differences across volumes.
-
iCloud items not downloaded; network offline.
-
Timezone/EXIF weirdness; files with creation date missing (fallback to modified date).
H) Regression Checklist (per release)
-
Bookmark restore on relaunch.
-
Gesture recognizers coexist with trackpad system gestures.
-
Trash API still reachable; deletion confirmation string localized.
I) Traceability (example)
-
FR-07 ↔ TC-03, TC-04, TC-05, PT-03
-
FR-11 ↔ TC-14
-
FR-15 ↔ TC-15, TC-16
-
FR-19 ↔ PT-01, PT-02
沒有留言:
張貼留言