Added possibility to Follow/Unfollow artists via the context menu (#868)
* Added possibility to Follow/Unfollow artists via the context menu * Formatted code properly. * Changed Show Artist to Artist (or Artists if there are many).
This commit is contained in:
@@ -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::<SelectArtistMenu>("selectartist") {
|
||||
select_artist.on_command(s, cmd)?
|
||||
} else if let Some(mut select_artist_action) =
|
||||
s.find_name::<SelectArtistActionMenu>("selectartistaction")
|
||||
{
|
||||
select_artist_action.on_command(s, cmd)?
|
||||
} else if let Some(mut play_track) = s.find_name::<PlayTrackMenu>("playtrackmenu") {
|
||||
play_track.on_command(s, cmd)?
|
||||
} else {
|
||||
|
||||
@@ -39,10 +39,15 @@ pub struct SelectArtistMenu {
|
||||
dialog: Modal<Dialog>,
|
||||
}
|
||||
|
||||
pub struct SelectArtistActionMenu {
|
||||
dialog: Modal<Dialog>,
|
||||
}
|
||||
|
||||
enum ContextMenuAction {
|
||||
PlayTrack(Box<Track>),
|
||||
ShowItem(Box<dyn ListItem>),
|
||||
SelectArtist(Vec<Artist>),
|
||||
SelectArtistAction(Artist),
|
||||
#[cfg(feature = "share_clipboard")]
|
||||
ShareUrl(String),
|
||||
AddToPlaylist(Box<Track>),
|
||||
@@ -53,10 +58,10 @@ enum ContextMenuAction {
|
||||
impl ContextMenu {
|
||||
pub fn play_track_dialog(queue: Arc<Queue>, track: Track) -> NamedView<PlayTrackMenu> {
|
||||
let track_title = track.title.clone();
|
||||
let mut list_select = SelectView::<bool>::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::<bool>::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<Queue>,
|
||||
artists: Vec<Artist>,
|
||||
) -> NamedView<SelectArtistMenu> {
|
||||
let mut list_select = SelectView::<Artist>::new();
|
||||
let mut artist_select = SelectView::<Artist>::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<Library>,
|
||||
queue: Arc<Queue>,
|
||||
artist: Artist,
|
||||
) -> NamedView<SelectArtistActionMenu> {
|
||||
let moved_artist = artist.clone();
|
||||
let mut artist_action_select = SelectView::<bool>::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<Queue>, library: Arc<Library>) -> NamedView<Self> {
|
||||
let mut content: SelectView<ContextMenuAction> = 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<CommandResult, String> {
|
||||
handle_move_command::<bool>(&mut self.dialog, s, cmd, "artist_action_select")
|
||||
}
|
||||
}
|
||||
|
||||
fn handle_move_command<T: 'static>(
|
||||
sel: &mut Modal<Dialog>,
|
||||
s: &mut Cursive,
|
||||
@@ -351,3 +427,7 @@ impl ViewWrapper for ContextMenu {
|
||||
impl ViewWrapper for SelectArtistMenu {
|
||||
wrap_impl!(self.dialog: Modal<Dialog>);
|
||||
}
|
||||
|
||||
impl ViewWrapper for SelectArtistActionMenu {
|
||||
wrap_impl!(self.dialog: Modal<Dialog>);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user