feat(slint): NowPlayingBar rebuild, Settings constraints, Discover fixes

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
This commit is contained in:
vicrodh committed 2026-05-18 21:22:40 -06:00
1 parent edca636a16
commit 99e3513d68
18 files changed
+589 -150

No files matched your search

@@ -137,8 +137,11 @@ export component AudioSettings inherits VerticalLayout {
SettingRow {
label: @tr("Exclusive mode");
description: @tr("Lock the device so no other app can resample it.");
// ALSA-only — disabled for PipeWire / Pulse / System default.
enabled: SettingsState.backend-is-alsa;
QbzToggle {
checked: SettingsState.exclusive-mode;
enabled: SettingsState.backend-is-alsa;
toggled(v) => {
SettingsState.exclusive-mode = v;
root.settings-bool("exclusive-mode", v);
@@ -159,8 +162,11 @@ export component AudioSettings inherits VerticalLayout {
SettingRow {
label: @tr("DAC passthrough");
description: @tr("Send the bitstream untouched to the DAC.");
// PipeWire-only — disabled for ALSA / Pulse / System default.
enabled: SettingsState.backend-is-pipewire;
QbzToggle {
checked: SettingsState.dac-passthrough;
enabled: SettingsState.backend-is-pipewire;
toggled(v) => {
SettingsState.dac-passthrough = v;
root.settings-bool("dac-passthrough", v);
@@ -210,8 +216,11 @@ export component AudioSettings inherits VerticalLayout {
if SettingsState.backend-is-pipewire: SettingRow {
label: @tr("Lock output device");
description: @tr("Keep external routing intact — skip switching the default sink.");
// Mutually exclusive with DAC passthrough — disabled while it is on.
enabled: !SettingsState.dac-passthrough;
QbzToggle {
checked: SettingsState.skip-sink-switch;
enabled: !SettingsState.dac-passthrough;
toggled(v) => {
SettingsState.skip-sink-switch = v;
root.settings-bool("skip-sink-switch", v);