From db165f05b6827b872750cebdffee6cb8922b3d1f Mon Sep 17 00:00:00 2001 From: ge72mum Date: Sun, 23 Oct 2022 08:58:02 +0200 Subject: [PATCH 1/7] Added 'add to library' entry to menu button for track in album --- src/app/components/details/details_model.rs | 1 + src/app/components/labels.rs | 3 +++ 2 files changed, 4 insertions(+) diff --git a/src/app/components/details/details_model.rs b/src/app/components/details/details_model.rs index 12d98315..e14375cb 100644 --- a/src/app/components/details/details_model.rs +++ b/src/app/components/details/details_model.rs @@ -213,6 +213,7 @@ impl PlaylistModel for DetailsModel { menu.append(Some(&*labels::COPY_LINK), Some("song.copy_link")); menu.append(Some(&*labels::ADD_TO_QUEUE), Some("song.queue")); + menu.append(Some(&*labels::ADD_TO_LIBRARY), Some("song.like")); Some(menu.upcast()) } } diff --git a/src/app/components/labels.rs b/src/app/components/labels.rs index 3bb216f6..270c7707 100644 --- a/src/app/components/labels.rs +++ b/src/app/components/labels.rs @@ -12,6 +12,9 @@ lazy_static! { // translators: This is part of a contextual menu attached to a single track; this entry removes a track from the play queue. pub static ref REMOVE_FROM_QUEUE: String = gettext("Remove from queue"); + + // translators: This is part of a contextual menu attached to a single track; this entry adds a track to the library. + pub static ref ADD_TO_LIBRARY: String = gettext("Add to library"); } pub fn add_to_playlist_label(playlist: &str) -> String { From f996e21cca8ff5cbaeda2f7542a339b7036fad27 Mon Sep 17 00:00:00 2001 From: ge72mum Date: Sun, 23 Oct 2022 09:25:37 +0200 Subject: [PATCH 2/7] Added the functionality to add tracks to the library through the dot menu --- src/app/components/details/details_model.rs | 1 + src/app/components/playlist/song_actions.rs | 21 ++++++++++++++++++++- 2 files changed, 21 insertions(+), 1 deletion(-) diff --git a/src/app/components/details/details_model.rs b/src/app/components/details/details_model.rs index e14375cb..ca5eaf46 100644 --- a/src/app/components/details/details_model.rs +++ b/src/app/components/details/details_model.rs @@ -195,6 +195,7 @@ impl PlaylistModel for DetailsModel { } group.add_action(&song.make_link_action(None)); group.add_action(&song.make_queue_action(self.dispatcher.box_clone(), None)); + group.add_action(&song.make_like_action(self.dispatcher.box_clone(),self.app_model.clone(), None)); Some(group.upcast()) } diff --git a/src/app/components/playlist/song_actions.rs b/src/app/components/playlist/song_actions.rs index c5a45ee6..963fe185 100644 --- a/src/app/components/playlist/song_actions.rs +++ b/src/app/components/playlist/song_actions.rs @@ -1,9 +1,11 @@ use gdk::prelude::*; +use gettextrs::gettext; use gio::SimpleAction; +use std::rc::Rc; use crate::app::models::SongDescription; use crate::app::state::{AppAction, PlaybackAction}; -use crate::app::ActionDispatcher; +use crate::app::{ActionDispatcher, AppModel}; impl SongDescription { pub fn make_queue_action( @@ -79,4 +81,21 @@ impl SongDescription { }) .collect() } + + pub fn make_like_action(&self, dispatcher: Box, app_model: Rc, name: Option<&str>)-> SimpleAction { + let track_id = self.id.clone(); + let like_track = SimpleAction::new(name.unwrap_or("like"), None); + like_track.connect_activate(move |_, _| { + let track_id = track_id.clone(); + let api = app_model.get_spotify(); + dispatcher + .call_spotify_and_dispatch_many(move || async move { + api.save_tracks(vec![track_id]).await?; + Ok(vec![ + AppAction::ShowNotification(gettext("Tracks saved!")), + ]) + }); + }); + like_track + } } From 720c782aaa908a95e044ba53fe13b295edf7cf2f Mon Sep 17 00:00:00 2001 From: ge72mum Date: Sun, 23 Oct 2022 09:45:45 +0200 Subject: [PATCH 3/7] Added functionality to remove track from library --- src/app/components/details/details_model.rs | 2 ++ src/app/components/labels.rs | 3 +++ src/app/components/playlist/song_actions.rs | 19 ++++++++++++++++++- 3 files changed, 23 insertions(+), 1 deletion(-) diff --git a/src/app/components/details/details_model.rs b/src/app/components/details/details_model.rs index ca5eaf46..43a6160c 100644 --- a/src/app/components/details/details_model.rs +++ b/src/app/components/details/details_model.rs @@ -196,6 +196,7 @@ impl PlaylistModel for DetailsModel { group.add_action(&song.make_link_action(None)); group.add_action(&song.make_queue_action(self.dispatcher.box_clone(), None)); group.add_action(&song.make_like_action(self.dispatcher.box_clone(),self.app_model.clone(), None)); + group.add_action(&song.make_unlike_action(self.dispatcher.box_clone(),self.app_model.clone(), None)); Some(group.upcast()) } @@ -215,6 +216,7 @@ impl PlaylistModel for DetailsModel { menu.append(Some(&*labels::COPY_LINK), Some("song.copy_link")); menu.append(Some(&*labels::ADD_TO_QUEUE), Some("song.queue")); menu.append(Some(&*labels::ADD_TO_LIBRARY), Some("song.like")); + menu.append(Some(&*labels::REMOVE_FROM_LIBRARY), Some("song.unlike")); Some(menu.upcast()) } } diff --git a/src/app/components/labels.rs b/src/app/components/labels.rs index 270c7707..e1955308 100644 --- a/src/app/components/labels.rs +++ b/src/app/components/labels.rs @@ -15,6 +15,9 @@ lazy_static! { // translators: This is part of a contextual menu attached to a single track; this entry adds a track to the library. pub static ref ADD_TO_LIBRARY: String = gettext("Add to library"); + + // translators: This is part of a contextual menu attached to a single track; this entry removes a track from the library. + pub static ref REMOVE_FROM_LIBRARY: String = gettext("Remove from library"); } pub fn add_to_playlist_label(playlist: &str) -> String { diff --git a/src/app/components/playlist/song_actions.rs b/src/app/components/playlist/song_actions.rs index 963fe185..f09f3e93 100644 --- a/src/app/components/playlist/song_actions.rs +++ b/src/app/components/playlist/song_actions.rs @@ -92,10 +92,27 @@ impl SongDescription { .call_spotify_and_dispatch_many(move || async move { api.save_tracks(vec![track_id]).await?; Ok(vec![ - AppAction::ShowNotification(gettext("Tracks saved!")), + AppAction::ShowNotification(gettext("Track saved!")), ]) }); }); like_track } + + pub fn make_unlike_action(&self, dispatcher: Box, app_model: Rc, name: Option<&str>)-> SimpleAction { + let track_id = self.id.clone(); + let unlike_track = SimpleAction::new(name.unwrap_or("unlike"), None); + unlike_track.connect_activate(move |_, _| { + let track_id = track_id.clone(); + let api = app_model.get_spotify(); + dispatcher + .call_spotify_and_dispatch_many(move || async move { + api.remove_saved_tracks(vec![track_id]).await?; + Ok(vec![ + AppAction::ShowNotification(gettext("Track unsaved!")), + ]) + }); + }); + unlike_track + } } From ff51890debd5d635efe4bd28fa1041189dc29f55 Mon Sep 17 00:00:00 2001 From: ge72mum Date: Mon, 24 Oct 2022 09:35:58 +0200 Subject: [PATCH 4/7] Added "add/remove track to/from library" to all track dot menus --- .../artist_details/artist_details_model.rs | 12 +++++++ src/app/components/details/details_model.rs | 12 +++++-- .../now_playing/now_playing_model.rs | 12 +++++++ src/app/components/playlist/song_actions.rs | 32 +++++++++++-------- .../playlist_details_model.rs | 12 +++++++ .../saved_tracks/saved_tracks_model.rs | 6 ++++ 6 files changed, 70 insertions(+), 16 deletions(-) diff --git a/src/app/components/artist_details/artist_details_model.rs b/src/app/components/artist_details/artist_details_model.rs index c8ccecec..7c073413 100644 --- a/src/app/components/artist_details/artist_details_model.rs +++ b/src/app/components/artist_details/artist_details_model.rs @@ -113,6 +113,16 @@ impl PlaylistModel for ArtistDetailsModel { group.add_action(&song.make_album_action(self.dispatcher.box_clone(), None)); group.add_action(&song.make_link_action(None)); group.add_action(&song.make_queue_action(self.dispatcher.box_clone(), None)); + group.add_action(&song.make_like_action( + self.dispatcher.box_clone(), + self.app_model.clone(), + None, + )); + group.add_action(&song.make_unlike_action( + self.dispatcher.box_clone(), + self.app_model.clone(), + None, + )); Some(group.upcast()) } @@ -132,6 +142,8 @@ impl PlaylistModel for ArtistDetailsModel { menu.append(Some(&*labels::COPY_LINK), Some("song.copy_link")); menu.append(Some(&*labels::ADD_TO_QUEUE), Some("song.queue")); + menu.append(Some(&*labels::ADD_TO_LIBRARY), Some("song.like")); + menu.append(Some(&*labels::REMOVE_FROM_LIBRARY), Some("song.unlike")); Some(menu.upcast()) } diff --git a/src/app/components/details/details_model.rs b/src/app/components/details/details_model.rs index 43a6160c..58ea3b6c 100644 --- a/src/app/components/details/details_model.rs +++ b/src/app/components/details/details_model.rs @@ -195,8 +195,16 @@ impl PlaylistModel for DetailsModel { } group.add_action(&song.make_link_action(None)); group.add_action(&song.make_queue_action(self.dispatcher.box_clone(), None)); - group.add_action(&song.make_like_action(self.dispatcher.box_clone(),self.app_model.clone(), None)); - group.add_action(&song.make_unlike_action(self.dispatcher.box_clone(),self.app_model.clone(), None)); + group.add_action(&song.make_like_action( + self.dispatcher.box_clone(), + self.app_model.clone(), + None, + )); + group.add_action(&song.make_unlike_action( + self.dispatcher.box_clone(), + self.app_model.clone(), + None, + )); Some(group.upcast()) } diff --git a/src/app/components/now_playing/now_playing_model.rs b/src/app/components/now_playing/now_playing_model.rs index 0e32558a..2384726b 100644 --- a/src/app/components/now_playing/now_playing_model.rs +++ b/src/app/components/now_playing/now_playing_model.rs @@ -79,6 +79,16 @@ impl PlaylistModel for NowPlayingModel { group.add_action(&song.make_album_action(self.dispatcher.box_clone(), None)); group.add_action(&song.make_link_action(None)); group.add_action(&song.make_dequeue_action(self.dispatcher.box_clone(), None)); + group.add_action(&song.make_like_action( + self.dispatcher.box_clone(), + self.app_model.clone(), + None, + )); + group.add_action(&song.make_unlike_action( + self.dispatcher.box_clone(), + self.app_model.clone(), + None, + )); Some(group.upcast()) } @@ -99,6 +109,8 @@ impl PlaylistModel for NowPlayingModel { menu.append(Some(&*labels::COPY_LINK), Some("song.copy_link")); menu.append(Some(&*labels::REMOVE_FROM_QUEUE), Some("song.dequeue")); + menu.append(Some(&*labels::ADD_TO_LIBRARY), Some("song.like")); + menu.append(Some(&*labels::REMOVE_FROM_LIBRARY), Some("song.unlike")); Some(menu.upcast()) } diff --git a/src/app/components/playlist/song_actions.rs b/src/app/components/playlist/song_actions.rs index f09f3e93..e5e99312 100644 --- a/src/app/components/playlist/song_actions.rs +++ b/src/app/components/playlist/song_actions.rs @@ -82,35 +82,39 @@ impl SongDescription { .collect() } - pub fn make_like_action(&self, dispatcher: Box, app_model: Rc, name: Option<&str>)-> SimpleAction { + pub fn make_like_action( + &self, + dispatcher: Box, + app_model: Rc, + name: Option<&str>, + ) -> SimpleAction { let track_id = self.id.clone(); let like_track = SimpleAction::new(name.unwrap_or("like"), None); like_track.connect_activate(move |_, _| { - let track_id = track_id.clone(); + let track_id = track_id.clone(); let api = app_model.get_spotify(); - dispatcher - .call_spotify_and_dispatch_many(move || async move { + dispatcher.call_spotify_and_dispatch_many(move || async move { api.save_tracks(vec![track_id]).await?; - Ok(vec![ - AppAction::ShowNotification(gettext("Track saved!")), - ]) + Ok(vec![AppAction::ShowNotification(gettext("Track saved!"))]) }); }); like_track } - pub fn make_unlike_action(&self, dispatcher: Box, app_model: Rc, name: Option<&str>)-> SimpleAction { + pub fn make_unlike_action( + &self, + dispatcher: Box, + app_model: Rc, + name: Option<&str>, + ) -> SimpleAction { let track_id = self.id.clone(); let unlike_track = SimpleAction::new(name.unwrap_or("unlike"), None); unlike_track.connect_activate(move |_, _| { - let track_id = track_id.clone(); + let track_id = track_id.clone(); let api = app_model.get_spotify(); - dispatcher - .call_spotify_and_dispatch_many(move || async move { + dispatcher.call_spotify_and_dispatch_many(move || async move { api.remove_saved_tracks(vec![track_id]).await?; - Ok(vec![ - AppAction::ShowNotification(gettext("Track unsaved!")), - ]) + Ok(vec![AppAction::ShowNotification(gettext("Track unsaved!"))]) }); }); unlike_track diff --git a/src/app/components/playlist_details/playlist_details_model.rs b/src/app/components/playlist_details/playlist_details_model.rs index 9349f8a1..a5ef43e0 100644 --- a/src/app/components/playlist_details/playlist_details_model.rs +++ b/src/app/components/playlist_details/playlist_details_model.rs @@ -132,6 +132,16 @@ impl PlaylistModel for PlaylistDetailsModel { group.add_action(&song.make_album_action(self.dispatcher.box_clone(), None)); group.add_action(&song.make_link_action(None)); group.add_action(&song.make_queue_action(self.dispatcher.box_clone(), None)); + group.add_action(&song.make_like_action( + self.dispatcher.box_clone(), + self.app_model.clone(), + None, + )); + group.add_action(&song.make_unlike_action( + self.dispatcher.box_clone(), + self.app_model.clone(), + None, + )); Some(group.upcast()) } @@ -151,6 +161,8 @@ impl PlaylistModel for PlaylistDetailsModel { menu.append(Some(&*labels::COPY_LINK), Some("song.copy_link")); menu.append(Some(&*labels::ADD_TO_QUEUE), Some("song.queue")); + menu.append(Some(&*labels::ADD_TO_LIBRARY), Some("song.like")); + menu.append(Some(&*labels::REMOVE_FROM_LIBRARY), Some("song.unlike")); Some(menu.upcast()) } diff --git a/src/app/components/saved_tracks/saved_tracks_model.rs b/src/app/components/saved_tracks/saved_tracks_model.rs index 5bc8349a..50d7e711 100644 --- a/src/app/components/saved_tracks/saved_tracks_model.rs +++ b/src/app/components/saved_tracks/saved_tracks_model.rs @@ -97,6 +97,11 @@ impl PlaylistModel for SavedTracksModel { } group.add_action(&song.make_album_action(self.dispatcher.box_clone(), None)); group.add_action(&song.make_link_action(None)); + group.add_action(&song.make_unlike_action( + self.dispatcher.box_clone(), + self.app_model.clone(), + None, + )); Some(group.upcast()) } @@ -115,6 +120,7 @@ impl PlaylistModel for SavedTracksModel { } menu.append(Some(&*labels::COPY_LINK), Some("song.copy_link")); + menu.append(Some(&*labels::REMOVE_FROM_LIBRARY), Some("song.unlike")); Some(menu.upcast()) } From 43d877dbb3dc3ed5138582148fd4a74b21dba433 Mon Sep 17 00:00:00 2001 From: ge72mum Date: Tue, 25 Oct 2022 16:06:02 +0200 Subject: [PATCH 5/7] Adding/ removing track from library also updates the 'saved tracks' view now --- src/app/components/playlist/song_actions.rs | 24 +++++++++++++-------- 1 file changed, 15 insertions(+), 9 deletions(-) diff --git a/src/app/components/playlist/song_actions.rs b/src/app/components/playlist/song_actions.rs index e5e99312..ba681544 100644 --- a/src/app/components/playlist/song_actions.rs +++ b/src/app/components/playlist/song_actions.rs @@ -4,7 +4,7 @@ use gio::SimpleAction; use std::rc::Rc; use crate::app::models::SongDescription; -use crate::app::state::{AppAction, PlaybackAction}; +use crate::app::state::{AppAction, PlaybackAction, SelectionAction}; use crate::app::{ActionDispatcher, AppModel}; impl SongDescription { @@ -88,14 +88,17 @@ impl SongDescription { app_model: Rc, name: Option<&str>, ) -> SimpleAction { - let track_id = self.id.clone(); + let track_id1 = self.id.clone(); + let song = self.clone(); let like_track = SimpleAction::new(name.unwrap_or("like"), None); like_track.connect_activate(move |_, _| { - let track_id = track_id.clone(); + let track_id2 = track_id1.clone(); + let song = song.clone(); let api = app_model.get_spotify(); + dispatcher.dispatch(SelectionAction::Select(vec![song]).into()); dispatcher.call_spotify_and_dispatch_many(move || async move { - api.save_tracks(vec![track_id]).await?; - Ok(vec![AppAction::ShowNotification(gettext("Track saved!"))]) + api.save_tracks(vec![track_id2]).await?; + Ok(vec![AppAction::SaveSelection, AppAction::ShowNotification(gettext("Track saved!"))]) }); }); like_track @@ -107,14 +110,17 @@ impl SongDescription { app_model: Rc, name: Option<&str>, ) -> SimpleAction { - let track_id = self.id.clone(); + let track_id1 = self.id.clone(); + let song = self.clone(); let unlike_track = SimpleAction::new(name.unwrap_or("unlike"), None); unlike_track.connect_activate(move |_, _| { - let track_id = track_id.clone(); + let track_id2 = track_id1.clone(); + let song = song.clone(); let api = app_model.get_spotify(); + dispatcher.dispatch(SelectionAction::Select(vec![song]).into()); dispatcher.call_spotify_and_dispatch_many(move || async move { - api.remove_saved_tracks(vec![track_id]).await?; - Ok(vec![AppAction::ShowNotification(gettext("Track unsaved!"))]) + api.remove_saved_tracks(vec![track_id2]).await?; + Ok(vec![AppAction::UnsaveSelection, AppAction::ShowNotification(gettext("Track unsaved!"))]) }); }); unlike_track From 8c2a41fc2cc532fc787cb18d5e6f46e70b3ee119 Mon Sep 17 00:00:00 2001 From: ge72mum Date: Wed, 26 Oct 2022 08:15:05 +0200 Subject: [PATCH 6/7] update format --- src/app/components/playlist/song_actions.rs | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/app/components/playlist/song_actions.rs b/src/app/components/playlist/song_actions.rs index ba681544..2a1ace1d 100644 --- a/src/app/components/playlist/song_actions.rs +++ b/src/app/components/playlist/song_actions.rs @@ -98,7 +98,10 @@ impl SongDescription { dispatcher.dispatch(SelectionAction::Select(vec![song]).into()); dispatcher.call_spotify_and_dispatch_many(move || async move { api.save_tracks(vec![track_id2]).await?; - Ok(vec![AppAction::SaveSelection, AppAction::ShowNotification(gettext("Track saved!"))]) + Ok(vec![ + AppAction::SaveSelection, + AppAction::ShowNotification(gettext("Track saved!")), + ]) }); }); like_track @@ -120,7 +123,10 @@ impl SongDescription { dispatcher.dispatch(SelectionAction::Select(vec![song]).into()); dispatcher.call_spotify_and_dispatch_many(move || async move { api.remove_saved_tracks(vec![track_id2]).await?; - Ok(vec![AppAction::UnsaveSelection, AppAction::ShowNotification(gettext("Track unsaved!"))]) + Ok(vec![ + AppAction::UnsaveSelection, + AppAction::ShowNotification(gettext("Track unsaved!")), + ]) }); }); unlike_track From 5d3775823c26c23ec0488668da9ba3064a95d2bc Mon Sep 17 00:00:00 2001 From: ge72mum Date: Wed, 26 Oct 2022 08:41:44 +0200 Subject: [PATCH 7/7] renamed vars --- src/app/components/playlist/song_actions.rs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/app/components/playlist/song_actions.rs b/src/app/components/playlist/song_actions.rs index 2a1ace1d..8a3d6e45 100644 --- a/src/app/components/playlist/song_actions.rs +++ b/src/app/components/playlist/song_actions.rs @@ -88,16 +88,16 @@ impl SongDescription { app_model: Rc, name: Option<&str>, ) -> SimpleAction { - let track_id1 = self.id.clone(); + let track_id = self.id.clone(); let song = self.clone(); let like_track = SimpleAction::new(name.unwrap_or("like"), None); like_track.connect_activate(move |_, _| { - let track_id2 = track_id1.clone(); + let track_id = track_id.clone(); let song = song.clone(); let api = app_model.get_spotify(); dispatcher.dispatch(SelectionAction::Select(vec![song]).into()); dispatcher.call_spotify_and_dispatch_many(move || async move { - api.save_tracks(vec![track_id2]).await?; + api.save_tracks(vec![track_id]).await?; Ok(vec![ AppAction::SaveSelection, AppAction::ShowNotification(gettext("Track saved!")), @@ -113,16 +113,16 @@ impl SongDescription { app_model: Rc, name: Option<&str>, ) -> SimpleAction { - let track_id1 = self.id.clone(); + let track_id = self.id.clone(); let song = self.clone(); let unlike_track = SimpleAction::new(name.unwrap_or("unlike"), None); unlike_track.connect_activate(move |_, _| { - let track_id2 = track_id1.clone(); + let track_id = track_id.clone(); let song = song.clone(); let api = app_model.get_spotify(); dispatcher.dispatch(SelectionAction::Select(vec![song]).into()); dispatcher.call_spotify_and_dispatch_many(move || async move { - api.remove_saved_tracks(vec![track_id2]).await?; + api.remove_saved_tracks(vec![track_id]).await?; Ok(vec![ AppAction::UnsaveSelection, AppAction::ShowNotification(gettext("Track unsaved!")),