- Replace every Unicode glyph placeholder with Lucide icons via QbzIcon (player transport, carousel nav, album-card overlay, album-page actions, gear, search, checkbox, sidebar). - Header: the search field is centered to the window width and gets a search icon; the header and player bar now use the elevated surface, so all chrome (header, sidebar, player bar) shares one color over the darker content area. - The sidebar user card moves to the header as a user element (name + QBZ logo) that opens a dropdown — Settings, Keyboard Shortcuts, Documentation, Report an Issue, About, plus Log Out and Close. Log Out clears the session and returns to login; Close quits the app. - Content ScrollViews disable the horizontal scrollbar — no view scrolls horizontally, so the phantom reserved lane is gone. cc
138 lines
4.6 KiB
Plaintext
138 lines
4.6 KiB
Plaintext
// Bottom now-playing / transport bar.
|
|
//
|
|
// Controls are laid out and hover-reactive but not yet wired to
|
|
// playback. Real playback state arrives in a later milestone.
|
|
|
|
import { Theme } from "../foundation/semantic-colors.slint";
|
|
import { Spacing } from "../foundation/spacing.slint";
|
|
import { Typography } from "../foundation/typography.slint";
|
|
import { Layout } from "../foundation/layout.slint";
|
|
import { Radius } from "../foundation/radius.slint";
|
|
import { QbzIcon } from "../primitives/QbzIcon.slint";
|
|
|
|
component IconButton inherits Rectangle {
|
|
in property <image> icon;
|
|
in property <length> icon-size: 18px;
|
|
callback clicked();
|
|
|
|
width: 34px;
|
|
height: 34px;
|
|
border-radius: Radius.sm;
|
|
background: ta.has-hover ? Theme.surface-hover : transparent;
|
|
|
|
QbzIcon {
|
|
source: root.icon;
|
|
width: root.icon-size;
|
|
height: root.icon-size;
|
|
x: (parent.width - self.width) / 2;
|
|
y: (parent.height - self.height) / 2;
|
|
tint: ta.has-hover ? Theme.text-primary : Theme.text-secondary;
|
|
}
|
|
|
|
ta := TouchArea {
|
|
mouse-cursor: pointer;
|
|
clicked => {
|
|
root.clicked();
|
|
}
|
|
}
|
|
}
|
|
|
|
export component PlayerBar inherits Rectangle {
|
|
height: Layout.player-bar-height;
|
|
background: Theme.surface-card;
|
|
|
|
VerticalLayout {
|
|
spacing: 0px;
|
|
|
|
// Progress line across the top edge.
|
|
Rectangle {
|
|
height: 2px;
|
|
background: Theme.surface-elevated;
|
|
Rectangle {
|
|
x: 0;
|
|
width: parent.width * 0.32;
|
|
background: Theme.accent;
|
|
}
|
|
}
|
|
|
|
HorizontalLayout {
|
|
vertical-stretch: 1;
|
|
padding-left: Spacing.md;
|
|
padding-right: Spacing.md;
|
|
spacing: Spacing.md;
|
|
|
|
// Transport controls.
|
|
VerticalLayout {
|
|
alignment: center;
|
|
HorizontalLayout {
|
|
spacing: 2px;
|
|
IconButton { icon: @image-url("../assets/icons/shuffle.svg"); }
|
|
IconButton { icon: @image-url("../assets/icons/skip-back.svg"); }
|
|
IconButton {
|
|
icon: @image-url("../assets/icons/play.svg");
|
|
icon-size: 22px;
|
|
}
|
|
IconButton { icon: @image-url("../assets/icons/skip-forward.svg"); }
|
|
IconButton { icon: @image-url("../assets/icons/repeat.svg"); }
|
|
}
|
|
}
|
|
|
|
// Now-playing.
|
|
VerticalLayout {
|
|
alignment: center;
|
|
horizontal-stretch: 1;
|
|
HorizontalLayout {
|
|
alignment: center;
|
|
spacing: Spacing.sm;
|
|
Rectangle {
|
|
width: 48px;
|
|
height: 48px;
|
|
border-radius: Radius.sm;
|
|
background: Theme.surface-elevated;
|
|
}
|
|
VerticalLayout {
|
|
alignment: center;
|
|
Text {
|
|
text: "Nothing playing";
|
|
color: Theme.text-primary;
|
|
font-size: Typography.body;
|
|
}
|
|
Text {
|
|
text: "QBZ MVP";
|
|
color: Theme.text-muted;
|
|
font-size: 12px;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// Right-side controls.
|
|
VerticalLayout {
|
|
alignment: center;
|
|
HorizontalLayout {
|
|
alignment: end;
|
|
spacing: Spacing.sm;
|
|
IconButton { icon: @image-url("../assets/icons/heart.svg"); }
|
|
IconButton { icon: @image-url("../assets/icons/maximize-2.svg"); }
|
|
IconButton { icon: @image-url("../assets/icons/volume-2.svg"); }
|
|
VerticalLayout {
|
|
alignment: center;
|
|
Rectangle {
|
|
width: 90px;
|
|
height: 4px;
|
|
border-radius: 2px;
|
|
background: Theme.surface-elevated;
|
|
Rectangle {
|
|
x: 0;
|
|
width: parent.width * 0.6;
|
|
border-radius: 2px;
|
|
background: Theme.accent;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|