mirror of
https://github.com/bahdotsh/wrkflw.git
synced 2025-12-16 11:47:45 +01:00
Merge pull request #38 from bahdotsh/improve-tui-help-tab
feat(ui): enhance TUI help tab with comprehensive documentation and s…
This commit is contained in:
@@ -189,6 +189,25 @@ fn run_tui_event_loop(
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Handle help overlay scrolling
|
||||||
|
if app.show_help {
|
||||||
|
match key.code {
|
||||||
|
KeyCode::Up | KeyCode::Char('k') => {
|
||||||
|
app.scroll_help_up();
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
KeyCode::Down | KeyCode::Char('j') => {
|
||||||
|
app.scroll_help_down();
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
KeyCode::Esc | KeyCode::Char('?') => {
|
||||||
|
app.show_help = false;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
match key.code {
|
match key.code {
|
||||||
KeyCode::Char('q') => {
|
KeyCode::Char('q') => {
|
||||||
// Exit and clean up
|
// Exit and clean up
|
||||||
@@ -223,6 +242,8 @@ fn run_tui_event_loop(
|
|||||||
} else {
|
} else {
|
||||||
app.scroll_logs_up();
|
app.scroll_logs_up();
|
||||||
}
|
}
|
||||||
|
} else if app.selected_tab == 3 {
|
||||||
|
app.scroll_help_up();
|
||||||
} else if app.selected_tab == 0 {
|
} else if app.selected_tab == 0 {
|
||||||
app.previous_workflow();
|
app.previous_workflow();
|
||||||
} else if app.selected_tab == 1 {
|
} else if app.selected_tab == 1 {
|
||||||
@@ -240,6 +261,8 @@ fn run_tui_event_loop(
|
|||||||
} else {
|
} else {
|
||||||
app.scroll_logs_down();
|
app.scroll_logs_down();
|
||||||
}
|
}
|
||||||
|
} else if app.selected_tab == 3 {
|
||||||
|
app.scroll_help_down();
|
||||||
} else if app.selected_tab == 0 {
|
} else if app.selected_tab == 0 {
|
||||||
app.next_workflow();
|
app.next_workflow();
|
||||||
} else if app.selected_tab == 1 {
|
} else if app.selected_tab == 1 {
|
||||||
|
|||||||
@@ -42,6 +42,9 @@ pub struct App {
|
|||||||
pub log_search_matches: Vec<usize>, // Indices of logs that match the search
|
pub log_search_matches: Vec<usize>, // Indices of logs that match the search
|
||||||
pub log_search_match_idx: usize, // Current match index for navigation
|
pub log_search_match_idx: usize, // Current match index for navigation
|
||||||
|
|
||||||
|
// Help tab scrolling
|
||||||
|
pub help_scroll: usize, // Scrolling position for help content
|
||||||
|
|
||||||
// Background log processing
|
// Background log processing
|
||||||
pub log_processor: LogProcessor,
|
pub log_processor: LogProcessor,
|
||||||
pub processed_logs: Vec<ProcessedLogEntry>,
|
pub processed_logs: Vec<ProcessedLogEntry>,
|
||||||
@@ -207,6 +210,7 @@ impl App {
|
|||||||
log_filter_level: Some(LogFilterLevel::All),
|
log_filter_level: Some(LogFilterLevel::All),
|
||||||
log_search_matches: Vec::new(),
|
log_search_matches: Vec::new(),
|
||||||
log_search_match_idx: 0,
|
log_search_match_idx: 0,
|
||||||
|
help_scroll: 0,
|
||||||
|
|
||||||
// Background log processing
|
// Background log processing
|
||||||
log_processor: LogProcessor::new(),
|
log_processor: LogProcessor::new(),
|
||||||
@@ -807,6 +811,18 @@ impl App {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Scroll help content up
|
||||||
|
pub fn scroll_help_up(&mut self) {
|
||||||
|
self.help_scroll = self.help_scroll.saturating_sub(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Scroll help content down
|
||||||
|
pub fn scroll_help_down(&mut self) {
|
||||||
|
// The help content has a fixed number of lines, so we set a reasonable max
|
||||||
|
const MAX_HELP_SCROLL: usize = 30; // Adjust based on help content length
|
||||||
|
self.help_scroll = (self.help_scroll + 1).min(MAX_HELP_SCROLL);
|
||||||
|
}
|
||||||
|
|
||||||
// Update progress for running workflows
|
// Update progress for running workflows
|
||||||
pub fn update_running_workflow_progress(&mut self) {
|
pub fn update_running_workflow_progress(&mut self) {
|
||||||
if let Some(idx) = self.current_execution {
|
if let Some(idx) = self.current_execution {
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
// Help overlay rendering
|
// Help overlay rendering
|
||||||
use ratatui::{
|
use ratatui::{
|
||||||
backend::CrosstermBackend,
|
backend::CrosstermBackend,
|
||||||
layout::Rect,
|
layout::{Constraint, Direction, Layout, Rect},
|
||||||
style::{Color, Modifier, Style},
|
style::{Color, Modifier, Style},
|
||||||
text::{Line, Span},
|
text::{Line, Span},
|
||||||
widgets::{Block, BorderType, Borders, Paragraph, Wrap},
|
widgets::{Block, BorderType, Borders, Paragraph, Wrap},
|
||||||
@@ -9,11 +9,22 @@ use ratatui::{
|
|||||||
};
|
};
|
||||||
use std::io;
|
use std::io;
|
||||||
|
|
||||||
// Render the help tab
|
// Render the help tab with scroll support
|
||||||
pub fn render_help_tab(f: &mut Frame<CrosstermBackend<io::Stdout>>, area: Rect) {
|
pub fn render_help_content(
|
||||||
let help_text = vec![
|
f: &mut Frame<CrosstermBackend<io::Stdout>>,
|
||||||
|
area: Rect,
|
||||||
|
scroll_offset: usize,
|
||||||
|
) {
|
||||||
|
// Split the area into columns for better organization
|
||||||
|
let chunks = Layout::default()
|
||||||
|
.direction(Direction::Horizontal)
|
||||||
|
.constraints([Constraint::Percentage(50), Constraint::Percentage(50)].as_ref())
|
||||||
|
.split(area);
|
||||||
|
|
||||||
|
// Left column content
|
||||||
|
let left_help_text = vec![
|
||||||
Line::from(Span::styled(
|
Line::from(Span::styled(
|
||||||
"Keyboard Controls",
|
"🗂 NAVIGATION",
|
||||||
Style::default()
|
Style::default()
|
||||||
.fg(Color::Cyan)
|
.fg(Color::Cyan)
|
||||||
.add_modifier(Modifier::BOLD),
|
.add_modifier(Modifier::BOLD),
|
||||||
@@ -21,35 +32,391 @@ pub fn render_help_tab(f: &mut Frame<CrosstermBackend<io::Stdout>>, area: Rect)
|
|||||||
Line::from(""),
|
Line::from(""),
|
||||||
Line::from(vec![
|
Line::from(vec![
|
||||||
Span::styled(
|
Span::styled(
|
||||||
"Tab",
|
"Tab / Shift+Tab",
|
||||||
Style::default()
|
Style::default()
|
||||||
.fg(Color::Yellow)
|
.fg(Color::Yellow)
|
||||||
.add_modifier(Modifier::BOLD),
|
.add_modifier(Modifier::BOLD),
|
||||||
),
|
),
|
||||||
Span::raw(" - Switch between tabs"),
|
Span::raw(" - Switch between tabs"),
|
||||||
]),
|
]),
|
||||||
// More help text would follow...
|
Line::from(vec![
|
||||||
|
Span::styled(
|
||||||
|
"1-4 / w,x,l,h",
|
||||||
|
Style::default()
|
||||||
|
.fg(Color::Yellow)
|
||||||
|
.add_modifier(Modifier::BOLD),
|
||||||
|
),
|
||||||
|
Span::raw(" - Jump to specific tab"),
|
||||||
|
]),
|
||||||
|
Line::from(vec![
|
||||||
|
Span::styled(
|
||||||
|
"↑/↓ or k/j",
|
||||||
|
Style::default()
|
||||||
|
.fg(Color::Yellow)
|
||||||
|
.add_modifier(Modifier::BOLD),
|
||||||
|
),
|
||||||
|
Span::raw(" - Navigate lists"),
|
||||||
|
]),
|
||||||
|
Line::from(vec![
|
||||||
|
Span::styled(
|
||||||
|
"Enter",
|
||||||
|
Style::default()
|
||||||
|
.fg(Color::Yellow)
|
||||||
|
.add_modifier(Modifier::BOLD),
|
||||||
|
),
|
||||||
|
Span::raw(" - Select/View details"),
|
||||||
|
]),
|
||||||
|
Line::from(vec![
|
||||||
|
Span::styled(
|
||||||
|
"Esc",
|
||||||
|
Style::default()
|
||||||
|
.fg(Color::Yellow)
|
||||||
|
.add_modifier(Modifier::BOLD),
|
||||||
|
),
|
||||||
|
Span::raw(" - Back/Exit help"),
|
||||||
|
]),
|
||||||
|
Line::from(""),
|
||||||
|
Line::from(Span::styled(
|
||||||
|
"🚀 WORKFLOW MANAGEMENT",
|
||||||
|
Style::default()
|
||||||
|
.fg(Color::Green)
|
||||||
|
.add_modifier(Modifier::BOLD),
|
||||||
|
)),
|
||||||
|
Line::from(""),
|
||||||
|
Line::from(vec![
|
||||||
|
Span::styled(
|
||||||
|
"Space",
|
||||||
|
Style::default()
|
||||||
|
.fg(Color::Yellow)
|
||||||
|
.add_modifier(Modifier::BOLD),
|
||||||
|
),
|
||||||
|
Span::raw(" - Toggle workflow selection"),
|
||||||
|
]),
|
||||||
|
Line::from(vec![
|
||||||
|
Span::styled(
|
||||||
|
"r",
|
||||||
|
Style::default()
|
||||||
|
.fg(Color::Yellow)
|
||||||
|
.add_modifier(Modifier::BOLD),
|
||||||
|
),
|
||||||
|
Span::raw(" - Run selected workflows"),
|
||||||
|
]),
|
||||||
|
Line::from(vec![
|
||||||
|
Span::styled(
|
||||||
|
"a",
|
||||||
|
Style::default()
|
||||||
|
.fg(Color::Yellow)
|
||||||
|
.add_modifier(Modifier::BOLD),
|
||||||
|
),
|
||||||
|
Span::raw(" - Select all workflows"),
|
||||||
|
]),
|
||||||
|
Line::from(vec![
|
||||||
|
Span::styled(
|
||||||
|
"n",
|
||||||
|
Style::default()
|
||||||
|
.fg(Color::Yellow)
|
||||||
|
.add_modifier(Modifier::BOLD),
|
||||||
|
),
|
||||||
|
Span::raw(" - Deselect all workflows"),
|
||||||
|
]),
|
||||||
|
Line::from(vec![
|
||||||
|
Span::styled(
|
||||||
|
"Shift+R",
|
||||||
|
Style::default()
|
||||||
|
.fg(Color::Yellow)
|
||||||
|
.add_modifier(Modifier::BOLD),
|
||||||
|
),
|
||||||
|
Span::raw(" - Reset workflow status"),
|
||||||
|
]),
|
||||||
|
Line::from(vec![
|
||||||
|
Span::styled(
|
||||||
|
"t",
|
||||||
|
Style::default()
|
||||||
|
.fg(Color::Yellow)
|
||||||
|
.add_modifier(Modifier::BOLD),
|
||||||
|
),
|
||||||
|
Span::raw(" - Trigger remote workflow"),
|
||||||
|
]),
|
||||||
|
Line::from(""),
|
||||||
|
Line::from(Span::styled(
|
||||||
|
"🔧 EXECUTION MODES",
|
||||||
|
Style::default()
|
||||||
|
.fg(Color::Magenta)
|
||||||
|
.add_modifier(Modifier::BOLD),
|
||||||
|
)),
|
||||||
|
Line::from(""),
|
||||||
|
Line::from(vec![
|
||||||
|
Span::styled(
|
||||||
|
"e",
|
||||||
|
Style::default()
|
||||||
|
.fg(Color::Yellow)
|
||||||
|
.add_modifier(Modifier::BOLD),
|
||||||
|
),
|
||||||
|
Span::raw(" - Toggle emulation mode"),
|
||||||
|
]),
|
||||||
|
Line::from(vec![
|
||||||
|
Span::styled(
|
||||||
|
"v",
|
||||||
|
Style::default()
|
||||||
|
.fg(Color::Yellow)
|
||||||
|
.add_modifier(Modifier::BOLD),
|
||||||
|
),
|
||||||
|
Span::raw(" - Toggle validation mode"),
|
||||||
|
]),
|
||||||
|
Line::from(""),
|
||||||
|
Line::from(vec![Span::styled(
|
||||||
|
"Runtime Modes:",
|
||||||
|
Style::default()
|
||||||
|
.fg(Color::White)
|
||||||
|
.add_modifier(Modifier::BOLD),
|
||||||
|
)]),
|
||||||
|
Line::from(vec![
|
||||||
|
Span::raw(" • "),
|
||||||
|
Span::styled("Docker", Style::default().fg(Color::Blue)),
|
||||||
|
Span::raw(" - Container isolation (default)"),
|
||||||
|
]),
|
||||||
|
Line::from(vec![
|
||||||
|
Span::raw(" • "),
|
||||||
|
Span::styled("Podman", Style::default().fg(Color::Blue)),
|
||||||
|
Span::raw(" - Rootless containers"),
|
||||||
|
]),
|
||||||
|
Line::from(vec![
|
||||||
|
Span::raw(" • "),
|
||||||
|
Span::styled("Emulation", Style::default().fg(Color::Red)),
|
||||||
|
Span::raw(" - Process mode (UNSAFE)"),
|
||||||
|
]),
|
||||||
|
Line::from(vec![
|
||||||
|
Span::raw(" • "),
|
||||||
|
Span::styled("Secure Emulation", Style::default().fg(Color::Yellow)),
|
||||||
|
Span::raw(" - Sandboxed processes"),
|
||||||
|
]),
|
||||||
];
|
];
|
||||||
|
|
||||||
let help_widget = Paragraph::new(help_text)
|
// Right column content
|
||||||
|
let right_help_text = vec![
|
||||||
|
Line::from(Span::styled(
|
||||||
|
"📄 LOGS & SEARCH",
|
||||||
|
Style::default()
|
||||||
|
.fg(Color::Blue)
|
||||||
|
.add_modifier(Modifier::BOLD),
|
||||||
|
)),
|
||||||
|
Line::from(""),
|
||||||
|
Line::from(vec![
|
||||||
|
Span::styled(
|
||||||
|
"s",
|
||||||
|
Style::default()
|
||||||
|
.fg(Color::Yellow)
|
||||||
|
.add_modifier(Modifier::BOLD),
|
||||||
|
),
|
||||||
|
Span::raw(" - Toggle log search"),
|
||||||
|
]),
|
||||||
|
Line::from(vec![
|
||||||
|
Span::styled(
|
||||||
|
"f",
|
||||||
|
Style::default()
|
||||||
|
.fg(Color::Yellow)
|
||||||
|
.add_modifier(Modifier::BOLD),
|
||||||
|
),
|
||||||
|
Span::raw(" - Toggle log filter"),
|
||||||
|
]),
|
||||||
|
Line::from(vec![
|
||||||
|
Span::styled(
|
||||||
|
"c",
|
||||||
|
Style::default()
|
||||||
|
.fg(Color::Yellow)
|
||||||
|
.add_modifier(Modifier::BOLD),
|
||||||
|
),
|
||||||
|
Span::raw(" - Clear search & filter"),
|
||||||
|
]),
|
||||||
|
Line::from(vec![
|
||||||
|
Span::styled(
|
||||||
|
"n",
|
||||||
|
Style::default()
|
||||||
|
.fg(Color::Yellow)
|
||||||
|
.add_modifier(Modifier::BOLD),
|
||||||
|
),
|
||||||
|
Span::raw(" - Next search match"),
|
||||||
|
]),
|
||||||
|
Line::from(vec![
|
||||||
|
Span::styled(
|
||||||
|
"↑/↓",
|
||||||
|
Style::default()
|
||||||
|
.fg(Color::Yellow)
|
||||||
|
.add_modifier(Modifier::BOLD),
|
||||||
|
),
|
||||||
|
Span::raw(" - Scroll logs/Navigate"),
|
||||||
|
]),
|
||||||
|
Line::from(""),
|
||||||
|
Line::from(Span::styled(
|
||||||
|
"ℹ️ TAB OVERVIEW",
|
||||||
|
Style::default()
|
||||||
|
.fg(Color::White)
|
||||||
|
.add_modifier(Modifier::BOLD),
|
||||||
|
)),
|
||||||
|
Line::from(""),
|
||||||
|
Line::from(vec![
|
||||||
|
Span::styled(
|
||||||
|
"1. Workflows",
|
||||||
|
Style::default()
|
||||||
|
.fg(Color::Cyan)
|
||||||
|
.add_modifier(Modifier::BOLD),
|
||||||
|
),
|
||||||
|
Span::raw(" - Browse & select workflows"),
|
||||||
|
]),
|
||||||
|
Line::from(vec![Span::raw(" • View workflow files")]),
|
||||||
|
Line::from(vec![Span::raw(" • Select multiple for batch execution")]),
|
||||||
|
Line::from(vec![Span::raw(" • Trigger remote workflows")]),
|
||||||
|
Line::from(""),
|
||||||
|
Line::from(vec![
|
||||||
|
Span::styled(
|
||||||
|
"2. Execution",
|
||||||
|
Style::default()
|
||||||
|
.fg(Color::Green)
|
||||||
|
.add_modifier(Modifier::BOLD),
|
||||||
|
),
|
||||||
|
Span::raw(" - Monitor job progress"),
|
||||||
|
]),
|
||||||
|
Line::from(vec![Span::raw(" • View job status and details")]),
|
||||||
|
Line::from(vec![Span::raw(" • Enter job details with Enter")]),
|
||||||
|
Line::from(vec![Span::raw(" • Navigate step execution")]),
|
||||||
|
Line::from(""),
|
||||||
|
Line::from(vec![
|
||||||
|
Span::styled(
|
||||||
|
"3. Logs",
|
||||||
|
Style::default()
|
||||||
|
.fg(Color::Blue)
|
||||||
|
.add_modifier(Modifier::BOLD),
|
||||||
|
),
|
||||||
|
Span::raw(" - View execution logs"),
|
||||||
|
]),
|
||||||
|
Line::from(vec![Span::raw(" • Search and filter logs")]),
|
||||||
|
Line::from(vec![Span::raw(" • Real-time log streaming")]),
|
||||||
|
Line::from(vec![Span::raw(" • Navigate search results")]),
|
||||||
|
Line::from(""),
|
||||||
|
Line::from(vec![
|
||||||
|
Span::styled(
|
||||||
|
"4. Help",
|
||||||
|
Style::default()
|
||||||
|
.fg(Color::Yellow)
|
||||||
|
.add_modifier(Modifier::BOLD),
|
||||||
|
),
|
||||||
|
Span::raw(" - This comprehensive guide"),
|
||||||
|
]),
|
||||||
|
Line::from(""),
|
||||||
|
Line::from(Span::styled(
|
||||||
|
"🎯 QUICK ACTIONS",
|
||||||
|
Style::default().fg(Color::Red).add_modifier(Modifier::BOLD),
|
||||||
|
)),
|
||||||
|
Line::from(""),
|
||||||
|
Line::from(vec![
|
||||||
|
Span::styled(
|
||||||
|
"?",
|
||||||
|
Style::default()
|
||||||
|
.fg(Color::Yellow)
|
||||||
|
.add_modifier(Modifier::BOLD),
|
||||||
|
),
|
||||||
|
Span::raw(" - Toggle help overlay"),
|
||||||
|
]),
|
||||||
|
Line::from(vec![
|
||||||
|
Span::styled(
|
||||||
|
"q",
|
||||||
|
Style::default()
|
||||||
|
.fg(Color::Yellow)
|
||||||
|
.add_modifier(Modifier::BOLD),
|
||||||
|
),
|
||||||
|
Span::raw(" - Quit application"),
|
||||||
|
]),
|
||||||
|
Line::from(""),
|
||||||
|
Line::from(Span::styled(
|
||||||
|
"💡 TIPS",
|
||||||
|
Style::default()
|
||||||
|
.fg(Color::Yellow)
|
||||||
|
.add_modifier(Modifier::BOLD),
|
||||||
|
)),
|
||||||
|
Line::from(""),
|
||||||
|
Line::from(vec![
|
||||||
|
Span::raw("• Use "),
|
||||||
|
Span::styled("emulation mode", Style::default().fg(Color::Red)),
|
||||||
|
Span::raw(" when containers"),
|
||||||
|
]),
|
||||||
|
Line::from(vec![Span::raw(" are unavailable or for quick testing")]),
|
||||||
|
Line::from(""),
|
||||||
|
Line::from(vec![
|
||||||
|
Span::raw("• "),
|
||||||
|
Span::styled("Secure emulation", Style::default().fg(Color::Yellow)),
|
||||||
|
Span::raw(" provides sandboxing"),
|
||||||
|
]),
|
||||||
|
Line::from(vec![Span::raw(" for untrusted workflows")]),
|
||||||
|
Line::from(""),
|
||||||
|
Line::from(vec![
|
||||||
|
Span::raw("• Use "),
|
||||||
|
Span::styled("validation mode", Style::default().fg(Color::Green)),
|
||||||
|
Span::raw(" to check"),
|
||||||
|
]),
|
||||||
|
Line::from(vec![Span::raw(" workflows without execution")]),
|
||||||
|
Line::from(""),
|
||||||
|
Line::from(vec![
|
||||||
|
Span::raw("• "),
|
||||||
|
Span::styled("Preserve containers", Style::default().fg(Color::Blue)),
|
||||||
|
Span::raw(" on failure"),
|
||||||
|
]),
|
||||||
|
Line::from(vec![Span::raw(" for debugging (Docker/Podman only)")]),
|
||||||
|
];
|
||||||
|
|
||||||
|
// Apply scroll offset to the content
|
||||||
|
let left_help_text = if scroll_offset < left_help_text.len() {
|
||||||
|
left_help_text.into_iter().skip(scroll_offset).collect()
|
||||||
|
} else {
|
||||||
|
vec![Line::from("")]
|
||||||
|
};
|
||||||
|
|
||||||
|
let right_help_text = if scroll_offset < right_help_text.len() {
|
||||||
|
right_help_text.into_iter().skip(scroll_offset).collect()
|
||||||
|
} else {
|
||||||
|
vec![Line::from("")]
|
||||||
|
};
|
||||||
|
|
||||||
|
// Render left column
|
||||||
|
let left_widget = Paragraph::new(left_help_text)
|
||||||
.block(
|
.block(
|
||||||
Block::default()
|
Block::default()
|
||||||
.borders(Borders::ALL)
|
.borders(Borders::ALL)
|
||||||
.border_type(BorderType::Rounded)
|
.border_type(BorderType::Rounded)
|
||||||
.title(Span::styled(" Help ", Style::default().fg(Color::Yellow))),
|
.title(Span::styled(
|
||||||
|
" WRKFLW Help - Controls & Features ",
|
||||||
|
Style::default()
|
||||||
|
.fg(Color::Yellow)
|
||||||
|
.add_modifier(Modifier::BOLD),
|
||||||
|
)),
|
||||||
)
|
)
|
||||||
.wrap(Wrap { trim: true });
|
.wrap(Wrap { trim: true });
|
||||||
|
|
||||||
f.render_widget(help_widget, area);
|
// Render right column
|
||||||
|
let right_widget = Paragraph::new(right_help_text)
|
||||||
|
.block(
|
||||||
|
Block::default()
|
||||||
|
.borders(Borders::ALL)
|
||||||
|
.border_type(BorderType::Rounded)
|
||||||
|
.title(Span::styled(
|
||||||
|
" Interface Guide & Tips ",
|
||||||
|
Style::default()
|
||||||
|
.fg(Color::Cyan)
|
||||||
|
.add_modifier(Modifier::BOLD),
|
||||||
|
)),
|
||||||
|
)
|
||||||
|
.wrap(Wrap { trim: true });
|
||||||
|
|
||||||
|
f.render_widget(left_widget, chunks[0]);
|
||||||
|
f.render_widget(right_widget, chunks[1]);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Render a help overlay
|
// Render a help overlay
|
||||||
pub fn render_help_overlay(f: &mut Frame<CrosstermBackend<io::Stdout>>) {
|
pub fn render_help_overlay(f: &mut Frame<CrosstermBackend<io::Stdout>>, scroll_offset: usize) {
|
||||||
let size = f.size();
|
let size = f.size();
|
||||||
|
|
||||||
// Create a slightly smaller centered modal
|
// Create a larger centered modal to accommodate comprehensive help content
|
||||||
let width = size.width.min(60);
|
let width = (size.width * 9 / 10).min(120); // Use 90% of width, max 120 chars
|
||||||
let height = size.height.min(20);
|
let height = (size.height * 9 / 10).min(40); // Use 90% of height, max 40 lines
|
||||||
let x = (size.width - width) / 2;
|
let x = (size.width - width) / 2;
|
||||||
let y = (size.height - height) / 2;
|
let y = (size.height - height) / 2;
|
||||||
|
|
||||||
@@ -60,10 +427,32 @@ pub fn render_help_overlay(f: &mut Frame<CrosstermBackend<io::Stdout>>) {
|
|||||||
height,
|
height,
|
||||||
};
|
};
|
||||||
|
|
||||||
// Create a clear background
|
// Create a semi-transparent dark background for better visibility
|
||||||
let clear = Block::default().style(Style::default().bg(Color::Black));
|
let clear = Block::default().style(Style::default().bg(Color::Black));
|
||||||
f.render_widget(clear, size);
|
f.render_widget(clear, size);
|
||||||
|
|
||||||
// Render the help content
|
// Add a border around the entire overlay for better visual separation
|
||||||
render_help_tab(f, help_area);
|
let overlay_block = Block::default()
|
||||||
|
.borders(Borders::ALL)
|
||||||
|
.border_type(BorderType::Double)
|
||||||
|
.style(Style::default().bg(Color::Black).fg(Color::White))
|
||||||
|
.title(Span::styled(
|
||||||
|
" Press ? or Esc to close help ",
|
||||||
|
Style::default()
|
||||||
|
.fg(Color::Gray)
|
||||||
|
.add_modifier(Modifier::ITALIC),
|
||||||
|
));
|
||||||
|
|
||||||
|
f.render_widget(overlay_block, help_area);
|
||||||
|
|
||||||
|
// Create inner area for content
|
||||||
|
let inner_area = Rect {
|
||||||
|
x: help_area.x + 1,
|
||||||
|
y: help_area.y + 1,
|
||||||
|
width: help_area.width.saturating_sub(2),
|
||||||
|
height: help_area.height.saturating_sub(2),
|
||||||
|
};
|
||||||
|
|
||||||
|
// Render the help content with scroll support
|
||||||
|
render_help_content(f, inner_area, scroll_offset);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ use std::io;
|
|||||||
pub fn render_ui(f: &mut Frame<CrosstermBackend<io::Stdout>>, app: &mut App) {
|
pub fn render_ui(f: &mut Frame<CrosstermBackend<io::Stdout>>, app: &mut App) {
|
||||||
// Check if help should be shown as an overlay
|
// Check if help should be shown as an overlay
|
||||||
if app.show_help {
|
if app.show_help {
|
||||||
help_overlay::render_help_overlay(f);
|
help_overlay::render_help_overlay(f, app.help_scroll);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -48,7 +48,7 @@ pub fn render_ui(f: &mut Frame<CrosstermBackend<io::Stdout>>, app: &mut App) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
2 => logs_tab::render_logs_tab(f, app, main_chunks[1]),
|
2 => logs_tab::render_logs_tab(f, app, main_chunks[1]),
|
||||||
3 => help_overlay::render_help_tab(f, main_chunks[1]),
|
3 => help_overlay::render_help_content(f, main_chunks[1], app.help_scroll),
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -181,7 +181,7 @@ pub fn render_status_bar(f: &mut Frame<CrosstermBackend<io::Stdout>>, app: &App,
|
|||||||
"[No logs to display]"
|
"[No logs to display]"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
3 => "[?] Toggle help overlay",
|
3 => "[↑/↓] Scroll help [?] Toggle help overlay",
|
||||||
_ => "",
|
_ => "",
|
||||||
};
|
};
|
||||||
status_items.push(Span::styled(
|
status_items.push(Span::styled(
|
||||||
|
|||||||
Reference in New Issue
Block a user