Add select artist dialog when multiple artists

This commit is contained in:
Qluxzz
2021-01-09 16:36:18 +01:00
committed by Henrik Friedrichsen
parent 68e51f263d
commit 2b20670743
6 changed files with 92 additions and 20 deletions

View File

@@ -248,10 +248,13 @@ impl ListItem for Album {
.map(|id| format!("https://open.spotify.com/album/{}", id))
}
fn artist(&self) -> Option<Artist> {
Some(Artist::new(
self.artist_ids[0].clone(),
self.artists[0].clone(),
))
fn artists(&self) -> Option<Vec<Artist>> {
Some(
self.artist_ids
.iter()
.zip(self.artists.iter())
.map(|(id, name)| Artist::new(id.clone(), name.clone()))
.collect(),
)
}
}

View File

@@ -120,8 +120,8 @@ impl ListItem for Playable {
self.as_listitem().album(queue)
}
fn artist(&self) -> Option<Artist> {
self.as_listitem().artist()
fn artists(&self) -> Option<Vec<Artist>> {
self.as_listitem().artists()
}
fn track(&self) -> Option<Track> {

View File

@@ -287,11 +287,14 @@ impl ListItem for Track {
}
}
fn artist(&self) -> Option<Artist> {
Some(Artist::new(
self.artist_ids[0].clone(),
self.artists[0].clone(),
))
fn artists(&self) -> Option<Vec<Artist>> {
Some(
self.artist_ids
.iter()
.zip(self.artists.iter())
.map(|(id, name)| Artist::new(id.clone(), name.clone()))
.collect(),
)
}
fn track(&self) -> Option<Track> {

View File

@@ -39,7 +39,7 @@ pub trait ListItem: Sync + Send + 'static {
None
}
fn artist(&self) -> Option<Artist> {
fn artists(&self) -> Option<Vec<Artist>> {
None
}

View File

@@ -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<Dialog>,
}
pub struct SelectArtistMenu {
dialog: Modal<Dialog>,
}
enum ContextMenuAction {
ShowItem(Box<dyn ListItem>),
SelectArtist(Box<Vec<Artist>>),
ShareUrl(String),
AddToPlaylist(Box<Track>),
ShowRecommentations(Box<dyn ListItem>),
@@ -94,6 +99,36 @@ impl ContextMenu {
.with_name("addtrackmenu")
}
pub fn select_artist_dialog(
library: Arc<Library>,
queue: Arc<Queue>,
artists: Vec<Artist>,
) -> NamedView<SelectArtistMenu> {
let mut list_select = SelectView::<Artist>::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<Queue>, library: Arc<Library>) -> NamedView<Self> {
let mut content: SelectView<ContextMenuAction> = 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<Dialog>);
}
impl ViewWrapper for SelectArtistMenu {
wrap_impl!(self.dialog: Modal<Dialog>);
}

View File

@@ -617,10 +617,22 @@ impl<I: ListItem + Clone> ViewExt for ListView<I> {
}
}
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))
}
};
}
}
}