diff --git a/src/library.rs b/src/library.rs index 3f17eb4..960fbf3 100644 --- a/src/library.rs +++ b/src/library.rs @@ -523,6 +523,18 @@ impl Library { } } + // Return true if the given playlist contains the given track + pub fn playlist_has_track(&self, playlist_id: &str, track_id: &str) -> bool { + let playlists = self.playlists.read().expect("can't readlock playlists"); + if let Some(playlist) = playlists.iter().find(|p| p.id == playlist_id) { + playlist.tracks.as_ref().map_or(false, |tracks| { + tracks.iter().any(|t| t.id == Some(track_id.to_string())) + }) + } else { + false + } + } + pub fn playlist_append_tracks(&self, playlist_id: &str, new_tracks: &[Track]) { let track_ids: Vec = new_tracks .to_vec() diff --git a/src/playlist.rs b/src/playlist.rs index 04193bc..4bc4f63 100644 --- a/src/playlist.rs +++ b/src/playlist.rs @@ -27,6 +27,10 @@ impl Playlist { return; } + self.tracks = Some(self.get_all_tracks(spotify)); + } + + pub fn get_all_tracks(&self, spotify: Arc) -> Vec { let mut collected_tracks = Vec::new(); let mut tracks_result = spotify.user_playlist_tracks(&self.id, 100, 0); @@ -52,7 +56,7 @@ impl Playlist { } } - self.tracks = Some(collected_tracks); + collected_tracks } pub fn delete_tracks(&mut self, track_pos_pairs: &[(Track, usize)], spotify: Arc) { diff --git a/src/ui/contextmenu.rs b/src/ui/contextmenu.rs index 23855ee..eb83fab 100644 --- a/src/ui/contextmenu.rs +++ b/src/ui/contextmenu.rs @@ -36,7 +36,28 @@ impl ContextMenu { } list_select.set_on_submit(move |s, selected| { - library.playlist_append_tracks(selected, &[track.clone()]); + let track = track.clone(); + + if library.playlist_has_track(selected, &track.id.as_ref().unwrap_or(&"".to_string())) { + let mut already_added_dialog = Self::track_already_added(); + + let lib = Arc::clone(&library); + let selected = selected.to_string(); + already_added_dialog.add_button("Add anyway", move |c| { + lib.playlist_append_tracks(&selected.clone(), &[track.clone()]); + c.pop_layer(); + + // Close add_track_dialog too + c.pop_layer(); + }); + + let modal = Modal::new(already_added_dialog); + s.add_layer(modal); + + return; + } + + library.playlist_append_tracks(selected, &[track]); s.pop_layer(); }); @@ -48,6 +69,13 @@ impl ContextMenu { Modal::new(dialog) } + fn track_already_added() -> Dialog { + Dialog::text("This track is already in your playlist") + .title("Track already exists") + .padding(Margins::lrtb(1, 1, 1, 0)) + .dismiss_button("Cancel") + } + pub fn new(item: &dyn ListItem, queue: Arc, library: Arc) -> NamedView { let mut content: SelectView = SelectView::new().autojump(); if let Some(a) = item.artist() {