2025/09/19

Mac App - Photo Clean up


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-07TC-03, TC-04, TC-05, PT-03

  • FR-11TC-14

  • FR-15TC-15, TC-16

  • FR-19PT-01, PT-02



沒有留言:

張貼留言