From 9d71ba17a5170700a5cf3cd16e6dbc376b718484 Mon Sep 17 00:00:00 2001 From: Benjamyn Love Date: Tue, 2 Apr 2024 14:39:45 +1100 Subject: [PATCH] added fs stuff --- src/app.rs | 15 +++++ src/{fs.rs => fsutil.rs} | 19 ++++++ src/main.rs | 55 ++++++++------- src/ui.rs | 142 ++++++++++++++++++++++++++------------- 4 files changed, 159 insertions(+), 72 deletions(-) rename src/{fs.rs => fsutil.rs} (68%) diff --git a/src/app.rs b/src/app.rs index 7459853..ea4bbc1 100644 --- a/src/app.rs +++ b/src/app.rs @@ -1,8 +1,17 @@ +use ratatui::widgets::ListState; + +use crate::config::*; + pub enum AppRenderDir { Vertical, Horizontal, } +pub enum MenuState { + Main, + List, +} + pub enum CurrentState { Lookup, Menu, @@ -14,6 +23,9 @@ pub struct App { pub dns_info: Vec, pub render_direction: AppRenderDir, pub current_state: CurrentState, + pub menu_state: MenuState, + pub config: Config, + pub state: ListState, } impl App { @@ -24,6 +36,9 @@ impl App { dns_info: vec![], render_direction: AppRenderDir::Vertical, current_state: CurrentState::Lookup, + menu_state: MenuState::Main, + config: Config::from_file("test.ini".to_string()), + state: ListState::default(), } } } diff --git a/src/fs.rs b/src/fsutil.rs similarity index 68% rename from src/fs.rs rename to src/fsutil.rs index 2b73cb0..e272f9b 100644 --- a/src/fs.rs +++ b/src/fsutil.rs @@ -4,6 +4,12 @@ use std::error::Error; use std::fs; use std::path::Path; +use ratatui::{ + style::{Modifier, Style}, + text::{Line, Span}, + widgets::ListItem, +}; + use crate::config::Config; #[derive(Serialize)] @@ -43,4 +49,17 @@ impl DomainData { Ok(()) // println!("{}", output); } + + pub fn list_lookups(config: &Config) -> Vec { + let mut items: Vec = vec![]; + for item in fs::read_dir(format!("{}/lookups", config.data_dir)).unwrap() { + let item_name = item.unwrap(); + items.push(ListItem::new(Line::from(Span::styled( + String::from(item_name.path().to_string_lossy().clone()), + Style::default(), + )))); + } + + return items; + } } diff --git a/src/main.rs b/src/main.rs index b208e0c..cd9621e 100644 --- a/src/main.rs +++ b/src/main.rs @@ -13,8 +13,8 @@ use crate::app::*; mod ui; use crate::ui::*; -mod fs; -use crate::fs::*; +mod fsutil; +use crate::fsutil::*; use crossterm::event::{ self, DisableMouseCapture, EnableMouseCapture, Event, KeyCode, KeyEventKind, @@ -41,7 +41,7 @@ fn main() -> Result<(), Box> { let config = Config::from_file("test.ini".to_string()); // Run the app - let _res = run_app(&mut terminal, &mut app, &config); + let _res = run_app(&mut terminal, &mut app); disable_raw_mode()?; execute!( @@ -53,11 +53,7 @@ fn main() -> Result<(), Box> { Ok(()) } -fn run_app( - terminal: &mut Terminal, - app: &mut App, - config: &Config, -) -> io::Result { +fn run_app(terminal: &mut Terminal, app: &mut App) -> io::Result { loop { terminal.draw(|f| ui(f, app))?; @@ -83,7 +79,7 @@ fn run_app( continue; } let mut domain = Domain::new(app.domain_input.clone()); - domain.apply_config(&config); + domain.apply_config(&app.config); domain.lookup_all_records(); app.dns_info = domain.to_vec(); let whois = WhoisData::new(app.domain_input.clone()); @@ -94,21 +90,32 @@ fn run_app( } _ => {} }, - CurrentState::Menu => match key.code { - KeyCode::Esc => { - app.current_state = CurrentState::Lookup; - } - KeyCode::Char('s') => { - let domain_data = DomainData::new( - app.domain_input.clone(), - app.dns_info.clone(), - app.whois_info.clone(), - ); - domain_data.save_lookup(&config).unwrap(); - app.current_state = CurrentState::Lookup; - } - KeyCode::Char('q') => return Ok(false), - _ => {} + CurrentState::Menu => match app.menu_state { + MenuState::Main => match key.code { + KeyCode::Esc => { + app.current_state = CurrentState::Lookup; + } + KeyCode::Char('s') => { + let domain_data = DomainData::new( + app.domain_input.clone(), + app.dns_info.clone(), + app.whois_info.clone(), + ); + domain_data.save_lookup(&app.config).unwrap(); + app.current_state = CurrentState::Lookup; + } + KeyCode::Char('l') => { + app.menu_state = MenuState::List; + } + KeyCode::Char('q') => return Ok(false), + _ => {} + }, + MenuState::List => match key.code { + KeyCode::Esc => { + app.menu_state = MenuState::Main; + } + _ => {} + }, }, } } diff --git a/src/ui.rs b/src/ui.rs index 1a5c9e9..e96609c 100644 --- a/src/ui.rs +++ b/src/ui.rs @@ -1,14 +1,17 @@ use ratatui::{ layout::{Constraint, Direction, Layout, Rect}, - style::{Color, Style, Styled}, + style::{Color, Modifier, Style, Styled}, text::{Line, Span, Text}, - widgets::{Block, Borders, Clear, List, ListItem, Paragraph, Wrap}, + widgets::{ + Block, Borders, Clear, HighlightSpacing, List, ListDirection, ListItem, ListState, + Paragraph, Wrap, + }, Frame, }; use crate::{ app::{App, AppRenderDir}, - CurrentState, + CurrentState, DomainData, MenuState, }; pub fn ui(f: &mut Frame, app: &mut App) { @@ -188,61 +191,104 @@ pub fn ui(f: &mut Frame, app: &mut App) { } } CurrentState::Menu => { - let chunks = Layout::default() - .direction(Direction::Vertical) - .constraints([ - Constraint::Length(3), - Constraint::Min(1), - Constraint::Length(3), - ]) - .split(f.size()); + match app.menu_state { + MenuState::Main => { + let chunks = Layout::default() + .direction(Direction::Vertical) + .constraints([ + Constraint::Length(3), + Constraint::Min(1), + Constraint::Length(3), + ]) + .split(f.size()); - let title_block = Block::new().borders(Borders::ALL).style(Style::default()); + let title_block = Block::new().borders(Borders::ALL).style(Style::default()); - let title = Paragraph::new(Text::styled( - "**** Menu ****", - Style::default().fg(Color::Cyan), - )) - .block(title_block); - f.render_widget(title, chunks[0]); + let title = Paragraph::new(Text::styled( + "**** Menu ****", + Style::default().fg(Color::Cyan), + )) + .block(title_block); + f.render_widget(title, chunks[0]); - let mut options_list = Vec::::new(); - options_list.push(ListItem::new(Line::from(Span::styled( - "ESC) Return to lookup", - Style::default(), - )))); + let mut options_list = Vec::::new(); + options_list.push(ListItem::new(Line::from(Span::styled( + "ESC) Return to lookup", + Style::default(), + )))); - // TODO: Add code to save lookup - options_list.push(ListItem::new(Line::from(Span::styled( - "S) Save lookup", - Style::default(), - )))); + // TODO: Add code to save lookup + options_list.push(ListItem::new(Line::from(Span::styled( + "S) Save lookup", + Style::default(), + )))); - // TODO: Add code to load and UI to list saved lookups - options_list.push(ListItem::new(Line::from(Span::styled( - "L) List previous lookups", - Style::default(), - )))); + // TODO: Add code to load and UI to list saved lookups + options_list.push(ListItem::new(Line::from(Span::styled( + "L) List previous lookups", + Style::default(), + )))); - // TODO: Add code to read lookup and display - options_list.push(ListItem::new(Line::from(Span::styled( - "V) View previous lookup", - Style::default(), - )))); + // TODO: Add code to read lookup and display + options_list.push(ListItem::new(Line::from(Span::styled( + "V) View previous lookup", + Style::default(), + )))); - options_list.push(ListItem::new(Line::from(Span::styled( - "Q) Quit", - Style::default(), - )))); + options_list.push(ListItem::new(Line::from(Span::styled( + "Q) Quit", + Style::default(), + )))); - let options = List::new(options_list); - f.render_widget(options, chunks[1]); + let options = List::new(options_list); + f.render_widget(options, chunks[1]); - let footer_block = Block::new().borders(Borders::ALL).style(Style::default()); + let footer_block = Block::new().borders(Borders::ALL).style(Style::default()); - let footer = Paragraph::new(Text::styled("[q] Quit", Style::default().fg(Color::Red))) - .block(footer_block); - f.render_widget(footer, chunks[2]); + let footer = + Paragraph::new(Text::styled("[q] Quit", Style::default().fg(Color::Red))) + .block(footer_block); + f.render_widget(footer, chunks[2]); + } + MenuState::List => { + let chunks = Layout::default() + .direction(Direction::Vertical) + .constraints([ + Constraint::Length(3), + Constraint::Min(1), + Constraint::Length(3), + ]) + .split(f.size()); + + let title_block = Block::new().borders(Borders::ALL).style(Style::default()); + + let title = Paragraph::new(Text::styled( + "**** List ****", + Style::default().fg(Color::Cyan), + )) + .block(title_block); + f.render_widget(title, chunks[0]); + + let item_list = DomainData::list_lookups(&app.config); + let items = List::new(item_list) + .block(Block::default().title("Lookups").borders(Borders::ALL)) + .style(Style::default()) + .highlight_style(Style::default().add_modifier(Modifier::BOLD)) + .highlight_symbol(">>") + .highlight_spacing(HighlightSpacing::Always) + .repeat_highlight_symbol(true); + f.render_stateful_widget(items, chunks[1], &mut app.state); + + let footer_block = Block::new().borders(Borders::ALL).style(Style::default()); + + let footer = Paragraph::new(Text::styled( + "[ESC] Return to menu", + Style::default().fg(Color::Red), + )) + .block(footer_block); + f.render_widget(footer, chunks[2]); + } + } } } }