Scrolling help

This commit is contained in:
Ian Keane 2025-11-23 12:21:03 -05:00
parent eb7790ff8f
commit 857362b558
2 changed files with 118 additions and 34 deletions

View file

@ -60,6 +60,7 @@ pub struct App {
pub log_view_content: Vec<String>,
pub log_view_scroll: usize,
pub log_view_selected: usize,
pub help_scroll: usize,
pub clipboard: Option<arboard::Clipboard>,
pub status_message: Option<(String, std::time::Instant)>,
}
@ -97,6 +98,7 @@ impl App {
log_view_content: Vec::new(),
log_view_scroll: 0,
log_view_selected: 0,
help_scroll: 0,
clipboard: arboard::Clipboard::new().ok(),
status_message: None,
})
@ -141,7 +143,10 @@ impl App {
(KeyCode::Char('p'), KeyModifiers::CONTROL) => self.change_pane(-1),
(KeyCode::Enter, _) => self.toggle_current_item()?,
(KeyCode::Char('e'), KeyModifiers::CONTROL) => self.edit_config()?,
(KeyCode::Char('?'), _) => self.current_screen = Screen::Help,
(KeyCode::Char('?'), _) => {
self.help_scroll = 0;
self.current_screen = Screen::Help;
}
(KeyCode::Char('c'), _) => self.edit_app_config()?,
(KeyCode::Char('n'), _) => self.start_new_entry(),
(KeyCode::Char('p'), _) => self.start_reassign_project(),
@ -245,8 +250,26 @@ impl App {
fn handle_help_event(&mut self, event: Event) -> anyhow::Result<bool> {
match event {
Event::Key(KeyEvent { code, .. }) => match code {
KeyCode::Char('c') => self.current_screen = Screen::ConfigHelp,
KeyCode::Esc | KeyCode::Char('q') => self.current_screen = Screen::Main,
KeyCode::Char('c') => {
self.help_scroll = 0;
self.current_screen = Screen::ConfigHelp;
}
KeyCode::Char('j') | KeyCode::Down => {
self.help_scroll = self.help_scroll.saturating_add(1);
}
KeyCode::Char('k') | KeyCode::Up => {
self.help_scroll = self.help_scroll.saturating_sub(1);
}
KeyCode::PageDown => {
self.help_scroll = self.help_scroll.saturating_add(10);
}
KeyCode::PageUp => {
self.help_scroll = self.help_scroll.saturating_sub(10);
}
KeyCode::Esc | KeyCode::Char('q') | KeyCode::Char('?') => {
self.help_scroll = 0;
self.current_screen = Screen::Main;
}
_ => {}
},
_ => {}
@ -257,7 +280,22 @@ impl App {
fn handle_config_help_event(&mut self, event: Event) -> anyhow::Result<bool> {
match event {
Event::Key(KeyEvent { code, .. }) => match code {
KeyCode::Esc | KeyCode::Char('q') => self.current_screen = Screen::Help,
KeyCode::Char('j') | KeyCode::Down => {
self.help_scroll = self.help_scroll.saturating_add(1);
}
KeyCode::Char('k') | KeyCode::Up => {
self.help_scroll = self.help_scroll.saturating_sub(1);
}
KeyCode::PageDown => {
self.help_scroll = self.help_scroll.saturating_add(10);
}
KeyCode::PageUp => {
self.help_scroll = self.help_scroll.saturating_sub(10);
}
KeyCode::Esc | KeyCode::Char('q') | KeyCode::Char('?') => {
self.help_scroll = 0;
self.current_screen = Screen::Help;
}
_ => {}
},
_ => {}
@ -268,7 +306,20 @@ impl App {
fn handle_log_view_help_event(&mut self, event: Event) -> anyhow::Result<bool> {
match event {
Event::Key(KeyEvent { code, .. }) => match code {
KeyCode::Char('j') | KeyCode::Down => {
self.help_scroll = self.help_scroll.saturating_add(1);
}
KeyCode::Char('k') | KeyCode::Up => {
self.help_scroll = self.help_scroll.saturating_sub(1);
}
KeyCode::PageDown => {
self.help_scroll = self.help_scroll.saturating_add(10);
}
KeyCode::PageUp => {
self.help_scroll = self.help_scroll.saturating_sub(10);
}
KeyCode::Esc | KeyCode::Char('q') | KeyCode::Char('?') => {
self.help_scroll = 0;
self.current_screen = Screen::LogView;
}
_ => {}
@ -332,6 +383,7 @@ impl App {
self.needs_clear = true;
}
KeyCode::Char('?') => {
self.help_scroll = 0;
self.current_screen = Screen::LogViewHelp;
}
KeyCode::Char('d') => {

View file

@ -214,7 +214,7 @@ fn render_help_command_bar(frame: &mut Frame) {
frame.render_widget(command_bar, bar_area);
}
fn render_help(frame: &mut Frame, _app: &App) {
fn render_help(frame: &mut Frame, app: &App) {
let width = frame.size().width.saturating_sub(4).min(60);
let area = centered_rect(width, frame.size().height.saturating_sub(2), frame.size());
@ -231,43 +231,53 @@ fn render_help(frame: &mut Frame, _app: &App) {
"3. Ad-Hoc Items: One-off tasks and quick entries",
"",
"Navigation:",
"- Use j/k or ↑/↓ to move selection up/down",
"- Use h/l or ←/→ to switch between panes",
"- Use Ctrl+n/Ctrl+p to switch between panes",
"- Press Enter to start/stop time tracking",
"- Press n to create a new task in the current section",
"- j/k or ↑/↓: Move selection up/down",
"- h/l or ←/→: Switch between panes",
"- Ctrl+n/Ctrl+p: Switch between panes",
"- Enter: Start/stop time tracking for selected item",
"- n: Create a new task in the current section",
"",
"Main Commands:",
"j/k, arrows - Navigate",
"h/l, arrows - Switch panes",
"Enter - Start/stop timer",
"d - Delete task",
"p - Reassign project",
"v - View Watson log (g to group, e to edit, x to delete, c to copy)",
"Ctrl+e - Edit tasks config",
"c - Edit app config",
"d - Delete task from list",
"p - Reassign project/tag",
"v - View Watson log",
"Ctrl+e - Edit tasks config file",
"c - Edit app config file",
"n - New task",
"q - Quit",
"? (or ESC) - Exit help",
"? - Show/hide this help (ESC also works)",
"",
"Log View (press 'v'):",
"Once in log view, you can:",
"- Switch time periods: d (day), w (week), m (month)",
"- Toggle grouping: g (by date or by project)",
"- Change selection: h/l (entry → project → day → all)",
"- Navigate: j/k to move through selections",
"- Edit entry: e (entry level only)",
"- Delete entry: x (entry level only)",
"- Copy to clipboard: c (works at all levels)",
"- Press ? for detailed log view help",
];
let text = help_text.join("\n");
let block = Block::default()
.title("Help")
.title("Help (j/k to scroll)")
.borders(Borders::ALL)
.style(Style::default().fg(Color::White));
let paragraph = Paragraph::new(text)
.block(block)
.style(Style::default().fg(Color::White))
.scroll((app.help_scroll as u16, 0))
.wrap(ratatui::widgets::Wrap { trim: true });
frame.render_widget(paragraph, area);
render_help_command_bar(frame);
}
fn render_config_help(frame: &mut Frame, _app: &App) {
fn render_config_help(frame: &mut Frame, app: &App) {
let width = frame.size().width.saturating_sub(4).min(60);
let area = centered_rect(width, frame.size().height.saturating_sub(2), frame.size());
@ -276,35 +286,49 @@ fn render_config_help(frame: &mut Frame, _app: &App) {
let help_text = vec![
"WAT Configuration",
"",
"The configuration file is in YAML format and supports these options:",
"Configuration file location:",
" ~/.config/wat/config.yaml",
"",
"Available options:",
"",
"show_help_hint: true/false",
" Controls visibility of the help hint in the bottom bar",
" Default: true",
" Shows '(?) for help' hint in the bottom-right corner",
"",
"projects: [list of strings]",
" List of available project names",
"projects: [list of project names]",
" Default: [] (empty)",
" List of available project names shown when reassigning",
" Example: [\"work\", \"personal\", \"client-a\"]",
"",
"strict_projects: true/false",
" If true, only projects from the projects list are allowed",
" Default: false",
" When true, only allows projects from the 'projects' list",
" When false, any project name can be used",
"",
"Example configuration:",
"---",
"show_help_hint: true",
"projects:",
" - project1",
" - project2",
"strict_projects: false",
"projects:",
" - work",
" - personal",
" - open-source",
"",
"Note: The config file is created automatically on first run.",
"Edit it with 'c' from the main screen or manually with your editor.",
];
let text = help_text.join("\n");
let block = Block::default()
.title("Configuration Help")
.title("Configuration Help (j/k to scroll)")
.borders(Borders::ALL)
.style(Style::default().fg(Color::White));
let paragraph = Paragraph::new(text)
.block(block)
.style(Style::default().fg(Color::White))
.scroll((app.help_scroll as u16, 0))
.wrap(ratatui::widgets::Wrap { trim: true });
frame.render_widget(paragraph, area);
@ -595,7 +619,7 @@ fn render_log_view(frame: &mut Frame, app: &App) {
}
}
fn render_log_view_help(frame: &mut Frame, _app: &App) {
fn render_log_view_help(frame: &mut Frame, app: &App) {
let width = frame.size().width.saturating_sub(4).min(60);
let area = centered_rect(width, frame.size().height.saturating_sub(2), frame.size());
@ -622,34 +646,42 @@ fn render_log_view_help(frame: &mut Frame, _app: &App) {
" - At Entry level: Move to next/previous entry",
" - At Project level: Jump to next/previous project group",
" - At Day level: Jump to next/previous day",
"- h/l or ←/→: Change selection level (Entry ↔ Project ↔ Day)",
" - At All level: No navigation (entire view selected)",
"- h/l or ←/→: Change selection level",
" - l (right): Zoom in (All → Day → Project → Entry)",
" - h (left): Zoom out (Entry → Project → Day → All)",
"- PageUp/PageDown: Jump 10 entries (Entry level only)",
"",
"Selection Levels:",
"Selection Levels (use h/l to change):",
"- Entry: Select individual entry (can edit/delete/copy)",
"- Project: Select whole project group (can copy only)",
"- Day: Select entire day (can copy only)",
"- All: Select entire view/period (can copy only)",
"",
"Actions:",
"- e: Edit the selected entry (Entry level only)",
"- x: Delete the selected entry (Entry level only)",
"- c: Copy selection to clipboard (works at all levels)",
" Copies based on current selection level",
"",
"Other:",
"- ?: Show this help",
"- ?: Show/hide this help",
"- q or ESC: Return to main screen",
"",
"Tip: Use h/l to quickly select larger blocks for copying!",
];
let text = help_text.join("\n");
let block = Block::default()
.title("Log View Help")
.title("Log View Help (j/k to scroll)")
.borders(Borders::ALL)
.style(Style::default().fg(Color::White));
let paragraph = Paragraph::new(text)
.block(block)
.style(Style::default().fg(Color::White))
.scroll((app.help_scroll as u16, 0))
.wrap(ratatui::widgets::Wrap { trim: true });
frame.render_widget(paragraph, area);