From 52e8c1b4deb361362f4adb992c960ec31f1db273 Mon Sep 17 00:00:00 2001 From: Tom <25043847+Douile@users.noreply.github.com> Date: Mon, 1 Mar 2021 22:34:36 +0000 Subject: [PATCH] #96: Add basic menus everywhere (#111) * Add menus to playlists * Add artist menus * Add copy menus * Add album menus --- .../artist_details/artist_details_model.rs | 56 +++++++++++++++-- src/app/components/details/details_model.rs | 48 +++++++++++++-- .../now_playing/now_playing_model.rs | 18 +++++- .../playlist_details_model.rs | 61 +++++++++++++++++-- 4 files changed, 166 insertions(+), 17 deletions(-) diff --git a/src/app/components/artist_details/artist_details_model.rs b/src/app/components/artist_details/artist_details_model.rs index e96d4b2f..15778d46 100644 --- a/src/app/components/artist_details/artist_details_model.rs +++ b/src/app/components/artist_details/artist_details_model.rs @@ -1,3 +1,7 @@ +use gdk::SELECTION_CLIPBOARD; +use gio::prelude::*; +use gio::{ActionMapExt, SimpleAction, SimpleActionGroup}; +use gtk::Clipboard; use std::ops::Deref; use std::rc::Rc; @@ -105,11 +109,55 @@ impl PlaylistModel for ArtistDetailsModel { ) } - fn actions_for(&self, _: String) -> Option { - None + fn actions_for(&self, id: String) -> Option { + let songs = self.tracks_ref()?; + let song = songs.iter().find(|song| song.id == id)?; + + let group = SimpleActionGroup::new(); + + let album_id = song.album.id.clone(); + let view_album = SimpleAction::new("view_album", None); + let dispatcher = self.dispatcher.box_clone(); + view_album.connect_activate(move |_, _| { + dispatcher.dispatch(AppAction::ViewAlbum(album_id.clone())); + }); + + group.add_action(&view_album); + + for (i, artist) in song.artists.iter().enumerate() { + let view_artist = SimpleAction::new(&format!("view_artist_{}", i), None); + let dispatcher = self.dispatcher.box_clone(); + let id = artist.id.clone(); + view_artist.connect_activate(move |_, _| { + dispatcher.dispatch(AppAction::ViewArtist(id.clone())); + }); + group.add_action(&view_artist); + } + + let track_id = song.id.clone(); + let copy_link = SimpleAction::new("copy_link", None); + copy_link.connect_activate(move |_, _| { + let clipboard = Clipboard::get(&SELECTION_CLIPBOARD); + clipboard.set_text(&format!("https://open.spotify.com/track/{}", &track_id,)); + }); + group.add_action(©_link); + + Some(group.upcast()) } - fn menu_for(&self, _: String) -> Option { - None + fn menu_for(&self, id: String) -> Option { + let songs = self.tracks_ref()?; + let song = songs.iter().find(|song| song.id == id)?; + + let menu = gio::Menu::new(); + menu.append(Some("View album"), Some("song.view_album")); + for (i, artist) in song.artists.iter().enumerate() { + menu.append( + Some(&format!("More from {}", artist.name)), + Some(&format!("song.view_artist_{}", i)), + ); + } + menu.append(Some("Copy link"), Some("song.copy_link")); + Some(menu.upcast()) } } diff --git a/src/app/components/details/details_model.rs b/src/app/components/details/details_model.rs index 4ee9babc..aaccb74b 100644 --- a/src/app/components/details/details_model.rs +++ b/src/app/components/details/details_model.rs @@ -1,3 +1,7 @@ +use gdk::SELECTION_CLIPBOARD; +use gio::prelude::*; +use gio::{ActionMapExt, SimpleAction, SimpleActionGroup}; +use gtk::Clipboard; use std::cell::Ref; use std::ops::Deref; use std::rc::Rc; @@ -118,11 +122,47 @@ impl PlaylistModel for DetailsModel { ) } - fn actions_for(&self, _: String) -> Option { - None + fn actions_for(&self, id: String) -> Option { + let songs = self.songs_ref()?; + let song = songs.iter().find(|song| song.id == id)?; + + let group = SimpleActionGroup::new(); + + for (i, artist) in song.artists.iter().enumerate() { + let view_artist = SimpleAction::new(&format!("view_artist_{}", i), None); + let dispatcher = self.dispatcher.box_clone(); + let id = artist.id.clone(); + view_artist.connect_activate(move |_, _| { + dispatcher.dispatch(AppAction::ViewArtist(id.clone())); + }); + group.add_action(&view_artist); + } + + let track_id = song.id.clone(); + let copy_link = SimpleAction::new("copy_link", None); + copy_link.connect_activate(move |_, _| { + let clipboard = Clipboard::get(&SELECTION_CLIPBOARD); + clipboard.set_text(&format!("https://open.spotify.com/track/{}", &track_id)); + }); + group.add_action(©_link); + + Some(group.upcast()) } - fn menu_for(&self, _: String) -> Option { - None + fn menu_for(&self, id: String) -> Option { + let songs = self.songs_ref()?; + let song = songs.iter().find(|song| song.id == id)?; + + let menu = gio::Menu::new(); + for (i, artist) in song.artists.iter().enumerate() { + menu.append( + Some(&format!("More from {}", artist.name)), + Some(&format!("song.view_artist_{}", i)), + ); + } + + menu.append(Some("Copy link"), Some("song.copy_link")); + + Some(menu.upcast()) } } diff --git a/src/app/components/now_playing/now_playing_model.rs b/src/app/components/now_playing/now_playing_model.rs index c02f42a5..34cb08e9 100644 --- a/src/app/components/now_playing/now_playing_model.rs +++ b/src/app/components/now_playing/now_playing_model.rs @@ -1,5 +1,7 @@ +use gdk::SELECTION_CLIPBOARD; use gio::prelude::*; use gio::{ActionMapExt, SimpleAction, SimpleActionGroup}; +use gtk::Clipboard; use std::cell::Ref; use std::rc::Rc; @@ -77,6 +79,14 @@ impl PlaylistModel for NowPlayingModel { group.add_action(&view_artist); } + let track_id = song.id.clone(); + let copy_link = SimpleAction::new("copy_link", None); + copy_link.connect_activate(move |_, _| { + let clipboard = Clipboard::get(&SELECTION_CLIPBOARD); + clipboard.set_text(&format!("https://open.spotify.com/track/{}", &track_id)); + }); + group.add_action(©_link); + Some(group.upcast()) } @@ -85,14 +95,16 @@ impl PlaylistModel for NowPlayingModel { let song = queue.song(&id)?; let menu = gio::Menu::new(); - menu.insert(0, Some("View album"), Some("song.view_album")); + menu.append(Some("View album"), Some("song.view_album")); for (i, artist) in song.artists.iter().enumerate() { - menu.insert( - (i + 1) as i32, + menu.append( Some(&format!("More from {}", artist.name)), Some(&format!("song.view_artist_{}", i)), ); } + + menu.append(Some("Copy link"), Some("song.copy_link")); + Some(menu.upcast()) } } diff --git a/src/app/components/playlist_details/playlist_details_model.rs b/src/app/components/playlist_details/playlist_details_model.rs index f7352d94..b97fd41d 100644 --- a/src/app/components/playlist_details/playlist_details_model.rs +++ b/src/app/components/playlist_details/playlist_details_model.rs @@ -1,12 +1,15 @@ +use gdk::SELECTION_CLIPBOARD; +use gio::prelude::*; +use gio::{ActionMapExt, SimpleAction, SimpleActionGroup}; +use gtk::Clipboard; use std::cell::Ref; use std::ops::Deref; use std::rc::Rc; use crate::app::components::{handle_error, PlaylistModel}; -use crate::app::dispatch::ActionDispatcher; use crate::app::models::*; use crate::app::state::{BrowserAction, BrowserEvent, PlaybackAction, PlaylistSource}; -use crate::app::{AppEvent, AppModel, AppState}; +use crate::app::{ActionDispatcher, AppAction, AppEvent, AppModel, AppState}; pub struct PlaylistDetailsModel { pub id: String, @@ -94,11 +97,57 @@ impl PlaylistModel for PlaylistDetailsModel { ) } - fn actions_for(&self, _: String) -> Option { - None + fn actions_for(&self, id: String) -> Option { + let songs = self.songs_ref()?; + let song = songs.iter().find(|song| song.id == id)?; + + let group = SimpleActionGroup::new(); + + let album_id = song.album.id.clone(); + let view_album = SimpleAction::new("view_album", None); + let dispatcher = self.dispatcher.box_clone(); + view_album.connect_activate(move |_, _| { + dispatcher.dispatch(AppAction::ViewAlbum(album_id.clone())); + }); + + group.add_action(&view_album); + + for (i, artist) in song.artists.iter().enumerate() { + let view_artist = SimpleAction::new(&format!("view_artist_{}", i), None); + let dispatcher = self.dispatcher.box_clone(); + let id = artist.id.clone(); + view_artist.connect_activate(move |_, _| { + dispatcher.dispatch(AppAction::ViewArtist(id.clone())); + }); + group.add_action(&view_artist); + } + + let track_id = song.id.clone(); + let copy_link = SimpleAction::new("copy_link", None); + copy_link.connect_activate(move |_, _| { + let clipboard = Clipboard::get(&SELECTION_CLIPBOARD); + clipboard.set_text(&format!("https://open.spotify.com/track/{}", &track_id)); + }); + group.add_action(©_link); + + Some(group.upcast()) } - fn menu_for(&self, _: String) -> Option { - None + fn menu_for(&self, id: String) -> Option { + let songs = self.songs_ref()?; + let song = songs.iter().find(|song| song.id == id)?; + + let menu = gio::Menu::new(); + menu.append(Some("View album"), Some("song.view_album")); + for (i, artist) in song.artists.iter().enumerate() { + menu.append( + Some(&format!("More from {}", artist.name)), + Some(&format!("song.view_artist_{}", i)), + ); + } + + menu.append(Some("Copy link"), Some("song.copy_link")); + + Some(menu.upcast()) } }