pub mod entry; mod settings; pub mod status; use std::{thread::sleep, time::Duration}; use crate::app::{ entry::Entry, settings::Settings, status::{AppStatus, CurrentScreen, EditingField, EntryValError}, }; use ratatui::widgets::TableState; pub struct AppState { pub fromIP: String, pub fromPort: String, pub toIP: String, pub toPort: String, pub currentlyEditing: Option, pub screen: CurrentScreen, pub entries: Vec, pub confDir: String, pub tableState: TableState, pub appStatus: AppStatus, pub savedHash: String, pub currentHash: String, pub settings: Settings, } impl AppState { pub fn new(confDir: String) -> Self { let settings = Settings::new(&confDir); AppState { fromIP: String::new(), fromPort: String::new(), toIP: String::new(), toPort: String::new(), currentlyEditing: None, screen: CurrentScreen::Main, savedHash: settings.entryHash(), currentHash: settings.entryHash(), entries: settings.entries.clone(), settings, confDir, tableState: TableState::default().with_selected(0), appStatus: AppStatus::Welcome, } } pub fn genCurrentEntriesHash(&mut self) { let mut entries = String::new(); for e in &self.entries { entries.push_str(&format!("{e}")); } self.currentHash = format!("{:x}", md5::compute(entries)); } pub fn store(&mut self) -> EntryValError { match Entry::new( self.fromIP.clone(), self.toIP.clone(), self.fromPort.clone(), self.toPort.clone(), ) { Ok(entry) => { self.entries.push(entry); self.fromIP = String::new(); self.toIP = String::new(); self.fromPort = String::new(); self.toPort = String::new(); self.currentlyEditing = None; self.tableState.select(Some(self.entries.len() - 1_usize)); self.genCurrentEntriesHash(); EntryValError::None } Err(e) => e, } } pub fn isHashDifferent(&self) -> bool { self.currentHash != self.savedHash } pub fn nextField(&mut self) { if let Some(currentField) = &self.currentlyEditing { self.currentlyEditing = match currentField { EditingField::FromIP => Some(EditingField::FromPort), EditingField::FromPort => Some(EditingField::ToIP), EditingField::ToIP => Some(EditingField::ToPort), EditingField::ToPort => Some(EditingField::FromIP), }; } } pub fn prevField(&mut self) { if let Some(currentField) = &self.currentlyEditing { self.currentlyEditing = match currentField { EditingField::FromIP => Some(EditingField::ToPort), EditingField::FromPort => Some(EditingField::FromIP), EditingField::ToIP => Some(EditingField::FromPort), EditingField::ToPort => Some(EditingField::ToIP), }; } } // pub fn print(&self) { // let tempEntry = &self.entries[0]; // let res = serde_json::to_string(tempEntry).unwrap(); // println!("{res}"); // let resString = tempEntry.to_string(); // println!("{resString}"); // } pub fn saveConfigToScript(&self) { let mut outputString: String = String::new(); outputString.push_str("#! /bin/bash\n\n# DO NOT EDIT THIS FILE MANUALLY\n# ANY MODIFICATIONS WILL BE OVERWRITTEN BY STECKBRETT\n# USE THAT STECKBRETT (stb) TO CONFIGURE PORT MAPPINGS.\n\n"); for ent in self.entries.iter() { outputString.push_str(&format!( "socat TCP-LISTEN:{},fork,reuseaddr,bind={} TCP:{}:{} &\n", ent.fromPort, ent.fromIP, ent.toIP, ent.toPort )) } outputString.push_str("\nwait"); // for o in 0..1 { // println!("test {o}"); // sleep(Duration::from_secs(1)); // } println!("Writing config to system"); sleep(Duration::from_millis(100)); let _ = std::fs::write("./forward.sh", outputString); } pub fn saveConfigToSettingsFile(&mut self) { // let mut settings = Settings::new(&self.confDir); // settings.entries = self.entries.clone(); // settings.save(&self.confDir); self.settings.entries = self.entries.clone(); self.settings.save(&self.confDir); self.savedHash = self.settings.entryHash(); } pub fn nextRow(&mut self) { let i = match self.tableState.selected() { Some(i) => { if i >= self.entries.len() - 1 { 0 } else { i + 1 } } None => 0, }; self.tableState.select(Some(i)); } pub fn prevRow(&mut self) { let i = match self.tableState.selected() { Some(i) => { if i == 0 { self.entries.len() - 1 } else { i - 1 } } None => 0, }; self.tableState.select(Some(i)); } pub fn delCur(&mut self) { if self.entries.is_empty() { self.screen = CurrentScreen::Main; return; } self.entries.remove(self.tableState.selected().unwrap()); self.genCurrentEntriesHash(); self.appStatus = AppStatus::Deleted; } }