3 Commits
Author SHA1 Message Date
dtourolleandClaude Opus 5 70435b712e Walk the grid with the arrow keys, and open with Return
Build and test / Desktop (Linux) (push) Successful in 17m36s
Build and test / Layer separation (push) Successful in 34s
Traceability / Requirement traces (push) Failing after 25s
🐳 Android image / Build and push (push) Successful in 3s
Build and test / android-image (push) Successful in 3s
Build and test / Android (aarch64) (push) Failing after 9m17s
A cull is thousands of decisions. The grid already bound 0-5, P, X and U so
the judgement itself needs no mouse, and then made the photographer reach
for one to move to the next frame — which is most of the gesture, most of
the time. Arrows now move a cursor, shift+arrow extends the selection,
Home/End and PageUp/PageDown cover ground, and Return opens what the cursor
is on.

The cursor is a library ordinal, not a row of the loaded window. The window
is a few screenfuls around wherever the user is looking, so a cursor held as
a row would stop at its edge or keep counting into cells belonging to other
photographs; walking out of the window reloads it around the new position,
exactly as scrolling does. This is the argument the selection already made
by keying on ids rather than rows.

The anchor had that fault for real: it was a window row, so a shift-click
after a scroll extended from whatever image had since drifted into it. It is
an ordinal now, and apply_press takes the window's offset to map between the
two. A range longer than the loaded window truncates to what is loaded,
since selection is by id and an image the catalog has not been asked for has
none.

The pointer and the keyboard share select_row so the two cannot drift apart.
The one deliberate difference: a plain arrow collapses the selection onto
the cursor, where a plain click on an already-selected cell leaves it alone
— that exception exists so a multi-image drag can start from one of its
members, and there is no drag behind a keystroke.

The grid scrolls to the cursor only when the cursor leaves the viewport, and
then by as little as will do it. Reusing the scrub's seek() would put the
cursor's row at the top on every press, which makes a row unreadable as you
walk along it.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-16 16:25:13 +02:00
dtourolleandClaude Opus 5 9b2ee0d0eb Show the colour mixer as three runs of twelve, each row a colour
Build and test / Desktop (Linux) (push) Successful in 17m20s
Build and test / Layer separation (push) Successful in 33s
🐳 Android image / Build and push (push) Successful in 2s
Build and test / android-image (push) Successful in 2s
Traceability / Requirement traces (push) Failing after 26s
Build and test / Android (aarch64) (push) Failing after 8m59s
The mixer was thirty-six sliders reading "Hue / Sat / Lum" twelve times
over with nothing saying which band any row belonged to. The identity was
there all along — the descriptor declares param.mixer.orange.sat and BANDS
carries orange at 30° — and was discarded on the way out: labels.rs had no
mixer entries, so every key fell through to a derived label that yields the
bare channel name.

A parameter can now say which aspect it adjusts and which subject it
adjusts it on, with the subject's hue where the subject is a colour
(descriptor::Facet). That is data about what the operation does, not a
layout: the mixer genuinely weights pixels around 30°. What to draw from
30°, and in what order to stack the runs, stay in dr-ui (ARCH §4.3a) —
develop.rs brings rows sharing an aspect together and marks the first of
each, and adjust.slint names the run once and draws a swatch, a track and a
readout on one line.

Grouped by channel rather than by band because an edit is almost never
"everything about orange"; it is the saturation of the greens, made by
comparing one channel across neighbouring bands. Twelve band sections put
those twelve rows in twelve different places.

The swatch is the label, which is what makes twelve rows fit where four
did. The band name is not lost: it is the row's accessible label, so the
control is not colour-only, and labels.rs is where the mapping is written
down — including chartreuse as "Yellow-Green" and spring as "Blue-Green",
since nobody hunting foliage scans a list for "Spring".

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-16 16:14:13 +02:00
dtourolleandClaude Opus 5 02b66ddfcf Document trash, collections, thumbnails, and the UI direction
Specs for the work that follows: soft delete via a MOVE that preserves the
remote id, the collection tree and smart collections, the thumbnail store,
and the derived-state folder.

Adds two design documents. ui-refinement.md names the structural gaps
between the v0.1 UI and something that feels like a photo editor.
view-composition.md proposes a view controller for the display layer,
against the 500-line run() that has become one by accretion.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-09 20:36:23 +02:00