feat(slint): playlist snapshot (names+membership) and offline favorites rail

Qobuz playlist snapshot, captured opportunistically with zero new API
traffic: every online sidebar/manager list load upserts id+name+owner+
track_count for the user's playlists; opening a playlist detail online
full-replaces its membership track ids (refusing playlists never listed,
so viewed public playlists don't land). Offline consumers: synthesized
sidebar/manager entries resolve the persisted name (killing the cold-start
'Playlist (N local)' fallback when a snapshot exists), and the mixed-
playlist offline detail now renders the snapshot tracks that are playable
(snapshot intersect cached intersect grace) from the offline-cache index -
snapshot block first in snapshot order, sidecar local/plex block after.
D11 availability widens: a playlist with zero sidecar rows but cached
snapshot tracks now shows offline. 4 repo tests.

Offline favorites rail: the Favorites placeholder gains an 'Available
offline (N)' block - disk-cached favorite ids intersected with the
offline-cache READY index and LocalLibrary qobuz_download copies, compact
rows with the offline cover chain, click plays the rail as a queue through
the cache tier. Shared OfflinePlaceholder gains an @children slot; only
the Favorites mount injects the rail.

Single commit: the two features interleave in main.rs/state wiring and
ship together to keep every commit compiling.

cc
This commit is contained in:
vicrodh committed 2026-06-10 02:27:54 -06:00
1 parent 23129cb98e
commit 81587f4d17
17 files changed
+1154 -95

No files matched your search

+20
View File
@@ -3192,3 +3192,23 @@ export global OfflineModeActions {
// persistence + #279 snapshot path as the Settings toggle.
callback set-offline(bool);
}
// B9 — offline Favorites "playable favorites" rail. While OFFLINE the
// Favorites view is replaced by the OfflinePlaceholder; this rail (mounted
// as the placeholder's children on the Favorites mount only) lists the
// favorite tracks that are still playable — offline-cache READY copies and
// library qobuz_download rows — so the view isn't a dead end.
export global OfflineFavoritesState {
// The playable favorite tracks, display order = play order (the Rust
// side keeps a matching queue; a row click plays the rail from there).
in property <[SlimItem]> tracks: [];
}
export global OfflineFavoritesActions {
// (Re)build the rail from the local stores — fired by the rail's init
// on every mount of the Favorites offline placeholder.
callback load();
// Play the rail starting at the clicked track id (offline-capable
// queue path; the cached copies play through the offline tier).
callback play(string);
}