NowPlayingBar (start of the playback-bar work): - height raised to 110px - SeekBar component: three-line track (total / cached / progress), a hover thumb, elapsed/remaining times, and a hover time bubble with a downward caret marking the seek position - song card: background and border dropped, gains the extra height, album/artist links and the context icon kept (context icon now always shown) - transport + secondary buttons copied from Tauri (shuffle, prev, play, next, repeat, add, favorite; cast, picture-in-picture, fullscreen, normalization; volume cluster). Queue/Lyrics stay in the header — and the header now orders them lyrics-then-queue. Settings constraints (1:1 with Tauri): - Exclusive Mode enabled only on ALSA; DAC Passthrough only on PipeWire; Lock Output Device disabled while DAC Passthrough is on; Gapless disabled while Streaming Only is on - backend change cascades: forces off DAC passthrough / force-bit- perfect / exclusive / gapless as appropriate; DAC-passthrough and streaming-only cascades; initial-buffer slider right-aligned Discover fixes: - navigation [<] [>] pair homologated to the same top/left margin across every view - album/artist description moved back into the metadata column (it now fills the width there) with uniform secondary text color - genre filter button hugs its label instead of stretching - Recently Played Albums and Tracks modules always render, with a placeholder until the play history has data - wider spacing between Discover rows; the Discover gear is no longer a Settings shortcut (it is the per-tab sort/show-hide control) cc
80 lines
2.4 KiB
Plaintext
80 lines
2.4 KiB
Plaintext
// Horizontal integer slider primitive — dark-themed, draggable.
|
|
//
|
|
// Like the other primitives it does not own its value: it emits
|
|
// `changed(new-value)` and the caller updates the bound state. The thumb
|
|
// position is derived from `value`, clamped to [minimum, maximum].
|
|
|
|
import { Theme } from "../foundation/semantic-colors.slint";
|
|
|
|
export component QbzSlider inherits Rectangle {
|
|
in property <int> minimum: 0;
|
|
in property <int> maximum: 10;
|
|
in property <int> value: 0;
|
|
callback changed(int);
|
|
|
|
width: 200px;
|
|
height: 22px;
|
|
|
|
// Fraction of the track the current value sits at, clamped to [0, 1].
|
|
property <float> fraction: root.maximum > root.minimum
|
|
? max(0.0, min(1.0, (root.value - root.minimum) / (root.maximum - root.minimum)))
|
|
: 0.0;
|
|
property <length> thumb-size: 16px;
|
|
// Travel range for the thumb centre.
|
|
property <length> travel: root.width - root.thumb-size;
|
|
|
|
// Track.
|
|
Rectangle {
|
|
y: (parent.height - self.height) / 2;
|
|
height: 4px;
|
|
border-radius: 2px;
|
|
background: Theme.surface-elevated;
|
|
}
|
|
|
|
// Accent fill.
|
|
Rectangle {
|
|
x: 0;
|
|
y: (parent.height - self.height) / 2;
|
|
width: root.thumb-size / 2 + root.fraction * root.travel;
|
|
height: 4px;
|
|
border-radius: 2px;
|
|
background: Theme.accent;
|
|
}
|
|
|
|
// Thumb.
|
|
Rectangle {
|
|
x: root.fraction * root.travel;
|
|
y: (parent.height - self.height) / 2;
|
|
width: root.thumb-size;
|
|
height: root.thumb-size;
|
|
border-radius: root.thumb-size / 2;
|
|
background: Theme.text-primary;
|
|
}
|
|
|
|
// Map a pointer x to a clamped, rounded integer value.
|
|
function value-from-x(px: length) -> int {
|
|
root.minimum + round(
|
|
max(0.0, min(1.0, (px - root.thumb-size / 2) / max(1px, root.travel)))
|
|
* (root.maximum - root.minimum)
|
|
)
|
|
}
|
|
|
|
ta := TouchArea {
|
|
mouse-cursor: pointer;
|
|
|
|
// Jump to the click point on press-down.
|
|
pointer-event(e) => {
|
|
if (e.kind == PointerEventKind.down
|
|
&& root.value-from-x(self.mouse-x) != root.value) {
|
|
root.changed(root.value-from-x(self.mouse-x));
|
|
}
|
|
}
|
|
// Continuous drag while held.
|
|
moved => {
|
|
if (root.value-from-x(self.mouse-x) != root.value) {
|
|
root.changed(root.value-from-x(self.mouse-x));
|
|
}
|
|
}
|
|
}
|
|
}
|