rmptuibf11d59
hmm stuff
+62 −47
4 files changed
- M src/app.rs +11 −10
- M src/connection.rs +1 −1
- M src/handler.rs +21 −12
- M src/ui.rs +29 −24
| @@ -12,7 +12,7 @@ pub struct App { | |||
| 12 | 12 | /// check if app is running | |
| 13 | 13 | pub running: bool, | |
| 14 | 14 | pub conn: Connection, | |
| 15 | − | pub play_deque: VecDeque<String>, | |
| 15 | + | pub play_deque: ContentList<String>, | |
| 16 | 16 | pub song_list: ContentList<String>, | |
| 17 | 17 | pub queue_list: ContentList<String>, | |
| 18 | 18 | pub pl_list: ContentList<String>, | |
| @@ -21,10 +21,11 @@ pub struct App { | |||
| 21 | 21 | impl App { | |
| 22 | 22 | pub fn builder(addrs: &str) -> AppResult<Self> { | |
| 23 | 23 | let mut conn = Connection::new(addrs).unwrap(); | |
| 24 | − | let mut vec: VecDeque<String> = VecDeque::new(); | |
| 24 | + | let mut queue = ContentList::new(); | |
| 25 | 25 | let mut pl_list = ContentList::new(); | |
| 26 | 26 | pl_list.list = Self::get_playlist(&mut conn.conn)?; | |
| 27 | − | Self::get_queue(&mut conn, &mut vec); | |
| 27 | + | ||
| 28 | + | Self::get_queue(&mut conn, &mut queue.list); | |
| 28 | 29 | ||
| 29 | 30 | let mut song_list = ContentList::new(); | |
| 30 | 31 | song_list.list = conn.songs_filenames.clone(); | |
| @@ -32,7 +33,7 @@ impl App { | |||
| 32 | 33 | Ok(Self { | |
| 33 | 34 | running: true, | |
| 34 | 35 | conn, | |
| 35 | − | play_deque: vec, | |
| 36 | + | play_deque: ContentList::new(), | |
| 36 | 37 | song_list, | |
| 37 | 38 | queue_list: ContentList::new(), | |
| 38 | 39 | pl_list, | |
| @@ -45,23 +46,23 @@ impl App { | |||
| 45 | 46 | self.running = false; | |
| 46 | 47 | } | |
| 47 | 48 | ||
| 48 | − | pub fn get_queue(conn: &mut Connection, vec: &mut VecDeque<String>) { | |
| 49 | + | pub fn get_queue(conn: &mut Connection, vec: &mut Vec<String>) { | |
| 49 | 50 | conn.conn.queue().unwrap().into_iter().for_each(|x| { | |
| 50 | 51 | if let Some(title) = x.title { | |
| 51 | 52 | if let Some(artist) = x.artist { | |
| 52 | − | vec.push_back(format!("{} - {}", artist, title)); | |
| 53 | + | vec.push(format!("{} - {}", artist, title)); | |
| 53 | 54 | } else { | |
| 54 | − | vec.push_back(title) | |
| 55 | + | vec.push(title) | |
| 55 | 56 | } | |
| 56 | 57 | } else { | |
| 57 | − | vec.push_back(x.file) | |
| 58 | + | vec.push(x.file) | |
| 58 | 59 | } | |
| 59 | 60 | }); | |
| 60 | 61 | } | |
| 61 | 62 | ||
| 62 | 63 | pub fn update_queue(&mut self) { | |
| 63 | − | self.play_deque.clear(); | |
| 64 | − | Self::get_queue(&mut self.conn, &mut self.play_deque); | |
| 64 | + | self.queue_list.list.clear(); | |
| 65 | + | Self::get_queue(&mut self.conn, &mut self.queue_list.list); | |
| 65 | 66 | } | |
| 66 | 67 | ||
| 67 | 68 | pub fn get_playlist(conn: &mut Client) -> AppResult<Vec<String>> { | |
| @@ -132,7 +132,7 @@ impl Connection { | |||
| 132 | 132 | ||
| 133 | 133 | /// Gives title of current playing song | |
| 134 | 134 | pub fn now_playing(&mut self) -> Result<Option<String>> { | |
| 135 | − | let song = self.conn.currentsong()?.unwrap(); | |
| 135 | + | let song = self.conn.currentsong()?.unwrap_or_default(); | |
| 136 | 136 | if let Some(s) = song.title { | |
| 137 | 137 | if let Some(a) = song.artist { | |
| 138 | 138 | return Ok(Some(format!("{} - {}", s, a))); | |
| @@ -19,7 +19,9 @@ pub fn handle_key_events(key_event: KeyEvent, app: &mut App) -> AppResult<()> { | |||
| 19 | 19 | } | |
| 20 | 20 | ||
| 21 | 21 | KeyCode::Enter | KeyCode::Char('l') => { | |
| 22 | − | let song = app.conn.get_song_with_only_filename(app.conn.songs_filenames.get(app.song_list.index).unwrap()); | |
| 22 | + | let song = app.conn.get_song_with_only_filename( | |
| 23 | + | app.conn.songs_filenames.get(app.song_list.index).unwrap(), | |
| 24 | + | ); | |
| 23 | 25 | app.conn.push(&song)?; | |
| 24 | 26 | // app.update_queue(); | |
| 25 | 27 | } | |
| @@ -35,7 +37,6 @@ pub fn handle_key_events(key_event: KeyEvent, app: &mut App) -> AppResult<()> { | |||
| 35 | 37 | app.conn.pause(); | |
| 36 | 38 | } | |
| 37 | 39 | ||
| 38 | − | ||
| 39 | 40 | // Clearn Queue | |
| 40 | 41 | KeyCode::Char('x') => { | |
| 41 | 42 | app.conn.conn.clear()?; | |
| @@ -46,31 +47,39 @@ pub fn handle_key_events(key_event: KeyEvent, app: &mut App) -> AppResult<()> { | |||
| 46 | 47 | app.conn.play_dmenu()?; | |
| 47 | 48 | } | |
| 48 | 49 | ||
| 49 | − | KeyCode::Down=> { | |
| 50 | − | app.pl_list.next(); | |
| 50 | + | KeyCode::Down => { | |
| 51 | + | if key_event.modifiers == KeyModifiers::SHIFT { | |
| 52 | + | app.queue_list.next(); | |
| 53 | + | } else { | |
| 54 | + | app.pl_list.next(); | |
| 55 | + | } | |
| 51 | 56 | } | |
| 52 | 57 | ||
| 53 | − | KeyCode::Up=> { | |
| 54 | − | app.pl_list.prev(); | |
| 58 | + | KeyCode::Up => { | |
| 59 | + | if key_event.modifiers == KeyModifiers::SHIFT { | |
| 60 | + | app.queue_list.prev(); | |
| 61 | + | } else { | |
| 62 | + | app.pl_list.prev(); | |
| 63 | + | } | |
| 55 | 64 | } | |
| 56 | 65 | ||
| 57 | − | ||
| 58 | 66 | KeyCode::Right => { | |
| 59 | − | app.conn.push_playlist(app.pl_list.list.get(app.pl_list.index).unwrap())?; | |
| 67 | + | app.conn | |
| 68 | + | .push_playlist(app.pl_list.list.get(app.pl_list.index).unwrap())?; | |
| 60 | 69 | } | |
| 61 | 70 | ||
| 62 | − | KeyCode::Char('f')=> { | |
| 71 | + | KeyCode::Char('f') => { | |
| 63 | 72 | // let place = app.conn.conn.status().unwrap().duration; | |
| 64 | 73 | let (pos, _) = app.conn.conn.status().unwrap().time.unwrap(); | |
| 65 | 74 | let pos: i64 = (pos.as_secs() + 2).try_into().unwrap(); | |
| 66 | − | app.conn.conn.seek(2, pos )?; | |
| 75 | + | app.conn.conn.seek(2, pos)?; | |
| 67 | 76 | } | |
| 68 | 77 | ||
| 69 | − | KeyCode::Char('b')=> { | |
| 78 | + | KeyCode::Char('b') => { | |
| 70 | 79 | // let place = app.conn.conn.status().unwrap().duration; | |
| 71 | 80 | let (pos, _) = app.conn.conn.status().unwrap().time.unwrap(); | |
| 72 | 81 | let pos: i64 = (pos.as_secs() - 2).try_into().unwrap(); | |
| 73 | − | app.conn.conn.seek(2, pos )?; | |
| 82 | + | app.conn.conn.seek(2, pos)?; | |
| 74 | 83 | } | |
| 75 | 84 | _ => {} | |
| 76 | 85 | } | |
| @@ -1,5 +1,5 @@ | |||
| 1 | 1 | use crate::app::{App, AppResult}; | |
| 2 | − | use ratatui::{prelude::*, widgets::*}; | |
| 2 | + | use ratatui::{prelude::*, widgets::{block::Title, *}}; | |
| 3 | 3 | ||
| 4 | 4 | /// Renders the user interface widgets | |
| 5 | 5 | pub fn render(app: &mut App, frame: &mut Frame) { | |
| @@ -29,32 +29,33 @@ pub fn render(app: &mut App, frame: &mut Frame) { | |||
| 29 | 29 | draw_playlists(frame, app, inner_layout[1]); | |
| 30 | 30 | ||
| 31 | 31 | // Status | |
| 32 | − | // let song = app | |
| 33 | − | // .conn | |
| 34 | − | // .now_playing().unwrap() | |
| 35 | − | // .unwrap_or_else(|| "No Title Found".to_string()); | |
| 36 | − | // | |
| 37 | − | // let (elapsed, total) = app.conn.conn.status().unwrap().time.unwrap(); | |
| 38 | − | // | |
| 39 | − | // let mut lines = vec![]; | |
| 40 | − | // lines.push(Line::from(vec![ | |
| 41 | − | // Span::styled("Current: ", Style::default().fg(Color::Red)), | |
| 42 | − | // Span::styled(song, Style::default().fg(Color::Yellow)), | |
| 43 | − | // Span::styled( | |
| 44 | − | // format!("[{}/{}]", elapsed.as_secs(), total.as_secs()), | |
| 45 | − | // Style::default().fg(Color::Yellow), | |
| 46 | − | // ), | |
| 47 | − | // ])); | |
| 48 | − | // let status = Paragraph::new(Text::from(lines)) | |
| 49 | − | // .block(Block::default().title("Status").borders(Borders::ALL)); | |
| 50 | − | // frame.render_widget(status, main_layout[1]); | |
| 32 | + | let song = app | |
| 33 | + | .conn | |
| 34 | + | .now_playing().unwrap() | |
| 35 | + | .unwrap_or_else(|| "No Title Found".to_string()); | |
| 36 | + | ||
| 37 | + | let (elapsed, total) = app.conn.conn.status().unwrap().time.unwrap_or_default(); | |
| 38 | + | ||
| 39 | + | let mut lines = vec![]; | |
| 40 | + | lines.push(Line::from(vec![ | |
| 41 | + | Span::styled("Current: ", Style::default().fg(Color::Red)), | |
| 42 | + | Span::styled(song, Style::default().fg(Color::Yellow)), | |
| 43 | + | Span::styled( | |
| 44 | + | format!("[{}/{}]", elapsed.as_secs(), total.as_secs()), | |
| 45 | + | Style::default().fg(Color::Yellow), | |
| 46 | + | ), | |
| 47 | + | ])); | |
| 48 | + | let status = Paragraph::new(Text::from(lines)) | |
| 49 | + | .block(Block::default().title("Status".bold().green()).borders(Borders::ALL)); | |
| 50 | + | frame.render_widget(status, main_layout[1]); | |
| 51 | + | ||
| 51 | 52 | } | |
| 52 | 53 | ||
| 53 | 54 | /// draws list of songs | |
| 54 | 55 | fn draw_song_list(frame: &mut Frame, app: &mut App, size: Rect) { | |
| 55 | 56 | let mut song_state = ListState::default(); | |
| 56 | 57 | let list = List::new(app.conn.songs_filenames.clone()) | |
| 57 | − | .block(Block::default().title("Song List").borders(Borders::ALL)) | |
| 58 | + | .block(Block::default().title("Song List".green().bold()).borders(Borders::ALL)) | |
| 58 | 59 | .highlight_style(Style::new().add_modifier(Modifier::REVERSED)) | |
| 59 | 60 | .highlight_symbol(">>") | |
| 60 | 61 | .repeat_highlight_symbol(true); | |
| @@ -66,21 +67,25 @@ fn draw_song_list(frame: &mut Frame, app: &mut App, size: Rect) { | |||
| 66 | 67 | /// draws playing queue | |
| 67 | 68 | fn draw_queue(frame: &mut Frame, app: &mut App, size: Rect) { | |
| 68 | 69 | let mut queue_state = ListState::default(); | |
| 69 | − | let list = List::new(app.play_deque.clone()) | |
| 70 | − | .block(Block::default().title("Play Queue").borders(Borders::ALL)) | |
| 70 | + | let title = Block::default().title(Title::from("Play Queue".green().bold())).title("Shift + ▲ ▼ to scroll, Shift + Enter to play".yellow()); | |
| 71 | + | let list = List::new(app.queue_list.list.clone()) | |
| 72 | + | .block(title.borders(Borders::ALL)) | |
| 71 | 73 | .highlight_style(Style::new().add_modifier(Modifier::REVERSED)) | |
| 72 | 74 | .highlight_symbol(">>") | |
| 73 | 75 | .repeat_highlight_symbol(true); | |
| 74 | 76 | ||
| 75 | 77 | app.update_queue(); | |
| 78 | + | queue_state.select(Some(app.queue_list.index)); | |
| 76 | 79 | frame.render_stateful_widget(list, size, &mut queue_state); | |
| 77 | 80 | } | |
| 78 | 81 | ||
| 79 | 82 | /// draws all playlists | |
| 80 | 83 | fn draw_playlists(frame: &mut Frame, app: &mut App, size: Rect) { | |
| 81 | 84 | let mut state = ListState::default(); | |
| 85 | + | ||
| 86 | + | let title = Block::default().title(Title::from("Playlist".green().bold())).title("▲ ▼ to scroll, Use ► to add playlist to queue".yellow()); | |
| 82 | 87 | let list = List::new(app.pl_list.list.clone()) | |
| 83 | − | .block(Block::default().title("Playlists").borders(Borders::ALL)) | |
| 88 | + | .block(title.borders(Borders::ALL)) | |
| 84 | 89 | .highlight_style(Style::new().add_modifier(Modifier::REVERSED)) | |
| 85 | 90 | .highlight_symbol(">>") | |
| 86 | 91 | .repeat_highlight_symbol(true); | |