feat(slint): network sidebar toggle in artist header
Adds the Network button to the artist action cluster (Heart / Build collection / Radio / Network), wired to NetworkSidebarState.open. While the sidebar is open the button stays "active" — accent-tinted icon over the same surface a hover would produce — mirroring Tauri's `.network-btn.active`. The CircleAction primitive grew an `active` prop to express this without bespoke per-button styling; existing buttons default it to false and are unaffected. The click toggles NetworkSidebarState.open and emits NetworkSidebarActions.toggle(). Rust persists the new flag through network_sidebar_prefs::set_open() so the sidebar reopens in the same state the user left it. Asset: element-connect.svg copied from the Tauri `static/` folder verbatim — same icon Tauri renders for the button. Hide (blacklist) button stays out of the cluster until the artist_blacklist module migrates out of src-tauri. The sidebar itself, its content, and the controllers that fill the state are landed in the following phases. cc
This commit is contained in:
4 files changed
+62
-9
No files matched your search
@@ -1087,6 +1087,22 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||
});
|
||||
}
|
||||
|
||||
// Artist network sidebar — persist the open/closed flag on every
|
||||
// toggle so the sidebar reopens in the same state next launch. The
|
||||
// Slint side already flipped NetworkSidebarState.open before
|
||||
// emitting the callback.
|
||||
{
|
||||
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);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
window.on_close_app(|| {
|
||||
log::info!("[qbz-slint] closing");
|
||||
let _ = slint::quit_event_loop();
|
||||
|
||||
@@ -17,7 +17,7 @@ import { LoginScreen } from "login/LoginScreen.slint";
|
||||
import { AppShell } from "shell/AppShell.slint";
|
||||
|
||||
// Re-export the state globals so the Rust layer can populate them.
|
||||
export { HomeState, AlbumState, ArtistState, NavState, SessionState, SettingsState, AlbumActions, NowPlayingState, QueueState, SearchState, SearchActions } from "state.slint";
|
||||
export { HomeState, AlbumState, ArtistState, NavState, SessionState, SettingsState, AlbumActions, NowPlayingState, QueueState, SearchState, SearchActions, NetworkSidebarState, NetworkSidebarActions } from "state.slint";
|
||||
|
||||
// Which top-level screen is shown. The app starts on `splash` while it
|
||||
// restores a saved session, then resolves to `shell` or `login`.
|
||||
|
||||
@@ -8,7 +8,14 @@
|
||||
import { Theme } from "../foundation/semantic-colors.slint";
|
||||
import { Typography } from "../foundation/typography.slint";
|
||||
import { Radius } from "../foundation/radius.slint";
|
||||
import { ArtistState, AlbumTrackItem, NavState, ContentView } from "../state.slint";
|
||||
import {
|
||||
ArtistState,
|
||||
AlbumTrackItem,
|
||||
NavState,
|
||||
ContentView,
|
||||
NetworkSidebarState,
|
||||
NetworkSidebarActions,
|
||||
} from "../state.slint";
|
||||
import { QbzIcon } from "../primitives/QbzIcon.slint";
|
||||
import { ContextMenu } from "../primitives/ContextMenu.slint";
|
||||
import { ContextMenuItem } from "../primitives/ContextMenuItem.slint";
|
||||
@@ -21,6 +28,9 @@ import { NavButtons } from "../shell/NavButtons.slint";
|
||||
component CircleAction inherits Rectangle {
|
||||
in property <image> icon;
|
||||
in property <bool> primary: false;
|
||||
// Stays "pressed" — same surface as a hover, icon tinted accent.
|
||||
// Used by the Network button while the sidebar is open.
|
||||
in property <bool> active: false;
|
||||
in property <length> diameter: 40px;
|
||||
callback clicked();
|
||||
|
||||
@@ -29,9 +39,9 @@ component CircleAction inherits Rectangle {
|
||||
border-radius: root.diameter / 2;
|
||||
// Ghost circle — translucent fill with a faint ring, never a solid
|
||||
// accent fill (mirrors the Tauri transport controls).
|
||||
background: ta.has-hover ? Theme.surface-hover : transparent;
|
||||
background: (ta.has-hover || root.active) ? Theme.surface-hover : transparent;
|
||||
border-width: 1px;
|
||||
border-color: ta.has-hover ? Theme.text-disabled : Theme.border-subtle;
|
||||
border-color: (ta.has-hover || root.active) ? Theme.text-disabled : Theme.border-subtle;
|
||||
|
||||
QbzIcon {
|
||||
source: root.icon;
|
||||
@@ -39,7 +49,9 @@ component CircleAction inherits Rectangle {
|
||||
height: root.primary ? 19px : 17px;
|
||||
x: (parent.width - self.width) / 2;
|
||||
y: (parent.height - self.height) / 2;
|
||||
tint: ta.has-hover ? Theme.text-primary : Theme.text-secondary;
|
||||
tint: root.active
|
||||
? Theme.accent
|
||||
: (ta.has-hover ? Theme.text-primary : Theme.text-secondary);
|
||||
}
|
||||
|
||||
ta := TouchArea {
|
||||
@@ -335,10 +347,11 @@ export component ArtistPageView inherits Rectangle {
|
||||
Rectangle { height: 18px; }
|
||||
|
||||
// Action buttons — Heart, Build collection, Radio
|
||||
// (with QBZ / Qobuz dropdown). Mirrors Tauri's
|
||||
// artist-actions: NO Play here (top tracks has its
|
||||
// own play). Network sidebar toggle and Hide are
|
||||
// deferred to Tanda 2 (sidebar work).
|
||||
// (with QBZ / Qobuz dropdown), Network. Mirrors
|
||||
// Tauri's artist-actions: NO Play here (top tracks
|
||||
// has its own play). Hide (blacklist) is still
|
||||
// deferred until the blacklist module migrates out
|
||||
// of src-tauri.
|
||||
HorizontalLayout {
|
||||
alignment: start;
|
||||
spacing: 12px;
|
||||
@@ -389,6 +402,17 @@ export component ArtistPageView inherits Rectangle {
|
||||
}
|
||||
}
|
||||
}
|
||||
// Network — toggles the artist network sidebar.
|
||||
// Stays active (accent-tinted) while the sidebar
|
||||
// is open, matching Tauri's `.network-btn.active`.
|
||||
CircleAction {
|
||||
icon: @image-url("../assets/icons/element-connect.svg");
|
||||
active: NetworkSidebarState.open;
|
||||
clicked => {
|
||||
NetworkSidebarState.open = !NetworkSidebarState.open;
|
||||
NetworkSidebarActions.toggle();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
<?xml version="1.0" ?>
|
||||
<!-- Uploaded to: SVG Repo, www.svgrepo.com, Generator: SVG Repo Mixer Tools -->
|
||||
<svg width="800px" height="800px" viewBox="0 0 512 512" id="svg2793" style="fill-rule:evenodd;clip-rule:evenodd;stroke-linejoin:round;stroke-miterlimit:2;" version="1.1" xml:space="preserve" xmlns="http://www.w3.org/2000/svg" xmlns:cc="http://creativecommons.org/ns#" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:serif="http://www.serif.com/" xmlns:svg="http://www.w3.org/2000/svg">
|
||||
<defs id="defs2797"/>
|
||||
<g id="_24-Connect" style="display:inline" transform="translate(-3072,-4096)">
|
||||
<g id="g2211" transform="translate(3339.32,4267.43)">
|
||||
<path d="m 0,169.14 c -44.818,0 -81.28,-36.462 -81.28,-81.28 0,-44.818 36.462,-81.28 81.28,-81.28 44.817,0 81.279,36.462 81.279,81.28 0,44.818 -36.462,81.28 -81.279,81.28 m -149.2,141.43 c -24.587,0 -44.59,-20.003 -44.59,-44.59 0,-24.587 20.003,-44.59 44.59,-44.59 24.587,0 44.59,20.003 44.59,44.59 0,24.587 -20.003,44.59 -44.59,44.59 m -83.91,-398.5 c 0,-29.5 24,-53.5 53.5,-53.5 29.494,0 53.49,24 53.49,53.5 0,29.494 -23.996,53.49 -53.49,53.49 -29.5,0 -53.5,-23.996 -53.5,-53.49 m 412.099,37 c 17.364,0 31.49,14.126 31.49,31.49 0,17.369 -14.126,31.5 -31.49,31.5 -17.369,0 -31.5,-14.131 -31.5,-31.5 0,-17.364 14.131,-31.49 31.5,-31.49 m -44.46,73.915 c 11.207,11.739 26.989,19.075 44.46,19.075 33.907,0 61.49,-27.589 61.49,-61.5 0,-33.906 -27.583,-61.49 -61.49,-61.49 -33.911,0 -61.5,27.584 -61.5,61.49 0,5.628 0.776,11.076 2.198,16.259 L 87.091,18.672 C 66.687,-6.959 35.231,-23.42 0,-23.42 c -26.243,0 -50.388,9.137 -69.436,24.388 l -44.024,-38.046 c 10.859,-14.093 17.34,-31.725 17.34,-50.852 0,-46.042 -37.453,-83.5 -83.49,-83.5 -46.042,0 -83.5,37.458 -83.5,83.5 0,46.036 37.458,83.49 83.5,83.49 16.012,0 30.98,-4.54 43.702,-12.388 l 45.751,39.538 c -13.281,18.326 -21.123,40.838 -21.123,65.15 0,27.971 10.377,53.562 27.478,73.133 l -30.6,39.04 c -10.397,-5.508 -22.236,-8.643 -34.798,-8.643 -41.129,0 -74.59,33.461 -74.59,74.59 0,41.129 33.461,74.59 74.59,74.59 41.129,0 74.59,-33.461 74.59,-74.59 0,-17.745 -6.24,-34.055 -16.625,-46.873 l 30.054,-38.343 c 17.567,11.607 38.596,18.376 61.181,18.376 61.359,0 111.279,-49.92 111.279,-111.28 0,-15.382 -3.138,-30.045 -8.806,-43.383 z" id="path2209" style="fill-rule:nonzero"/>
|
||||
</g>
|
||||
<g id="g2215" transform="translate(3521.08,4502.59)">
|
||||
<path d="M 0,57.45 C -15.842,57.45 -28.73,44.562 -28.73,28.72 -28.73,12.884 -15.842,0 0,0 15.836,0 28.72,12.884 28.72,28.72 28.72,44.562 15.836,57.45 0,57.45 M 0,-30 c -32.384,0 -58.73,26.342 -58.73,58.72 0,32.384 26.346,58.73 58.73,58.73 32.378,0 58.72,-26.346 58.72,-58.73 C 58.72,-3.658 32.378,-30 0,-30" id="path2213" style="fill-rule:nonzero"/>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 2.7 KiB |
Reference in new issue
Block a user