From dbc6e92cd84f9dd254684bd7887cfbd3b21e028c Mon Sep 17 00:00:00 2001 From: NickWilder Date: Fri, 11 Oct 2024 22:21:00 -0500 Subject: [PATCH] Extend layout functionality --- spotify_player/src/config/mod.rs | 47 +++++++-- spotify_player/src/ui/page.rs | 168 +++++++++++++++++++------------ 2 files changed, 143 insertions(+), 72 deletions(-) diff --git a/spotify_player/src/config/mod.rs b/spotify_player/src/config/mod.rs index 397d596b..cff31cad 100644 --- a/spotify_player/src/config/mod.rs +++ b/spotify_player/src/config/mod.rs @@ -191,8 +191,9 @@ pub struct LayoutConfig { #[derive(Debug, Deserialize, Serialize, ConfigParse, Clone)] pub struct LibraryLayoutConfig { - pub playlist_percent: u16, - pub album_percent: u16, + pub playlist_percent: Option, + pub album_percent: Option, + pub artist_percent: Option, } #[derive(Debug, Deserialize, Serialize, Clone, PartialEq)] @@ -339,8 +340,9 @@ impl Default for LayoutConfig { fn default() -> Self { Self { library: LibraryLayoutConfig { - playlist_percent: 40, - album_percent: 40, + playlist_percent: Some(40), + album_percent: Some(40), + artist_percent: Some(20), }, playback_window_position: Position::Top, playback_window_height: 6, @@ -350,8 +352,28 @@ impl Default for LayoutConfig { impl LayoutConfig { fn check_values(&self) -> anyhow::Result<()> { - if self.library.album_percent + self.library.playlist_percent > 99 { - anyhow::bail!("Invalid library layout: summation of album_percent and playlist_percent cannot be greater than 99!"); + let mut total_percent = 0; + let mut set_columns = 0; + + if let Some(percent) = self.library.playlist_percent { + total_percent += percent; + set_columns += 1; + } + if let Some(percent) = self.library.album_percent { + total_percent += percent; + set_columns += 1; + } + if let Some(percent) = self.library.artist_percent { + total_percent += percent; + set_columns += 1; + } + + if total_percent > 100 { + anyhow::bail!( + "Invalid library layout: summation of set percentages cannot be greater than 100!" + ); + } else if set_columns == 0 { + anyhow::bail!("Invalid library layout: at least one of album_percent, playlist_percent, or artist_percentage must be set!"); } else { Ok(()) } @@ -361,8 +383,17 @@ impl LayoutConfig { impl AppConfig { pub fn new(path: &Path) -> Result { let mut config = Self::default(); - if !config.parse_config_file(path)? { - config.write_config_file(path)? + if config.parse_config_file(path)? { + // If a config file was found and parsed, reset the library percentages + // to ensure only the user-specified values are set + config.layout.library.playlist_percent = None; + config.layout.library.album_percent = None; + config.layout.library.artist_percent = None; + + // Re-parse the config file to set only the user-specified values + config.parse_config_file(path)?; + } else { + config.write_config_file(path)?; } config.layout.check_values()?; diff --git a/spotify_player/src/ui/page.rs b/spotify_player/src/ui/page.rs index d88ce461..a4082b2a 100644 --- a/spotify_player/src/ui/page.rs +++ b/spotify_player/src/ui/page.rs @@ -317,8 +317,8 @@ pub fn render_library_page( let data = state.data.read(); let configs = config::get_config(); - let (focus_state, playlist_folder_id) = match ui.current_page() { - PageState::Library { state } => (state.focus, state.playlist_folder_id), + let focus_state = match ui.current_page() { + PageState::Library { state } => state.focus, _ => return, }; @@ -328,52 +328,84 @@ pub fn render_library_page( // - a saved albums window // - a followed artists window - let chunks = Layout::horizontal([ - Constraint::Percentage(configs.app_config.layout.library.playlist_percent), - Constraint::Percentage(configs.app_config.layout.library.album_percent), - Constraint::Percentage( - 100 - (configs.app_config.layout.library.album_percent - + configs.app_config.layout.library.playlist_percent), - ), - ]) - .split(rect); - - let playlist_rect = construct_and_render_block( - "Playlists", - &ui.theme, - Borders::TOP | Borders::LEFT | Borders::BOTTOM, - frame, - chunks[0], - ); - let album_rect = construct_and_render_block( - "Albums", - &ui.theme, - Borders::TOP | Borders::LEFT | Borders::BOTTOM, - frame, - chunks[1], - ); - let artist_rect = - construct_and_render_block("Artists", &ui.theme, Borders::ALL, frame, chunks[2]); + // Calculate constraints based on visible columns + let mut constraints: Vec = Vec::new(); + if let Some(percent) = configs.app_config.layout.library.playlist_percent { + constraints.push(Constraint::Percentage(percent)); + } + if let Some(percent) = configs.app_config.layout.library.album_percent { + constraints.push(Constraint::Percentage(percent)); + } + if let Some(percent) = configs.app_config.layout.library.artist_percent { + constraints.push(Constraint::Percentage(percent)); + } + + let total_sections = constraints.len(); + let chunks = Layout::horizontal(&constraints).split(rect); + + let mut _chunk_index = 0; + + let mut playlist_rect = None; + let mut album_rect = None; + let mut artist_rect = None; + + if configs.app_config.layout.library.playlist_percent.is_some() { + let borders = if _chunk_index == total_sections - 1 { + Borders::ALL + } else { + Borders::TOP | Borders::LEFT | Borders::BOTTOM + }; + playlist_rect = Some(construct_and_render_block( + "Playlists", + &ui.theme, + borders, + frame, + chunks[_chunk_index], + )); + _chunk_index += 1; + } + + if configs.app_config.layout.library.album_percent.is_some() { + let borders = if _chunk_index == total_sections - 1 { + Borders::ALL + } else { + Borders::TOP | Borders::LEFT | Borders::BOTTOM + }; + album_rect = Some(construct_and_render_block( + "Albums", + &ui.theme, + borders, + frame, + chunks[_chunk_index], + )); + _chunk_index += 1; + } + + if configs.app_config.layout.library.artist_percent.is_some() { + let borders = Borders::ALL; // This will always be the last section if it exists + artist_rect = Some(construct_and_render_block( + "Artists", + &ui.theme, + borders, + frame, + chunks[_chunk_index], + )); + } // 3. Construct the page's widgets // Construct the playlist window - let items = ui - .search_filtered_items(&data.user_data.folder_playlists_items(playlist_folder_id)) - .into_iter() - .map(|item| match item { - PlaylistFolderItem::Playlist(p) => { - (p.to_string(), curr_context_uri == Some(p.id.uri())) - } - PlaylistFolderItem::Folder(f) => (f.to_string(), false), - }) - .collect::>(); - let (playlist_list, n_playlists) = utils::construct_list_widget( &ui.theme, - items, - is_active - && focus_state != LibraryFocusState::SavedAlbums - && focus_state != LibraryFocusState::FollowedArtists, + ui.search_filtered_items(&data.user_data.playlists) + .into_iter() + .map(|item| match item { + PlaylistFolderItem::Playlist(p) => { + (p.to_string(), curr_context_uri == Some(p.id.uri())) + } + PlaylistFolderItem::Folder(f) => (f.to_string(), false), + }) + .collect(), + is_active && focus_state == LibraryFocusState::Playlists, ); // Construct the saved album window let (album_list, n_albums) = utils::construct_list_widget( @@ -402,27 +434,35 @@ pub fn render_library_page( _ => return, }; - utils::render_list_window( - frame, - playlist_list, - playlist_rect, - n_playlists, - &mut page_state.playlist_list, - ); - utils::render_list_window( - frame, - album_list, - album_rect, - n_albums, - &mut page_state.saved_album_list, - ); - utils::render_list_window( - frame, - artist_list, - artist_rect, - n_artists, - &mut page_state.followed_artist_list, - ); + if let Some(rect) = playlist_rect { + utils::render_list_window( + frame, + playlist_list, + rect, + n_playlists, + &mut page_state.playlist_list, + ); + } + + if let Some(rect) = album_rect { + utils::render_list_window( + frame, + album_list, + rect, + n_albums, + &mut page_state.saved_album_list, + ); + } + + if let Some(rect) = artist_rect { + utils::render_list_window( + frame, + artist_list, + rect, + n_artists, + &mut page_state.followed_artist_list, + ); + } } pub fn render_browse_page(