ommp.git

ommp

~ Oh My Music Player — a standalone terminal music player built with Rust and ratatui
git clone https://github.com/debuman/ommp.git

src/ui/widgets/progress_bar.rs (2711B)

      1 use ratatui::layout::{Constraint, Direction, Layout, Rect};
      2 use ratatui::style::{Color, Style};
      3 use ratatui::text::{Line, Span};
      4 use ratatui::widgets::{Block, Borders, Paragraph, Gauge};
      5 use ratatui::Frame;
      6 
      7 use crate::app::App;
      8 use crate::app::state::PlayState;
      9 use crate::ui::theme::Theme;
     10 use crate::ui::text::format_time;
     11 
     12 pub fn render_progress_bar(frame: &mut Frame, area: Rect, app: &App, theme: &Theme) {
     13     let block = Block::default()
     14         .borders(Borders::ALL)
     15         .border_style(Style::default().fg(theme.border_unfocused));
     16 
     17     let inner = block.inner(area);
     18     frame.render_widget(block, area);
     19 
     20     let cols = Layout::default()
     21         .direction(Direction::Horizontal)
     22         .constraints([
     23             Constraint::Length(3),  // Play icon
     24             Constraint::Min(10),   // Gauge bar
     25             Constraint::Length(13), // Time display
     26         ])
     27         .split(inner);
     28 
     29     // Play icon
     30     let icon = match app.playback.state {
     31         PlayState::Playing => "\u{F04B}",  // nf-fa-play
     32         PlayState::Paused => "\u{F04C}",   // nf-fa-pause
     33         PlayState::Stopped => "\u{F04D}",  // nf-fa-stop
     34     };
     35     let icon_color = match app.playback.state {
     36         PlayState::Playing => Color::Rgb(80, 255, 120),
     37         PlayState::Paused => Color::Rgb(255, 200, 80),
     38         PlayState::Stopped => Color::Rgb(255, 100, 100),
     39     };
     40     let icon_widget = Paragraph::new(Line::from(Span::styled(
     41         format!(" {}", icon),
     42         Style::default().fg(icon_color),
     43     )));
     44     frame.render_widget(icon_widget, cols[0]);
     45 
     46     // Gauge
     47     let ratio = if app.playback.duration_secs > 0.0 {
     48         (app.playback.position_secs / app.playback.duration_secs).clamp(0.0, 1.0)
     49     } else {
     50         0.0
     51     };
     52 
     53     let gauge = Gauge::default()
     54         .ratio(ratio)
     55         .label("")
     56         .gauge_style(Style::default().fg(theme.progress_filled).bg(theme.progress_empty));
     57     frame.render_widget(gauge, cols[1]);
     58 
     59     // Time
     60     let pos = format_time(app.playback.position_secs);
     61     let dur = format_time(app.playback.duration_secs);
     62     let time_widget = Paragraph::new(Line::from(Span::styled(
     63         format!(" {} / {}", pos, dur),
     64         Style::default().fg(Color::White),
     65     )));
     66     frame.render_widget(time_widget, cols[2]);
     67 }
     68 
     69 /// Returns the gauge area for mouse click seeking
     70 pub fn progress_gauge_area(area: Rect) -> Rect {
     71     let block = Block::default().borders(Borders::ALL);
     72     let inner = block.inner(area);
     73 
     74     let cols = Layout::default()
     75         .direction(Direction::Horizontal)
     76         .constraints([
     77             Constraint::Length(3),
     78             Constraint::Min(10),
     79             Constraint::Length(13),
     80         ])
     81         .split(inner);
     82 
     83     cols[1]
     84 }
     85