Pin "Export N" to the right of the library's selection bar

It was the last of a dozen buttons in a row that scrolls sideways once
it outgrows the window, which at a desktop width it does. The button
sat past the right edge and nothing says the row scrolls to a mouse,
so batch export of a selection looked like a feature the library did
not have. The rest of the row still scrolls; Export, which is also the
cancel for a running batch, now sits beside it and is always visible.
This commit is contained in:
2026-09-23 19:05:42 -04:00
parent 2be80d4203
commit 949fe40d5b
3 changed files with 58 additions and 46 deletions
File diff suppressed because one or more lines are too long
+3 -3
View File
@@ -372,7 +372,7 @@ A folded burst draws its earliest frame, which is a fact about the clock and not
Distinct from Done, which leaves the mode entirely. Clearing keeps it, so the next selection can start straight away. 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:4454`</sub> <sub>`ui/dr-ui/ui/library.slint:4464`</sub>
### Select everything the grid is showing ### Select everything the grid is showing
@@ -381,7 +381,7 @@ 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. 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:4471`</sub> <sub>`ui/dr-ui/ui/library.slint:4481`</sub>
### Take photographs out of a collection ### Take photographs out of a collection
@@ -390,4 +390,4 @@ A scoped grid of two hundred frames is two hundred taps otherwise, and "all of t
The badge on a cell says a photograph is filed in three collections and never which. This is the sheet that names them, and the only way out of one the grid is not currently scoped to. The badge on a cell says a photograph is filed in three collections and never which. This is the sheet that names them, and the only way out of one the grid is not currently scoped to.
<sub>`ui/dr-ui/ui/library.slint:4594`</sub> <sub>`ui/dr-ui/ui/library.slint:4604`</sub>
+46 -34
View File
@@ -4372,9 +4372,19 @@ export component LibraryGrid inherits Rectangle {
// the count beside the buttons elides, so the row genuinely has a // the count beside the buttons elides, so the row genuinely has a
// smaller footprint than its natural one and a window with room for // smaller footprint than its natural one and a window with room for
// the shrunk row should get it shrunk rather than scrolled. // the shrunk row should get it shrunk rather than scrolled.
//
// The row scrolls sideways once it outgrows the window, which at a
// desktop width it does. Export is pinned beside it rather than inside
// it: last in a scrolling row put it past the right edge, and with a
// mouse nothing says the row scrolls — so batch export looked like a
// feature the library did not have. A layout, not the Rectangle, is
// the parent of the two, or both sit at the origin and overlap.
HorizontalLayout {
padding-right: Theme.gap;
spacing: Theme.gap-sm;
Flickable { Flickable {
width: 100%; horizontal-stretch: 1;
height: 100%;
viewport-height: self.height; viewport-height: self.height;
viewport-width: max(self.width, selection-row.min-width); viewport-width: max(self.width, selection-row.min-width);
@@ -4605,38 +4615,40 @@ export component LibraryGrid inherits Rectangle {
clicked => { root.open-membership(); } clicked => { root.open-membership(); }
} }
// TRACES: FR-EXP-7 | NFR-ARCH-3 }
// Export the selection, and stop the batch that is running. }
//
// One button doing both, because they are the same thought a // TRACES: FR-EXP-7 | NFR-ARCH-3
// moment apart and a separate cancel would have to appear from // Export the selection, and stop the batch that is running.
// somewhere — shifting the row under the pointer at the exact //
// moment the user is reaching for it. // One button doing both, because they are the same thought a
// // moment apart and a separate cancel would have to appear from
// Last on the bar because it is the last thing done to a // somewhere — shifting the row under the pointer at the exact
// selection, and because it is the one control here that outlives // moment the user is reaching for it.
// the selection: the bar itself stays up for a running batch (see //
// the note on the bar) so this is always reachable while there is // Pinned at the right end of the bar, outside the scrolling row
// something to cancel. // (see above), because it is the last thing done to a selection
// // and the one control here that outlives the selection: the bar
// The count is in the label rather than behind a confirmation, // stays up for a running batch, so this is always reachable while
// exactly as the paste above puts it there: "Export 40" read // there is something to cancel.
// before the click is worth more than a dialogue asking the same //
// question after it. // The count is in the label rather than behind a confirmation,
if !root.ranging: Button { // exactly as the paste above puts it there: "Export 40" read
text: root.exporting // before the click is worth more than a dialogue asking the same
? "Cancel export" // question after it.
: (root.export-to-server if !root.ranging: Button {
? "Export " + root.selected-count + " to the library" text: root.exporting
: "Export " + root.selected-count); ? "Cancel export"
active: root.exporting; : (root.export-to-server
y: (parent.height - self.height) / 2; ? "Export " + root.selected-count + " to the library"
clicked => { : "Export " + root.selected-count);
if (root.exporting) { active: root.exporting;
root.cancel-export(); y: (parent.height - self.height) / 2;
} else { clicked => {
root.export-selection(); if (root.exporting) {
} root.cancel-export();
} else {
root.export-selection();
} }
} }
} }