Use new pagination interface for user playlists

This commit is contained in:
Henrik Friedrichsen
2021-04-06 16:20:38 +02:00
parent 02921752e1
commit 67aa5b2bad
2 changed files with 27 additions and 28 deletions

View File

@@ -5,7 +5,6 @@ use std::path::PathBuf;
use std::sync::{Arc, RwLock, RwLockReadGuard}; use std::sync::{Arc, RwLock, RwLockReadGuard};
use std::thread; use std::thread;
use rspotify::model::playlist::SimplifiedPlaylist;
use serde::de::DeserializeOwned; use serde::de::DeserializeOwned;
use serde::Serialize; 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() self.playlists()
.iter() .iter()
.find(|local| local.id == remote.id) .find(|local| local.id == remote.id)
@@ -255,9 +254,10 @@ impl Library {
let mut stale_lists = self.playlists.read().unwrap().clone(); let mut stale_lists = self.playlists.read().unwrap().clone();
let mut list_order = Vec::new(); let mut list_order = Vec::new();
let mut lists_result = self.spotify.current_user_playlist(50, 0); let lists_page = self.spotify.current_user_playlist();
while let Some(ref lists) = lists_result.clone() { let mut lists_batch = Some(lists_page.items.read().unwrap().clone());
for (index, remote) in lists.items.iter().enumerate() { while let Some(lists) = &lists_batch {
for (index, remote) in lists.iter().enumerate() {
list_order.push(remote.id.clone()); list_order.push(remote.id.clone());
// remove from stale playlists so we won't prune it later on // remove from stale playlists so we won't prune it later on
@@ -267,7 +267,7 @@ impl Library {
if self.needs_download(remote) { if self.needs_download(remote) {
info!("updating playlist {} (index: {})", remote.name, index); info!("updating playlist {} (index: {})", remote.name, index);
let mut playlist: Playlist = remote.into(); let mut playlist: Playlist = remote.clone();
playlist.tracks = None; playlist.tracks = None;
playlist.load_tracks(self.spotify.clone()); playlist.load_tracks(self.spotify.clone());
self.append_or_update(&playlist); self.append_or_update(&playlist);
@@ -275,16 +275,7 @@ impl Library {
self.ev.trigger(); self.ev.trigger();
} }
} }
lists_batch = lists_page.next();
// 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,
}
} }
// remove stale playlists // remove stale playlists

View File

@@ -14,7 +14,7 @@ use rspotify::blocking::client::Spotify as SpotifyAPI;
use rspotify::model::album::{FullAlbum, SavedAlbum}; use rspotify::model::album::{FullAlbum, SavedAlbum};
use rspotify::model::artist::FullArtist; use rspotify::model::artist::FullArtist;
use rspotify::model::page::{CursorBasedPage, Page}; 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::search::SearchResult;
use rspotify::model::track::{FullTrack, SavedTrack, SimplifiedTrack}; use rspotify::model::track::{FullTrack, SavedTrack, SimplifiedTrack};
use rspotify::model::user::PrivateUser; use rspotify::model::user::PrivateUser;
@@ -50,6 +50,7 @@ use crate::spotify_worker::{Worker, WorkerCommand};
use crate::track::Track; use crate::track::Track;
use crate::album::Album; use crate::album::Album;
use crate::playlist::Playlist;
use crate::ui::pagination::{ApiPage, ApiResult}; use crate::ui::pagination::{ApiPage, ApiResult};
use rspotify::model::recommend::Recommendations; use rspotify::model::recommend::Recommendations;
use rspotify::model::show::{FullEpisode, FullShow, Show, SimplifiedEpisode}; use rspotify::model::show::{FullEpisode, FullShow, Show, SimplifiedEpisode};
@@ -532,12 +533,21 @@ impl Spotify {
.take() .take()
} }
pub fn current_user_playlist( pub fn current_user_playlist(&self) -> ApiResult<Playlist> {
&self, const MAX_LIMIT: u32 = 50;
limit: u32, let spotify = self.clone();
offset: u32, let fetch_page = move |offset: u32| {
) -> Option<Page<SimplifiedPlaylist>> { debug!("fetching user playlists, offset: {}", offset);
self.api_with_retry(|api| api.current_user_playlists(limit, 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( pub fn user_playlist_tracks(
@@ -574,6 +584,7 @@ impl Spotify {
let spotify = self.clone(); let spotify = self.clone();
let artist_id = artist_id.to_string(); let artist_id = artist_id.to_string();
let fetch_page = move |offset: u32| { let fetch_page = move |offset: u32| {
debug!("fetching artist {} albums, offset: {}", artist_id, offset);
spotify.api_with_retry(|api| { spotify.api_with_retry(|api| {
match api.artist_albums( match api.artist_albums(
&artist_id, &artist_id,
@@ -583,11 +594,8 @@ impl Spotify {
Some(offset), Some(offset),
) { ) {
Ok(page) => { Ok(page) => {
let mut albums: Vec<Album> = page let mut albums: Vec<Album> =
.items page.items.iter().map(|sa| sa.into()).collect();
.iter()
.map(|sa| sa.into())
.collect();
albums.sort_by(|a, b| b.year.cmp(&a.year)); albums.sort_by(|a, b| b.year.cmp(&a.year));
Ok(ApiPage { Ok(ApiPage {
offset: page.offset, offset: page.offset,