The tooltip was centered on the badge and overflowed past the card
edge, where the next card painted over it. Right-anchor it so it
extends leftward into the card and stays clear of the neighbor.
cc
Add a first cut of context menus, opened from the "more" (ellipsis)
button on Discover album cards and on album track rows.
- ContextMenu / ContextMenuItem primitives (PopupWindow-hosted panel)
- AlbumCard: the overlay action buttons are now interactive (they gate
their pointer handling so non-hovered cards still open on click); the
more button opens a menu — Open album, Play, Add to queue, Add to
favorites
- TrackRow: a hover-revealed more button opens a menu — Play, Add to
queue, Add to favorites; AlbumTrackItem and TrackData carry the
track id
- Menu actions bubble up as a single media-action(kind, id, action)
callback through the shell; main.rs logs it for now — playback and
favorites wiring lands with the playback session
- user and list-plus icons
cc
Three corrections to the Discover album card:
- Overlay meta: the genre is one point larger and bold, and the year
now sits a single line below it (conditional `if` rows with explicit
heights, instead of `visible` toggles that left a phantom gap)
- Award ribbon: width hugs its label (capped at 200px, below the card
width) instead of spanning the full card — it reads as a ribbon again
- Quality badge: extracted to a QualityBadge primitive that reveals
the exact quality ("Hi-Res: 24-bit / 96 kHz") on hover, mirroring the
Tauri QualityBadge; home.rs derives the label from the discover
audio info
cc
Introduce the Settings page, reachable from the Discover gear and the
header menu. Two sub-sections backed by the existing UI-agnostic stores.
- Audio panel: backend, output device and sample-rate dropdowns;
toggles for exclusive mode, DAC passthrough, PipeWire force
bit-perfect, gapless, normalization and quality fallback
- Playback panel: autoplay mode, show context icon, remember session
and resume position
- settings.rs controller owns AudioSettingsStore + PlaybackPreferencesStore
at the shared global path; persists changes and applies audio ones to
the live Player (reload_settings, plus reinit_device for routing-
critical changes); a backend switch re-enumerates output devices
- QbzToggle (switch) and QbzSelect (PopupWindow dropdown) primitives,
SettingRow layout helper, chevron-down icon
- SettingsState global, ContentView::settings, settings-bool /
settings-select callbacks wired through the shell
cc
- 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
Adds 28 Lucide icons (the same set the QBZ Svelte app uses) as SVGs
under ui/assets/icons/, plus a QbzIcon primitive — an Image wrapper that
applies `colorize` so a monochrome SVG renders in any theme color.
cc
M1 progress. Adds the foundation token layer (palette, semantic
colors, spacing, radius, typography) bound to the QBZ dark theme,
three primitives (QbzCheckbox, QbzPrimaryButton, QbzTextLink), and
the LoginScreen feature component.
The login screen mirrors the Svelte LoginView: centered card, logo,
QBZ wordmark, Qobuz ToS checkbox, "Sign in via Browser" button,
system-browser and offline links, and the legal disclaimer. Colors
are lifted verbatim from src/app.css; strings use @tr() markers.
Rust side: typed AppCommand enum; UI callbacks dispatch through it.
M2 wires the command handler to AppRuntime.
cc