Wire the launch screen into the app
The app now opens on the login screen when there is nothing else to show
— no local paths and no configured library — and goes straight to the
images otherwise. Making someone click past a login they already
completed is pure friction.
launch.slint imported by app.slint, replacing the window rather
than overlaying it: there is no library to look at
until an account is configured
launch_ui.rs the Slint wiring, kept out of lib.rs so the launch
flow can change without touching the develop window
Login runs on a worker thread and posts results back through a channel,
since Slint's event loop is single-threaded and a 20-minute browser wait
cannot block it. The system browser is opened via xdg-open, never an
embedded webview (FR-NC-1).
Sign-out deletes the local credential even if server-side revocation
fails: a network error must not leave a usable secret on the machine.
Format tick-boxes persist on each toggle, so a selection survives a
crash before the library is opened.
Two things deliberately incomplete rather than faked:
- "Choose folder" lists the account's folders and reports them, but
there is no picker widget yet, so selection still happens via the
connect example.
- "Open library" logs the request. Opening a remote library needs the
scan-and-cache path, which belongs with the catalog work in flight.
Earlier I broke the other in-flight dr-ui work by calling
slint_build::compile twice, which replaces the generated module. The
correct wiring is an import inside app.slint, which is what this does.
30 dr-ui tests passing; both launch paths verified by running the app.
This commit is contained in:
@@ -22,7 +22,7 @@
|
||||
|
||||
use std::fmt::Write as _;
|
||||
|
||||
use crate::descriptor::{OpDescriptor, ParamId};
|
||||
use crate::descriptor::{OpDescriptor, ParamId, Presentation};
|
||||
use crate::framing::{Framing, FRAMING_UNIFORM_FIELDS};
|
||||
|
||||
/// What an operation's parameters affect, for cache invalidation scoping.
|
||||
@@ -100,6 +100,22 @@ pub trait Operation: Send + Sync {
|
||||
fn helpers(&self) -> &'static [Helper] {
|
||||
&[]
|
||||
}
|
||||
|
||||
/// TRACES: FR-DEV-3a | FR-DEV-3b
|
||||
/// How this operation would like its parameters presented.
|
||||
///
|
||||
/// `None` — the default, and the right answer for nearly every operation
|
||||
/// — means one control per parameter, chosen from its
|
||||
/// [`crate::ParamKind`]. Returning a [`Presentation`] says that several
|
||||
/// parameters form a single conceptual control and names the widget that
|
||||
/// draws it.
|
||||
///
|
||||
/// Purely a hint. The parameters remain individually addressable
|
||||
/// scalars, so a UI that does not implement the named widget falls back
|
||||
/// to sliders and stays fully functional.
|
||||
fn presentation(&self) -> Option<Presentation> {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
/// A named WGSL helper function, deduplicated across operations.
|
||||
|
||||
Reference in New Issue
Block a user