Integrate the Kiosk profile hardening round: 12 dedicated Kiosk views plus 22 shared opt-in hosts, shared navigation history with Back/Forward, Albums as the default library tab, native paged Local Library (artists/tracks), lightweight MyQBZ grid and detail, Ephemeral lifecycle, bounded lists and artwork sized to the physical frame, static skeletons, 64px transport bar, Settings touch reflow and a persistent Immersive exit. Desktop keeps its prior behavior: every shared component defaults to the desktop path and only opts into Kiosk behavior through explicit properties (origin-relative ScrollMemory, viewport-bounded artwork requests). Regression coverage: kiosk navigation and artwork Node tests added to the runtime gate, scroll-origin fixtures for fixed and grouped rows, i18n strings for all eight locales. Verified by 750 release tests, six QML audits, Kiosk smokes at 800x480 and 1280x800 and a Desktop A/B with seven pixel-identical captures. cc
175 lines
8.3 KiB
QML
175 lines
8.3 KiB
QML
// Settings > Offline — the QML port of crates/qbz-ui/ui/settings/
|
|
// OfflineSettings.slint.
|
|
//
|
|
// OFFLINE MODE (the app running without Qobuz) is the shared engine: the
|
|
// status line reads the LIVE QbzSession properties the engine forwarder
|
|
// publishes (tri-state online / no connection / induced + captive portal),
|
|
// and the toggle rides settingsBool("offline-mode-enabled") into
|
|
// `OfflineModeEngine::set_induced` (which also takes the #279 stream-first
|
|
// snapshot).
|
|
//
|
|
// "Check now" IS shipped (`offline-recheck`); so is the live tri-state status
|
|
// line (QbzSession.offlineMode / captivePortal) and the lyrics-cache row.
|
|
//
|
|
// Still missing: the whole OFFLINE CACHE group (Open manager / Open folder /
|
|
// Clear all). What blocks it is the MANAGER VIEW, which has no Qt counterpart
|
|
// yet — not the engine: `offline_cache_qt.rs` already runs the downloads from
|
|
// the album page and the track row.
|
|
|
|
import QtQuick
|
|
import com.blitzfc.qbz
|
|
import "../controls"
|
|
import "../theme"
|
|
|
|
Column {
|
|
property bool kioskHost: false
|
|
|
|
id: root
|
|
|
|
property var doc: ({})
|
|
readonly property var off: doc.offline || ({})
|
|
/// The view-level SettingsConfirmHost (SettingsView.qml). Null in previews
|
|
/// — the Clear-all row guards, so a preview degrades to the unconfirmed
|
|
/// call rather than swallowing the click.
|
|
property var confirmHost: null
|
|
|
|
QbzTheme { id: theme }
|
|
|
|
spacing: 4
|
|
|
|
// ========================== OFFLINE MODE =============================
|
|
GroupHeader { kioskHost: root.kioskHost; text: QbzSession.tr("OFFLINE MODE", QbzSession.trRev) }
|
|
SettingRow { kioskHost: root.kioskHost;
|
|
label: QbzSession.tr("Status", QbzSession.trRev)
|
|
description: QbzSession.captivePortal
|
|
? QbzSession.tr("Captive portal detected — sign in to the network to get online.", QbzSession.trRev)
|
|
: ""
|
|
Text {
|
|
// Tri-state: online green / real-offline amber / induced accent.
|
|
text: QbzSession.offlineMode === 2 ? QbzSession.tr("Offline mode enabled", QbzSession.trRev)
|
|
: QbzSession.offlineMode === 1 ? QbzSession.tr("No connection", QbzSession.trRev)
|
|
: QbzSession.tr("Online", QbzSession.trRev)
|
|
color: QbzSession.offlineMode === 2 ? theme.accent
|
|
: QbzSession.offlineMode === 1 ? theme.warning : theme.success
|
|
font.pixelSize: root.kioskHost ? (theme.fontBody) * 1.2 : (theme.fontBody)
|
|
font.weight: theme.weightMedium
|
|
}
|
|
}
|
|
SettingRow { kioskHost: root.kioskHost;
|
|
label: QbzSession.tr("Enable Offline Mode", QbzSession.trRev)
|
|
description: QbzSession.tr("Manually switch to offline mode even with internet.", QbzSession.trRev)
|
|
QbzToggle { kioskHost: root.kioskHost;
|
|
checked: root.off.modeEnabled === true
|
|
onToggled: function (v) { QbzBridge.settingsBool("offline-mode-enabled", v) }
|
|
}
|
|
}
|
|
// Restored from the Tauri offline settings. Immediate and accumulated
|
|
// modes are mutually exclusive in SQLite, so one settings republish keeps
|
|
// both toggles in lock-step even if the write originates elsewhere.
|
|
SettingRow { kioskHost: root.kioskHost;
|
|
visible: root.off.modeEnabled === true
|
|
label: QbzSession.tr("Immediate scrobbling", QbzSession.trRev)
|
|
description: QbzSession.tr("Send scrobbles immediately while manual offline mode is enabled.", QbzSession.trRev)
|
|
QbzToggle { kioskHost: root.kioskHost;
|
|
checked: root.off.allowImmediateScrobbling === true
|
|
onToggled: function (v) {
|
|
QbzBridge.settingsBool("offline-scrobble-immediate", v)
|
|
}
|
|
}
|
|
}
|
|
SettingRow { kioskHost: root.kioskHost;
|
|
visible: root.off.modeEnabled === true
|
|
label: QbzSession.tr("Accumulated scrobbling", QbzSession.trRev)
|
|
description: QbzSession.tr("Queue scrobbles while the network is unavailable and send them when it returns. Last.fm accepts scrobbles up to 2 weeks old.", QbzSession.trRev)
|
|
QbzToggle { kioskHost: root.kioskHost;
|
|
checked: root.off.allowAccumulatedScrobbling === true
|
|
onToggled: function (v) {
|
|
QbzBridge.settingsBool("offline-scrobble-accumulated", v)
|
|
}
|
|
}
|
|
}
|
|
// Ask the connectivity actor for an immediate probe rather than waiting
|
|
// for its next scheduled one. Disabled under MANUAL offline (mode 2),
|
|
// where the answer is a user decision and not a network fact.
|
|
SettingRow { kioskHost: root.kioskHost;
|
|
label: QbzSession.tr("Check connection", QbzSession.trRev)
|
|
description: QbzSession.tr("Test the connection now instead of waiting for the next automatic check.", QbzSession.trRev)
|
|
SettingsButton { kioskHost: root.kioskHost;
|
|
text: QbzSession.tr("Check now", QbzSession.trRev)
|
|
enabled: QbzSession.offlineMode !== 2
|
|
onClicked: QbzBridge.settingsString("offline-recheck", "")
|
|
}
|
|
}
|
|
|
|
SettingsSpacer { }
|
|
SettingsDivider { }
|
|
SettingsSpacer { }
|
|
|
|
// ========================== OFFLINE CACHE ============================
|
|
// The downloads half: the manager view plus the two whole-cache actions.
|
|
// All three ride QbzOffline, the same bridge the manager view uses —
|
|
// "Open folder" and "Clear all" are the manager's own stats-bar buttons,
|
|
// offered here too exactly as the reference offers them
|
|
// (OfflineSettings.slint:135-167).
|
|
GroupHeader { kioskHost: root.kioskHost; text: QbzSession.tr("OFFLINE CACHE", QbzSession.trRev) }
|
|
SettingRow { kioskHost: root.kioskHost;
|
|
label: QbzSession.tr("Manage offline cache", QbzSession.trRev)
|
|
description: QbzSession.tr("Browse and manage your downloaded tracks and albums.", QbzSession.trRev)
|
|
SettingsButton { kioskHost: root.kioskHost;
|
|
text: QbzSession.tr("Open manager", QbzSession.trRev)
|
|
onClicked: QbzOffline.openManager()
|
|
}
|
|
}
|
|
SettingRow { kioskHost: root.kioskHost;
|
|
label: QbzSession.tr("Cache folder", QbzSession.trRev)
|
|
description: QbzSession.tr("Open the folder where offline tracks are stored on disk.", QbzSession.trRev)
|
|
SettingsButton { kioskHost: root.kioskHost;
|
|
text: QbzSession.tr("Open folder", QbzSession.trRev)
|
|
onClicked: QbzOffline.openFolder()
|
|
}
|
|
}
|
|
SettingRow { kioskHost: root.kioskHost;
|
|
label: QbzSession.tr("Clear cache", QbzSession.trRev)
|
|
description: QbzSession.tr("Frees up cached data. Your downloaded albums are kept — remove those from the offline manager above.", QbzSession.trRev)
|
|
SettingsButton { kioskHost: root.kioskHost;
|
|
danger: true
|
|
text: QbzSession.tr("Clear all", QbzSession.trRev)
|
|
// ONE prompt before the purge. The reference fires straight from
|
|
// the button; this port confirms every destructive settings row,
|
|
// and undoing this one means re-downloading the whole cache.
|
|
onClicked: {
|
|
if (!root.confirmHost) {
|
|
QbzOffline.clearAll()
|
|
return
|
|
}
|
|
root.confirmHost.ask(
|
|
QbzSession.tr("Clear cache", QbzSession.trRev),
|
|
QbzSession.tr("Frees up cached data. Your downloaded albums are kept — remove those from the offline manager above.", QbzSession.trRev),
|
|
QbzSession.tr("Clear all", QbzSession.trRev),
|
|
function () { QbzOffline.clearAll() })
|
|
}
|
|
}
|
|
}
|
|
|
|
SettingsSpacer { }
|
|
SettingsDivider { }
|
|
SettingsSpacer { }
|
|
|
|
// ============================= LYRICS ================================
|
|
GroupHeader { kioskHost: root.kioskHost; text: QbzSession.tr("LYRICS", QbzSession.trRev) }
|
|
SettingRow { kioskHost: root.kioskHost;
|
|
label: QbzSession.tr("Clear lyrics cache", QbzSession.trRev)
|
|
// "{} entries using {}" — the real per-user lyrics.db stats.
|
|
description: root.off.lyricsLoaded === true
|
|
? QbzSession.tr("{} entries using {}", QbzSession.trRev)
|
|
.replace("{}", root.off.lyricsEntries)
|
|
.replace("{}", root.off.lyricsSize)
|
|
: ""
|
|
SettingsButton { kioskHost: root.kioskHost;
|
|
danger: true
|
|
text: QbzSession.tr("Clear", QbzSession.trRev)
|
|
onClicked: QbzBridge.settingsString("lyrics-cache-clear", "")
|
|
}
|
|
}
|
|
}
|