Merge master into tablet-selection
Two real conflicts, both from work that landed either side of the same lines rather than against them. `lib.rs`: the settings controller was hoisted above the People screen's wiring, and Android's thumbnail-tier eviction registered itself at the same point. Independent, so both stay. `library.rs`: manual collection ordering and burst folding each added a clause to the same two queries. The scoped range read now carries both — the folding matters there for one step further on than it does in the grid, because a collapsed burst is one cell, so an ordinal counted over a list still holding every frame names a photograph several places away from the one the user pointed at. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -468,6 +468,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.
|
||||
@@ -860,6 +870,9 @@ component HeaderActions inherits HorizontalLayout {
|
||||
callback export-selection();
|
||||
callback cancel-export();
|
||||
callback paste-settings-to-selection();
|
||||
/// TRACES: FR-DEV-6
|
||||
/// Open the named-preset sheet over the selection.
|
||||
callback open-presets();
|
||||
callback remove-from-collection();
|
||||
/// Open the sheet that files the selection in a collection.
|
||||
callback add-to-collection();
|
||||
@@ -941,6 +954,20 @@ component HeaderActions inherits HorizontalLayout {
|
||||
clicked => { root.paste-settings-to-selection(); }
|
||||
}
|
||||
|
||||
// TRACES: FR-DEV-6
|
||||
// The saved settings, beside the copied ones.
|
||||
//
|
||||
// Gated on the selection alone, unlike the paste beside it: that button
|
||||
// needs a clipboard *this session*, where the preset list is whatever the
|
||||
// photographer saved last month. Requiring an armed clipboard here would
|
||||
// hide the saved presets behind an unrelated action — which is the shape
|
||||
// of bug that makes a feature only its author knows about (FR-UI-4).
|
||||
if root.selected-count > 0: Button {
|
||||
text: "Presets";
|
||||
y: root.centred ? (root.row-height - self.height) / 2 : 0;
|
||||
clicked => { root.open-presets(); }
|
||||
}
|
||||
|
||||
// TRACES: FR-EXP-7 | NFR-ARCH-3
|
||||
// Export the selection, and stop the batch that is running.
|
||||
//
|
||||
@@ -1148,6 +1175,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
|
||||
@@ -1433,6 +1465,8 @@ export component LibraryGrid inherits Rectangle {
|
||||
in property <bool> settings-armed: false;
|
||||
in property <string> settings-summary;
|
||||
callback paste-settings-to-selection();
|
||||
/// TRACES: FR-DEV-6
|
||||
callback open-presets();
|
||||
|
||||
// TRACES: FR-EXP-7
|
||||
// Exporting the selection. The grid owns neither the settings that decide
|
||||
@@ -1819,6 +1853,7 @@ export component LibraryGrid inherits Rectangle {
|
||||
export-selection => { root.export-selection(); }
|
||||
cancel-export => { root.cancel-export(); }
|
||||
paste-settings-to-selection => { root.paste-settings-to-selection(); }
|
||||
open-presets => { root.open-presets(); }
|
||||
remove-from-collection => { root.remove-from-collection(); }
|
||||
select-mode: root.select-mode;
|
||||
toggle-select-mode => { root.toggle-select-mode(); }
|
||||
@@ -1904,6 +1939,7 @@ export component LibraryGrid inherits Rectangle {
|
||||
export-selection => { root.export-selection(); }
|
||||
cancel-export => { root.cancel-export(); }
|
||||
paste-settings-to-selection => { root.paste-settings-to-selection(); }
|
||||
open-presets => { root.open-presets(); }
|
||||
remove-from-collection => { root.remove-from-collection(); }
|
||||
select-mode: root.select-mode;
|
||||
toggle-select-mode => { root.toggle-select-mode(); }
|
||||
@@ -3226,6 +3262,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); }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// Where the run would land. A bar in the gutter beside the
|
||||
|
||||
Reference in New Issue
Block a user