Let the photographer say which frame the burst stands for

`choose_representative` has been in the catalog since the grouping landed,
with tests behind it and nothing calling it. So the frame a folded burst drew
was always the earliest one, and the only way to disagree was to open the
group and leave it open — which is to say there was no way to disagree at all,
because a burst that stays open is a burst that was never collapsed.

The earliest frame is the right default and it is deliberately not a
judgement: nothing here scores a photograph, and FR-CULL-5 names the failure
that rule avoids. But the whole point of a burst is that one of the twelve is
better than the other eleven, and the person who knows which is the one
looking at them.

So a ring on each frame of an open group, ticked on the one the group folds
to. It is drawn only while the burst is open, because that is the one moment
the alternatives are on screen to be compared — offering the choice on a
folded burst would be asking about frames it is hiding. Bottom right, opposite
the count in the other corner, clear of the flag and the collection badge and,
deliberately, of the trash target: a slip between the ring and the fifth star
sets a rating, which is the harmless direction for an ambiguous press.

The mark stays live on the frame that already wears it. A disabled TouchArea
would let the press fall through to the cell behind it, so tapping the one
ring that is ticked would have opened the photograph — and pressing it is a
thing the user may mean anyway: it records the choice the default was making
silently, which then survives a regroup that finds an earlier frame.

Choosing repaints the badges instead of reloading the window, which is what
separates it from folding a group up. Folding changes what the grid's query
returns; this changes only which cell wears the tick, and the tick has to
leave the frame that was carrying it, so the whole window is refilled in the
one statement `sync_badges` already runs.

The gesture is documented where FR-UI-4 requires it to be documented: in a
tagged comment beside the control, which is the only copy. The gesture book,
the gesture document and the requirements matrix are regenerated from the tree
alongside it.
This commit is contained in:
2026-09-06 19:01:49 +02:00
parent 5fa4c0772b
commit 1c5c55b4c9
7 changed files with 276 additions and 56 deletions
+22 -13
View File
@@ -5,7 +5,7 @@
Every entry here is extracted from the comment beside the code that implements it, so this file cannot describe a gesture the application does not have. Add one by writing a `GESTURE:` block next to the implementation; there is nowhere else to write it.
16 gestures, in 2 places.
17 gestures, in 2 places.
## People
@@ -54,7 +54,7 @@ The right match confidence is a property of your library, not of the model. "Wha
Touch has no ctrl, so without a mode there is no way to select a second photograph — the first tap would open it. The hold is the fast way in and the button is the one that can be found.
<sub>`ui/dr-ui/ui/library.slint:1292`</sub>
<sub>`ui/dr-ui/ui/library.slint:1302`</sub>
### Add or remove one photograph
@@ -63,7 +63,7 @@ Touch has no ctrl, so without a mode there is no way to select a second photogra
While selecting, a tap never opens. That is the whole point of the mode: one meaning per gesture at a time. Press Done to get tap-to-open back.
<sub>`ui/dr-ui/ui/library.slint:1301`</sub>
<sub>`ui/dr-ui/ui/library.slint:1311`</sub>
### Leave selecting
@@ -71,7 +71,7 @@ While selecting, a tap never opens. That is the whole point of the mode: one mea
- **Pointer** — Press Done in the header
- **Keyboard** — Escape
<sub>`ui/dr-ui/ui/library.slint:1309`</sub>
<sub>`ui/dr-ui/ui/library.slint:1319`</sub>
### Pick a photograph up to drag it
@@ -80,7 +80,7 @@ While selecting, a tap never opens. That is the whole point of the mode: one mea
A finger on a photograph might be starting a scroll, and for the first half-second the grid assumes it is. Holding says otherwise, and the ring is the grid saying it heard — from there the drag cannot be lost to a scroll. A mouse never waits: the cursor is precise enough that a sideways drag is unambiguous from the first pixel.
<sub>`ui/dr-ui/ui/library.slint:1339`</sub>
<sub>`ui/dr-ui/ui/library.slint:1349`</sub>
### Select a range
@@ -89,7 +89,7 @@ A finger on a photograph might be starting a scroll, and for the first half-seco
This replaced a double tap, which had no visible state and could take forty photographs by accident. The run is resolved by the catalog rather than by what is on screen, so the grid can scroll between the two taps — the ranges that hurt on a tablet are longer than a screenful, which is exactly where a finger sweep runs out.
<sub>`ui/dr-ui/ui/library.slint:1404`</sub>
<sub>`ui/dr-ui/ui/library.slint:1414`</sub>
### Find photographs with two people in them
@@ -98,7 +98,7 @@ This replaced a double tap, which had no visible state and could take forty phot
"Any of them" is a union and "all of them" is an intersection. The tray is where both terms and the choice between them live, because a filter belongs on the filter bar.
<sub>`ui/dr-ui/ui/library.slint:2086`</sub>
<sub>`ui/dr-ui/ui/library.slint:2096`</sub>
### Resize the thumbnails
@@ -107,7 +107,7 @@ This replaced a double tap, which had no visible state and could take forty phot
There is no wheel on a tablet, so without the pinch the cell size could only be changed by a control a finger cannot reach.
<sub>`ui/dr-ui/ui/library.slint:2739`</sub>
<sub>`ui/dr-ui/ui/library.slint:2749`</sub>
### File photographs in a collection
@@ -116,7 +116,7 @@ There is no wheel on a tablet, so without the pinch the cell size could only be
The selection is what the drag carries, which is why selecting several is worth the mode: forty photographs file in one gesture.
<sub>`ui/dr-ui/ui/library.slint:2936`</sub>
<sub>`ui/dr-ui/ui/library.slint:2946`</sub>
### Open a photograph
@@ -125,7 +125,7 @@ The selection is what the drag carries, which is why selecting several is worth
A tap opens; a tap that *moved* does not. Travel is what separates a deliberate tap from a hand brushing past, and it is the only thing that does: the two are the same length. An earlier version required the finger to dwell 120 ms instead, and that rejected ordinary taps — a real tap is often quicker than a brush.
<sub>`ui/dr-ui/ui/library.slint:3204`</sub>
<sub>`ui/dr-ui/ui/library.slint:3214`</sub>
### Rate a photograph without opening it
@@ -135,7 +135,16 @@ A tap opens; a tap that *moved* does not. Travel is what separates a deliberate
A star has to take the press without it also reaching the cell, or every rating throws the user into develop.
<sub>`ui/dr-ui/ui/library.slint:3324`</sub>
<sub>`ui/dr-ui/ui/library.slint:3334`</sub>
### Choose the frame a folded burst shows
- **Touch** — Open the burst, then tap the ring on the frame you want
- **Pointer** — Open the burst, then click the ring on the frame you want
A folded burst draws its earliest frame, which is a fact about the clock and not a judgement about the photograph — nothing in this application ranks a frame (FR-CULL-5). But the point of a burst is that one of the twelve is better than the other eleven, and the photographer is the only one who knows which. So the choice is offered on the frames themselves, while they are open and side by side, which is the one moment the alternatives are on screen to be compared.
<sub>`ui/dr-ui/ui/library.slint:3465`</sub>
### Drop the selection but keep selecting
@@ -144,7 +153,7 @@ A star has to take the press without it also reaching the cell, or every rating
Distinct from Done, which leaves the mode entirely. Clearing keeps it, so the next selection can start straight away.
<sub>`ui/dr-ui/ui/library.slint:4032`</sub>
<sub>`ui/dr-ui/ui/library.slint:4126`</sub>
### Select everything the grid is showing
@@ -153,4 +162,4 @@ Distinct from Done, which leaves the mode entirely. Clearing keeps it, so the ne
A scoped grid of two hundred frames is two hundred taps otherwise, and "all of them, except those three" is a far more common shape than the taps it took to say it.
<sub>`ui/dr-ui/ui/library.slint:4049`</sub>
<sub>`ui/dr-ui/ui/library.slint:4143`</sub>