diff --git a/src/ui.rs b/src/ui.rs index 34be178..36ca508 100644 --- a/src/ui.rs +++ b/src/ui.rs @@ -3,9 +3,10 @@ use crossterm::event::{KeyCode, KeyEvent, KeyModifiers}; use ratatui::{ prelude::*, widgets::*, - Frame, + style::{Color, Modifier, Style}, + text::{Line, Span, Text}, + layout::{Alignment, Constraint, Direction, Layout, Rect}, }; -use std::borrow::Cow; pub struct App<'a> { pub sessions: &'a [SMTPSession], @@ -16,6 +17,7 @@ pub struct App<'a> { filter_type: Option, filter_text: String, pub log_display_mode: LogDisplayMode, + pub show_help: bool, } #[derive(PartialEq)] @@ -42,6 +44,7 @@ impl<'a> App<'a> { filter_type: None, filter_text: String::new(), log_display_mode: LogDisplayMode::SingleLine, + show_help: false, } } @@ -81,6 +84,12 @@ impl<'a> App<'a> { } pub fn on_key(&mut self, key: KeyEvent) { + // If help is shown, any key should close it + if self.show_help { + self.show_help = false; + return; + } + match key.code { KeyCode::Char('q') => self.should_quit = true, KeyCode::Char('c') if key.modifiers.intersects(KeyModifiers::CONTROL) => self.should_quit = true, @@ -181,12 +190,61 @@ impl<'a> App<'a> { self.selected_session = Some(self.filtered_sessions[0]); } } + KeyCode::Char('h') => { + self.show_help = !self.show_help; + } _ => {} } } } +fn render_help(f: &mut Frame, area: Rect) { + let block = Block::default() + .title(" Help ") + .borders(Borders::ALL) + .border_style(Style::default().fg(Color::Yellow)); + + let text = vec![ + Line::from("Navigation:".bold()), + Line::from(" ↑/↓ - Move selection up/down"), + Line::from(" PgUp/PgDn - Move by 10 entries"), + Line::from(" Home/End - Jump to first/last entry"), + Line::from(" j/k - Scroll log view up/down"), + Line::from(""), + Line::from("Filtering:".bold()), + Line::from(" f - Filter by sender"), + Line::from(" t - Filter by recipient"), + Line::from(" r - Reset filter"), + Line::from(" - Type to filter"), + Line::from(" Enter - Apply filter"), + Line::from(" Esc - Cancel filter"), + Line::from(""), + Line::from("View:".bold()), + Line::from(" l - Toggle log display mode (single/multi-line)"), + Line::from(" h - Toggle this help"), + Line::from(""), + Line::from("Quit:".bold()), + Line::from(" q - Quit"), + Line::from(" Ctrl+c - Quit"), + Line::from(""), + Line::from("Usage:".bold()), + Line::from(" postfix-log-viewer [FILE]..."), + Line::from(" postfix-log-viewer mail.log mail.log.1.gz"), + ]; + + let paragraph = Paragraph::new(text) + .block(block) + .alignment(Alignment::Left); + + f.render_widget(paragraph, area); +} + pub fn ui(f: &mut Frame, app: &App) { + if app.show_help { + render_help(f, f.size()); + return; + } + let chunks = Layout::default() .direction(Direction::Horizontal) .constraints([Constraint::Percentage(40), Constraint::Percentage(60)].as_ref())