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:
4 files changed
+46
No files matched your search
@@ -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(
|
||||
|
||||
@@ -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") {
|
||||
|
||||
Reference in new issue
Block a user