Files
qbz/crates/qbz-slint/ui/offline/OfflinePlaceholder.slint
T
vicrodh 74142e9a44 feat(slint): app-wide offline gating (placeholder, nav, playback fast-fail)
New OfflinePlaceholder (mode-aware copy + Open Settings shortcut for induced
mode) mounted at the AppShell routing seam over the 12 Qobuz-only content
views; the matching nav rows (sidebar, header tabs, compact rail) render
disabled while offline instead of hiding (layout stability). Playback gains
the offline playable rule (local always, plex only under induced, qobuz only
when cached and within the subscription grace): explicit plays fast-fail
with an honest toast (distinct copy when the grace expired), manual and
auto advance skip unavailable tracks bounded by 5 consecutive (gapless
target structurally exempt), gapless prefetch skips unplayable successors,
and the network prefetch warmer pauses offline.

cc
2026-06-09 21:26:25 -06:00

67 lines
2.5 KiB
Plaintext

// Offline placeholder — mounted INSTEAD of the Qobuz-only content views
// while the app is offline (ADR-010 conditional mount at the AppShell
// routing seam, broader than Tauri's three gated view families). The body
// copy distinguishes real offline (no connectivity) from induced offline
// (the Settings toggle); induced adds an "Open Settings" shortcut straight
// to Settings > Offline so the user can flip the mode back off.
import { Theme } from "../foundation/semantic-colors.slint";
import { Typography } from "../foundation/typography.slint";
import { QbzIcon } from "../primitives/QbzIcon.slint";
import { SecondaryButton } from "../primitives/SecondaryButton.slint";
import { OfflineState, NavState, SettingsState } from "../state.slint";
export component OfflinePlaceholder inherits Rectangle {
background: Theme.surface-main;
// 2 = induced offline (OfflineState.mode semantics: 0 online / 1 real / 2 induced).
property <bool> induced: OfflineState.mode == 2;
VerticalLayout {
alignment: center;
HorizontalLayout {
alignment: center;
QbzIcon {
source: @image-url("../assets/icons/cloud-off.svg");
width: 56px;
height: 56px;
tint: Theme.text-muted;
}
}
Rectangle { height: 18px; }
Text {
text: @tr("You're offline");
color: Theme.text-primary;
font-size: Typography.heading;
font-weight: Typography.semibold;
horizontal-alignment: center;
}
Rectangle { height: 8px; }
HorizontalLayout {
alignment: center;
Text {
max-width: 420px;
text: root.induced
? @tr("Offline mode is enabled. Disable it in Settings to use Qobuz.")
: @tr("No internet connection. Your local library and downloads keep working.");
color: Theme.text-secondary;
font-size: Typography.body;
horizontal-alignment: center;
wrap: word-wrap;
}
}
if root.induced: Rectangle { height: 20px; }
if root.induced: HorizontalLayout {
alignment: center;
SecondaryButton {
label: @tr("Open Settings");
clicked => {
// Settings > Offline is section index 3 (SettingsView nav).
SettingsState.section = 3;
NavState.request-settings();
}
}
}
}
}