From 35e6e420eaa6dfee28b9886b7879462e92717bd8 Mon Sep 17 00:00:00 2001 From: Kristofers Solo Date: Thu, 1 Jan 2026 04:20:55 +0200 Subject: [PATCH] feat: add status bar with keybind hints and torrent count --- src/ui/mod.rs | 9 +++++++- src/ui/status.rs | 57 ++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 65 insertions(+), 1 deletion(-) create mode 100644 src/ui/status.rs diff --git a/src/ui/mod.rs b/src/ui/mod.rs index 16cae0b..a4f8475 100644 --- a/src/ui/mod.rs +++ b/src/ui/mod.rs @@ -1,5 +1,6 @@ mod help; mod input; +mod status; mod table; use crate::{ @@ -27,7 +28,11 @@ pub fn render(app: &mut App, frame: &mut Frame) { let chunks = Layout::default() .direction(Direction::Vertical) - .constraints([Constraint::Length(3), Constraint::Min(0)].as_ref()) + .constraints([ + Constraint::Length(3), + Constraint::Min(0), + Constraint::Length(3), + ]) .split(size); let titles = app @@ -54,6 +59,8 @@ pub fn render(app: &mut App, frame: &mut Frame) { frame.render_stateful_widget(table, chunks[1], &mut app.state); + status::render(frame, app, chunks[2]); + if app.show_help { render_help(frame, app); } diff --git a/src/ui/status.rs b/src/ui/status.rs new file mode 100644 index 0000000..b99e6f5 --- /dev/null +++ b/src/ui/status.rs @@ -0,0 +1,57 @@ +use crate::app::{App, InputMode}; +use ratatui::{ + prelude::*, + text::Span, + widgets::{Block, BorderType, Borders, Paragraph}, +}; + +pub fn render(frame: &mut Frame, app: &App, area: Rect) { + let total = app.torrents.len(); + let selected_count = app.torrents.selected.len(); + + let left = if selected_count > 0 { + format!(" {selected_count}/{total} selected") + } else { + format!(" {total} torrents") + }; + + let mode_text = match app.input_mode { + InputMode::Move => Some("MOVE"), + InputMode::Rename => Some("RENAME"), + InputMode::ConfirmDelete(_) => Some("DELETE"), + InputMode::None => None, + }; + + let keybinds = match app.input_mode { + InputMode::None => "q Quit │ ? Help │ ↑↓ Navigate │ Space Select │ Enter Toggle", + InputMode::Move | InputMode::Rename => "Enter Submit │ Esc Cancel │ Tab Complete", + InputMode::ConfirmDelete(_) => "y Confirm │ n Cancel", + }; + + let right = format!("{keybinds} "); + + let available_width = area.width.saturating_sub(2) as usize; + let left_len = left.chars().count(); + let right_len = right.chars().count(); + + let content = if left_len + right_len < available_width { + let padding = available_width.saturating_sub(left_len + right_len); + format!("{left}{}{right}", " ".repeat(padding)) + } else { + right + }; + + let mut block = Block::default() + .borders(Borders::ALL) + .border_type(BorderType::Rounded); + + if let Some(mode) = mode_text { + block = block + .title(format!(" {mode} ")) + .title_style(Style::default().fg(Color::Yellow).bold()); + } + + let paragraph = Paragraph::new(Span::raw(content)).block(block); + + frame.render_widget(paragraph, area); +}