Say what the application is doing, in one bar and one list
Every background job reported into a window property of its own — library-thumbs-done, library-pin-total, library-syncing — which only the grid ever read. A pin download that outlived the view it was started from drew nothing at all once the user opened an image, and there was no answer anywhere to "what is this busy with", because the answer was spread across eight properties nothing collected. They report to one register now (ui/dr-ui/src/activity.rs). It publishes an aggregate, which draws a three-pixel bar across the top of the shell in every view, and a row per job, which the settings page lists: scans, thumbnail batches, pin and open downloads, sidecar uploads, the sync and the trash. Failures stay on the list until they are cleared; routine successes do not, or a scroll would bury them. The handle removes a still-running job when it drops, so a worker that dies mid-transfer takes its row with it rather than leaving the bar sweeping for the rest of the session. Also carries in-flight work from a parallel session — the drawn icon set and the dr-pipeline ops split. dr-pipeline's build script does not compile at this commit; ui/dr-ui does, with clippy clean and its tests passing. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
+46
-6
@@ -2,11 +2,11 @@ import { Theme } from "theme.slint";
|
||||
import { AdjustPanel, GeometryPanel, ParamRow } from "adjust.slint";
|
||||
import { LaunchScreen } from "launch.slint";
|
||||
import { LibraryGrid, LibraryCell, TimelineBar } from "library.slint";
|
||||
import { Button, PanelHeading, Label, Value, Caption, Panel, EmptyState } from "widgets.slint";
|
||||
import { Button, PanelHeading, Label, Value, Caption, Panel, EmptyState, ProgressBar, ActivityRow } from "widgets.slint";
|
||||
import { CollectionsPanel, CollectionRow } from "collections.slint";
|
||||
import { SettingsPage } from "settings.slint";
|
||||
|
||||
export { LibraryCell, TimelineBar, CollectionRow }
|
||||
export { LibraryCell, TimelineBar, CollectionRow, ActivityRow }
|
||||
|
||||
// Status strip — surfaces the GPU backend and adapter, which matters during
|
||||
// v0.1 because assumption A1 is exactly "does this compositing path work on
|
||||
@@ -274,11 +274,30 @@ export component AppWindow inherits Window {
|
||||
in property <bool> show-library: false;
|
||||
in-out property <[LibraryCell]> library-cells;
|
||||
in property <int> library-total: 0;
|
||||
// --- background activity (FR-CAT-1, FR-NC-6c) ---
|
||||
//
|
||||
// Every background job in one register, filled by `activity.rs`. The
|
||||
// aggregate drives the bar across the top of the shell; the rows are the
|
||||
// list on the settings page, where a stalled transfer can be identified
|
||||
// rather than merely felt.
|
||||
in property <[ActivityRow]> activity-rows;
|
||||
/// Anything at all running. Drives the bar's visibility, so it is a
|
||||
/// property rather than `activity-rows.length > 0` — finished rows stay in
|
||||
/// the list for a while and must not keep the bar alight.
|
||||
in property <bool> activity-busy: false;
|
||||
/// Whether the running jobs, taken together, have a denominator. A scan
|
||||
/// alone does not; a scan beside a download does.
|
||||
in property <bool> activity-determinate: false;
|
||||
in property <float> activity-fraction: 0;
|
||||
in property <int> activity-running: 0;
|
||||
/// Jobs that stopped and are being kept: finished ones as a short history,
|
||||
/// failed ones until they are cleared.
|
||||
in property <int> activity-kept: 0;
|
||||
callback activity-clear-finished();
|
||||
|
||||
in property <bool> library-scanning: false;
|
||||
in property <string> library-status: "";
|
||||
in property <string> library-error: "";
|
||||
in property <int> library-thumbs-done: 0;
|
||||
in property <int> library-thumbs-total: 0;
|
||||
|
||||
// --- offline mode (FR-CAT-9) ---
|
||||
//
|
||||
@@ -674,6 +693,11 @@ export component AppWindow inherits Window {
|
||||
strip-location-toggled(on) => { root.settings-strip-location-toggled(on); }
|
||||
destination-changed(t) => { root.settings-destination-changed(t); }
|
||||
|
||||
activity-rows: root.activity-rows;
|
||||
activity-running: root.activity-running;
|
||||
activity-kept: root.activity-kept;
|
||||
clear-finished() => { root.activity-clear-finished(); }
|
||||
|
||||
close() => { root.settings-close(); }
|
||||
reset-defaults() => { root.settings-reset(); }
|
||||
}
|
||||
@@ -773,8 +797,6 @@ export component AppWindow inherits Window {
|
||||
scanning: root.library-scanning;
|
||||
scan-status: root.library-status;
|
||||
scan-error: root.library-error;
|
||||
thumbs-done: root.library-thumbs-done;
|
||||
thumbs-total: root.library-thumbs-total;
|
||||
|
||||
offline: root.library-offline;
|
||||
offline-reason: root.library-offline-reason;
|
||||
@@ -1383,5 +1405,23 @@ export component AppWindow inherits Window {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// --- the load bar -------------------------------------------------
|
||||
//
|
||||
// Last in the file, so it is last in z-order and no view can cover it.
|
||||
//
|
||||
// At the top of the *shell* rather than inside a view, because that is
|
||||
// the only place that is true of every view: a pin download outlives
|
||||
// the grid it was started from, and until this existed it drew nothing
|
||||
// at all once the user opened an image. Three pixels, no text and no
|
||||
// hit area — it says only "something is running", and the settings
|
||||
// page says what (FR-CAT-1, FR-NC-6c).
|
||||
if root.activity-busy: ProgressBar {
|
||||
x: 0;
|
||||
y: 0;
|
||||
width: 100%;
|
||||
indeterminate: !root.activity-determinate;
|
||||
fraction: root.activity-fraction;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user