Clicking an album card opens the album detail view: a back button,
the album header (224px artwork, title, artist, and info line — year,
label, genre, track count, duration — plus play / shuffle / favorite /
more action buttons), and the track list with a column header (#,
title, artist, duration, quality).
- album.rs: fetches the album via QbzCore::get_album, maps it (info
line, per-track quality tier, durations) onto the AlbumState global,
and loads the header artwork through the shared image cache.
- AlbumPageView.slint, with NavState driving the shell content region
between Home and the album page.
- Album clicks bubble AlbumCard -> Carousel -> HomeView -> AppShell ->
AppWindow -> main; the back button returns to Home.
cc
Album cards gain the AlbumCardLite-style hover overlay: a dark scrim,
genre/year meta in the top-left, and circular favorite / play / more
action buttons (play primary, white). The action buttons are visual
for now; one TouchArea over the artwork drives the hover state and
emits a clicked(album_id) callback for navigation.
AlbumCardItem carries genre and year; home.rs maps them from the
discover album (genre name, year from the release dates).
cc
- The sidebar now uses the elevated surface (#1a1a1a) over the #0f0f0f
content area, matching the QBZ dark theme (--bg-secondary over
--bg-primary).
- Discover Home gains a proper 56px toolbar with a bottom border: the
tab pill on the left, a "Filter by genre" button and a settings gear
on the right. The toolbar is fixed; only the section carousels scroll
below it.
cc
Adds a splash screen (logo, wordmark, spinner) shown while the app
boots and restores a saved session. The login form no longer flashes
for returning users — the app starts on `splash` and resolves to
`shell` (restored) or `login` (no saved session), matching the current
QBZ app behavior.
cc
Discover sections now use a Carousel: a clipped, sliding track of
album cards with prev/next page controls, paginated by slice like the
Svelte DiscoverySection. With no ScrollView the row height is exactly
the card height — the horizontal scrollbar no longer injects vertical
space, so the earlier internal-scroll problem is resolved structurally
rather than patched.
per-page is derived from the viewport width and self-corrects on
resize. Replaces SectionRow.
cc
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
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
The album card now has a fully deterministic 266px height (artwork 220
+ 6 spacer + 40 meta, with fixed-height title and artist text). The
section row's ScrollView pins viewport-height to its height, so the
vertical scroll range is zero — the row can no longer scroll
vertically, even invisibly.
cc
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
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
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
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
M1 progress. Adds the post-login shell: HeaderBar (nav tabs and
search), Sidebar (playlists list and user card), PlayerBar (transport,
now-playing, volume), and AppShell composing them with the content
region as a placeholder.
app.slint gains an AppScreen enum; clicking sign-in or start-offline
navigates login -> shell (no real auth yet — that is M2). New layout
foundation tokens (sidebar width, header/player-bar heights) plus
border and hover semantic colors.
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
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