fix(player): attach a cover to queued rows that were enqueued without one
The sibling of patch_plex_quality, for the other thing a row can learn after it was enqueued. A disc carries no artwork — it is fetched, and the fetch outlives the click that started playback — so a CD queued at second two is still holding artwork_url: None when the cover lands at second ten. Every consumer downstream reads the QUEUE row (the now-playing bar, the miniplayer, MPRIS through art_url_for), so patching the session store alone left all of them blank. Rows that already have art are left alone: this fills a gap rather than overwriting a cover somebody else resolved. It answers two questions separately, because they drive different work — any patch makes the queue panel's thumbnails stale, only the current one needs the now-playing stamp re-pushed. cc
This commit is contained in:
2 files changed
+59
No files matched your search
@@ -902,6 +902,23 @@ impl<A: FrontendAdapter + Send + Sync + 'static> QbzCore<A> {
|
||||
current_patched
|
||||
}
|
||||
|
||||
/// Attach a resolved cover to any queued track in `ids` that has none.
|
||||
/// Frontend-agnostic hook for art that resolves AFTER the row was
|
||||
/// enqueued — a disc's cover is fetched, and the fetch outlives the click
|
||||
/// that started playback. Returns true if the CURRENT track was patched;
|
||||
/// the caller then re-pushes the now-playing stamp.
|
||||
pub async fn patch_queue_artwork(&self, ids: &[u64], url: &str) -> bool {
|
||||
let queue = self.queue.write().await;
|
||||
let (any, current_patched) = queue.patch_artwork(ids, url);
|
||||
if any {
|
||||
self.emit(CoreEvent::QueueUpdated {
|
||||
state: queue.get_state(),
|
||||
})
|
||||
.await;
|
||||
}
|
||||
current_patched
|
||||
}
|
||||
|
||||
// ==================== Search & Catalog ====================
|
||||
|
||||
/// Search for albums
|
||||
|
||||
@@ -119,6 +119,48 @@ impl QueueManager {
|
||||
current_patched
|
||||
}
|
||||
|
||||
/// Attach an artwork url to every queued track whose id is in `ids`.
|
||||
///
|
||||
/// The sibling of [`Self::patch_plex_quality`], for the other thing a row
|
||||
/// can learn AFTER it was enqueued: a cover. A disc carries none — it is
|
||||
/// fetched, and the fetch outlives the click that started playback — so a
|
||||
/// CD queued at second two is still holding `artwork_url: None` when the
|
||||
/// cover lands at second ten. Every consumer downstream reads the QUEUE
|
||||
/// row (the now-playing bar, the miniplayer, MPRIS through
|
||||
/// `art_url_for`), so patching the session store alone leaves all of them
|
||||
/// blank.
|
||||
///
|
||||
/// Rows that already have art are left alone: this fills a gap, it does
|
||||
/// not overwrite a cover somebody else resolved.
|
||||
///
|
||||
/// Returns `(any patched, the CURRENT track was patched)`. The two are
|
||||
/// separate answers because they drive different work: any patch makes the
|
||||
/// queue panel's thumbnails stale, while only the current one needs the
|
||||
/// now-playing stamp re-pushed.
|
||||
pub fn patch_artwork(&self, ids: &[u64], url: &str) -> (bool, bool) {
|
||||
if ids.is_empty() || url.is_empty() {
|
||||
return (false, false);
|
||||
}
|
||||
let mut state = self.state.lock().unwrap();
|
||||
let current_idx = state.current_index;
|
||||
let mut any = false;
|
||||
let mut current_patched = false;
|
||||
for (idx, track) in state.tracks.iter_mut().enumerate() {
|
||||
if track.artwork_url.as_deref().is_some_and(|u| !u.is_empty()) {
|
||||
continue;
|
||||
}
|
||||
if !ids.contains(&track.id) {
|
||||
continue;
|
||||
}
|
||||
track.artwork_url = Some(url.to_string());
|
||||
any = true;
|
||||
if current_idx == Some(idx) {
|
||||
current_patched = true;
|
||||
}
|
||||
}
|
||||
(any, current_patched)
|
||||
}
|
||||
|
||||
/// Add a track to the end of the queue
|
||||
pub fn add_track(&self, track: QueueTrack) {
|
||||
let mut state = self.state.lock().unwrap();
|
||||
|
||||
Reference in new issue
Block a user