From 21b41f5593c92131788f5ebb46d0148fec4bd061 Mon Sep 17 00:00:00 2001 From: Trevor Merritt Date: Wed, 30 Apr 2025 16:09:22 -0400 Subject: [PATCH] WIP: working on better ui interaction --- src/tui/mode_monitoring.rs | 98 ++++++++++++++++++++++++++++---------- src/tui/ratatui_app.rs | 42 +++++----------- 2 files changed, 86 insertions(+), 54 deletions(-) diff --git a/src/tui/mode_monitoring.rs b/src/tui/mode_monitoring.rs index 35f5536..1142410 100644 --- a/src/tui/mode_monitoring.rs +++ b/src/tui/mode_monitoring.rs @@ -1,3 +1,4 @@ +use std::collections::BTreeMap; use crate::duration_to_string; use color_eyre::Result; use crossterm::event; @@ -7,37 +8,23 @@ use ratatui::widgets::{Block, Borders, Cell, Clear, List, ListItem, ListState, P use ratatui::Frame; use std::time::{Duration, SystemTime}; use ratatui::layout::Flex; +use crate::target_state::TargetState; use crate::tui::ratatui_app::RatatuiApp; use crate::tui::ratatui_screens::RatatuiScreens::{Adding, Deleting, Editing}; pub struct RatatuiMonitoringMode {} impl RatatuiMonitoringMode { - pub fn render(frame: &mut Frame, state: &mut RatatuiApp) { - let layouts = Layout::default() - .direction(Direction::Vertical) - .constraints([ - Constraint::Fill(1), - Constraint::Length(10), - Constraint::Length(3), - ]) - .split(frame.area()); - - let body_layout = layouts[0]; - let logs_layout = layouts[1]; - let footer_layout = layouts[2]; - - frame.render_widget(Paragraph::new("") - .block(Block::bordered()) - .centered(), - body_layout); - + fn render_hosts_list(frame: &mut Frame, state: &mut RatatuiApp, area: Rect) { + /// Headers let headers = ["Host", "RTT", "Last Change"] .iter() .map(|h| Cell::from(*h)); let header = Row::new(headers) .style(Style::default().fg(Color::Yellow)) .bottom_margin(1); + + /// Rows let mut rows = vec![]; for (_, current) in state.state.iter() { @@ -70,6 +57,7 @@ impl RatatuiMonitoringMode { rows.push(Row::new(to_push)); } + /// Table Builder let table = Table::new(rows, vec![Constraint::Min(30), Constraint::Min(6), Constraint::Min(5), Constraint::Min(30)]) .header(header) .block(Block::default() @@ -89,11 +77,10 @@ impl RatatuiMonitoringMode { .highlight_symbol(">> "); // frame.render_widget(table, layouts[0]); - frame.render_stateful_widget(table, layouts[0], &mut make_state(state.selected_host)); - - // let footer_text = "Press or q to exit"; - let footer_text = "Press or q to exit | Press d to delete host | Press a to add host"; + frame.render_stateful_widget(table, area, &mut make_state(state.selected_host)); + } + fn render_logs(frame: &mut Frame, state: &mut RatatuiApp, logs_layout: Rect) { let mut list_items = vec![]; for entry in state.get_log_entries(10) { list_items.push(ListItem::new(entry)); @@ -109,6 +96,12 @@ impl RatatuiMonitoringMode { // Log frame.render_widget(list, logs_layout); + } + + fn render_footer_block(frame: &mut Frame, footer_layout: Rect) { + // let footer_text = "Press or q to exit"; + let footer_text = "Press or q to exit | Press d to delete host | Press a to add host"; + frame.render_widget( Paragraph::new(footer_text) .block(Block::bordered()) @@ -116,6 +109,27 @@ impl RatatuiMonitoringMode { footer_layout, ); + } + pub fn render(frame: &mut Frame, state: &mut RatatuiApp) { + let layouts = Layout::default() + .direction(Direction::Vertical) + .constraints([ + Constraint::Fill(1), + Constraint::Length(10), + Constraint::Length(3), + ]) + .split(frame.area()); + + Self::render_hosts_list(frame, state, layouts[0]); + Self::render_logs(frame, state, layouts[1]); + Self::render_footer_block(frame, layouts[2]); + + Self::add_popup(state, frame); + Self::exit_popup(state, frame); + Self::delete_popup(state, frame); + } + + fn add_popup(state: &RatatuiApp, frame: &mut Frame) { if state.showing_add_popup { let block = Block::bordered().title("Add Host"); let area = RatatuiMonitoringMode::popup_area(frame.area(), 60, 20); @@ -123,7 +137,9 @@ impl RatatuiMonitoringMode { frame.render_widget(Clear, area); frame.render_widget(block, area); } + } + fn exit_popup(state: &RatatuiApp, frame: &mut Frame) { if state.trying_to_exit { let block = Paragraph::new("Are you sure? (Y/N)") .block(Block::bordered().title("Exit")); @@ -134,8 +150,25 @@ impl RatatuiMonitoringMode { } } + fn delete_popup(state: &RatatuiApp, frame: &mut Frame) { + if state.trying_to_delete { + let as_list = state.state.clone(); + let mut host_name = String::new(); + for (index, (label, _)) in as_list.iter().enumerate() { + if index == state.selected_host { + host_name = label.clone(); + } + } + let block = Paragraph::new(format!("Delete {}", host_name)) + .centered() + .block(Block::bordered()); + + frame.render_widget(block, frame.area()); + } + } + fn popup_area(area: Rect, percent_x: u16, percent_y: u16) -> Rect { - let vertical = Layout::vertical([Constraint::Percentage(percent_y)]).flex(Flex::Center); + let vertical = Layout::vertical([Constraint::Percentage(percent_x)]).flex(Flex::Center); let horizontal = Layout::horizontal([Constraint::Percentage(percent_y)]).flex(Flex::Center); let [area] = vertical.areas(area); let [area] = horizontal.areas(area); @@ -195,12 +228,25 @@ impl RatatuiMonitoringMode { app.showing_add_popup = true; } KeyCode::Char('d') | KeyCode::Char('D') => { - app.set_screen(Deleting); + app.trying_to_delete = true; } _ => {} } } + fn handle_delete_popup_inputs(app: &mut RatatuiApp, key: KeyCode) { + match key { + KeyCode::Char('y') | KeyCode::Char('Y') => { + // app.remove_selected_host(); + dbg!("Delete this item."); + }, + KeyCode::Char('n') | KeyCode::Char('N') => { + dbg!("Do not delete this item."); + }, + _ => {} + } + } + pub fn handle_crossterm_events(app: &mut RatatuiApp) -> Result<()> { if event::poll(Duration::from_millis(100))? { match event::read()? { @@ -210,6 +256,8 @@ impl RatatuiMonitoringMode { Self::handle_add_popup_inputs(app, key.code); } else if app.trying_to_exit { Self::handle_exit_popup_inputs(app, key.code); + } else if app.trying_to_delete { + Self::handle_delete_popup_inputs(app, key.code); } else { Self::handle_monitoring_screen_inputs(app, key.code); } diff --git a/src/tui/ratatui_app.rs b/src/tui/ratatui_app.rs index b138449..002ee08 100644 --- a/src/tui/ratatui_app.rs +++ b/src/tui/ratatui_app.rs @@ -27,7 +27,7 @@ pub struct RatatuiApp { pub state: BTreeMap, current_screen: RatatuiScreens, log_entries: Vec, - pub filename: Option, + filename: Option, pub selected_host: usize, pub showing_add_popup: bool, pub trying_to_exit: bool, @@ -39,6 +39,14 @@ pub struct RatatuiApp { /// Private Methods impl RatatuiApp { + pub fn set_filename(mut self, new_filename: String) { + self.filename = Some(new_filename) + } + + pub fn get_filename(self) -> String { + self.filename.unwrap_or(String::new()) + } + pub fn add_new_host(mut self, new_target: TargetState) -> Result<()> { self.state.insert(new_target.name.clone(), new_target); Ok(()) @@ -53,27 +61,10 @@ impl RatatuiApp { // check for any waiting ping results... self.consume_waiting_results(&receiver); - match self.current_screen { - RatatuiScreens::Deleting => { - terminal - .draw(|frame| RatatuiDeletingMode::render(frame, &mut self))?; - RatatuiDeletingMode::handle_crossterm_events(&mut self)? + terminal + .draw(|frame| RatatuiMonitoringMode::render(frame, &mut self))?; + RatatuiMonitoringMode::handle_crossterm_events(&mut self)?; - } - RatatuiScreens::Monitoring => { - terminal - .draw(|frame| RatatuiMonitoringMode::render(frame, &mut self))?; - RatatuiMonitoringMode::handle_crossterm_events(&mut self)?; - } - RatatuiScreens::Editing => { - terminal.draw(|frame| RatatuiEditingMode::render(frame, &mut self.state))?; - RatatuiEditingMode::handle_crossterm_events(&mut self)?; - } - RatatuiScreens::Adding => { - terminal.draw(|frame| RatatuiAddingMode::render(frame, &mut self))?; - RatatuiAddingMode::handle_crossterm_events(&mut self)? - } - } } Ok(()) } @@ -132,12 +123,7 @@ impl RatatuiApp { } fn render(&mut self, frame: &mut Frame) { - match self.current_screen { - RatatuiScreens::Monitoring => RatatuiMonitoringMode::render(frame, self), - RatatuiScreens::Editing => RatatuiEditingMode::render(frame, &mut self.state), - RatatuiScreens::Deleting => RatatuiDeletingMode::render(frame,self), - RatatuiScreens::Adding => RatatuiAddingMode::render(frame, self) - } + RatatuiMonitoringMode::render(frame, self) } fn quit(&mut self) { @@ -248,6 +234,4 @@ impl RatatuiApp { } return_value } - - }