diff --git a/crates/qbz-slint/src/artist.rs b/crates/qbz-slint/src/artist.rs index 094ca8345..1f382ec62 100644 --- a/crates/qbz-slint/src/artist.rs +++ b/crates/qbz-slint/src/artist.rs @@ -555,11 +555,14 @@ pub struct MbOrigin { pub location_clickable: bool, } -/// Reset the network sidebar's MB-driven state. Called when the artist -/// changes so a stale Origin/Relationships/Discovery never bleeds -/// across artists. +/// Reset the network sidebar's MB-driven state and force-open the +/// panel. Called when the artist changes so a stale Origin / +/// Relationships / Discovery never bleeds across artists, and so the +/// sidebar always starts open on every artist visit (per user policy +/// — close is per-session, never persisted). pub fn reset_network_sidebar(window: &AppWindow) { let state = window.global::(); + state.set_open(true); state.set_mb_available(true); state.set_mb_mbid("".into()); state.set_origin_loading(false); diff --git a/crates/qbz-slint/src/main.rs b/crates/qbz-slint/src/main.rs index c8598b3c2..f24f56775 100644 --- a/crates/qbz-slint/src/main.rs +++ b/crates/qbz-slint/src/main.rs @@ -23,7 +23,6 @@ mod commands; mod discovery_dismiss; mod home; mod nav; -mod network_sidebar_prefs; mod playback; mod queue; mod recently; @@ -1167,24 +1166,14 @@ fn main() -> Result<(), Box> { }); } - // Artist network sidebar — load the persisted open/closed flag - // (defaults to true on first launch), then persist on every toggle. - // The Slint side flips NetworkSidebarState.open before emitting - // the callback. + // Artist network sidebar — no persistence. Default open, user can + // close per-session, and reset_network_sidebar reopens it on every + // artist navigation. The toggle callback stays a no-op on the + // Rust side — Slint already flips NetworkSidebarState.open + // directly in the click handler. window - .global::() - .set_open(network_sidebar_prefs::load_open()); - { - let weak = window.as_weak(); - window - .global::() - .on_toggle(move || { - if let Some(w) = weak.upgrade() { - let open = w.global::().get_open(); - network_sidebar_prefs::set_open(open); - } - }); - } + .global::() + .on_toggle(|| {}); // Network sidebar — typed click callbacks. Each delivers the // minimum payload the future target views (ArtistsByLocation, diff --git a/crates/qbz-slint/src/network_sidebar_prefs.rs b/crates/qbz-slint/src/network_sidebar_prefs.rs deleted file mode 100644 index 52eb77f64..000000000 --- a/crates/qbz-slint/src/network_sidebar_prefs.rs +++ /dev/null @@ -1,69 +0,0 @@ -//! Persistence for the artist network sidebar open/closed preference. -//! -//! A tiny JSON file at the shared QBZ data path so the sidebar reopens -//! in the same state the user left it. Loaded on demand; written on -//! every toggle. Failures degrade silently — at worst the sidebar -//! starts closed on the next launch. - -use std::path::PathBuf; - -use serde::{Deserialize, Serialize}; - -#[derive(Serialize, Deserialize)] -struct Prefs { - #[serde(default = "default_open")] - open: bool, -} - -fn default_open() -> bool { - true -} - -impl Default for Prefs { - fn default() -> Self { - Self { open: true } - } -} - -fn store_path() -> Option { - Some(dirs::data_dir()?.join("qbz").join("network_sidebar.json")) -} - -/// Read the persisted open/closed flag. Defaults to `true` (open) on a -/// fresh install — the artist network sidebar is one of the visible -/// improvements over a generic Linux music player, so it should be on -/// out of the box until the user closes it. -pub fn load_open() -> bool { - let Some(path) = store_path() else { - return true; - }; - match std::fs::read(&path) { - Ok(bytes) => serde_json::from_slice::(&bytes) - .map(|p| p.open) - .unwrap_or(true), - Err(_) => true, - } -} - -/// Persist the open/closed flag. Called on every sidebar toggle. -#[allow(dead_code)] // wired by the artist controller in phase 3 (network button) -pub fn set_open(open: bool) { - let Some(path) = store_path() else { - return; - }; - if let Some(parent) = path.parent() { - if let Err(e) = std::fs::create_dir_all(parent) { - log::warn!("[qbz-slint] network-sidebar prefs dir failed: {e}"); - return; - } - } - let prefs = Prefs { open }; - match serde_json::to_vec_pretty(&prefs) { - Ok(json) => { - if let Err(e) = std::fs::write(&path, json) { - log::warn!("[qbz-slint] network-sidebar prefs write failed: {e}"); - } - } - Err(e) => log::warn!("[qbz-slint] network-sidebar prefs serialize failed: {e}"), - } -} diff --git a/crates/qbz-slint/ui/artist/ArtistPageView.slint b/crates/qbz-slint/ui/artist/ArtistPageView.slint index 9b8cbcd09..5b2bd296d 100644 --- a/crates/qbz-slint/ui/artist/ArtistPageView.slint +++ b/crates/qbz-slint/ui/artist/ArtistPageView.slint @@ -601,10 +601,16 @@ export component ArtistPageView inherits Rectangle { width: 300px; spacing: 0px; - // 44px to clear the NavButtons row at the top of the - // artist body — mirrors Tauri's sticky jump-nav offset - // (`top: 44px`). - Rectangle { height: 44px; } + // Top inset clears the entire artist header — NavButtons + // (11 padding + ~32 row + 22 spacer = 65) + the artist + // header itself (~214px: ARTIST label + name + truncated + // bio + Read more + action buttons) + the 36px spacer + // before Popular Tracks. Total ~315px so the sidebar's + // top edge sits inline with where Popular Tracks starts, + // matching Tauri's `.network-sidebar-column` natural flow + // position (inside the body, alongside the sections — + // never overlapping the artist header). + Rectangle { height: 320px; } sidebar-panel := Rectangle { vertical-stretch: 1;