Let a photographer name the state they liked, and go back to it or look at it

FR-DEV-5 asked for named snapshots of an edit state and FR-DEV-7 for a
comparison against a chosen one, and neither existed. The history stack
is per sitting and forgotten with it, on purpose — the gap that mattered
was an automatically saved mis-drag with no way back, and that was closed
first. What was left was the other half: a state the photographer wants
to keep *because* it is worth keeping, which is a different thing from a
step and is not served by making the steps last longer.

A snapshot is an edit state, and an edit state is exactly what a sidecar
version stores, so it is stored as one: a `[version]` block carrying
`snapshot-of = <uuid>`. The parameters, the masks and their parts, the
repairs and the film all arrive through the blocks that already carry
them, a merge keys on the uuid as it does for any version, and a build
that predates the key reads the block as a named version and keeps it —
the right failure. Only the pointer is new. The one reader that has to
know is `default_version`, which must never answer with a snapshot: a
file whose edit is missing is not a file whose edit is one of its saved
moments. The snapshots of an edit are listed by that pointer, oldest
first, the same on every device.

Writing them back removes what this sitting deleted and puts in what it
holds, and leaves standing whatever it never saw — a snapshot the other
device took since the photograph was opened here is not this device's to
remove by not knowing about it. That is the rule the version merge
already keeps, applied one level down, and it is why the save carries
the deleted ids rather than replacing the list wholesale as the masks
are. Each is re-pointed at the uuid the save settled on, because the
default may have been fused onto its canonical identity since the
snapshot was taken.

Restoring is one history step, so undo takes it back whole, as a paste
is. Taking and deleting are not steps: they change nothing about the
photograph, and an undo that removed a snapshot would be undoing a
decision to remember. Holding the eye beside one renders the snapshot
and hands the edit straight back — the same suspension "Before" uses,
against a point the photographer chose rather than the file. Two
sessions on the same photograph get ids that cannot collide, stamped
with the second and a random word, because the merge folds equal ids
into one.
This commit is contained in:
2026-09-12 01:08:10 +02:00
parent 369eb8fbf0
commit d3b6127db6
11 changed files with 903 additions and 68 deletions
+14
View File
@@ -113,6 +113,20 @@ pub const GESTURES: &[Gesture] = &[
pointer: "Double-click its track, or right-click it",
keys: "R, for the control last moved",
},
Gesture {
title: "See the photograph as a snapshot had it",
section: "Develop",
touch: "Press and hold the eye beside the snapshot",
pointer: "Press and hold the eye beside the snapshot",
keys: "",
},
Gesture {
title: "Keep the photograph as it is now, under a name",
section: "Develop",
touch: "Type a name in the History panel and press Snapshot",
pointer: "Type a name in the History panel and press Snapshot",
keys: "",
},
Gesture {
title: "Show or hide one mask layer",
section: "Develop",