Review fixes. folder_records_follow now drops records left at the
destination even when the moved folder carries none, so an unlabelled
folder renamed onto an old path no longer inherits that path's label.
folder.label {label: none} works once the folder's photos are gone (a
label can no longer get stuck); setting a label still needs photos.
Adds tests for both, undo/redo of a labelled move, and labels replayed
from the journal without a snapshot.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Right-click a folder or disk row in the sidebar's Folders section ▸
Set Color Label ▸ a colour or None (folder.label). A labelled row shows
the label's dot before its count, and its spoken name includes the label.
The colour items are shared with the photo menu (grid::label_items):
each is now a control-channel widget (photoLabel:/folderLabel:<colour>),
and choosing None closes the photo menu like choosing a colour does.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
folder.label {path, label} gives a library folder a colour label (or
takes it off) as one undo step; only folders the library holds photos in
are accepted. library.folders reports each row's label. folder.rename and
folder.move commit the folder records with the photos' relinks, so the
labels of the folder and the folders inside it go along and undo/redo
carry them back and forth.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Library folders can now carry what the library knows about them beyond
their photos: FolderRecord (for now a colour label), kept in
Catalog.folder_records under the folder's identity (folder_key) and
changed through Op::SetFolderRecord, one undo step. An empty record is
never kept; a path that names no folder is refused.
folder_records_follow builds the ops that carry a folder's records and
those of its subfolders to its new place on rename or move (dropping
stale records left at the destination), so they can be committed with
the photos' relinks. FolderNode reports the label.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
preset, background, resize, subfolder, conflict, tiffCompression and
dngCompression were in the export tool's schema (and so passed the new
argument check) but were dropped before reaching app.export.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
std::process::exit skipped eframe's on_exit (ui.json, close_library) and the
may_close check, so changes still in memory could be lost on Cmd+Q.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>