Changelog
All notable changes to Phosor are documented on this page.
The format is based on Keep a Changelog, and this project adheres to Semantic Versioning.
[0.9.3] — Culling Workflow Release
A note on versioning. This release follows 0.9.21, which was an internal-beta label. 0.9.3 adopts the cleaner release numbering convention used from here on. This is a versioning convention reset, not a product regression.
Added
- Bottom filmstrip — A resizable strip along the bottom shows thumbnails, filenames, and category color indicators for the photos around the current one. It scrolls horizontally with left/right arrows and tracks the active photo as you navigate, making the culling workflow easier to review at a glance.
- Filmstrip navigation — Click a thumbnail to jump straight to that photo; the strip's height can be adjusted.
Changed
- Unified preview pipeline — Photo previews now flow through a single URI-based pipeline (PreviewProcessor → PreviewManager → PreviewHandler). The legacy Base64/Data URL preview path and its duplicate decode/encode/cache code were removed; FileService now depends on the PreviewManager.
- Cost-aware preview cache — The existing LRU cache remains bounded at 30 entries, but each entry now tracks its regeneration cost. Preview generation is classified as Cheap (<250 ms), Normal (250 ms–1 s), or Expensive (>1 s). Eviction prefers Cheap → Normal → Expensive, so expensive-to-regenerate previews are retained longer and unnecessary regeneration during navigation is reduced. This is a deterministic heuristic, and decoded images are still not cached.
- Frontend modularization — Shared UI pieces (filmstrip, sidebar structure, icons, a generic
mount(), a reusablecreateResizer(), and a shared Lucide icon primitive) were extracted into reusable modules.photo_render.jsremains the authoritative source for the current photo index, and the former dependency cycle between the filmstrip and photo rendering was removed. - Memory architecture — The legacy second image cache is gone. Only encoded previews are cached; decoded bitmaps are not retained in the preview cache. Decode concurrency remains bounded and memory-pressure handling stays in place. A memory audit found no evidence of a Go heap leak.
- RAW format metadata architecture — Supported-extension detection is now consolidated into a single source of truth, and RAW detection and scan filtering use the same format metadata.
- Category mutation ownership — Category mutations have clearer ownership.
- Design-system polish — Centralized CSS design tokens, more consistent borders/radii/scrollbars, calmer category indicators, more subtle panel boundaries, segmented status-bar utility controls, a simplified move-progress UI, and an improved category empty state.
Fixed
- Stale photo navigation index — clicking a filmstrip thumbnail now updates the authoritative current-photo index correctly.
- Category indicator synchronization/flicker.
- Preview thumbnail visual state (visual flicker) stabilized.
- Safer file move semantics — the destination is now synced before the source is deleted.
- Destination path traversal — destination filenames are sanitized with
filepath.Base.
Removed
- Legacy Base64/Data URL image pipeline and image service.
- DebuggerService and demo/GreetService API endpoints.
- Unused WindowService APIs and demo time events.
- Obsolete TIFF preview compatibility code and dead frontend exports.
Engineering
go build ./...andgo vetpass.- Dedicated cost-aware cache tests and
go test -race ./internal/preview/pass. - The memory audit found no evidence of a retained decoded-image leak.
Known Limitations
- The cost-aware cache uses static 250 ms / 1 s thresholds with no adaptive or historical cost tuning yet.
- There is no committed repeatable memory benchmark suite.
- CR3 and RAF remain recognized but unsupported RAW formats.
[0.9.21] — Internal Beta
Version 0.9.21 (Internal Beta)
Overview
Phosor is a desktop application designed to help photographers quickly browse, evaluate, and organize large collections of photos. It provides a fast, keyboard-driven culling experience in a lightweight, single-file application for Windows, macOS, and Linux.
Features
- Folder scanning — Recursively scans selected folders for supported image files.
- Photo preview — Displays photos one at a time with fast loading and smooth navigation.
- Category system — Fully customizable categories with names, colors, keyboard shortcuts, and output folders.
- Single & Burst Mode — Sort one photo per keypress or rapidly assign photos at a configurable interval.
- Undo/Redo — Up to 100 levels of undo for all sorting actions.
- Metadata display — Shows EXIF metadata including camera, lens, exposure, and GPS.
- Image controls — Zoom (10%–200% slider, 20%–400% wheel), pan, and 3×3 composition grid.
- Execute & Move — Batch move flagged photos to category-specific output folders.
- Keyboard shortcuts — Fully keyboard-operable with platform-aware shortcuts.
- Toast notifications — Brief, non-intrusive feedback for user actions.
- Modal dialogs — Confirmation, alert, warning, error, and progress dialogs.
- Sidebar — Resizable, responsive sidebar with Source, Categories, Metadata, and Action sections.
Supported Formats
- Supported: JPEG (
.jpg,.jpeg), PNG (.png), WebP (.webp), TIFF (.tif,.tiff) - RAW: Canon (
.cr2), Nikon (.nef), Sony (.arw), Adobe DNG (.dng), Olympus (.orf), Panasonic (.rw2)
Changes
- RAW format support: Canon CR2, Nikon NEF, Sony ARW, Adobe DNG, Olympus ORF, and Panasonic RW2 files are now supported.
Known Limitations
- Category configuration is not persisted between sessions.
- There is no drag-to-reorder for categories.
- There is no file-type filter during scanning.
- The scan order is determined by the filesystem, not by filename or date.
- There is no fit-to-screen or 100% zoom shortcut.
- The grid is always 3×3 — no other grid configurations are available.
- Pan is not available when the image is at default zoom.
- The move operation is irreversible — there is no "undo move" feature.
- Photos without an assigned category are not moved.
- The move does not create subfolders by date or any other criteria.
- There is no toast history or log.
- Toasts cannot be dismissed manually.
- Modals cannot be dismissed by clicking outside (except for the shortcut guide).
- There is no modal timeout.
- There is no visual undo/redo history list.
- The undo history limit is 100 entries.
- Only sorting actions are recorded in the undo history — navigation is not.
- Very large JPEG files may cause memory spikes.
- The sidebar cannot be manually hidden on large screens.
- There is no collapse/expand toggle button for the sidebar.