From 87bc21f476bb19369d95d0100177a329e027c8e7 Mon Sep 17 00:00:00 2001 From: nick42d <133559267+nick42d@users.noreply.github.com> Date: Thu, 29 Aug 2024 20:23:30 +0800 Subject: [PATCH] feat: Highlight now playing song in playlist (#156) * Add playing indicator to playlist * Implement highlight selected row --- .../app/ui/browser/artistalbums/albumsongs.rs | 4 ++++ youtui/src/app/ui/draw.rs | 2 ++ youtui/src/app/ui/playlist.rs | 17 ++++++++++++++++- youtui/src/app/view.rs | 4 +++- youtui/src/app/view/draw.rs | 11 +++++++++-- 5 files changed, 34 insertions(+), 4 deletions(-) diff --git a/youtui/src/app/ui/browser/artistalbums/albumsongs.rs b/youtui/src/app/ui/browser/artistalbums/albumsongs.rs index aa2403b1..906b7d7c 100644 --- a/youtui/src/app/ui/browser/artistalbums/albumsongs.rs +++ b/youtui/src/app/ui/browser/artistalbums/albumsongs.rs @@ -432,6 +432,10 @@ impl TableView for AlbumSongsPanel { fn get_headings(&self) -> Box<(dyn Iterator + 'static)> { Box::new(["#", "Album", "Song", "Duration", "Year"].into_iter()) } + + fn get_highlighted_row(&self) -> Option { + None + } } impl SortableTableView for AlbumSongsPanel { fn get_sortable_columns(&self) -> &[usize] { diff --git a/youtui/src/app/ui/draw.rs b/youtui/src/app/ui/draw.rs index 029a32f2..226ac791 100644 --- a/youtui/src/app/ui/draw.rs +++ b/youtui/src/app/ui/draw.rs @@ -175,6 +175,8 @@ fn draw_help(f: &mut Frame, w: &YoutuiWindow, state: &mut TableState, chunk: Rec ); } +// At this stage, this is the most efficient way to call this function. +#[allow(clippy::too_many_arguments)] fn draw_generic_scrollable_table<'a, T: IntoIterator>>( f: &mut Frame, table_items: T, diff --git a/youtui/src/app/ui/playlist.rs b/youtui/src/app/ui/playlist.rs index 58eb5017..19821be4 100644 --- a/youtui/src/app/ui/playlist.rs +++ b/youtui/src/app/ui/playlist.rs @@ -149,7 +149,19 @@ impl TableView for Playlist { } fn get_items(&self) -> Box + '_> { Box::new(self.list.get_list_iter().enumerate().map(|(i, ls)| { - Box::new(iter::once((i + 1).to_string().into()).chain(ls.get_fields_iter())) + let first_field = if Some(i) == self.get_cur_playing_index() { + match self.play_status { + PlayState::NotPlaying => ">>>".to_string(), + PlayState::Playing(_) => "".to_string(), + PlayState::Paused(_) => "".to_string(), + PlayState::Stopped => ">>>".to_string(), + PlayState::Error(_) => ">>>".to_string(), + PlayState::Buffering(_) => "".to_string(), + } + } else { + (i + 1).to_string() + }; + Box::new(iter::once(first_field.to_string().into()).chain(ls.get_fields_iter())) as Box>> })) } @@ -161,6 +173,9 @@ impl TableView for Playlist { .into_iter(), ) } + fn get_highlighted_row(&self) -> Option { + self.get_cur_playing_index() + } } impl ActionHandler for Playlist { diff --git a/youtui/src/app/view.rs b/youtui/src/app/view.rs index d6d91620..212bb1d9 100644 --- a/youtui/src/app/view.rs +++ b/youtui/src/app/view.rs @@ -151,11 +151,13 @@ pub trait TableView: Scrollable + Loadable { // need for this in both Table and List fn get_title(&self) -> Cow; fn get_layout(&self) -> &[BasicConstraint]; + // A row can be highlighted. + fn get_highlighted_row(&self) -> Option; // TODO: Consider if generics can be used instead of dyn Iterator. fn get_items(&self) -> Box + '_>; // XXX: This doesn't need to be so fancy - could return a static slice. fn get_headings(&self) -> Box>; - // Not a particularyl useful function for a sortabletableview + // Not a particularly useful function for a sortabletableview fn len(&self) -> usize { self.get_items().len() } diff --git a/youtui/src/app/view/draw.rs b/youtui/src/app/view/draw.rs index afbeb793..17a60a98 100644 --- a/youtui/src/app/view/draw.rs +++ b/youtui/src/app/view/draw.rs @@ -10,7 +10,7 @@ use crate::{ }; use ratatui::{ prelude::{Margin, Rect}, - style::{Modifier, Style}, + style::{Modifier, Style, Stylize}, symbols::{block, line}, text::Line, widgets::{ @@ -108,8 +108,15 @@ where { // Set the state to the currently selected item. state.select(Some(table.get_selected_item())); + let cur_highlighted = table.get_highlighted_row(); // TODO: theming - let table_items = table.get_items().map(Row::new); + let table_items = table.get_items().enumerate().map(|(idx, items)| { + if Some(idx) == cur_highlighted { + Row::new(items).bold().italic() + } else { + Row::new(items) + } + }); let number_items = table.len(); // Minus for height of block and heading. let table_height = chunk.height.saturating_sub(4) as usize;