added fs stuff

This commit is contained in:
Benjamyn Love 2024-04-02 14:39:45 +11:00
parent c6c7808876
commit 9d71ba17a5
4 changed files with 159 additions and 72 deletions

View File

@ -1,8 +1,17 @@
use ratatui::widgets::ListState;
use crate::config::*;
pub enum AppRenderDir { pub enum AppRenderDir {
Vertical, Vertical,
Horizontal, Horizontal,
} }
pub enum MenuState {
Main,
List,
}
pub enum CurrentState { pub enum CurrentState {
Lookup, Lookup,
Menu, Menu,
@ -14,6 +23,9 @@ pub struct App {
pub dns_info: Vec<String>, pub dns_info: Vec<String>,
pub render_direction: AppRenderDir, pub render_direction: AppRenderDir,
pub current_state: CurrentState, pub current_state: CurrentState,
pub menu_state: MenuState,
pub config: Config,
pub state: ListState,
} }
impl App { impl App {
@ -24,6 +36,9 @@ impl App {
dns_info: vec![], dns_info: vec![],
render_direction: AppRenderDir::Vertical, render_direction: AppRenderDir::Vertical,
current_state: CurrentState::Lookup, current_state: CurrentState::Lookup,
menu_state: MenuState::Main,
config: Config::from_file("test.ini".to_string()),
state: ListState::default(),
} }
} }
} }

View File

@ -4,6 +4,12 @@ use std::error::Error;
use std::fs; use std::fs;
use std::path::Path; use std::path::Path;
use ratatui::{
style::{Modifier, Style},
text::{Line, Span},
widgets::ListItem,
};
use crate::config::Config; use crate::config::Config;
#[derive(Serialize)] #[derive(Serialize)]
@ -43,4 +49,17 @@ impl DomainData {
Ok(()) Ok(())
// println!("{}", output); // println!("{}", output);
} }
pub fn list_lookups(config: &Config) -> Vec<ListItem> {
let mut items: Vec<ListItem> = 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;
}
} }

View File

@ -13,8 +13,8 @@ use crate::app::*;
mod ui; mod ui;
use crate::ui::*; use crate::ui::*;
mod fs; mod fsutil;
use crate::fs::*; use crate::fsutil::*;
use crossterm::event::{ use crossterm::event::{
self, DisableMouseCapture, EnableMouseCapture, Event, KeyCode, KeyEventKind, self, DisableMouseCapture, EnableMouseCapture, Event, KeyCode, KeyEventKind,
@ -41,7 +41,7 @@ fn main() -> Result<(), Box<dyn Error>> {
let config = Config::from_file("test.ini".to_string()); let config = Config::from_file("test.ini".to_string());
// Run the app // Run the app
let _res = run_app(&mut terminal, &mut app, &config); let _res = run_app(&mut terminal, &mut app);
disable_raw_mode()?; disable_raw_mode()?;
execute!( execute!(
@ -53,11 +53,7 @@ fn main() -> Result<(), Box<dyn Error>> {
Ok(()) Ok(())
} }
fn run_app<B: Backend>( fn run_app<B: Backend>(terminal: &mut Terminal<B>, app: &mut App) -> io::Result<bool> {
terminal: &mut Terminal<B>,
app: &mut App,
config: &Config,
) -> io::Result<bool> {
loop { loop {
terminal.draw(|f| ui(f, app))?; terminal.draw(|f| ui(f, app))?;
@ -83,7 +79,7 @@ fn run_app<B: Backend>(
continue; continue;
} }
let mut domain = Domain::new(app.domain_input.clone()); let mut domain = Domain::new(app.domain_input.clone());
domain.apply_config(&config); domain.apply_config(&app.config);
domain.lookup_all_records(); domain.lookup_all_records();
app.dns_info = domain.to_vec(); app.dns_info = domain.to_vec();
let whois = WhoisData::new(app.domain_input.clone()); let whois = WhoisData::new(app.domain_input.clone());
@ -94,21 +90,32 @@ fn run_app<B: Backend>(
} }
_ => {} _ => {}
}, },
CurrentState::Menu => match key.code { CurrentState::Menu => match app.menu_state {
KeyCode::Esc => { MenuState::Main => match key.code {
app.current_state = CurrentState::Lookup; KeyCode::Esc => {
} app.current_state = CurrentState::Lookup;
KeyCode::Char('s') => { }
let domain_data = DomainData::new( KeyCode::Char('s') => {
app.domain_input.clone(), let domain_data = DomainData::new(
app.dns_info.clone(), app.domain_input.clone(),
app.whois_info.clone(), app.dns_info.clone(),
); app.whois_info.clone(),
domain_data.save_lookup(&config).unwrap(); );
app.current_state = CurrentState::Lookup; domain_data.save_lookup(&app.config).unwrap();
} app.current_state = CurrentState::Lookup;
KeyCode::Char('q') => return Ok(false), }
_ => {} 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;
}
_ => {}
},
}, },
} }
} }

142
src/ui.rs
View File

@ -1,14 +1,17 @@
use ratatui::{ use ratatui::{
layout::{Constraint, Direction, Layout, Rect}, layout::{Constraint, Direction, Layout, Rect},
style::{Color, Style, Styled}, style::{Color, Modifier, Style, Styled},
text::{Line, Span, Text}, text::{Line, Span, Text},
widgets::{Block, Borders, Clear, List, ListItem, Paragraph, Wrap}, widgets::{
Block, Borders, Clear, HighlightSpacing, List, ListDirection, ListItem, ListState,
Paragraph, Wrap,
},
Frame, Frame,
}; };
use crate::{ use crate::{
app::{App, AppRenderDir}, app::{App, AppRenderDir},
CurrentState, CurrentState, DomainData, MenuState,
}; };
pub fn ui(f: &mut Frame, app: &mut App) { pub fn ui(f: &mut Frame, app: &mut App) {
@ -188,61 +191,104 @@ pub fn ui(f: &mut Frame, app: &mut App) {
} }
} }
CurrentState::Menu => { CurrentState::Menu => {
let chunks = Layout::default() match app.menu_state {
.direction(Direction::Vertical) MenuState::Main => {
.constraints([ let chunks = Layout::default()
Constraint::Length(3), .direction(Direction::Vertical)
Constraint::Min(1), .constraints([
Constraint::Length(3), Constraint::Length(3),
]) Constraint::Min(1),
.split(f.size()); 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( let title = Paragraph::new(Text::styled(
"**** Menu ****", "**** Menu ****",
Style::default().fg(Color::Cyan), Style::default().fg(Color::Cyan),
)) ))
.block(title_block); .block(title_block);
f.render_widget(title, chunks[0]); f.render_widget(title, chunks[0]);
let mut options_list = Vec::<ListItem>::new(); let mut options_list = Vec::<ListItem>::new();
options_list.push(ListItem::new(Line::from(Span::styled( options_list.push(ListItem::new(Line::from(Span::styled(
"ESC) Return to lookup", "ESC) Return to lookup",
Style::default(), Style::default(),
)))); ))));
// TODO: Add code to save lookup // TODO: Add code to save lookup
options_list.push(ListItem::new(Line::from(Span::styled( options_list.push(ListItem::new(Line::from(Span::styled(
"S) Save lookup", "S) Save lookup",
Style::default(), Style::default(),
)))); ))));
// TODO: Add code to load and UI to list saved lookups // TODO: Add code to load and UI to list saved lookups
options_list.push(ListItem::new(Line::from(Span::styled( options_list.push(ListItem::new(Line::from(Span::styled(
"L) List previous lookups", "L) List previous lookups",
Style::default(), Style::default(),
)))); ))));
// TODO: Add code to read lookup and display // TODO: Add code to read lookup and display
options_list.push(ListItem::new(Line::from(Span::styled( options_list.push(ListItem::new(Line::from(Span::styled(
"V) View previous lookup", "V) View previous lookup",
Style::default(), Style::default(),
)))); ))));
options_list.push(ListItem::new(Line::from(Span::styled( options_list.push(ListItem::new(Line::from(Span::styled(
"Q) Quit", "Q) Quit",
Style::default(), Style::default(),
)))); ))));
let options = List::new(options_list); let options = List::new(options_list);
f.render_widget(options, chunks[1]); 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))) let footer =
.block(footer_block); Paragraph::new(Text::styled("[q] Quit", Style::default().fg(Color::Red)))
f.render_widget(footer, chunks[2]); .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]);
}
}
} }
} }
} }