feat(slint): album-header "Make album offline" + direct button on favorites rows

- offline_cache::cache_album fetches an album's tracks and batches them; wired
  to a new ("album","cache") media-action arm + a cloud-download CircleAction in
  the AlbumPageView header action row.
- Favorites track rows now enable show-download, so the direct per-row offline
  button shows there too (not just album rows / cached tracks).

Rounds out Slice 2: trigger surfaces (per-row button on album+favorites, context
menu everywhere, bulk multi-select, album header), live status (spinner/check/
alert) + seeding, and the unlock padlock. qbz-slint compiles clean.

cc
This commit is contained in:
vicrodh committed 2026-05-28 09:29:20 -06:00
1 parent 6bea6a7a0a
commit 6572d6f33f
4 files changed
+46

No files matched your search

+6
View File
@@ -2191,6 +2191,12 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
}
});
}
("album", "cache") => offline_cache::cache_album(
runtime.clone(),
weak.clone(),
handle.clone(),
id,
),
("track", "play-next") => {
if let Ok(track_id) = id.parse::<u64>() {
playback::play_track_next(
+30
View File
@@ -280,6 +280,36 @@ pub fn cache_tracks(
});
}
/// Cache a whole album for offline playback: fetch its tracks, then batch them.
pub fn cache_album(
runtime: Runtime,
weak: slint::Weak<AppWindow>,
handle: tokio::runtime::Handle,
album_id: String,
) {
let inner = handle.clone();
handle.spawn(async move {
let album = match runtime.core().get_album(&album_id).await {
Ok(a) => a,
Err(e) => {
log::error!("[qbz-slint] cache album {album_id} failed: {e}");
crate::toast::error_weak(&weak, "Couldn't load that album");
return;
}
};
let tracks: Vec<qbz_models::Track> = album
.tracks
.as_ref()
.map(|c| c.items.clone())
.unwrap_or_default();
if tracks.is_empty() {
crate::toast::error_weak(&weak, "This album has no playable tracks");
return;
}
cache_tracks(runtime, weak, inner, tracks);
});
}
/// Remove a track's offline copy (DB row + on-disk bundle/file + library row).
pub fn remove_cached(
_runtime: Runtime,
@@ -347,6 +347,15 @@ export component AlbumPageView inherits Rectangle {
}
}
}
VerticalLayout {
alignment: center;
CircleAction {
icon: @image-url("../assets/icons/cloud-download.svg");
clicked => {
root.media-action("album", AlbumState.id, "cache");
}
}
}
VerticalLayout {
alignment: center;
CircleAction { icon: @image-url("../assets/icons/radio.svg"); }
@@ -1066,6 +1066,7 @@ export component FavoritesView inherits Rectangle {
show-artwork: true;
show-album: FavoritesState.tracks-group-mode != "album";
show-favorite: true;
show-download: true;
multi-select-mode: FavoritesState.tracks-multi-select;
media-action(kind, id, action) => {
if (kind == "album" && action == "open") {