use std::sync::Arc; use cursive::view::{Margins, ViewWrapper}; use cursive::views::{Dialog, ScrollView, SelectView}; use cursive::Cursive; use crate::library::Library; use crate::queue::Queue; use crate::track::Track; use crate::traits::ListItem; use crate::ui::layout::Layout; use crate::ui::modal::Modal; #[cfg(feature = "share_clipboard")] use clipboard::{ClipboardContext, ClipboardProvider}; pub struct ContextMenu { dialog: Modal, } enum ContextMenuAction { ShowItem(Box), ShareUrl(String), AddToPlaylist(Box), } impl ContextMenu { pub fn add_track_dialog(library: Arc, track: Track) -> Modal { let mut list_select: SelectView = SelectView::new().autojump(); for list in library.items().iter() { list_select.add_item(list.name.clone(), list.id.clone()); } list_select.set_on_submit(move |s, selected| { library.playlist_append_tracks(selected, &[track.clone()]); s.pop_layer(); }); let dialog = Dialog::new() .title("Add track to playlist") .dismiss_button("Cancel") .padding(Margins::lrtb(1, 1, 1, 0)) .content(ScrollView::new(list_select)); Modal::new(dialog) } pub fn new(item: &dyn ListItem, queue: Arc, library: Arc) -> Self { let mut content: SelectView = SelectView::new().autojump(); if let Some(a) = item.artist() { content.add_item("Show artist", ContextMenuAction::ShowItem(Box::new(a))); } if let Some(a) = item.album(queue.clone()) { content.add_item("Show album", ContextMenuAction::ShowItem(Box::new(a))); } if let Some(url) = item.share_url() { #[cfg(feature = "share_clipboard")] content.add_item("Share", ContextMenuAction::ShareUrl(url)); } if let Some(t) = item.track() { content.add_item( "Add to playlist", ContextMenuAction::AddToPlaylist(Box::new(t)), ) } // open detail view of artist/album content.set_on_submit(move |s: &mut Cursive, action: &ContextMenuAction| { s.pop_layer(); let queue = queue.clone(); let library = library.clone(); match action { ContextMenuAction::ShowItem(item) => { if let Some(view) = item.open(queue, library) { s.call_on_name("main", move |v: &mut Layout| v.push_view(view)); } } ContextMenuAction::ShareUrl(url) => { #[cfg(feature = "share_clipboard")] ClipboardProvider::new() .and_then(|mut ctx: ClipboardContext| ctx.set_contents(url.to_string())) .ok(); } ContextMenuAction::AddToPlaylist(track) => { let dialog = Self::add_track_dialog(library, *track.clone()); s.add_layer(dialog); } } }); let dialog = Dialog::new() .title(item.display_left()) .dismiss_button("Cancel") .padding(Margins::lrtb(1, 1, 1, 0)) .content(content); Self { dialog: Modal::new(dialog), } } } impl ViewWrapper for ContextMenu { wrap_impl!(self.dialog: Modal); }