fix(slint): sidebar starts below the artist header, always opens
Two adjustments to land the sidebar truly 1:1 with the Tauri visual.
Top inset now 320px — clears the entire artist header (NavButtons
row + ARTIST label + name + truncated bio + Read more + action
buttons + the 36px spacer before Popular Tracks). 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 header).
Sidebar is always open by default on every artist navigation, with
no cross-session persistence — closing it is a per-view choice only:
- reset_network_sidebar (called at the start of navigate_artist)
flips NetworkSidebarState.open back to true alongside the other
per-artist state resets.
- network_sidebar_prefs.rs is removed; the on_toggle Rust handler
is a no-op (Slint already mutates the open flag directly in the
button click). The previous `<data-dir>/qbz/network_sidebar.json`
persistence file is no longer written or read.
cc
This commit is contained in:
4 files changed
+23
-94
No files matched your search
@@ -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::<NetworkSidebarState>();
|
||||
state.set_open(true);
|
||||
state.set_mb_available(true);
|
||||
state.set_mb_mbid("".into());
|
||||
state.set_origin_loading(false);
|
||||
|
||||
@@ -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<dyn std::error::Error>> {
|
||||
});
|
||||
}
|
||||
|
||||
// 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::<NetworkSidebarState>()
|
||||
.set_open(network_sidebar_prefs::load_open());
|
||||
{
|
||||
let weak = window.as_weak();
|
||||
window
|
||||
.global::<NetworkSidebarActions>()
|
||||
.on_toggle(move || {
|
||||
if let Some(w) = weak.upgrade() {
|
||||
let open = w.global::<NetworkSidebarState>().get_open();
|
||||
network_sidebar_prefs::set_open(open);
|
||||
}
|
||||
});
|
||||
}
|
||||
.global::<NetworkSidebarActions>()
|
||||
.on_toggle(|| {});
|
||||
|
||||
// Network sidebar — typed click callbacks. Each delivers the
|
||||
// minimum payload the future target views (ArtistsByLocation,
|
||||
|
||||
@@ -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<PathBuf> {
|
||||
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::<Prefs>(&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}"),
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
|
||||
Reference in new issue
Block a user