diff --git a/src/app.rs b/src/app.rs index dddcd75..3315e6b 100755 --- a/src/app.rs +++ b/src/app.rs @@ -1,7 +1,6 @@ use crate::connection::Connection; use crate::list::ContentList; use mpd::Client; -use std::collections::VecDeque; // Application result type pub type AppResult = std::result::Result>; @@ -15,6 +14,25 @@ pub struct App { pub song_list: ContentList, pub queue_list: ContentList, pub pl_list: ContentList, + pub selected_tab: SelectedTab, +} + + +#[derive(Debug, PartialEq, Clone)] +pub enum SelectedTab { + SongList, + Queue, + Playlists, +} + +impl SelectedTab { + fn as_usize(&self) { + match self { + SelectedTab::SongList => 0, + SelectedTab::Queue => 1, + SelectedTab::Playlists => 2, + }; + } } impl App { @@ -35,6 +53,7 @@ impl App { song_list, queue_list, pl_list, + selected_tab: SelectedTab::SongList, }) } @@ -73,4 +92,12 @@ impl App { Self::get_playlist(&mut self.conn.conn)?; Ok(()) } + + pub fn cycle_tabls(&mut self) { + self.selected_tab = match self.selected_tab { + SelectedTab::SongList => SelectedTab::Queue, + SelectedTab::Queue => SelectedTab::Playlists, + SelectedTab::Playlists=> SelectedTab::SongList, + }; + } } diff --git a/src/connection.rs b/src/connection.rs index 16055a5..9cfd61e 100755 --- a/src/connection.rs +++ b/src/connection.rs @@ -158,15 +158,17 @@ impl Connection { } // Volume controls - /// Sets the volume - pub fn set_volume(&mut self, u: String) { + pub fn inc_volume(&mut self, v: i8) { let cur = self.conn.status().unwrap().volume; - let sym = u.get(0..1).unwrap(); - let u: i8 = u.parse::().unwrap(); - if sym == "+" || sym == "-" { - self.conn.volume(cur + u).unwrap(); - } else { - self.conn.volume(u).unwrap(); + if cur + v <= 100 { + self.conn.volume(cur + v).unwrap(); + } + } + + pub fn dec_volume(&mut self, v: i8) { + let cur = self.conn.status().unwrap().volume; + if cur - v >= 0 { + self.conn.volume(cur - v).unwrap(); } } } diff --git a/src/handler.rs b/src/handler.rs index 6024322..3d67bb2 100755 --- a/src/handler.rs +++ b/src/handler.rs @@ -1,7 +1,8 @@ use std::time::Duration; -use crate::app::{App, AppResult}; +use crate::app::{App, AppResult, SelectedTab}; use crossterm::event::{KeyCode, KeyEvent, KeyModifiers}; +use ratatui::style::Modifier; pub fn handle_key_events(key_event: KeyEvent, app: &mut App) -> AppResult<()> { match key_event.code { @@ -12,36 +13,53 @@ pub fn handle_key_events(key_event: KeyEvent, app: &mut App) -> AppResult<()> { } } - KeyCode::Char('j') => { - app.song_list.next(); - } + KeyCode::Char('j') | KeyCode::Down => match app.selected_tab { + SelectedTab::SongList => app.song_list.next(), + SelectedTab::Queue => app.queue_list.next(), + SelectedTab::Playlists => app.pl_list.next(), + }, - KeyCode::Char('k') => { - app.song_list.prev(); - } + KeyCode::Char('k') | KeyCode::Up => match app.selected_tab { + SelectedTab::SongList => app.song_list.prev(), + SelectedTab::Queue => app.queue_list.prev(), + SelectedTab::Playlists => app.pl_list.prev(), + }, KeyCode::Enter | KeyCode::Char('l') => { - let song = app.conn.get_song_with_only_filename( - app.conn.songs_filenames.get(app.song_list.index).unwrap(), - ); - app.conn.push(&song)?; // app.update_queue(); + + match app.selected_tab { + SelectedTab::SongList => { + let song = app.conn.get_song_with_only_filename( + app.conn.songs_filenames.get(app.song_list.index).unwrap(), + ); + app.conn.push(&song)?; + } + SelectedTab::Queue => {} + SelectedTab::Playlists => { + app.conn + .push_playlist(app.pl_list.list.get(app.pl_list.index).unwrap())?; + } + } } // Playback controls // Toggle Pause KeyCode::Char('p') => { app.conn.toggle_pause(); + app.conn.update_state(); } // Pause KeyCode::Char('s') => { app.conn.pause(); + app.conn.update_state(); } - // Clearn Queue + // Clear Queue KeyCode::Char('x') => { app.conn.conn.clear()?; + app.conn.update_state(); // app.update_queue(); } @@ -49,22 +67,6 @@ pub fn handle_key_events(key_event: KeyEvent, app: &mut App) -> AppResult<()> { app.conn.play_dmenu()?; } - KeyCode::Down => { - if key_event.modifiers == KeyModifiers::SHIFT { - app.queue_list.next(); - } else { - app.pl_list.next(); - } - } - - KeyCode::Up => { - if key_event.modifiers == KeyModifiers::SHIFT { - app.queue_list.prev(); - } else { - app.pl_list.prev(); - } - } - KeyCode::Right => { app.conn .push_playlist(app.pl_list.list.get(app.pl_list.index).unwrap())?; @@ -83,6 +85,43 @@ pub fn handle_key_events(key_event: KeyEvent, app: &mut App) -> AppResult<()> { let pos = Duration::from_secs(pos.as_secs().wrapping_add(2)); app.conn.conn.seek(place, pos)?; } + + KeyCode::Tab => { + app.cycle_tabls(); + } + + KeyCode::Char('1') => { + app.selected_tab = SelectedTab::SongList; + } + + KeyCode::Char('2') => { + app.selected_tab = SelectedTab::Queue; + } + + KeyCode::Char('3') => { + app.selected_tab = SelectedTab::Playlists; + } + + + KeyCode::Char('n') => { + app.conn.conn.next()?; + } + + KeyCode::Char('N') => { + app.conn.conn.prev()?; + } + + // Volume controls + KeyCode::Char('=') => { + app.conn.inc_volume(2); + } + + KeyCode::Char('-') => { + app.conn.dec_volume(2); + } + + + _ => {} } diff --git a/src/ui.rs b/src/ui.rs index 5a52003..624e302 100755 --- a/src/ui.rs +++ b/src/ui.rs @@ -1,6 +1,7 @@ -use crate::app::{App, AppResult}; +use crate::app::{App, AppResult, SelectedTab}; use ratatui::{ prelude::*, + style::palette::tailwind, widgets::{block::Title, *}, }; @@ -12,25 +13,45 @@ pub fn render(app: &mut App, frame: &mut Frame) { // - https://github.com/ratatui-org/ratatui/tree/master/examples // Layout - let main_layout = Layout::default() + let layout = Layout::default() .direction(Direction::Vertical) - .constraints(vec![Constraint::Percentage(93), Constraint::Percentage(7)]) + .constraints(vec![ + Constraint::Percentage(5), + Constraint::Percentage(88), + Constraint::Percentage(7), + ]) .split(frame.size()); + // + // let outer_layout = Layout::default() + // .direction(Direction::Horizontal) + // .constraints(vec![Constraint::Percentage(50), Constraint::Percentage(50)]) + // .split(main_layout[1]); + // + // let inner_layout = Layout::default() + // .direction(Direction::Vertical) + // .constraints(vec![Constraint::Percentage(50), Constraint::Percentage(50)]) + // .split(outer_layout[1]); - let outer_layout = Layout::default() - .direction(Direction::Horizontal) - .constraints(vec![Constraint::Percentage(50), Constraint::Percentage(50)]) - .split(main_layout[0]); + // draw_song_list(frame, app, outer_layout[0]); + // draw_queue(frame, app, inner_layout[0]); + // draw_playlists(frame, app, inner_layout[1]); + draw_progress_bar(frame, app, layout[2]); - let inner_layout = Layout::default() - .direction(Direction::Vertical) - .constraints(vec![Constraint::Percentage(50), Constraint::Percentage(50)]) - .split(outer_layout[1]); + let highlight_style = (Color::default(), tailwind::YELLOW.c700); + let tab = Tabs::new(vec!["Songs List", "Play Queue", "Playlists"]) + .block(Block::default().title("Tabs").borders(Borders::ALL)) + .style(Style::default().white()) + .highlight_style(highlight_style) + .divider(" ") + .select(app.selected_tab.clone() as usize) + .padding("", ""); + frame.render_widget(tab, layout[0]); - draw_song_list(frame, app, outer_layout[0]); - draw_queue(frame, app, inner_layout[0]); - draw_playlists(frame, app, inner_layout[1]); - draw_progress_bar(frame, app, main_layout[1]); + match app.selected_tab { + SelectedTab::SongList => draw_song_list(frame, app, layout[1]), + SelectedTab::Queue => draw_queue(frame, app, layout[1]), + SelectedTab::Playlists => draw_playlists(frame, app, layout[1]), + } } /// draws list of songs @@ -98,6 +119,7 @@ fn draw_progress_bar(frame: &mut Frame, app: &mut App, size: Rect) { let title = Block::default() .title(Title::from(format!("{}: ", state).red().bold())) .title(Title::from(song.green().bold())); + // .title(Title::from(app.conn.conn.status().unwrap_or_default().volume.to_string().yellow())).title_alignment(Alignment::Right); let progress_bar = LineGauge::default() .block(title.borders(Borders::ALL)) .gauge_style(