diff --git a/src/commands.rs b/src/commands.rs index 03f1405..80e227e 100644 --- a/src/commands.rs +++ b/src/commands.rs @@ -11,7 +11,9 @@ use crate::library::Library; use crate::queue::{Queue, RepeatSetting}; use crate::spotify::{Spotify, VOLUME_PERCENT}; use crate::traits::{IntoBoxedViewExt, ViewExt}; -use crate::ui::contextmenu::{AddToPlaylistMenu, ContextMenu, PlayTrackMenu, SelectArtistMenu}; +use crate::ui::contextmenu::{ + AddToPlaylistMenu, ContextMenu, PlayTrackMenu, SelectArtistActionMenu, SelectArtistMenu, +}; use crate::ui::help::HelpView; use crate::ui::layout::Layout; use crate::ui::modal::Modal; @@ -301,6 +303,10 @@ impl CommandManager { add_track_menu.on_command(s, cmd)? } else if let Some(mut select_artist) = s.find_name::("selectartist") { select_artist.on_command(s, cmd)? + } else if let Some(mut select_artist_action) = + s.find_name::("selectartistaction") + { + select_artist_action.on_command(s, cmd)? } else if let Some(mut play_track) = s.find_name::("playtrackmenu") { play_track.on_command(s, cmd)? } else { diff --git a/src/ui/contextmenu.rs b/src/ui/contextmenu.rs index 2cadd50..cb377c2 100644 --- a/src/ui/contextmenu.rs +++ b/src/ui/contextmenu.rs @@ -39,10 +39,15 @@ pub struct SelectArtistMenu { dialog: Modal, } +pub struct SelectArtistActionMenu { + dialog: Modal, +} + enum ContextMenuAction { PlayTrack(Box), ShowItem(Box), SelectArtist(Vec), + SelectArtistAction(Artist), #[cfg(feature = "share_clipboard")] ShareUrl(String), AddToPlaylist(Box), @@ -53,10 +58,10 @@ enum ContextMenuAction { impl ContextMenu { pub fn play_track_dialog(queue: Arc, track: Track) -> NamedView { let track_title = track.title.clone(); - let mut list_select = SelectView::::new(); - list_select.add_item("Play now", true); - list_select.add_item("Add to queue", false); - list_select.set_on_submit(move |s, selected| { + let mut track_action_select = SelectView::::new(); + track_action_select.add_item("Play now", true); + track_action_select.add_item("Add to queue", false); + track_action_select.set_on_submit(move |s, selected| { match selected { true => track.borrow().clone().play(queue.clone()), false => track.borrow().clone().queue(queue.clone()), @@ -67,7 +72,9 @@ impl ContextMenu { .title(format!("Play track: {}", track_title)) .dismiss_button("Cancel") .padding(Margins::lrtb(1, 1, 1, 0)) - .content(ScrollView::new(list_select.with_name("playtrack_select"))); + .content(ScrollView::new( + track_action_select.with_name("playtrack_select"), + )); PlayTrackMenu { dialog: Modal::new_ext(dialog), @@ -136,24 +143,27 @@ impl ContextMenu { queue: Arc, artists: Vec, ) -> NamedView { - let mut list_select = SelectView::::new(); + let mut artist_select = SelectView::::new(); for artist in artists { - list_select.add_item(artist.name.clone(), artist); + artist_select.add_item(artist.name.clone(), artist); } - list_select.set_on_submit(move |s, selected| { - if let Some(view) = selected.open(queue.clone(), library.clone()) { - s.call_on_name("main", move |v: &mut Layout| v.push_view(view)); - s.pop_layer(); - } + artist_select.set_on_submit(move |s, selected_artist| { + let dialog = Self::select_artist_action_dialog( + library.clone(), + queue.clone(), + selected_artist.clone(), + ); + s.pop_layer(); + s.add_layer(dialog); }); let dialog = Dialog::new() .title("Select artist") .dismiss_button("Cancel") .padding(Margins::lrtb(1, 1, 1, 0)) - .content(ScrollView::new(list_select.with_name("artist_select"))); + .content(ScrollView::new(artist_select.with_name("artist_select"))); SelectArtistMenu { dialog: Modal::new_ext(dialog), @@ -161,6 +171,58 @@ impl ContextMenu { .with_name("selectartist") } + pub fn select_artist_action_dialog( + library: Arc, + queue: Arc, + artist: Artist, + ) -> NamedView { + let moved_artist = artist.clone(); + let mut artist_action_select = SelectView::::new(); + artist_action_select.add_item("View Artist", true); + artist_action_select.add_item( + format!( + "{}ollow Artist", + if library.is_followed_artist(&artist) { + "Unf" + } else { + "F" + } + ), + false, + ); + artist_action_select.set_on_submit(move |s, selected_action| { + match selected_action { + true => { + if let Some(view) = moved_artist.clone().open(queue.clone(), library.clone()) { + s.call_on_name("main", |v: &mut Layout| v.push_view(view)); + } + } + false => { + if library.clone().is_followed_artist(&moved_artist) { + moved_artist.clone().unsave(library.clone()); + } else { + moved_artist.clone().save(library.clone()); + } + } + } + s.pop_layer(); + }); + let dialog = Dialog::new() + .title(format!( + "Select action for artist: {}", + artist.clone().name.as_str() + )) + .dismiss_button("Cancel") + .padding(Margins::lrtb(1, 1, 1, 0)) + .content(ScrollView::new( + artist_action_select.with_name("artist_action_select"), + )); + SelectArtistActionMenu { + dialog: Modal::new_ext(dialog), + } + .with_name("selectartistaction") + } + fn track_already_added() -> Dialog { Dialog::text("This track is already in your playlist") .title("Track already exists") @@ -170,15 +232,18 @@ impl ContextMenu { pub fn new(item: &dyn ListItem, queue: Arc, library: Arc) -> NamedView { let mut content: SelectView = SelectView::new(); - if let Some(a) = item.artists() { - let action = match a.len() { + if let Some(artists) = item.artists() { + let action = match artists.len() { 0 => None, - 1 => Some(ContextMenuAction::ShowItem(Box::new(a[0].clone()))), - _ => Some(ContextMenuAction::SelectArtist(a)), + 1 => Some(ContextMenuAction::SelectArtistAction(artists[0].clone())), + _ => Some(ContextMenuAction::SelectArtist(artists.clone())), }; if let Some(a) = action { - content.add_item("Show artist", a) + content.add_item( + format!("Artist{}", if artists.len() > 1 { "s" } else { "" }), + a, + ) } } if let Some(a) = item.album(queue.clone()) { @@ -256,6 +321,11 @@ impl ContextMenu { let dialog = Self::select_artist_dialog(library, queue, artists.clone()); s.add_layer(dialog); } + ContextMenuAction::SelectArtistAction(artist) => { + let dialog = + Self::select_artist_action_dialog(library, queue, artist.clone()); + s.add_layer(dialog); + } } }); } @@ -299,6 +369,12 @@ impl ViewExt for SelectArtistMenu { } } +impl ViewExt for SelectArtistActionMenu { + fn on_command(&mut self, s: &mut Cursive, cmd: &Command) -> Result { + handle_move_command::(&mut self.dialog, s, cmd, "artist_action_select") + } +} + fn handle_move_command( sel: &mut Modal, s: &mut Cursive, @@ -351,3 +427,7 @@ impl ViewWrapper for ContextMenu { impl ViewWrapper for SelectArtistMenu { wrap_impl!(self.dialog: Modal); } + +impl ViewWrapper for SelectArtistActionMenu { + wrap_impl!(self.dialog: Modal); +}