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:
Bettehem
2022-07-27 23:07:30 +03:00
committed by GitHub
parent 5158a13e19
commit bba70b1809
2 changed files with 105 additions and 19 deletions

View File

@@ -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 {

View File

@@ -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>);
}