Added UI base code
This commit is contained in:
1 parent
6b54955fd2
commit
d932bb234b
5 files changed
+507
-29
No files matched your search
+29
@@ -0,0 +1,29 @@
|
||||
pub enum AppRenderDir {
|
||||
Vertical,
|
||||
Horizontal,
|
||||
}
|
||||
|
||||
pub enum CurrentState {
|
||||
Lookup,
|
||||
Menu,
|
||||
}
|
||||
|
||||
pub struct App {
|
||||
pub domain_input: String,
|
||||
pub whois_info: Vec<String>,
|
||||
pub dns_info: Vec<String>,
|
||||
pub render_direction: AppRenderDir,
|
||||
pub current_state: CurrentState,
|
||||
}
|
||||
|
||||
impl App {
|
||||
pub fn new() -> App {
|
||||
App {
|
||||
domain_input: String::new(),
|
||||
whois_info: vec![],
|
||||
dns_info: vec![],
|
||||
render_direction: AppRenderDir::Horizontal,
|
||||
current_state: CurrentState::Lookup,
|
||||
}
|
||||
}
|
||||
}
|
||||
+96
-27
@@ -7,38 +7,107 @@ use crate::config::Config;
|
||||
mod whois;
|
||||
use crate::whois::WhoisData;
|
||||
|
||||
use std::io;
|
||||
use std::io::Write;
|
||||
mod app;
|
||||
use crate::app::*;
|
||||
|
||||
fn main() {
|
||||
// let mut running = true;
|
||||
mod ui;
|
||||
use crate::ui::*;
|
||||
|
||||
use crossterm::event::{
|
||||
self, DisableMouseCapture, EnableMouseCapture, Event, KeyCode, KeyEventKind,
|
||||
};
|
||||
use crossterm::execute;
|
||||
use crossterm::terminal::{
|
||||
disable_raw_mode, enable_raw_mode, EnterAlternateScreen, LeaveAlternateScreen,
|
||||
};
|
||||
use ratatui::backend::{Backend, CrosstermBackend};
|
||||
use ratatui::Terminal;
|
||||
use std::error::Error;
|
||||
use std::io::Write;
|
||||
use std::io::{self, stderr};
|
||||
|
||||
fn main() -> Result<(), Box<dyn Error>> {
|
||||
enable_raw_mode()?;
|
||||
let mut stderr = stderr();
|
||||
execute!(stderr, EnterAlternateScreen, EnableMouseCapture)?;
|
||||
|
||||
let backend = CrosstermBackend::new(stderr);
|
||||
let mut terminal = Terminal::new(backend)?;
|
||||
|
||||
// Initialise the App and config
|
||||
let mut app = App::new();
|
||||
let config = Config::from_file("test.ini".to_string());
|
||||
|
||||
// Run the app
|
||||
let res = run_app(&mut terminal, &mut app, &config);
|
||||
|
||||
disable_raw_mode()?;
|
||||
execute!(
|
||||
terminal.backend_mut(),
|
||||
LeaveAlternateScreen,
|
||||
DisableMouseCapture
|
||||
)?;
|
||||
terminal.show_cursor()?;
|
||||
// Clear screen
|
||||
// print!("{}[2J", 27 as char);
|
||||
//
|
||||
// loop {
|
||||
// let mut domain = String::new();
|
||||
// print!("Enter domain name: ");
|
||||
// io::stdout().flush().expect("Failed to flush buffer");
|
||||
// match io::stdin().read_line(&mut domain) {
|
||||
// Ok(_n) => {
|
||||
// domain = String::from(domain.trim());
|
||||
// match domain.as_ref() {
|
||||
// "q" => break,
|
||||
// "" => continue,
|
||||
// _ => {
|
||||
// let mut dns = Domain::new(domain.clone());
|
||||
// dns.apply_config(&config);
|
||||
// dns.lookup_all_records();
|
||||
// let whois = WhoisData::new(domain);
|
||||
// println!("DNS: {}\n\n\nWhois: {}", dns, whois); // Replace this with fancy UI render update command
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// Err(err) => {
|
||||
// println!("{}", err);
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn run_app<B: Backend>(
|
||||
terminal: &mut Terminal<B>,
|
||||
app: &mut App,
|
||||
config: &Config,
|
||||
) -> io::Result<bool> {
|
||||
loop {
|
||||
let mut domain = String::new();
|
||||
print!("Enter domain name: ");
|
||||
io::stdout().flush().expect("Failed to flush buffer");
|
||||
match io::stdin().read_line(&mut domain) {
|
||||
Ok(_n) => {
|
||||
if domain.trim() == "q" {
|
||||
break;
|
||||
}
|
||||
let mut dns = Domain::new(String::from(domain.trim()));
|
||||
dns.apply_config(&config);
|
||||
dns.lookup_all_records();
|
||||
let whois = WhoisData::new(String::from(domain.trim()));
|
||||
println!("DNS: {}\n\n\nWhois: {}", dns, whois);
|
||||
terminal.draw(|f| ui(f, app))?;
|
||||
|
||||
if let Event::Key(key) = event::read()? {
|
||||
if key.kind == event::KeyEventKind::Release {
|
||||
continue;
|
||||
}
|
||||
Err(err) => {
|
||||
println!("{}", err);
|
||||
match app.current_state {
|
||||
CurrentState::Lookup => match key.code {
|
||||
KeyCode::Esc => return Ok(false),
|
||||
KeyCode::Backspace => {
|
||||
app.domain_input.pop();
|
||||
}
|
||||
KeyCode::Char(char) => {
|
||||
app.domain_input.push(char);
|
||||
}
|
||||
KeyCode::Enter => {
|
||||
// This will do the lookup and populate the UI with the info
|
||||
let mut domain = Domain::new(app.domain_input.clone());
|
||||
domain.lookup_all_records();
|
||||
}
|
||||
_ => {}
|
||||
},
|
||||
CurrentState::Menu => {}
|
||||
}
|
||||
}
|
||||
}
|
||||
// let mut test = Domain::new("ventraip.com.au".to_string());
|
||||
// let config = Config::from_file("test.ini".to_string());
|
||||
// test.apply_config(&config);
|
||||
|
||||
// test.lookup_all_records();
|
||||
// let whois = WhoisData::new(test.domain_name.clone());
|
||||
|
||||
// println!("Domain: {}\n{}", test.domain_name.clone(), whois);
|
||||
}
|
||||
@@ -0,0 +1,126 @@
|
||||
use ratatui::{
|
||||
layout::{Constraint, Direction, Layout, Rect},
|
||||
style::{Color, Style, Styled},
|
||||
text::{Line, Span, Text},
|
||||
widgets::{Block, Borders, Clear, List, ListItem, Paragraph, Wrap},
|
||||
Frame,
|
||||
};
|
||||
|
||||
use crate::{
|
||||
app::{App, AppRenderDir},
|
||||
CurrentState,
|
||||
};
|
||||
|
||||
pub fn ui(f: &mut Frame, app: &App) {
|
||||
match app.current_state {
|
||||
CurrentState::Lookup => {
|
||||
match app.render_direction {
|
||||
/*
|
||||
Initial contianer is vertical but we have the large center Rect that we will split horizontally
|
||||
Constraint 1: 30px title bar
|
||||
Constraint 2: Rest of unused space
|
||||
Constraint 3: 30px input / key hints
|
||||
|
||||
Constraint 2.a: 50% of usable space for whois
|
||||
Constraint 2.b: 50% of usable space for dns
|
||||
*/
|
||||
AppRenderDir::Horizontal => {
|
||||
let chunks = Layout::default()
|
||||
.direction(Direction::Vertical)
|
||||
.constraints([
|
||||
Constraint::Length(3),
|
||||
Constraint::Min(1),
|
||||
Constraint::Length(3),
|
||||
])
|
||||
.split(f.size());
|
||||
|
||||
let title_block = Block::default()
|
||||
.borders(Borders::ALL)
|
||||
.style(Style::default());
|
||||
|
||||
let title = Paragraph::new(Span::styled(
|
||||
"Dns Lookup tool",
|
||||
Style::default().fg(Color::White),
|
||||
))
|
||||
.block(title_block);
|
||||
|
||||
f.render_widget(title, chunks[0]);
|
||||
|
||||
let data_layout = Layout::default()
|
||||
.direction(Direction::Horizontal)
|
||||
.constraints([Constraint::Percentage(50), Constraint::Percentage(50)])
|
||||
.split(chunks[1]);
|
||||
|
||||
let whois_block = Block::default()
|
||||
.borders(Borders::RIGHT)
|
||||
.style(Style::default());
|
||||
|
||||
let whois_text = Paragraph::new(Text::styled(
|
||||
"Whois data in
|
||||
style
|
||||
with
|
||||
multiline support",
|
||||
Style::default().fg(Color::Green),
|
||||
))
|
||||
.block(whois_block);
|
||||
f.render_widget(whois_text, data_layout[0]);
|
||||
|
||||
let dns_block = Block::default().style(Style::default());
|
||||
let dns_text = Paragraph::new(Text::styled(
|
||||
"Dns records
|
||||
also
|
||||
with
|
||||
multiline
|
||||
support",
|
||||
Style::default().fg(Color::Red),
|
||||
))
|
||||
.block(dns_block);
|
||||
f.render_widget(dns_text, data_layout[1]);
|
||||
|
||||
let footer_chunks = Layout::default()
|
||||
.direction(Direction::Horizontal)
|
||||
.constraints([Constraint::Percentage(50), Constraint::Percentage(50)])
|
||||
.split(chunks[2]);
|
||||
|
||||
let domain_block = Block::new().borders(Borders::ALL).style(Style::default());
|
||||
let mut domain_string = String::from("Domain: ");
|
||||
domain_string.push_str(&app.domain_input);
|
||||
let domain_text = Paragraph::new(Text::styled(
|
||||
domain_string,
|
||||
Style::default().fg(Color::Blue),
|
||||
))
|
||||
.block(domain_block);
|
||||
f.render_widget(domain_text, footer_chunks[0]);
|
||||
|
||||
let key_hint_block = Block::default()
|
||||
.borders(Borders::ALL)
|
||||
.style(Style::default());
|
||||
let key_hint = Paragraph::new(Text::styled(
|
||||
"[ESC] Quit / [Enter] Check domain",
|
||||
Style::default().fg(Color::Red),
|
||||
))
|
||||
.block(key_hint_block);
|
||||
f.render_widget(key_hint, footer_chunks[1]);
|
||||
}
|
||||
/*
|
||||
Constraint 1: 30px title bar
|
||||
Constraint 2: 50% of unused space for whois
|
||||
Constraint 3: 50% of unused space for dns
|
||||
Constraint 4: 30px input / key hints
|
||||
*/
|
||||
AppRenderDir::Vertical => {
|
||||
let chunks = Layout::default()
|
||||
.direction(Direction::Vertical)
|
||||
.constraints([
|
||||
Constraint::Max(30),
|
||||
Constraint::Percentage(50),
|
||||
Constraint::Percentage(50),
|
||||
Constraint::Max(30),
|
||||
])
|
||||
.split(f.size());
|
||||
}
|
||||
}
|
||||
}
|
||||
CurrentState::Menu => {}
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user