aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorkrolxon <krolyxon@tutanota.com>2024-04-25 12:58:13 +0530
committerkrolxon <krolyxon@tutanota.com>2024-04-25 12:58:13 +0530
commitf665c4e9f3b4eaa226b0c813f6845e247a4e6977 (patch)
tree03119ed4587357a34f3728700f3a3e19ac89e1b2
parent4bc03ce8f4dea2ed6d68f2694bd095c9e3857e5e (diff)
better event handling with tick, search
-rwxr-xr-xCargo.lock7
-rwxr-xr-xCargo.toml1
-rwxr-xr-xsrc/app.rs11
-rwxr-xr-xsrc/connection.rs27
-rwxr-xr-xsrc/handler.rs32
-rwxr-xr-xsrc/ui.rs62
6 files changed, 107 insertions, 33 deletions
diff --git a/Cargo.lock b/Cargo.lock
index 161af92..79b2484 100755
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -388,11 +388,18 @@ dependencies = [
"crossterm",
"mpd",
"ratatui",
+ "rust-fuzzy-search",
"rust_fzf",
"simple-dmenu",
]
[[package]]
+name = "rust-fuzzy-search"
+version = "0.1.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a157657054ffe556d8858504af8a672a054a6e0bd9e8ee531059100c0fa11bb2"
+
+[[package]]
name = "rust_fzf"
version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
diff --git a/Cargo.toml b/Cargo.toml
index 1127b66..ef3cf49 100755
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -12,3 +12,4 @@ rust_fzf = "0.3.1"
simple-dmenu = "0.1.0"
ratatui = "0.26.2"
crossterm = "0.27.0"
+rust-fuzzy-search = "0.1.1"
diff --git a/src/app.rs b/src/app.rs
index 7b80584..f129fe3 100755
--- a/src/app.rs
+++ b/src/app.rs
@@ -1,3 +1,5 @@
+use std::time::Duration;
+
use crate::connection::Connection;
use crate::list::ContentList;
use mpd::Client;
@@ -56,7 +58,11 @@ impl App {
})
}
- pub fn tick(&self) {}
+ pub fn tick(&mut self) {
+ self.conn.update_state();
+ self.conn.update_progress();
+ self.update_queue();
+ }
pub fn quit(&mut self) {
self.running = false;
@@ -76,8 +82,7 @@ impl App {
// });
conn.conn.queue().unwrap().into_iter().for_each(|x| {
vec.push(x.file);
- }
- );
+ });
}
pub fn update_queue(&mut self) {
diff --git a/src/connection.rs b/src/connection.rs
index b464b23..a741206 100755
--- a/src/connection.rs
+++ b/src/connection.rs
@@ -2,6 +2,7 @@ use mpd::song::Song;
use mpd::{Client, State};
use simple_dmenu::dmenu;
use std::process::Command;
+use std::time::Duration;
pub type Result<T> = core::result::Result<T, Error>;
pub type Error = Box<dyn std::error::Error>;
@@ -11,6 +12,8 @@ pub struct Connection {
pub conn: Client,
pub songs_filenames: Vec<String>,
pub state: String,
+ pub elapsed: Duration,
+ pub total_duration: Duration,
}
impl Connection {
@@ -24,10 +27,14 @@ impl Connection {
.map(|x| x.file)
.collect();
+ let (elapsed, total) = conn.status().unwrap().time.unwrap_or_default();
+
Ok(Self {
conn,
songs_filenames,
state: "Stopped".to_string(),
+ elapsed,
+ total_duration: total,
})
}
@@ -64,6 +71,26 @@ impl Connection {
self.state.clone()
}
+ pub fn update_progress(&mut self) {
+ let (elapsed, total) = self.conn.status().unwrap().time.unwrap_or_default();
+ self.elapsed = elapsed;
+ self.total_duration = total;
+ }
+
+ pub fn get_progress_ratio(&self) -> f64 {
+ let total = self.total_duration.as_secs_f64();
+ if total == 0.0 {
+ 0.0
+ } else {
+ let ratio = self.elapsed.as_secs_f64() / self.total_duration.as_secs_f64();
+ if ratio > 1.0 || ratio == 0.0 {
+ 1.0
+ } else {
+ ratio
+ }
+ }
+ }
+
/// push the given song to queue
pub fn push(&mut self, song: &Song) -> Result<()> {
if self.conn.queue().unwrap().is_empty() {
diff --git a/src/handler.rs b/src/handler.rs
index 67121fb..fce3aa8 100755
--- a/src/handler.rs
+++ b/src/handler.rs
@@ -2,6 +2,10 @@ use std::time::Duration;
use crate::app::{App, AppResult, SelectedTab};
use crossterm::event::{KeyCode, KeyEvent, KeyModifiers};
+use mpd::{Query, Term};
+use ratatui::style::Modifier;
+use rust_fuzzy_search;
+use simple_dmenu::dmenu;
pub fn handle_key_events(key_event: KeyEvent, app: &mut App) -> AppResult<()> {
match key_event.code {
@@ -39,7 +43,6 @@ pub fn handle_key_events(key_event: KeyEvent, app: &mut App) -> AppResult<()> {
app.queue_list.list.get(app.queue_list.index).unwrap(),
);
app.conn.push(&song)?;
-
}
SelectedTab::Playlists => {
app.conn
@@ -52,19 +55,16 @@ pub fn handle_key_events(key_event: KeyEvent, app: &mut App) -> AppResult<()> {
// Toggle Pause
KeyCode::Char('p') => {
app.conn.toggle_pause();
- app.conn.update_state();
}
// Pause
KeyCode::Char('s') => {
app.conn.pause();
- app.conn.update_state();
}
// Clear Queue
KeyCode::Char('x') => {
app.conn.conn.clear()?;
- app.conn.update_state();
// app.update_queue();
}
@@ -73,7 +73,6 @@ pub fn handle_key_events(key_event: KeyEvent, app: &mut App) -> AppResult<()> {
app.conn.play_dmenu()?;
}
-
// add to queue
KeyCode::Char('a') => {
let song = app.conn.get_song_with_only_filename(
@@ -82,7 +81,6 @@ pub fn handle_key_events(key_event: KeyEvent, app: &mut App) -> AppResult<()> {
app.conn.conn.push(&song)?;
}
-
KeyCode::Right => {
app.conn
.push_playlist(app.pl_list.list.get(app.pl_list.index).unwrap())?;
@@ -138,6 +136,28 @@ pub fn handle_key_events(key_event: KeyEvent, app: &mut App) -> AppResult<()> {
// Delete highlighted song from the queue
KeyCode::Char('d') => {
app.conn.conn.delete(app.queue_list.index as u32)?;
+ app.update_queue();
+ }
+
+ KeyCode::Char('U') => {
+ app.conn.conn.update()?;
+ }
+
+ KeyCode::Char('L') => {
+ let str = dmenu!(prompt "Search: ");
+ let list = app
+ .conn
+ .songs_filenames
+ .iter()
+ .map(|f| f.as_str())
+ .collect::<Vec<&str>>();
+ let (filename, _) = rust_fuzzy_search::fuzzy_search_sorted(&str, &list)
+ .get(0)
+ .unwrap()
+ .clone();
+
+ let song = app.conn.get_song_with_only_filename(filename);
+ app.conn.push(&song)?;
}
_ => {}
diff --git a/src/ui.rs b/src/ui.rs
index 624e302..d9ef39b 100755
--- a/src/ui.rs
+++ b/src/ui.rs
@@ -1,7 +1,6 @@
use crate::app::{App, AppResult, SelectedTab};
use ratatui::{
prelude::*,
- style::palette::tailwind,
widgets::{block::Title, *},
};
@@ -16,8 +15,9 @@ pub fn render(app: &mut App, frame: &mut Frame) {
let layout = Layout::default()
.direction(Direction::Vertical)
.constraints(vec![
- Constraint::Percentage(5),
- Constraint::Percentage(88),
+ Constraint::Percentage(0),
+ // Constraint::Percentage(88),
+ Constraint::Percentage(93),
Constraint::Percentage(7),
])
.split(frame.size());
@@ -37,30 +37,35 @@ pub fn render(app: &mut App, frame: &mut Frame) {
// draw_playlists(frame, app, inner_layout[1]);
draw_progress_bar(frame, app, layout[2]);
- 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]);
+ // 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]);
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]),
+ SelectedTab::Queue => draw_queue(frame, app, layout[1]),
+ SelectedTab::Playlists => draw_playlists(frame, app, layout[1]),
}
}
/// draws list of songs
fn draw_song_list(frame: &mut Frame, app: &mut App, size: Rect) {
let mut song_state = ListState::default();
+ let total_songs = app.conn.conn.stats().unwrap().songs.to_string();
let list = List::new(app.conn.songs_filenames.clone())
.block(
Block::default()
.title("Song List".green().bold())
+ .title(
+ Title::from(format!("Total Songs: {}", total_songs).bold().green())
+ .alignment(Alignment::Right),
+ )
.borders(Borders::ALL),
)
.highlight_style(Style::new().add_modifier(Modifier::REVERSED))
@@ -74,16 +79,13 @@ fn draw_song_list(frame: &mut Frame, app: &mut App, size: Rect) {
/// draws playing queue
fn draw_queue(frame: &mut Frame, app: &mut App, size: Rect) {
let mut queue_state = ListState::default();
- let title = Block::default()
- .title(Title::from("Play Queue".green().bold()))
- .title("Shift + ▲ ▼ to scroll, Shift + Enter to play".yellow());
+ let title = Block::default().title(Title::from("Play Queue".green().bold()));
let list = List::new(app.queue_list.list.clone())
.block(title.borders(Borders::ALL))
.highlight_style(Style::new().add_modifier(Modifier::REVERSED))
.highlight_symbol(">>")
.repeat_highlight_symbol(true);
- app.update_queue();
queue_state.select(Some(app.queue_list.index));
frame.render_stateful_widget(list, size, &mut queue_state);
}
@@ -92,9 +94,7 @@ fn draw_queue(frame: &mut Frame, app: &mut App, size: Rect) {
fn draw_playlists(frame: &mut Frame, app: &mut App, size: Rect) {
let mut state = ListState::default();
- let title = Block::default()
- .title(Title::from("Playlist".green().bold()))
- .title("▲ ▼ to scroll, Use ► to add playlist to queue".yellow());
+ let title = Block::default().title(Title::from("Playlist".green().bold()));
let list = List::new(app.pl_list.list.clone())
.block(title.borders(Borders::ALL))
.highlight_style(Style::new().add_modifier(Modifier::REVERSED))
@@ -118,8 +118,22 @@ 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);
+ .title(Title::from(song.green().bold()))
+ .title(
+ Title::from(
+ format!(
+ "{}/{}",
+ app.conn.elapsed.as_secs(),
+ app.conn.total_duration.as_secs()
+ )
+ .cyan()
+ .bold(),
+ )
+ .alignment(Alignment::Right),
+ )
+ .borders(Borders::ALL);
+
+ // .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(
@@ -129,7 +143,7 @@ fn draw_progress_bar(frame: &mut Frame, app: &mut App, size: Rect) {
.add_modifier(Modifier::BOLD),
)
.line_set(symbols::line::THICK)
- .ratio(0.2);
+ .ratio(app.conn.get_progress_ratio());
frame.render_widget(progress_bar, size);
}