rmptuib9d6169
highlight current playing songs in lists
+52 −9
2 files changed
- M src/connection.rs +25 −5
- M src/ui.rs +27 −4
| @@ -19,24 +19,40 @@ pub struct Connection { | |||
| 19 | 19 | pub volume: u8, | |
| 20 | 20 | pub repeat: bool, | |
| 21 | 21 | pub random: bool, | |
| 22 | + | pub current_song: Song, | |
| 22 | 23 | } | |
| 23 | 24 | ||
| 24 | 25 | impl Connection { | |
| 25 | 26 | /// Create a new connection | |
| 26 | 27 | pub fn new(addrs: &str) -> Result<Self> { | |
| 27 | 28 | let mut conn = Client::connect(addrs).unwrap(); | |
| 29 | + | ||
| 30 | + | let empty_song = Song { | |
| 31 | + | file: "No Song in the Queue".to_string(), | |
| 32 | + | artist: None, | |
| 33 | + | title: None, | |
| 34 | + | duration: None, | |
| 35 | + | last_mod: None, | |
| 36 | + | name: None, | |
| 37 | + | place: None, | |
| 38 | + | range: None, | |
| 39 | + | tags: vec![("".to_string(), "".to_string())], | |
| 40 | + | }; | |
| 41 | + | ||
| 28 | 42 | let songs_filenames: Vec<String> = conn | |
| 29 | 43 | .listall() | |
| 30 | 44 | .unwrap() | |
| 31 | 45 | .into_iter() | |
| 32 | 46 | .map(|x| x.file) | |
| 33 | 47 | .collect(); | |
| 48 | + | ||
| 34 | 49 | let status = conn.status().unwrap(); | |
| 35 | 50 | let (elapsed, total) = status.time.unwrap_or_default(); | |
| 36 | 51 | let volume: u8 = status.volume as u8; | |
| 37 | 52 | let repeat = status.repeat; | |
| 38 | 53 | let random = status.random; | |
| 39 | 54 | ||
| 55 | + | let current_song = conn.currentsong().unwrap_or_else(|_| Some(empty_song.clone())).unwrap_or_else(|| empty_song); | |
| 40 | 56 | Ok(Self { | |
| 41 | 57 | conn, | |
| 42 | 58 | songs_filenames, | |
| @@ -46,6 +62,7 @@ impl Connection { | |||
| 46 | 62 | volume, | |
| 47 | 63 | repeat, | |
| 48 | 64 | random, | |
| 65 | + | current_song, | |
| 49 | 66 | }) | |
| 50 | 67 | } | |
| 51 | 68 | ||
| @@ -76,6 +93,8 @@ impl Connection { | |||
| 76 | 93 | /// Update status | |
| 77 | 94 | pub fn update_status(&mut self) { | |
| 78 | 95 | let status = self.conn.status().unwrap(); | |
| 96 | + | let empty_song = self.get_song_with_only_filename("No Song in the Queue"); | |
| 97 | + | let current_song = self.conn.currentsong().unwrap_or_else(|_| Some(empty_song.clone())).unwrap_or_else(|| empty_song); | |
| 79 | 98 | ||
| 80 | 99 | // Playback State | |
| 81 | 100 | match status.state { | |
| @@ -97,6 +116,8 @@ impl Connection { | |||
| 97 | 116 | ||
| 98 | 117 | // Random mode | |
| 99 | 118 | self.random = status.random; | |
| 119 | + | ||
| 120 | + | self.current_song = current_song; | |
| 100 | 121 | } | |
| 101 | 122 | ||
| 102 | 123 | /// Get progress ratio of current playing song | |
| @@ -200,15 +221,14 @@ impl Connection { | |||
| 200 | 221 | ||
| 201 | 222 | /// Gives title of current playing song | |
| 202 | 223 | pub fn now_playing(&mut self) -> Result<Option<String>> { | |
| 203 | − | let song = self.conn.currentsong()?.unwrap_or_default(); | |
| 204 | − | if let Some(s) = song.title { | |
| 205 | − | if let Some(a) = song.artist { | |
| 224 | + | if let Some(s) = &self.current_song.title { | |
| 225 | + | if let Some(a) = &self.current_song.artist { | |
| 206 | 226 | return Ok(Some(format!("\"{}\" By {}", s, a))); | |
| 207 | 227 | } else { | |
| 208 | − | return Ok(Some(s)); | |
| 228 | + | return Ok(Some(s.to_string())); | |
| 209 | 229 | } | |
| 210 | 230 | } else { | |
| 211 | − | return Ok(Some(song.file)); | |
| 231 | + | return Ok(Some(self.current_song.file.clone())); | |
| 212 | 232 | } | |
| 213 | 233 | } | |
| 214 | 234 | ||
| @@ -1,4 +1,5 @@ | |||
| 1 | 1 | use crate::app::{App, SelectedTab}; | |
| 2 | + | use clap::builder::styling::RgbColor; | |
| 2 | 3 | use ratatui::{ | |
| 3 | 4 | prelude::*, | |
| 4 | 5 | widgets::{block::Title, *}, | |
| @@ -51,12 +52,25 @@ pub fn render(app: &mut App, frame: &mut Frame) { | |||
| 51 | 52 | fn draw_directory_browser(frame: &mut Frame, app: &mut App, size: Rect) { | |
| 52 | 53 | let mut song_state = ListState::default(); | |
| 53 | 54 | let total_songs = app.conn.conn.stats().unwrap().songs.to_string(); | |
| 54 | − | let mut list: Vec<String> = vec![]; | |
| 55 | + | let mut list: Vec<ListItem> = vec![]; | |
| 55 | 56 | for (t, s) in app.browser.filetree.iter() { | |
| 56 | 57 | if t == "file" { | |
| 57 | − | list.push(s.to_string()); | |
| 58 | + | let mut status: bool = false; | |
| 59 | + | for sn in app.queue_list.list.iter() { | |
| 60 | + | if sn.contains(s) { | |
| 61 | + | status = true; | |
| 62 | + | } | |
| 63 | + | } | |
| 64 | + | if status { | |
| 65 | + | list.push(ListItem::new(s.clone().bold())); | |
| 66 | + | } else { | |
| 67 | + | list.push(ListItem::new(Line::styled(s, Style::default()))); | |
| 68 | + | } | |
| 58 | 69 | } else { | |
| 59 | − | list.push(format!("[{}]", *s)); | |
| 70 | + | list.push(ListItem::new(Line::styled( | |
| 71 | + | format!("[{}]", *s), | |
| 72 | + | Style::default(), | |
| 73 | + | ))); | |
| 60 | 74 | } | |
| 61 | 75 | } | |
| 62 | 76 | let list = List::new(list) | |
| @@ -97,7 +111,16 @@ fn draw_queue(frame: &mut Frame, app: &mut App, size: Rect) { | |||
| 97 | 111 | Title::from(format!("Volume: {}%", app.conn.volume).bold().green()) | |
| 98 | 112 | .alignment(Alignment::Right), | |
| 99 | 113 | ); | |
| 100 | − | let list = List::new(app.queue_list.list.clone()) | |
| 114 | + | ||
| 115 | + | let mut items: Vec<ListItem> = vec![]; | |
| 116 | + | for item in app.queue_list.list.iter() { | |
| 117 | + | if item.contains(&app.conn.current_song.file) { | |
| 118 | + | items.push(ListItem::new(item.clone().bold())) | |
| 119 | + | } else { | |
| 120 | + | items.push(ListItem::new(item.clone())); | |
| 121 | + | } | |
| 122 | + | } | |
| 123 | + | let list = List::new(items) | |
| 101 | 124 | .block(title.borders(Borders::ALL)) | |
| 102 | 125 | .highlight_style( | |
| 103 | 126 | Style::new() | |