couple ui and data
This commit is contained in:
44
src/app.rs
44
src/app.rs
@@ -1,18 +1,22 @@
|
|||||||
use std::io;
|
use std::{default, io};
|
||||||
|
|
||||||
use crossterm::event::{self, Event, KeyCode, KeyEvent, KeyEventKind};
|
use crossterm::event::{self, Event, KeyCode, KeyEvent, KeyEventKind};
|
||||||
use ratatui::{DefaultTerminal, Frame};
|
use ratatui::{DefaultTerminal, Frame};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
session::{connection::ConnectionManager, credential::CredentialManager},
|
session::{connection::ConnectionManager, credential::CredentialManager, SessionManager},
|
||||||
view::{home::Home, View},
|
view::{home::Home, View},
|
||||||
};
|
};
|
||||||
|
|
||||||
pub struct App {
|
pub struct App {
|
||||||
running: bool,
|
running: bool,
|
||||||
view: Home,
|
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 {
|
impl Default for App {
|
||||||
@@ -20,33 +24,45 @@ impl Default for App {
|
|||||||
App {
|
App {
|
||||||
running: true,
|
running: true,
|
||||||
view: Home::default(),
|
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 {
|
impl App {
|
||||||
pub fn run(&mut self, terminal: &mut DefaultTerminal) -> io::Result<()> {
|
pub fn run(&mut self, terminal: &mut DefaultTerminal) -> io::Result<()> {
|
||||||
while self.running {
|
let mut state = AppState::default();
|
||||||
terminal.draw(|frame| self.draw(frame))?;
|
while state.running {
|
||||||
self.handle_event()?;
|
terminal.draw(|frame| self.draw(frame, &state))?;
|
||||||
|
self.handle_event(&mut state)?;
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn draw(&self, frame: &mut Frame) {
|
fn draw(&mut self, frame: &mut Frame, ctx: &AppState) {
|
||||||
self.view.draw(frame);
|
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()? {
|
match event::read()? {
|
||||||
Event::Key(KeyEvent {
|
Event::Key(KeyEvent {
|
||||||
kind: KeyEventKind::Press,
|
kind: KeyEventKind::Press,
|
||||||
code: KeyCode::Esc,
|
code: KeyCode::Esc,
|
||||||
..
|
..
|
||||||
}) => self.running = false,
|
}) => ctx.running = false,
|
||||||
event => self.view.handle_event(&event)?,
|
event => self.view.handle_event(&event, ctx)?,
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -22,6 +22,11 @@ fn main() -> io::Result<()> {
|
|||||||
app_result
|
app_result
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* fn main() {
|
||||||
|
let mut conf = SessionManager::read_from_file();
|
||||||
|
println!("{:?}", conf.connection_manager.connections().len());
|
||||||
|
} */
|
||||||
|
|
||||||
// fn main() -> io::Result<()> {
|
// fn main() -> io::Result<()> {
|
||||||
// // let sh = ShConnection::new("zsh".to_string(), "/usr/bin/nu".to_string(), None);
|
// // let sh = ShConnection::new("zsh".to_string(), "/usr/bin/nu".to_string(), None);
|
||||||
// // let _ = sh.exec_cmd();
|
// // let _ = sh.exec_cmd();
|
||||||
|
|||||||
@@ -2,13 +2,16 @@ use connection::ConnectionManager;
|
|||||||
use credential::CredentialManager;
|
use credential::CredentialManager;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
|
use crate::global;
|
||||||
|
use crate::util::file;
|
||||||
|
|
||||||
pub mod connection;
|
pub mod connection;
|
||||||
pub mod credential;
|
pub mod credential;
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize)]
|
#[derive(Serialize, Deserialize)]
|
||||||
pub struct SessionManager {
|
pub struct SessionManager {
|
||||||
connection_manager: ConnectionManager,
|
pub connection_manager: ConnectionManager,
|
||||||
credential_manager: CredentialManager,
|
pub credential_manager: CredentialManager,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl SessionManager {
|
impl SessionManager {
|
||||||
@@ -18,4 +21,12 @@ impl SessionManager {
|
|||||||
credential_manager: crm,
|
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
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ use std::{env, fs, io, path::Path, process::Command};
|
|||||||
|
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
|
use crate::global;
|
||||||
use crate::util::file;
|
use crate::util::file;
|
||||||
|
|
||||||
use super::credential::{Credential, CredentialType};
|
use super::credential::{Credential, CredentialType};
|
||||||
@@ -12,7 +13,7 @@ pub trait Connection {
|
|||||||
|
|
||||||
#[derive(Serialize, Deserialize)]
|
#[derive(Serialize, Deserialize)]
|
||||||
pub struct ShConnection {
|
pub struct ShConnection {
|
||||||
name: String,
|
pub name: String,
|
||||||
path: String,
|
path: String,
|
||||||
args: Vec<String>,
|
args: Vec<String>,
|
||||||
}
|
}
|
||||||
@@ -45,7 +46,7 @@ impl ShConnection {
|
|||||||
|
|
||||||
#[derive(Serialize, Deserialize)]
|
#[derive(Serialize, Deserialize)]
|
||||||
pub struct SshConnection {
|
pub struct SshConnection {
|
||||||
name: String,
|
pub name: String,
|
||||||
host: String,
|
host: String,
|
||||||
port: u16,
|
port: u16,
|
||||||
user: String,
|
user: String,
|
||||||
@@ -113,4 +114,8 @@ impl ConnectionManager {
|
|||||||
pub fn connections(&mut self) -> &mut Vec<Connections> {
|
pub fn connections(&mut self) -> &mut Vec<Connections> {
|
||||||
&mut self.connections
|
&mut self.connections
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn connections_imut(&self) -> &Vec<Connections> {
|
||||||
|
&self.connections
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ use std::{
|
|||||||
};
|
};
|
||||||
|
|
||||||
pub fn read_file(path: &Path) -> String {
|
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 file = File::open(path).unwrap();
|
||||||
let mut content = String::new();
|
let mut content = String::new();
|
||||||
file.read_to_string(&mut content).unwrap();
|
file.read_to_string(&mut content).unwrap();
|
||||||
|
|||||||
@@ -6,13 +6,15 @@ use ratatui::{
|
|||||||
Frame,
|
Frame,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
use crate::app::AppState;
|
||||||
|
|
||||||
pub mod component;
|
pub mod component;
|
||||||
pub mod home;
|
pub mod home;
|
||||||
pub mod setting;
|
pub mod setting;
|
||||||
|
|
||||||
pub trait View {
|
pub trait View {
|
||||||
fn draw(&self, frame: &mut Frame);
|
fn draw(&mut self, frame: &mut Frame, ctx: &AppState);
|
||||||
fn handle_event(&mut self, event: &Event) -> io::Result<()>;
|
fn handle_event(&mut self, event: &Event, ctx: &mut AppState) -> io::Result<()>;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait PopupView {
|
pub trait PopupView {
|
||||||
|
|||||||
@@ -26,8 +26,8 @@ pub struct ListComponent {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl ListComponent {
|
impl ListComponent {
|
||||||
pub fn add_item(&mut self, _item_keys: Vec<String>) {
|
pub fn add_item(&mut self, item_keys: Vec<String>) {
|
||||||
self.item_keys.extend(vec!["S".to_string()]);
|
self.item_keys = item_keys;
|
||||||
}
|
}
|
||||||
pub fn name(mut self, name: String) -> Self {
|
pub fn name(mut self, name: String) -> Self {
|
||||||
self.name = name;
|
self.name = name;
|
||||||
@@ -43,7 +43,7 @@ impl Default for ListComponent {
|
|||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
ListComponent {
|
ListComponent {
|
||||||
name: String::default(),
|
name: String::default(),
|
||||||
item_keys: vec!["1".to_string(), "2".to_string(), "3".to_string()],
|
item_keys: vec![],
|
||||||
cursor: 0,
|
cursor: 0,
|
||||||
selectable: false,
|
selectable: false,
|
||||||
active_state: Default::default(),
|
active_state: Default::default(),
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
use std::io;
|
use std::{io, string};
|
||||||
|
|
||||||
use crossterm::event::{Event, KeyCode, KeyEvent, KeyEventKind};
|
use crossterm::event::{Event, KeyCode, KeyEvent, KeyEventKind};
|
||||||
use ratatui::{
|
use ratatui::{
|
||||||
@@ -7,6 +7,9 @@ use ratatui::{
|
|||||||
widgets::{Block, BorderType, Borders},
|
widgets::{Block, BorderType, Borders},
|
||||||
Frame,
|
Frame,
|
||||||
};
|
};
|
||||||
|
use serde::Serialize;
|
||||||
|
|
||||||
|
use crate::{app::AppState, session::connection::{Connection, Connections, ShConnection}};
|
||||||
|
|
||||||
use super::{
|
use super::{
|
||||||
component::{
|
component::{
|
||||||
@@ -44,7 +47,7 @@ impl Default for Home {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl View 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()
|
let layout = Layout::default()
|
||||||
.direction(Direction::Vertical)
|
.direction(Direction::Vertical)
|
||||||
.constraints(vec![
|
.constraints(vec![
|
||||||
@@ -54,26 +57,42 @@ impl View for Home {
|
|||||||
])
|
])
|
||||||
.split(frame.area());
|
.split(frame.area());
|
||||||
self.input.show_cursor(frame, layout[0]);
|
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.input.widget(), layout[0]);
|
||||||
frame.render_widget(self.table.widget(), layout[1]);
|
frame.render_widget(self.table.widget(), layout[1]);
|
||||||
frame.render_widget(self.help.widget(), layout[2]);
|
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) {
|
match self.input.event_handler(event) {
|
||||||
Ok(InputEvent::None) => {}
|
Ok(InputEvent::None) => {}
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
match self.table.event_handler(event) {
|
match self.table.event_handler(event) {
|
||||||
Ok(ListEvent::Select(i)) => {
|
Ok(ListEvent::Select(i)) => {
|
||||||
let active_state = self.setting.active_state().is_active();
|
let conn = &ctx.connection_manager.connections()[i];
|
||||||
self.setting.active_state().set_active(active_state);
|
match &conn {
|
||||||
println!("{}", i);
|
&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(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,6 +5,8 @@ use ratatui::{
|
|||||||
widgets::{Block, Clear},
|
widgets::{Block, Clear},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
use crate::app::AppState;
|
||||||
|
|
||||||
use super::{
|
use super::{
|
||||||
center_rect,
|
center_rect,
|
||||||
component::{
|
component::{
|
||||||
@@ -36,7 +38,7 @@ impl Default for SettingView {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl View 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() {
|
if !self.activate_state.is_active() {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -47,7 +49,11 @@ impl View for SettingView {
|
|||||||
frame.render_widget(self.menu.widget(), layout[0]);
|
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) {
|
match self.menu.event_handler(event) {
|
||||||
Ok(ListEvent::Select(idx)) => {
|
Ok(ListEvent::Select(idx)) => {
|
||||||
self.activate_state.set_active(false);
|
self.activate_state.set_active(false);
|
||||||
|
|||||||
Reference in New Issue
Block a user