diff --git a/src/app.rs b/src/app.rs index 843ba9e..dfe4fb7 100644 --- a/src/app.rs +++ b/src/app.rs @@ -1,18 +1,22 @@ -use std::io; +use std::{default, io}; use crossterm::event::{self, Event, KeyCode, KeyEvent, KeyEventKind}; use ratatui::{DefaultTerminal, Frame}; use crate::{ - session::{connection::ConnectionManager, credential::CredentialManager}, + session::{connection::ConnectionManager, credential::CredentialManager, SessionManager}, view::{home::Home, View}, }; pub struct App { running: bool, view: Home, - connection_manager: ConnectionManager, - credential_manager: CredentialManager, +} + +pub struct AppState { + pub connection_manager: ConnectionManager, + pub credential_manager: CredentialManager, + pub running: bool, } impl Default for App { @@ -20,33 +24,45 @@ impl Default for App { App { running: true, view: Home::default(), - connection_manager: ConnectionManager::default(), - credential_manager: CredentialManager::default(), + } + } +} + +impl Default for AppState { + fn default() -> Self { + let mut sem = SessionManager::read_from_file(); + let mut cnm = sem.connection_manager; + let mut crm = sem.credential_manager; + AppState { + connection_manager: cnm, + credential_manager: crm, + running: true, } } } impl App { pub fn run(&mut self, terminal: &mut DefaultTerminal) -> io::Result<()> { - while self.running { - terminal.draw(|frame| self.draw(frame))?; - self.handle_event()?; + let mut state = AppState::default(); + while state.running { + terminal.draw(|frame| self.draw(frame, &state))?; + self.handle_event(&mut state)?; } Ok(()) } - fn draw(&self, frame: &mut Frame) { - self.view.draw(frame); + fn draw(&mut self, frame: &mut Frame, ctx: &AppState) { + self.view.draw(frame, ctx); } - fn handle_event(&mut self) -> io::Result<()> { + fn handle_event(&mut self, ctx: &mut AppState) -> io::Result<()> { match event::read()? { Event::Key(KeyEvent { kind: KeyEventKind::Press, code: KeyCode::Esc, .. - }) => self.running = false, - event => self.view.handle_event(&event)?, + }) => ctx.running = false, + event => self.view.handle_event(&event, ctx)?, } Ok(()) } diff --git a/src/main.rs b/src/main.rs index ba97086..39f5220 100644 --- a/src/main.rs +++ b/src/main.rs @@ -22,6 +22,11 @@ fn main() -> io::Result<()> { app_result } +/* fn main() { + let mut conf = SessionManager::read_from_file(); + println!("{:?}", conf.connection_manager.connections().len()); +} */ + // fn main() -> io::Result<()> { // // let sh = ShConnection::new("zsh".to_string(), "/usr/bin/nu".to_string(), None); // // let _ = sh.exec_cmd(); diff --git a/src/session.rs b/src/session.rs index b8e6711..e1a7fe3 100644 --- a/src/session.rs +++ b/src/session.rs @@ -2,13 +2,16 @@ use connection::ConnectionManager; use credential::CredentialManager; use serde::{Deserialize, Serialize}; +use crate::global; +use crate::util::file; + pub mod connection; pub mod credential; #[derive(Serialize, Deserialize)] pub struct SessionManager { - connection_manager: ConnectionManager, - credential_manager: CredentialManager, + pub connection_manager: ConnectionManager, + pub credential_manager: CredentialManager, } impl SessionManager { @@ -18,4 +21,12 @@ impl SessionManager { credential_manager: crm, } } + + pub fn read_from_file() -> SessionManager { + let conf = file::read_file(&global::CONFIG_DIR.join("tethers.toml")); + // println!("{}", conf); + let sem: SessionManager = toml::from_str(&conf).unwrap(); + // let cnm: ConnectionManager = ConnectionManager { connections: vec![] }; + sem + } } diff --git a/src/session/connection.rs b/src/session/connection.rs index c8693ea..9a6151e 100644 --- a/src/session/connection.rs +++ b/src/session/connection.rs @@ -2,6 +2,7 @@ use std::{env, fs, io, path::Path, process::Command}; use serde::{Deserialize, Serialize}; +use crate::global; use crate::util::file; use super::credential::{Credential, CredentialType}; @@ -12,7 +13,7 @@ pub trait Connection { #[derive(Serialize, Deserialize)] pub struct ShConnection { - name: String, + pub name: String, path: String, args: Vec, } @@ -45,7 +46,7 @@ impl ShConnection { #[derive(Serialize, Deserialize)] pub struct SshConnection { - name: String, + pub name: String, host: String, port: u16, user: String, @@ -113,4 +114,8 @@ impl ConnectionManager { pub fn connections(&mut self) -> &mut Vec { &mut self.connections } + + pub fn connections_imut(&self) -> &Vec { + &self.connections + } } diff --git a/src/util/file.rs b/src/util/file.rs index 6dee3b9..0f344bc 100644 --- a/src/util/file.rs +++ b/src/util/file.rs @@ -5,7 +5,7 @@ use std::{ }; pub fn read_file(path: &Path) -> String { - let path = dirs::home_dir().unwrap().join(".ssh/Server"); + // let path = dirs::home_dir().unwrap().join(".ssh/Server"); let mut file = File::open(path).unwrap(); let mut content = String::new(); file.read_to_string(&mut content).unwrap(); diff --git a/src/view.rs b/src/view.rs index feb4f0e..a36ca9f 100644 --- a/src/view.rs +++ b/src/view.rs @@ -6,13 +6,15 @@ use ratatui::{ Frame, }; +use crate::app::AppState; + pub mod component; pub mod home; pub mod setting; pub trait View { - fn draw(&self, frame: &mut Frame); - fn handle_event(&mut self, event: &Event) -> io::Result<()>; + fn draw(&mut self, frame: &mut Frame, ctx: &AppState); + fn handle_event(&mut self, event: &Event, ctx: &mut AppState) -> io::Result<()>; } pub trait PopupView { diff --git a/src/view/component/list.rs b/src/view/component/list.rs index 15ce9d9..2b553c1 100644 --- a/src/view/component/list.rs +++ b/src/view/component/list.rs @@ -26,8 +26,8 @@ pub struct ListComponent { } impl ListComponent { - pub fn add_item(&mut self, _item_keys: Vec) { - self.item_keys.extend(vec!["S".to_string()]); + pub fn add_item(&mut self, item_keys: Vec) { + self.item_keys = item_keys; } pub fn name(mut self, name: String) -> Self { self.name = name; @@ -43,7 +43,7 @@ impl Default for ListComponent { fn default() -> Self { ListComponent { name: String::default(), - item_keys: vec!["1".to_string(), "2".to_string(), "3".to_string()], + item_keys: vec![], cursor: 0, selectable: false, active_state: Default::default(), diff --git a/src/view/home.rs b/src/view/home.rs index b28b851..8d31b71 100644 --- a/src/view/home.rs +++ b/src/view/home.rs @@ -1,4 +1,4 @@ -use std::io; +use std::{io, string}; use crossterm::event::{Event, KeyCode, KeyEvent, KeyEventKind}; use ratatui::{ @@ -7,6 +7,9 @@ use ratatui::{ widgets::{Block, BorderType, Borders}, Frame, }; +use serde::Serialize; + +use crate::{app::AppState, session::connection::{Connection, Connections, ShConnection}}; use super::{ component::{ @@ -44,7 +47,7 @@ impl Default for Home { } impl View for Home { - fn draw(&self, frame: &mut Frame) { + fn draw(&mut self, frame: &mut Frame, ctx: &AppState) { let layout = Layout::default() .direction(Direction::Vertical) .constraints(vec![ @@ -54,26 +57,42 @@ impl View for Home { ]) .split(frame.area()); self.input.show_cursor(frame, layout[0]); + let conn_names: Vec<_> = ctx + .connection_manager + .connections_imut() + .iter() + .map(|conn| match conn { + Connections::Sh(sh) => sh.name.clone(), + Connections::Ssh(ssh) => ssh.name.clone(), + }) + .collect(); + self.table.add_item(conn_names); frame.render_widget(self.input.widget(), layout[0]); frame.render_widget(self.table.widget(), layout[1]); frame.render_widget(self.help.widget(), layout[2]); - self.setting.draw(frame); + self.setting.draw(frame, ctx); } - fn handle_event(&mut self, event: &Event) -> io::Result<()> { + fn handle_event(&mut self, event: &Event, ctx: &mut AppState) -> io::Result<()> { match self.input.event_handler(event) { Ok(InputEvent::None) => {} _ => {} } match self.table.event_handler(event) { Ok(ListEvent::Select(i)) => { - let active_state = self.setting.active_state().is_active(); - self.setting.active_state().set_active(active_state); - println!("{}", i); + let conn = &ctx.connection_manager.connections()[i]; + match &conn { + &Connections::Sh(sh) => { + sh.exec_cmd(); + }, + &Connections::Ssh(ssh) => { + println!("{:?}", toml::to_string_pretty(&ctx.credential_manager)); + }, + }; } _ => {} } - self.setting.handle_event(event)?; + // self.setting.handle_event(event)?; Ok(()) } } diff --git a/src/view/setting.rs b/src/view/setting.rs index 1c74c55..795457a 100644 --- a/src/view/setting.rs +++ b/src/view/setting.rs @@ -5,6 +5,8 @@ use ratatui::{ widgets::{Block, Clear}, }; +use crate::app::AppState; + use super::{ center_rect, component::{ @@ -36,7 +38,7 @@ impl Default for SettingView { } impl View for SettingView { - fn draw(&self, frame: &mut ratatui::Frame) { + fn draw(&mut self, frame: &mut ratatui::Frame, ctx: &AppState) { if !self.activate_state.is_active() { return; } @@ -47,7 +49,11 @@ impl View for SettingView { frame.render_widget(self.menu.widget(), layout[0]); } - fn handle_event(&mut self, event: &crossterm::event::Event) -> io::Result<()> { + fn handle_event( + &mut self, + event: &crossterm::event::Event, + ctx: &mut AppState, + ) -> io::Result<()> { match self.menu.event_handler(event) { Ok(ListEvent::Select(idx)) => { self.activate_state.set_active(false);