Commit Graph
10 Commits
Author SHA1 Message Date
vicrodh d132636caa feat(slint): recently-played store and Discover Home section
Close the Recently Played Tracks tech debt: a JSON-backed play-history
store at the shared QBZ data path, surfaced as a slim-card section on
Discover Home (it hides while empty).

- recently.rs: load() reads the store newest-first; record() prepends a
  track, dedupes by id and caps the list — the playback session calls
  record() when a track starts
- home.rs threads a `recent` list into HomeData; HomeView renders a
  "Recently Played" GridSection; artwork pipeline gains an
  ArtworkTarget::Recent

The data path is complete end to end; only record() awaits the
playback session.

cc
2026-05-18 18:47:24 -06:00
vicrodh 5d78fb0a09 feat(slint): add Settings page with Audio and Playback panels
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
2026-05-18 17:08:24 -06:00
vicrodh 3871143bd3 feat(qbz-slint): restore saved sessions from the encrypted token store
The MVP no longer requires re-authenticating on every launch. On
startup it loads the saved OAuth token via qbz-credentials, validates
it against Qobuz, and — if valid — activates the session and goes
straight to the Discover/Home view. A rejected token is cleared and
the login screen is shown instead. Successful sign-ins now persist the
token to the shared encrypted store.

- auth.rs: save_oauth_token after login, restore_saved_session at
  startup.
- main.rs: enter_shell helper shared by the login and restore paths.

cc
2026-05-18 13:42:17 -06:00
vicrodh 3e61ec3b0f feat(qbz-slint): route album artwork through the shared image cache
Cover art now goes through the QBZ image cache instead of being
downloaded directly every time, matching the Tauri behavior.

- Moves ImageCacheService / ImageCacheStats into the qbz-cache crate
  (LRU disk cache, MD5-keyed, SQLite index). src-tauri/image_cache.rs
  re-exports it and keeps the Tauri managed-state wrapper, so the Tauri
  app stays behavior-identical and both shells share one implementation
  and one on-disk cache (~/.cache/qbz/images).
- qbz-slint artwork.rs checks the cache first, downloads and stores on
  a miss, and trims the cache to 200MB on startup.

cc
2026-05-18 13:32:10 -06:00
vicrodh 7801478819 fix(qbz-slint): match current QBZ Discover Home
Corrections from testing feedback:
- Remove the greeting — the current QBZ discovery view has no greeting,
  only the tab selector. Drops HomeState.greeting and the chrono dep.
- Quality badge is now the icon-only badge (hi-res.svg, or cd.svg in a
  framed square), not a numeric text pill. AlbumCardItem carries a
  quality tier instead of a quality string.
- Tighten the album card: deterministic 274px height, title and artist
  in a 2px-spaced stack — removes the large gap between them.
- SectionRow no longer scrolls vertically (vertical-scrollbar-policy
  always-off, height pinned to the card height).
- Artwork is downscaled to 264px on decode instead of holding ~600px
  source textures.

cc
2026-05-18 13:20:52 -06:00
vicrodh e2e409cf93 feat(qbz-slint): album artwork pipeline
Discover cards now show real Qobuz cover art. Artwork is fetched and
decoded off the UI thread, capped at 16 concurrent downloads, and each
result is applied to its own card row on the Slint event loop — so a
cover arriving never resets a section.

- artwork.rs: download + decode worker and per-row apply.
- AlbumCardItem gains an `artwork` image field; AlbumCard overlays the
  cover, falling back to the elevated placeholder until it resolves.
- main.rs: after the discover sections render, artwork jobs are spawned
  for every card with an image URL.

qbz-slint now depends on reqwest and image.

cc
2026-05-18 13:05:12 -06:00
vicrodh 8246ad5dd6 feat(qbz-slint): real Discover Home view
After sign-in the app loads the real Qobuz discover index and renders
the Home view: a time-based greeting with the user's name, the tab
pill (Home / Editor's Picks / For You), and discover sections — New
Releases, Press Accolades, Ideal Discography, Qobuzissimes, Albums of
the Week — each a horizontally scrolling row of album cards.

- state.slint: AlbumCardItem / DiscoverSection structs, HomeState global.
- discover/: AlbumCard (artwork area, award ribbon, title, artist,
  quality badge), SectionRow, HomeView.
- home.rs: discover-index fetch and mapping (award-ribbon priority,
  quality string), greeting, and event-loop model application. Unit
  tests for ribbon, quality, and greeting logic.
- AppShell content region is now the HomeView.

Album artwork images load in the next increment (artwork pipeline);
cards currently show the elevated placeholder. No fixtures — all data
is the live discover index.

cc
2026-05-18 13:01:45 -06:00
vicrodh 03b9a1c528 feat(qbz-slint): functional system-browser OAuth login
Wires real authentication. "Sign in via Browser" now runs the actual
Qobuz OAuth flow with no Tauri and no WebView: opens the system
browser, captures the authorization code on a one-shot localhost
listener, exchanges it via QbzCore's Qobuz client, and activates a
real per-user session through AppRuntime.

- adapter.rs: SlintAdapter implements FrontendAdapter.
- auth.rs: system-browser OAuth, mirrors v2_start_system_browser_oauth
  without Tauri. Includes a query-param parse test.
- main.rs: tokio runtime; sign-in / offline callbacks run real async
  work and navigate to the shell on success.
- Sidebar: placeholder playlist fixtures removed.

qbz-slint now depends on qbz-app, qbz-core, and qbz-models.

cc
2026-05-18 12:48:13 -06:00
vicrodh d5be0029b6 feat(qbz-slint): foundation tokens and login screen
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
2026-05-18 12:13:52 -06:00
vicrodh f1748383a5 feat(qbz-slint): scaffold Slint POC crate
First increment of M1 of the Slint functional POC. Adds the qbz-slint
workspace member: Slint 1.x dependency, build.rs compiling ui/app.slint,
a minimal AppWindow, and the binary entry point.

Verifies the Slint toolchain builds in this environment before the
foundation layer (tokens, shell, theme, i18n, typed commands) lands.

Private slint-poc branch only (ADR-007).

cc
2026-05-18 11:57:49 -06:00