From 67aa5b2bad4887026659e5b2ae4f74142952279d Mon Sep 17 00:00:00 2001 From: Henrik Friedrichsen Date: Tue, 6 Apr 2021 16:20:38 +0200 Subject: [PATCH] Use new pagination interface for user playlists --- src/library.rs | 23 +++++++---------------- src/spotify.rs | 32 ++++++++++++++++++++------------ 2 files changed, 27 insertions(+), 28 deletions(-) diff --git a/src/library.rs b/src/library.rs index a6039ef..77df4d2 100644 --- a/src/library.rs +++ b/src/library.rs @@ -5,7 +5,6 @@ use std::path::PathBuf; use std::sync::{Arc, RwLock, RwLockReadGuard}; use std::thread; -use rspotify::model::playlist::SimplifiedPlaylist; use serde::de::DeserializeOwned; use serde::Serialize; @@ -100,7 +99,7 @@ impl Library { } } - fn needs_download(&self, remote: &SimplifiedPlaylist) -> bool { + fn needs_download(&self, remote: &Playlist) -> bool { self.playlists() .iter() .find(|local| local.id == remote.id) @@ -255,9 +254,10 @@ impl Library { let mut stale_lists = self.playlists.read().unwrap().clone(); let mut list_order = Vec::new(); - let mut lists_result = self.spotify.current_user_playlist(50, 0); - while let Some(ref lists) = lists_result.clone() { - for (index, remote) in lists.items.iter().enumerate() { + let lists_page = self.spotify.current_user_playlist(); + let mut lists_batch = Some(lists_page.items.read().unwrap().clone()); + while let Some(lists) = &lists_batch { + for (index, remote) in lists.iter().enumerate() { list_order.push(remote.id.clone()); // remove from stale playlists so we won't prune it later on @@ -267,7 +267,7 @@ impl Library { if self.needs_download(remote) { info!("updating playlist {} (index: {})", remote.name, index); - let mut playlist: Playlist = remote.into(); + let mut playlist: Playlist = remote.clone(); playlist.tracks = None; playlist.load_tracks(self.spotify.clone()); self.append_or_update(&playlist); @@ -275,16 +275,7 @@ impl Library { self.ev.trigger(); } } - - // load next batch if necessary - lists_result = match lists.next { - Some(_) => { - debug!("requesting playlists again.."); - self.spotify - .current_user_playlist(50, lists.offset + lists.items.len() as u32) - } - None => None, - } + lists_batch = lists_page.next(); } // remove stale playlists diff --git a/src/spotify.rs b/src/spotify.rs index cdb82f1..e83e10c 100644 --- a/src/spotify.rs +++ b/src/spotify.rs @@ -14,7 +14,7 @@ use rspotify::blocking::client::Spotify as SpotifyAPI; use rspotify::model::album::{FullAlbum, SavedAlbum}; use rspotify::model::artist::FullArtist; use rspotify::model::page::{CursorBasedPage, Page}; -use rspotify::model::playlist::{FullPlaylist, PlaylistTrack, SimplifiedPlaylist}; +use rspotify::model::playlist::{FullPlaylist, PlaylistTrack}; use rspotify::model::search::SearchResult; use rspotify::model::track::{FullTrack, SavedTrack, SimplifiedTrack}; use rspotify::model::user::PrivateUser; @@ -50,6 +50,7 @@ use crate::spotify_worker::{Worker, WorkerCommand}; use crate::track::Track; use crate::album::Album; +use crate::playlist::Playlist; use crate::ui::pagination::{ApiPage, ApiResult}; use rspotify::model::recommend::Recommendations; use rspotify::model::show::{FullEpisode, FullShow, Show, SimplifiedEpisode}; @@ -532,12 +533,21 @@ impl Spotify { .take() } - pub fn current_user_playlist( - &self, - limit: u32, - offset: u32, - ) -> Option> { - self.api_with_retry(|api| api.current_user_playlists(limit, offset)) + pub fn current_user_playlist(&self) -> ApiResult { + const MAX_LIMIT: u32 = 50; + let spotify = self.clone(); + let fetch_page = move |offset: u32| { + debug!("fetching user playlists, offset: {}", offset); + spotify.api_with_retry(|api| match api.current_user_playlists(MAX_LIMIT, offset) { + Ok(page) => Ok(ApiPage { + offset: page.offset, + total: page.total, + items: page.items.iter().map(|sp| sp.into()).collect(), + }), + Err(e) => Err(e), + }) + }; + ApiResult::new(MAX_LIMIT, Arc::new(fetch_page)) } pub fn user_playlist_tracks( @@ -574,6 +584,7 @@ impl Spotify { let spotify = self.clone(); let artist_id = artist_id.to_string(); let fetch_page = move |offset: u32| { + debug!("fetching artist {} albums, offset: {}", artist_id, offset); spotify.api_with_retry(|api| { match api.artist_albums( &artist_id, @@ -583,11 +594,8 @@ impl Spotify { Some(offset), ) { Ok(page) => { - let mut albums: Vec = page - .items - .iter() - .map(|sa| sa.into()) - .collect(); + let mut albums: Vec = + page.items.iter().map(|sa| sa.into()).collect(); albums.sort_by(|a, b| b.year.cmp(&a.year)); Ok(ApiPage { offset: page.offset,