add methods and api usage to delete track from playlist (#211)
* wip: add methods and api usage to delete track from playlist * enh: add ability to remove track from playlist with immediate visual feedback * minor cosmetic changes Co-authored-by: Henrik Friedrichsen <henrik@affekt.org>
This commit is contained in:
@@ -51,6 +51,16 @@ impl Playlist {
|
||||
|
||||
self.tracks = Some(collected_tracks);
|
||||
}
|
||||
|
||||
pub fn delete_tracks(&mut self, track_pos_pairs: &[(Track, usize)], spotify: Arc<Spotify>) {
|
||||
if spotify.delete_tracks(&self.id, track_pos_pairs) {
|
||||
if let Some(tracks) = &mut self.tracks {
|
||||
for (_track, pos) in track_pos_pairs {
|
||||
tracks.remove(*pos);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<&SimplifiedPlaylist> for Playlist {
|
||||
|
||||
@@ -24,6 +24,8 @@ use rspotify::spotify::model::search::{
|
||||
use rspotify::spotify::model::track::{FullTrack, SavedTrack};
|
||||
use rspotify::spotify::model::user::PrivateUser;
|
||||
|
||||
use serde_json::json;
|
||||
|
||||
use failure::Error;
|
||||
|
||||
use futures_01::future::Future as v01_Future;
|
||||
@@ -566,6 +568,27 @@ impl Spotify {
|
||||
.is_some()
|
||||
}
|
||||
|
||||
pub fn delete_tracks(&self, playlist_id: &str, track_pos_pairs: &[(Track, usize)]) -> bool {
|
||||
let mut tracks = Vec::new();
|
||||
for (track, pos) in track_pos_pairs {
|
||||
let track_occurrence = json!({
|
||||
"uri": format!("spotify:track:{}", track.id.clone().unwrap()),
|
||||
"positions": [pos]
|
||||
});
|
||||
let track_occurrence_object = track_occurrence.as_object();
|
||||
tracks.push(track_occurrence_object.unwrap().clone());
|
||||
}
|
||||
self.api_with_retry(|api| {
|
||||
api.user_playlist_remove_specific_occurrenes_of_tracks(
|
||||
self.user.as_ref().unwrap(),
|
||||
playlist_id,
|
||||
tracks.clone(),
|
||||
None,
|
||||
)
|
||||
})
|
||||
.is_some()
|
||||
}
|
||||
|
||||
pub fn overwrite_playlist(&self, id: &str, tracks: &[Track]) {
|
||||
// extract only track IDs
|
||||
let mut tracks: Vec<String> = tracks
|
||||
|
||||
@@ -154,6 +154,11 @@ impl<I: ListItem> ListView<I> {
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
pub fn remove(&self, index: usize) {
|
||||
let mut c = self.content.write().unwrap();
|
||||
c.remove(index);
|
||||
}
|
||||
}
|
||||
|
||||
impl<I: ListItem> View for ListView<I> {
|
||||
|
||||
@@ -8,6 +8,7 @@ use crate::commands::CommandResult;
|
||||
use crate::library::Library;
|
||||
use crate::playlist::Playlist;
|
||||
use crate::queue::Queue;
|
||||
use crate::spotify::Spotify;
|
||||
use crate::track::Track;
|
||||
use crate::traits::ViewExt;
|
||||
use crate::ui::listview::ListView;
|
||||
@@ -15,12 +16,12 @@ use crate::ui::listview::ListView;
|
||||
pub struct PlaylistView {
|
||||
playlist: Playlist,
|
||||
list: ListView<Track>,
|
||||
spotify: Arc<Spotify>,
|
||||
}
|
||||
|
||||
impl PlaylistView {
|
||||
pub fn new(queue: Arc<Queue>, library: Arc<Library>, playlist: &Playlist) -> Self {
|
||||
let mut playlist = playlist.clone();
|
||||
|
||||
playlist.load_tracks(queue.get_spotify());
|
||||
|
||||
let tracks = if let Some(t) = playlist.tracks.as_ref() {
|
||||
@@ -29,9 +30,14 @@ impl PlaylistView {
|
||||
Vec::new()
|
||||
};
|
||||
|
||||
let spotify = queue.get_spotify();
|
||||
let list = ListView::new(Arc::new(RwLock::new(tracks)), queue, library);
|
||||
|
||||
Self { playlist, list }
|
||||
Self {
|
||||
playlist,
|
||||
list,
|
||||
spotify,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -45,6 +51,22 @@ impl ViewExt for PlaylistView {
|
||||
}
|
||||
|
||||
fn on_command(&mut self, s: &mut Cursive, cmd: &Command) -> Result<CommandResult, String> {
|
||||
if let Command::Delete = cmd {
|
||||
let pos = self.list.get_selected_index();
|
||||
let tracks = if let Some(t) = self.playlist.tracks.as_ref() {
|
||||
t.clone()
|
||||
} else {
|
||||
Vec::new()
|
||||
};
|
||||
let track = tracks.get(pos);
|
||||
if let Some(t) = track {
|
||||
self.playlist
|
||||
.delete_tracks(&[(t.clone(), pos)], self.spotify.clone());
|
||||
self.list.remove(pos);
|
||||
}
|
||||
return Ok(CommandResult::Consumed(None));
|
||||
}
|
||||
|
||||
self.list.on_command(s, cmd)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user