Mark a burst in the grid, and let it be folded away
The counterpart to the grouping: where the signatures come from, and how a group reaches a cell. Signatures are computed from the 256px thumbnails dr-thumbs already holds -- vastly more resolution than a 9x8 reduction can use -- so a library that has been browsed, or that has synced somebody else's shards, has already paid for them and no RAW is decoded for this. The consequence is stated rather than hidden: an image with no thumbnail gets no signature and never joins a burst. That is self-correcting, and it is why the pass runs when the thumbnail sweep finishes rather than on a timer. Nothing happens at import and nothing happens at query time. The mark is drawn as a child of the cell's TouchArea, for the same reason the star strip is: a click on it must not also reach `cell-clicked` and throw the user into develop, and children are hit-tested before the element they sit in. It is never hidden on hover the way the stars are -- a collapsed burst stands in for frames that are not on screen, and something has to say so whether or not a pointer is nearby. Folding changes what the grid's *query* returns rather than what its cells draw, because the grid is a window over an ordered query and the frames a fold hides are mostly not loaded. So the predicate joins VISIBLE in every query that lists or counts cells -- the window, the header's count, the run a shift-click resolves, and the ordinal a scrub lands on -- under the discipline VISIBLE's own comment sets out: present in four places of five is worse than absent, because the counts disagree with the cells and neither looks wrong on its own. There is a test for exactly that. `the_window_read_walks_the_ordering_index` now includes the burst clause. It asserts on the query plan while holding its own copy of the query, so left alone it would have gone on reporting green against a query the grid no longer runs. If the clause costs `images_grid_order` and puts the sort back, that fails here rather than becoming jitter someone measures in six months. The pass keeps its own drain timer in a thread-local instead of taking fields on the library controller, so everything the feature needs to run lives in one file and the screen that starts it holds nothing. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -458,6 +458,16 @@ export struct LibraryCell {
|
||||
// 0 unflagged, 1 pick, 2 reject. Independent of the stars: rejecting a
|
||||
// four-star frame is a normal thing to do mid-cull.
|
||||
flag: int,
|
||||
// Frames in the burst this cell belongs to (FR-CULL-5), itself included; 0 where it
|
||||
// belongs to none, which is most of a library. A burst that is collapsed
|
||||
// draws only its representative, so on that cell this is the count of what
|
||||
// is hidden behind it — the reason it is shown at all.
|
||||
burst-count: int,
|
||||
// Whether the group is currently open. Drawn differently rather than
|
||||
// hidden: a burst the user has expanded is the one thing on screen that
|
||||
// needs a way back, and a control that disappears once used is a control
|
||||
// nobody finds twice.
|
||||
burst-expanded: bool,
|
||||
}
|
||||
|
||||
// The photo roll: the grid's loaded window along the foot of the develop view.
|
||||
@@ -1138,6 +1148,11 @@ export component LibraryGrid inherits Rectangle {
|
||||
callback cell-clicked(int);
|
||||
/// A star was clicked on a cell: row, and the rating 0..5.
|
||||
callback cell-rated(int, int);
|
||||
/// The burst mark on a cell was clicked (FR-CULL-5): open the group, or fold it back
|
||||
/// up. Which of the two is decided in Rust, from what the catalog says the
|
||||
/// group is currently doing, so the mark cannot get out of step with the
|
||||
/// query that actually hides the frames.
|
||||
callback burst-toggled(int);
|
||||
/// Whether the grid is currently listing the trash rather than the
|
||||
/// library. Suppresses the per-cell trash target, which would be inert
|
||||
/// there — `plan_trash` skips an already-trashed image — and offering a
|
||||
@@ -2904,6 +2919,75 @@ export component LibraryGrid inherits Rectangle {
|
||||
rate(n) => { root.cell-rated(i, n); }
|
||||
trash() => { root.cell-trashed(i); }
|
||||
}
|
||||
|
||||
// The burst mark (FR-CULL-5): how many frames this
|
||||
// moment holds,
|
||||
// and the way in and out of them.
|
||||
//
|
||||
// A child of `cell-touch` for exactly the reason the
|
||||
// stars above are: a click here must not also reach
|
||||
// `cell-clicked` and throw the user into develop, and
|
||||
// children are hit-tested before the element they sit
|
||||
// in. Unlike the stars it is never hidden — a collapsed
|
||||
// burst is standing in for frames that are not on
|
||||
// screen, and there has to be something visible saying
|
||||
// so whether or not a pointer is anywhere near.
|
||||
//
|
||||
// Bottom left, clear of the centred star strip and of
|
||||
// both top corners, which the flag and the collection
|
||||
// badge already have.
|
||||
if cell.burst-count > 1: Rectangle {
|
||||
x: 6px;
|
||||
y: parent.height - self.height - 26px;
|
||||
width: 30px;
|
||||
height: 18px;
|
||||
|
||||
// The pile behind the top card, drawn only while the
|
||||
// group is folded up. It is the whole of the "there
|
||||
// is more than one of these" cue; once the burst is
|
||||
// open the frames themselves say it.
|
||||
Rectangle {
|
||||
x: 3px;
|
||||
y: -3px;
|
||||
width: parent.width - 3px;
|
||||
height: parent.height;
|
||||
visible: !cell.burst-expanded;
|
||||
background: Theme.surface;
|
||||
border-radius: Theme.radius-sm;
|
||||
border-width: 1px;
|
||||
border-color: Theme.rule;
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background: cell.burst-expanded ? Theme.selected
|
||||
: Theme.surface;
|
||||
border-radius: Theme.radius-sm;
|
||||
border-width: 1px;
|
||||
border-color: cell.burst-expanded ? Theme.selected-ring
|
||||
: Theme.rule;
|
||||
|
||||
Text {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
horizontal-alignment: center;
|
||||
vertical-alignment: center;
|
||||
// No "of": the number is the size of the
|
||||
// group, and a cell this small cannot
|
||||
// afford a word to say so.
|
||||
text: cell.burst-count;
|
||||
color: Theme.ink;
|
||||
font-size: 10px;
|
||||
font-weight: 700;
|
||||
}
|
||||
}
|
||||
|
||||
TouchArea {
|
||||
mouse-cursor: pointer;
|
||||
clicked => { root.burst-toggled(i); }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user