The api() helper only sends POST when a body argument is passed;
Browse Folder, Pause, Stop, Retry Failed (x2), Undo All, and Scan for
Duplicates were all called with no body, so they defaulted to GET
against POST-only server routes and 404'd. Verified live via the actual
browser: Pause/Stop now correctly transition server status
(running -> paused -> idle) instead of silently failing.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
- Stop/pause could block the downscale thread for up to 60s and throw an
unhandled exception on shutdown; queue puts are now stop-aware
- /api/delete_photo(s) now refuse to delete anything outside the
configured photo folder
- organize_alias used a stale startup-time default folder instead of the
folder actually being scanned/tagged
- journal_write is append-only, so retagging a photo left stale duplicate
lines that inflated category counts and search results; reads now dedupe
by path and the journal is compacted once on startup
- batch delete now does one journal rewrite for the whole set instead of
one per file
- add PHOTON.app: a signed, dependency-free Swift menu-bar app that starts
server.py in the background (or attaches to an already-running instance),
opens the console, and exposes Open/Restart/Stop/Show Log/Quit
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
- Search & Edit becomes a multi-view library: Tagged/Untagged/Failed/Videos/Duplicates
- Bulk select (click, shift-click range, select-all-matching) with bulk recategorize,
CSV/JSON export, and original-quality ZIP download (verified byte-identical)
- Video browsing/tagging via ffmpeg frame extraction, native playback with range support
- Duplicate detection via a lightweight perceptual-hash index (no new dependencies)
- Full-resolution photo/video viewer with editable metadata, prev/next navigation
- Date range, file-type, and category quick-filters; saved searches (localStorage)
- Appearance settings: accent color picker, grid density, results-per-page; full dark mode
- Auto-detects its photo folder (CLI arg > env var > last used > parent directory),
so the app can be dropped into any photo collection and just work