Skip to content

Commit

Permalink
Use separate entities for playlist and folders
Browse files Browse the repository at this point in the history
  • Loading branch information
aNNiMON committed Aug 5, 2024
1 parent 3475e0c commit 6fb37d2
Show file tree
Hide file tree
Showing 13 changed files with 231 additions and 147 deletions.
31 changes: 25 additions & 6 deletions spotify_player/src/client/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -305,6 +305,10 @@ impl Client {
crate::playlist_folders::structurize(playlists, node.children)
} else {
playlists
.iter()
.cloned()
.map(PlaylistFolderItem::Playlist)
.collect()
};
store_data_into_file_cache(
FileCacheKey::Playlists,
Expand Down Expand Up @@ -908,9 +912,11 @@ impl Client {
_ => anyhow::bail!("expect an album search result"),
},
match playlist_result {
rspotify_model::SearchResult::Playlists(p) => {
p.items.into_iter().map(|i| i.into()).collect()
}
rspotify_model::SearchResult::Playlists(p) => p
.items
.into_iter()
.map(|i| PlaylistFolderItem::Playlist(i.into()))
.collect(),
_ => anyhow::bail!("expect a playlist search result"),
},
);
Expand Down Expand Up @@ -1091,7 +1097,12 @@ impl Client {
if !follows[0] {
self.playlist_follow(playlist.id.as_ref(), None).await?;
// update the in-memory `user_data`
state.data.write().user_data.playlists.insert(0, playlist);
state
.data
.write()
.user_data
.playlists
.insert(0, PlaylistFolderItem::Playlist(playlist));
}
}
}
Expand Down Expand Up @@ -1131,7 +1142,10 @@ impl Client {
.write()
.user_data
.playlists
.retain(|p| p.id != id);
.retain(|item| match item {
PlaylistFolderItem::Playlist(p) => p.id != id,
_ => true,
});
self.playlist_unfollow(id).await?;
}
}
Expand Down Expand Up @@ -1484,7 +1498,12 @@ impl Client {
playlist.name,
playlist.id
);
state.data.write().user_data.playlists.insert(0, playlist);
state
.data
.write()
.user_data
.playlists
.insert(0, PlaylistFolderItem::Playlist(playlist));
Ok(())
}

Expand Down
39 changes: 24 additions & 15 deletions spotify_player/src/command.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use crate::state::{Album, Artist, DataReadGuard, Playlist, Track};
use crate::state::{Album, Artist, DataReadGuard, PlaylistFolderItem, Track};
use serde::Deserialize;

#[derive(Copy, Clone, Debug, Deserialize, PartialEq, Eq, PartialOrd, Ord)]
Expand Down Expand Up @@ -104,7 +104,7 @@ pub enum ActionContext {
Track(Track),
Album(Album),
Artist(Artist),
Playlist(Playlist),
Playlist(PlaylistFolderItem),
}

pub enum CommandOrAction {
Expand All @@ -130,8 +130,8 @@ impl From<Album> for ActionContext {
}
}

impl From<Playlist> for ActionContext {
fn from(v: Playlist) -> Self {
impl From<PlaylistFolderItem> for ActionContext {
fn from(v: PlaylistFolderItem) -> Self {
Self::Playlist(v)
}
}
Expand Down Expand Up @@ -204,18 +204,27 @@ pub fn construct_artist_actions(artist: &Artist, data: &DataReadGuard) -> Vec<Ac
}

/// constructs a list of actions on an playlist
pub fn construct_playlist_actions(playlist: &Playlist, data: &DataReadGuard) -> Vec<Action> {
if playlist.is_folder {
vec![]
} else {
let mut actions = vec![Action::GoToRadio, Action::CopyLink];

if data.user_data.playlists.iter().any(|a| a.id == playlist.id) {
actions.push(Action::DeleteFromLibrary);
} else {
actions.push(Action::AddToLibrary);
pub fn construct_playlist_actions(
playlist_item: &PlaylistFolderItem,
data: &DataReadGuard,
) -> Vec<Action> {
match playlist_item {
PlaylistFolderItem::Folder(_) => vec![],
PlaylistFolderItem::Playlist(playlist) => {
let mut actions = vec![Action::GoToRadio, Action::CopyLink];

if data
.user_data
.playlists
.iter()
.any(|item| matches!(item, PlaylistFolderItem::Playlist(p) if p.id == playlist.id))
{
actions.push(Action::DeleteFromLibrary);
} else {
actions.push(Action::AddToLibrary);
}
actions
}
actions
}
}

Expand Down
58 changes: 31 additions & 27 deletions spotify_player/src/event/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -276,34 +276,38 @@ pub fn handle_action_in_context(
}
_ => {}
},
ActionContext::Playlist(playlist) => match action {
Action::AddToLibrary => {
client_pub.send(ClientRequest::AddToLibrary(Item::Playlist(playlist)))?;
ui.popup = None;
}
Action::GoToRadio => {
let uri = playlist.id.uri();
let name = playlist.name;
ui.new_radio_page(&uri);
client_pub.send(ClientRequest::GetRadioTracks {
seed_uri: uri,
seed_name: name,
})?;
}
Action::CopyLink => {
let playlist_url =
format!("https://open.spotify.com/playlist/{}", playlist.id.id());
execute_copy_command(playlist_url)?;
ui.popup = None;
}
Action::DeleteFromLibrary => {
client_pub.send(ClientRequest::DeleteFromLibrary(ItemId::Playlist(
playlist.id,
)))?;
ui.popup = None;
ActionContext::Playlist(item) => {
if let PlaylistFolderItem::Playlist(playlist) = item {
match action {
Action::AddToLibrary => {
client_pub.send(ClientRequest::AddToLibrary(Item::Playlist(playlist)))?;
ui.popup = None;
}
Action::GoToRadio => {
let uri = playlist.id.uri();
let name = playlist.name;
ui.new_radio_page(&uri);
client_pub.send(ClientRequest::GetRadioTracks {
seed_uri: uri,
seed_name: name,
})?;
}
Action::CopyLink => {
let playlist_url =
format!("https://open.spotify.com/playlist/{}", playlist.id.id());
execute_copy_command(playlist_url)?;
ui.popup = None;
}
Action::DeleteFromLibrary => {
client_pub.send(ClientRequest::DeleteFromLibrary(ItemId::Playlist(
playlist.id,
)))?;
ui.popup = None;
}
_ => {}
}
}
_ => {}
},
}
}

Ok(())
Expand Down
14 changes: 7 additions & 7 deletions spotify_player/src/event/page.rs
Original file line number Diff line number Diff line change
Expand Up @@ -55,15 +55,15 @@ fn handle_action_for_library_page(
_ => anyhow::bail!("expect a library page state"),
};
match focus_state {
LibraryFocusState::Playlists(level) => window::handle_action_for_selected_item(
LibraryFocusState::Playlists(folder_id) => window::handle_action_for_selected_item(
action,
ui.search_filtered_items(
&data
.user_data
.folder_playlists(level)
.folder_playlists_items(folder_id)
.into_iter()
.cloned()
.collect::<Vec<Playlist>>(),
.collect::<Vec<PlaylistFolderItem>>(),
),
&data,
ui,
Expand Down Expand Up @@ -104,16 +104,16 @@ fn handle_command_for_library_page(
_ => anyhow::bail!("expect a library page state"),
};
match focus_state {
LibraryFocusState::Playlists(level) => {
LibraryFocusState::Playlists(folder_id) => {
window::handle_command_for_playlist_list_window(
command,
ui.search_filtered_items(
&data
.user_data
.folder_playlists(level)
.folder_playlists_items(folder_id)
.into_iter()
.cloned()
.collect::<Vec<Playlist>>(),
.collect::<Vec<PlaylistFolderItem>>(),
),
&data,
ui,
Expand Down Expand Up @@ -285,7 +285,7 @@ fn handle_action_for_browse_page(

handle_action_in_context(
action,
playlists[selected].clone().into(),
PlaylistFolderItem::Playlist(playlists[selected].clone()).into(),
client_pub,
&data,
ui,
Expand Down
35 changes: 26 additions & 9 deletions spotify_player/src/event/popup.rs
Original file line number Diff line number Diff line change
Expand Up @@ -89,14 +89,17 @@ pub fn handle_key_sequence_for_popup(
)
}
PopupState::UserPlaylistList(action, _) => match action {
PlaylistPopupAction::Browse(level) => {
PlaylistPopupAction::Browse(folder_id) => {
let playlist_uris = state
.data
.read()
.user_data
.folder_playlists(*level)
.folder_playlists_items(*folder_id)
.iter()
.map(|p| (p.id.uri(), p.is_folder, p.level.1))
.map(|item| match item {
PlaylistFolderItem::Playlist(p) => (p.id.uri(), false, 0),
PlaylistFolderItem::Folder(f) => ("".to_string(), true, f.target_id),
})
.collect::<Vec<_>>();

handle_command_for_list_popup(
Expand All @@ -108,7 +111,7 @@ pub fn handle_key_sequence_for_popup(
if playlist_uris[id].1 {
ui.popup = Some(PopupState::UserPlaylistList(
PlaylistPopupAction::Browse(playlist_uris[id].2),
new_list_state(),
ListState::default(),
));
} else {
let uri = crate::utils::parse_uri(&playlist_uris[id].0);
Expand All @@ -127,16 +130,30 @@ pub fn handle_key_sequence_for_popup(
},
)
}
PlaylistPopupAction::AddTrack(level, track_id) => {
PlaylistPopupAction::AddTrack(folder_id, track_id) => {
let track_id = track_id.clone();
let playlist_ids = state
.data
.read()
.user_data
.modifiable_playlists()
.into_iter()
.filter(|p| p.level.0 == *level)
.map(|p| (p.id.clone(), p.is_folder, p.level.1))
.filter_map(|item| match item {
PlaylistFolderItem::Playlist(p) => {
if p.current_id == *folder_id {
Some((p.id.id().to_string(), false, 0))
} else {
None
}
}
PlaylistFolderItem::Folder(f) => {
if f.current_id == *folder_id {
Some(("".to_string(), true, f.target_id))
} else {
None
}
}
})
.collect::<Vec<_>>();

handle_command_for_list_popup(
Expand All @@ -148,11 +165,11 @@ pub fn handle_key_sequence_for_popup(
ui.popup = if playlist_ids[id].1 {
Some(PopupState::UserPlaylistList(
PlaylistPopupAction::AddTrack(playlist_ids[id].2, track_id.clone()),
new_list_state(),
ListState::default(),
))
} else {
client_pub.send(ClientRequest::AddTrackToPlaylist(
playlist_ids[id].0.clone(),
PlaylistId::from_id(playlist_ids[id].0.clone()).unwrap(),
track_id.clone(),
))?;
None
Expand Down
39 changes: 22 additions & 17 deletions spotify_player/src/event/window.rs
Original file line number Diff line number Diff line change
Expand Up @@ -275,11 +275,13 @@ fn handle_command_for_track_table_window(
}

if let Some(ContextId::Playlist(ref playlist_id)) = context_id {
let modifiable = data
.user_data
.modifiable_playlists()
.iter()
.any(|p| p.id.eq(playlist_id));
let modifiable = data.user_data.modifiable_playlists().iter().any(|item| {
if let PlaylistFolderItem::Playlist(p) = item {
p.id.eq(playlist_id)
} else {
false
}
});
if modifiable
&& handle_playlist_modify_command(
id,
Expand Down Expand Up @@ -456,7 +458,7 @@ pub fn handle_command_for_album_list_window(

pub fn handle_command_for_playlist_list_window(
command: Command,
playlists: Vec<&Playlist>,
playlists: Vec<&PlaylistFolderItem>,
data: &DataReadGuard,
ui: &mut UIStateGuard,
) -> Result<bool> {
Expand All @@ -475,20 +477,23 @@ pub fn handle_command_for_playlist_list_window(
_ => return Ok(false),
};
let playlist = playlists[id];
if playlist.is_folder {
state.playlist_list.select(Some(0));
state.focus = LibraryFocusState::Playlists(playlist.level.1);
} else {
let context_id = ContextId::Playlist(playlists[id].id.clone());
ui.new_page(PageState::Context {
id: None,
context_page_type: ContextPageType::Browsing(context_id),
state: None,
});
match playlist {
PlaylistFolderItem::Folder(f) => {
state.playlist_list.select(Some(0));
state.focus = LibraryFocusState::Playlists(f.target_id);
}
PlaylistFolderItem::Playlist(p) => {
let context_id = ContextId::Playlist(p.id.clone());
ui.new_page(PageState::Context {
id: None,
context_page_type: ContextPageType::Browsing(context_id),
state: None,
});
}
}
}
Command::ShowActionsOnSelectedItem => {
if !playlists[id].is_folder {
if let PlaylistFolderItem::Playlist(_) = playlists[id] {
let actions = construct_playlist_actions(playlists[id], data);
ui.popup = Some(PopupState::ActionList(
Box::new(ActionListItem::Playlist(playlists[id].clone(), actions)),
Expand Down
Loading

0 comments on commit 6fb37d2

Please sign in to comment.