feat(slint): offline status UI plumbing, login affordances, recovery banner

New OfflineState global mirrored from the shared engine by a status
forwarder task. Login screen: start-offline link gated on a previous
session existing, connectivity-down callout pointing at it (with captive
portal hint), init-error callout fed from the restore flow. Shell: D2
recovery banner (connection back during an unauthenticated offline
session) with one-click token sign-in that lifts the offline gate for the
login attempt and re-enters the full online shell.

Double-init hardening for the recovery path re-running enter_shell over a
live shell: synchronous guard on the Linux tray init (its OnceLock was set
asynchronously, leaving a duplicate-tray window) and a start guard on the
playback poll loop (a second loop would double-advance the queue).

cc
This commit is contained in:
vicrodh committed 2026-06-09 20:31:07 -06:00
1 parent 904b5f7b40
commit 38e0b4be27
8 files changed
+275 -6

No files matched your search

+28
View File
@@ -3093,3 +3093,31 @@ export global SearchActions {
// Request the next page for the given tab.
callback load-more(int);
}
// ============================ Offline MODE ================================
// App-wide offline MODE status (the app operating without Qobuz — NOT the
// offline CACHE/downloads). Mirrors `qbz_app::offline_mode::OfflineStatus`;
// pushed by crate::offline_mode::start_ui_forwarder on every engine
// broadcast. Read by the login screen (offline-boot affordances) and the
// shell (D2 recovery banner); the gating slice adds more consumers.
export global OfflineState {
// Any offline flavor active (mode != online).
in property <bool> offline: false;
// 0 = online, 1 = real offline, 2 = induced offline.
in property <int> mode: 0;
// Raw connectivity, independent of the mode: 0 unknown, 1 up, 2 down.
in property <int> connectivity: 0;
// A probe was answered by a redirect — typical captive portal.
in property <bool> captive-portal: false;
// D2: unauthenticated offline session while connectivity is back up —
// the shell shows the one-click "Sign in" banner.
in property <bool> show-recovery-banner: false;
// A previous login exists (last_user_id on disk). Gates the login
// screen's "Start offline" affordance: offline mode needs a prior
// user's data, never the empty user-0 profile.
in property <bool> has-previous-session: false;
// Startup session-restore failure detail, shown on the login screen
// ("" = none). Set by the restore task's error arm; cleared on any
// successful shell entry.
in property <string> login-error: "";
}