From 2b20670743db67515882babc247f33f39ee43632 Mon Sep 17 00:00:00 2001 From: Qluxzz Date: Sat, 9 Jan 2021 16:36:18 +0100 Subject: [PATCH] Add select artist dialog when multiple artists --- src/album.rs | 13 ++++++---- src/playable.rs | 4 +-- src/track.rs | 13 ++++++---- src/traits.rs | 2 +- src/ui/contextmenu.rs | 60 ++++++++++++++++++++++++++++++++++++++++--- src/ui/listview.rs | 20 ++++++++++++--- 6 files changed, 92 insertions(+), 20 deletions(-) diff --git a/src/album.rs b/src/album.rs index 2d7622d..f8f379f 100644 --- a/src/album.rs +++ b/src/album.rs @@ -248,10 +248,13 @@ impl ListItem for Album { .map(|id| format!("https://open.spotify.com/album/{}", id)) } - fn artist(&self) -> Option { - Some(Artist::new( - self.artist_ids[0].clone(), - self.artists[0].clone(), - )) + fn artists(&self) -> Option> { + Some( + self.artist_ids + .iter() + .zip(self.artists.iter()) + .map(|(id, name)| Artist::new(id.clone(), name.clone())) + .collect(), + ) } } diff --git a/src/playable.rs b/src/playable.rs index 687fb1a..e1fe69a 100644 --- a/src/playable.rs +++ b/src/playable.rs @@ -120,8 +120,8 @@ impl ListItem for Playable { self.as_listitem().album(queue) } - fn artist(&self) -> Option { - self.as_listitem().artist() + fn artists(&self) -> Option> { + self.as_listitem().artists() } fn track(&self) -> Option { diff --git a/src/track.rs b/src/track.rs index 0af73cf..1b48658 100644 --- a/src/track.rs +++ b/src/track.rs @@ -287,11 +287,14 @@ impl ListItem for Track { } } - fn artist(&self) -> Option { - Some(Artist::new( - self.artist_ids[0].clone(), - self.artists[0].clone(), - )) + fn artists(&self) -> Option> { + Some( + self.artist_ids + .iter() + .zip(self.artists.iter()) + .map(|(id, name)| Artist::new(id.clone(), name.clone())) + .collect(), + ) } fn track(&self) -> Option { diff --git a/src/traits.rs b/src/traits.rs index e6d9794..2126301 100644 --- a/src/traits.rs +++ b/src/traits.rs @@ -39,7 +39,7 @@ pub trait ListItem: Sync + Send + 'static { None } - fn artist(&self) -> Option { + fn artists(&self) -> Option> { None } diff --git a/src/ui/contextmenu.rs b/src/ui/contextmenu.rs index 6e408a9..73b1d77 100644 --- a/src/ui/contextmenu.rs +++ b/src/ui/contextmenu.rs @@ -4,7 +4,6 @@ use cursive::view::{Margins, ViewWrapper}; use cursive::views::{Dialog, NamedView, ScrollView, SelectView}; use cursive::Cursive; -use crate::commands::CommandResult; use crate::library::Library; use crate::playable::Playable; use crate::queue::Queue; @@ -14,6 +13,7 @@ use crate::track::Track; use crate::traits::{ListItem, ViewExt}; use crate::ui::layout::Layout; use crate::ui::modal::Modal; +use crate::{artist::Artist, commands::CommandResult}; use crate::{ command::{Command, MoveAmount, MoveMode}, playlist::Playlist, @@ -29,8 +29,13 @@ pub struct AddToPlaylistMenu { dialog: Modal, } +pub struct SelectArtistMenu { + dialog: Modal, +} + enum ContextMenuAction { ShowItem(Box), + SelectArtist(Box>), ShareUrl(String), AddToPlaylist(Box), ShowRecommentations(Box), @@ -94,6 +99,36 @@ impl ContextMenu { .with_name("addtrackmenu") } + pub fn select_artist_dialog( + library: Arc, + queue: Arc, + artists: Vec, + ) -> NamedView { + let mut list_select = SelectView::::new(); + + for artist in artists { + list_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(); + } + }); + + 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"))); + + SelectArtistMenu { + dialog: Modal::new_ext(dialog), + } + .with_name("selectartist") + } + fn track_already_added() -> Dialog { Dialog::text("This track is already in your playlist") .title("Track already exists") @@ -103,8 +138,19 @@ impl ContextMenu { pub fn new(item: &dyn ListItem, queue: Arc, library: Arc) -> NamedView { let mut content: SelectView = SelectView::new(); - if let Some(a) = item.artist() { - content.add_item("Show artist", ContextMenuAction::ShowItem(Box::new(a))); + if let Some(a) = item.artists() { + let action = match a.len() { + 0 => None, + 1 => Some(ContextMenuAction::ShowItem(Box::new(a[0].clone()))), + _ => Some(ContextMenuAction::SelectArtist(Box::new(a))), + }; + + if let Some(a) = action { + content.add_item( + "Show artist", + a + ) + } } if let Some(a) = item.album(queue.clone()) { content.add_item("Show album", ContextMenuAction::ShowItem(Box::new(a))); @@ -161,6 +207,10 @@ impl ContextMenu { let mut track: Track = *track.clone(); track.toggle_saved(library); } + ContextMenuAction::SelectArtist(artists) => { + let dialog = Self::select_artist_dialog(library, queue, *artists.clone()); + s.add_layer(dialog); + } } }); @@ -232,3 +282,7 @@ impl ViewWrapper for AddToPlaylistMenu { impl ViewWrapper for ContextMenu { wrap_impl!(self.dialog: Modal); } + +impl ViewWrapper for SelectArtistMenu { + wrap_impl!(self.dialog: Modal); +} diff --git a/src/ui/listview.rs b/src/ui/listview.rs index e06a8d5..433146c 100644 --- a/src/ui/listview.rs +++ b/src/ui/listview.rs @@ -617,10 +617,22 @@ impl ViewExt for ListView { } } GotoMode::Artist => { - if let Some(artist) = item.artist() { - let view = - ArtistView::new(queue, library, &artist).as_boxed_view_ext(); - return Ok(CommandResult::View(view)); + if let Some(artists) = item.artists() { + return match artists.len() { + 0 => Ok(CommandResult::Consumed(None)), + 1 => { + let view = ArtistView::new(queue, library, &artists[0]).as_boxed_view_ext(); + Ok(CommandResult::View(view)) + } + _ => { + let dialog = ContextMenu::select_artist_dialog( + library, queue, artists, + ); + _s.add_layer(dialog); + + Ok(CommandResult::Consumed(None)) + } + }; } } }