diff --git a/CHANGELOG.md b/CHANGELOG.md index ff6f7495..1e150117 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,7 +6,7 @@ - Show currently playing track in song search menu and play through the searched tracks [#343](https://github.com/Rigellute/spotify-tui/pull/343) - Add a "basic view" that only shows the playbar [#344](https://github.com/Rigellute/spotify-tui/pull/344) - Show currently playing top track [#347](https://github.com/Rigellute/spotify-tui/pull/347) - +- Press shift-s to pick a random song on track-lists [#339](https://github.com/Rigellute/spotify-tui/pull/339) ## [0.16.0] - 2020-03-12 ### Fixed diff --git a/Cargo.lock b/Cargo.lock index aaa5d8f8..cfd840cf 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1107,7 +1107,7 @@ dependencies = [ [[package]] name = "rand" -version = "0.7.2" +version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "getrandom 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1498,6 +1498,7 @@ dependencies = [ "dirs 2.0.2 (registry+https://github.com/rust-lang/crates.io-index)", "failure 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", "proc-macro2 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)", "rspotify 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.104 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.48 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1555,7 +1556,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)", "redox_syscall 0.1.56 (registry+https://github.com/rust-lang/crates.io-index)", "remove_dir_all 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2116,7 +2117,7 @@ dependencies = [ "checksum quote 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)" = "6ce23b6b870e8f94f81fb0a363d65d86675884b34a09043c81e5562f11c1f8e1" "checksum quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "053a8c8bcc71fcce321828dc897a98ab9760bef03a4fc36693c231e5b3216cfe" "checksum rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)" = "6d71dacdc3c88c1fde3885a3be3fbab9f35724e6ce99467f7d9c5026132184ca" -"checksum rand 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)" = "3ae1b169243eaf61759b8475a998f0a385e42042370f3a7dbaf35246eacc8412" +"checksum rand 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)" = "6a6b1679d49b24bbfe0c803429aa1874472f50d9b363131f0e89fc356b544d03" "checksum rand_chacha 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "556d3a1ca6600bfcbab7c7c91ccb085ac7fbbcd70e008a98742e7847f4f7bcef" "checksum rand_chacha 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "03a2a90da8c7523f554344f921aa97283eadf6ac484a6d2a7d0212fa7f8d6853" "checksum rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7a6fdeb83b075e8266dcc8762c22776f6877a63111121f5f8c7411e5be7eed4b" diff --git a/Cargo.toml b/Cargo.toml index 5b224857..bddb43a2 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -28,6 +28,7 @@ clipboard = "0.5.0" crossterm = "0.16" tokio = { version = "0.2", features = ["full"] } proc-macro2 = "1.0.9" +rand="0.7.3" [[bin]] bench = false diff --git a/src/handlers/track_table.rs b/src/handlers/track_table.rs index a606f007..29c03ce0 100644 --- a/src/handlers/track_table.rs +++ b/src/handlers/track_table.rs @@ -4,6 +4,8 @@ use super::{ }; use crate::event::Key; use crate::network::IoEvent; +use rand::{thread_rng, Rng}; +use serde_json::from_value; pub fn handler(key: Key, app: &mut App) { match key { @@ -139,6 +141,7 @@ pub fn handler(key: Key, app: &mut App) { None => {} }; } + Key::Char('S') => play_random_song(app), Key::Ctrl('e') => jump_to_end(app), Key::Ctrl('a') => jump_to_start(app), //recommended song radio @@ -149,6 +152,106 @@ pub fn handler(key: Key, app: &mut App) { } } +fn play_random_song(app: &mut App) { + if let Some(context) = &app.track_table.context { + match context { + TrackTableContext::MyPlaylists => { + let (context_uri, track_json) = match (&app.selected_playlist_index, &app.playlists) { + (Some(selected_playlist_index), Some(playlists)) => { + if let Some(selected_playlist) = playlists.items.get(selected_playlist_index.to_owned()) + { + ( + Some(selected_playlist.uri.to_owned()), + selected_playlist.tracks.get("total"), + ) + } else { + (None, None) + } + } + _ => (None, None), + }; + + if let Some(val) = track_json { + let num_tracks: usize = from_value(val.clone()).unwrap(); + app.dispatch(IoEvent::StartPlayback( + context_uri, + None, + Some(thread_rng().gen_range(0, num_tracks)), + )); + } + } + TrackTableContext::RecommendedTracks => {} + TrackTableContext::SavedTracks => { + if let Some(saved_tracks) = &app.library.saved_tracks.get_results(None) { + let track_uris: Vec = saved_tracks + .items + .iter() + .map(|item| item.track.uri.to_owned()) + .collect(); + let rand_idx = thread_rng().gen_range(0, track_uris.len()); + app.dispatch(IoEvent::StartPlayback( + None, + Some(track_uris), + Some(rand_idx), + )) + } + } + TrackTableContext::AlbumSearch => {} + TrackTableContext::PlaylistSearch => { + let (context_uri, playlist_track_json) = match ( + &app.search_results.selected_playlists_index, + &app.search_results.playlists, + ) { + (Some(selected_playlist_index), Some(playlist_result)) => { + if let Some(selected_playlist) = playlist_result + .playlists + .items + .get(selected_playlist_index.to_owned()) + { + ( + Some(selected_playlist.uri.to_owned()), + selected_playlist.tracks.get("total"), + ) + } else { + (None, None) + } + } + _ => (None, None), + }; + if let Some(val) = playlist_track_json { + let num_tracks: usize = from_value(val.clone()).unwrap(); + app.dispatch(IoEvent::StartPlayback( + context_uri, + None, + Some(thread_rng().gen_range(0, num_tracks)), + )) + } + } + TrackTableContext::MadeForYou => { + if let Some(playlist) = &app + .library + .made_for_you_playlists + .get_results(Some(0)) + .and_then(|playlist| playlist.items.get(app.made_for_you_index)) + { + if let Some(num_tracks) = &playlist + .tracks + .get("total") + .and_then(|total| -> Option { from_value(total.clone()).ok() }) + { + let uri = Some(playlist.uri.clone()); + app.dispatch(IoEvent::StartPlayback( + uri, + None, + Some(thread_rng().gen_range(0, num_tracks)), + )) + }; + }; + } + } + }; +} + fn handle_recommended_tracks(app: &mut App) { let (selected_index, tracks) = (&app.track_table.selected_index, &app.track_table.tracks); if let Some(track) = tracks.get(*selected_index) { diff --git a/src/ui/help.rs b/src/ui/help.rs index cd4a50c0..599dd491 100644 --- a/src/ui/help.rs +++ b/src/ui/help.rs @@ -92,5 +92,6 @@ pub fn get_help_docs() -> Vec> { vec!["Delete saved album", "D", "Library -> Albums"], vec!["Delete saved playist", "D", "Playlist"], vec!["Follow an artists/playlist", "w", "Search result"], + vec!["Play random song in playlist", "S", "Selected Playlist"], ] }