diff --git a/CHANGELOG.md b/CHANGELOG.md index 504f975..b7ad0aa 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -18,7 +18,10 @@ Released on FIXME: date -- REPL +- Enhancements: + - Improved performance regarding configuration I/O (config client is now shared in the activity context) +- Bugfix: + - Fixed file format cursor position in the GUI ## 0.3.3 diff --git a/src/activity_manager.rs b/src/activity_manager.rs index 9e1fe57..6d0ecfb 100644 --- a/src/activity_manager.rs +++ b/src/activity_manager.rs @@ -28,6 +28,8 @@ use std::path::PathBuf; // Deps use crate::filetransfer::FileTransferProtocol; use crate::host::{HostError, Localhost}; +use crate::system::config_client::ConfigClient; +use crate::system::environment; use crate::ui::activities::{ auth_activity::AuthActivity, filetransfer_activity::FileTransferActivity, filetransfer_activity::FileTransferParams, setup_activity::SetupActivity, Activity, @@ -66,7 +68,13 @@ impl ActivityManager { Ok(h) => h, Err(e) => return Err(e), }; - let ctx: Context = Context::new(host); + // Initialize configuration client + let (config_client, error): (Option, Option) = + match Self::init_config_client() { + Ok(cli) => (Some(cli), None), + Err(err) => (None, Some(err)), + }; + let ctx: Context = Context::new(host, config_client, error); Ok(ActivityManager { context: Some(ctx), ftparams: None, @@ -117,7 +125,7 @@ impl ActivityManager { drop(self.context.take()); } - // Loops + // -- Activity Loops /// ### run_authentication /// @@ -251,4 +259,35 @@ impl ActivityManager { // This activity always returns to AuthActivity Some(NextActivity::Authentication) } + + // -- misc + + /// ### init_config_client + /// + /// Initialize configuration client + fn init_config_client() -> Result { + // Get config dir + match environment::init_config_dir() { + Ok(config_dir) => { + match config_dir { + Some(config_dir) => { + // Get config client paths + let (config_path, ssh_dir): (PathBuf, PathBuf) = + environment::get_config_paths(config_dir.as_path()); + match ConfigClient::new(config_path.as_path(), ssh_dir.as_path()) { + Ok(cli) => Ok(cli), + Err(err) => Err(format!("Could not read configuration: {}", err)), + } + } + None => Err(String::from( + "Your system doesn't support configuration paths", + )), + } + } + Err(err) => Err(format!( + "Could not initialize configuration directory: {}", + err + )), + } + } } diff --git a/src/ui/activities/auth_activity/mod.rs b/src/ui/activities/auth_activity/mod.rs index ffe55d3..b9d701b 100644 --- a/src/ui/activities/auth_activity/mod.rs +++ b/src/ui/activities/auth_activity/mod.rs @@ -38,14 +38,11 @@ extern crate unicode_width; use super::{Activity, Context}; use crate::filetransfer::FileTransferProtocol; use crate::system::bookmarks_client::BookmarksClient; -use crate::system::config_client::ConfigClient; -use crate::system::environment; use crate::utils::git; // Includes use crossterm::event::Event as InputEvent; use crossterm::terminal::{disable_raw_mode, enable_raw_mode}; -use std::path::PathBuf; use tui::style::Color; // Types @@ -107,7 +104,6 @@ pub struct AuthActivity { pub setup: bool, // Becomes true if user has requested setup context: Option, bookmarks_client: Option, - config_client: Option, selected_field: InputField, // Selected field in AuthCredentials Form popup: Option, input_form: InputForm, @@ -145,7 +141,6 @@ impl AuthActivity { setup: false, context: None, bookmarks_client: None, - config_client: None, selected_field: InputField::Address, popup: None, input_form: InputForm::AuthCredentials, @@ -161,47 +156,11 @@ impl AuthActivity { } } - /// ### init_config_client - /// - /// Initialize config client - fn init_config_client(&mut self) { - // Get config dir - match environment::init_config_dir() { - Ok(config_dir) => { - if let Some(config_dir) = config_dir { - // Get config client paths - let (config_path, ssh_dir): (PathBuf, PathBuf) = - environment::get_config_paths(config_dir.as_path()); - match ConfigClient::new(config_path.as_path(), ssh_dir.as_path()) { - Ok(cli) => { - // Set default protocol - self.protocol = cli.get_default_protocol(); - // Set client - self.config_client = Some(cli); - } - Err(err) => { - self.popup = Some(Popup::Alert( - Color::Red, - format!("Could not initialize user configuration: {}", err), - )) - } - } - } - } - Err(err) => { - self.popup = Some(Popup::Alert( - Color::Red, - format!("Could not initialize configuration directory: {}", err), - )) - } - } - } - /// ### on_create /// /// If enabled in configuration, check for updates from Github fn check_for_updates(&mut self) { - if let Some(client) = self.config_client.as_ref() { + if let Some(client) = self.context.as_ref().unwrap().config_client.as_ref() { if client.get_check_for_updates() { // Send request match git::check_for_updates(env!("CARGO_PKG_VERSION")) { @@ -237,9 +196,9 @@ impl Activity for AuthActivity { if self.bookmarks_client.is_none() { self.init_bookmarks_client(); } - // init config client - if self.config_client.is_none() { - self.init_config_client(); + // Verify error state from context + if let Some(err) = self.context.as_mut().unwrap().get_error() { + self.popup = Some(Popup::Alert(Color::Red, err)); } // If check for updates is enabled, check for updates self.check_for_updates(); diff --git a/src/ui/activities/filetransfer_activity/misc.rs b/src/ui/activities/filetransfer_activity/misc.rs index 736ac22..3c68e80 100644 --- a/src/ui/activities/filetransfer_activity/misc.rs +++ b/src/ui/activities/filetransfer_activity/misc.rs @@ -147,7 +147,7 @@ impl FileTransferActivity { /// /// Set text editor to use pub(super) fn setup_text_editor(&self) { - if let Some(config_cli) = &self.config_cli { + if let Some(config_cli) = self.context.as_ref().unwrap().config_client.as_ref() { // Set text editor env::set_var("EDITOR", config_cli.get_text_editor()); } diff --git a/src/ui/activities/filetransfer_activity/mod.rs b/src/ui/activities/filetransfer_activity/mod.rs index 62ebe4b..66f9a35 100644 --- a/src/ui/activities/filetransfer_activity/mod.rs +++ b/src/ui/activities/filetransfer_activity/mod.rs @@ -229,7 +229,6 @@ pub struct FileTransferActivity { context: Option, // Context holder params: FileTransferParams, // FT connection params client: Box, // File transfer client - config_cli: Option, // Config Client local: FileExplorer, // Local File explorer state remote: FileExplorer, // Remote File explorer state tab: FileExplorerTab, // Current selected tab @@ -267,7 +266,6 @@ impl FileTransferActivity { params, local: Self::build_explorer(config_client.as_ref()), remote: Self::build_explorer(config_client.as_ref()), - config_cli: config_client, tab: FileExplorerTab::Local, log_index: 0, log_records: VecDeque::with_capacity(256), // 256 events is enough I guess @@ -308,6 +306,10 @@ impl Activity for FileTransferActivity { self.local.index_at_first(); // Configure text editor self.setup_text_editor(); + // Verify error state from context + if let Some(err) = self.context.as_mut().unwrap().get_error() { + self.popup = Some(Popup::Fatal(err)); + } } /// ### on_draw diff --git a/src/ui/activities/setup_activity/callbacks.rs b/src/ui/activities/setup_activity/callbacks.rs index 9074124..a766aba 100644 --- a/src/ui/activities/setup_activity/callbacks.rs +++ b/src/ui/activities/setup_activity/callbacks.rs @@ -69,7 +69,7 @@ impl SetupActivity { /// Callback for performing the delete of a ssh key pub(super) fn callback_delete_ssh_key(&mut self) { // Get key - if let Some(config_cli) = self.config_cli.as_mut() { + if let Some(config_cli) = self.context.as_mut().unwrap().config_client.as_mut() { let key: Option = match config_cli.iter_ssh_keys().nth(self.ssh_key_idx) { Some(k) => Some(k.clone()), None => None, @@ -100,7 +100,7 @@ impl SetupActivity { /// /// Create a new ssh key with provided parameters pub(super) fn callback_new_ssh_key(&mut self, host: String, username: String) { - if let Some(cli) = self.config_cli.as_ref() { + if let Some(cli) = self.context.as_mut().unwrap().config_client.as_mut() { // Prepare text editor env::set_var("EDITOR", cli.get_text_editor()); let placeholder: String = format!("# Type private SSH key for {}@{}\n", username, host); diff --git a/src/ui/activities/setup_activity/config.rs b/src/ui/activities/setup_activity/config.rs index fad56d8..564cf6f 100644 --- a/src/ui/activities/setup_activity/config.rs +++ b/src/ui/activities/setup_activity/config.rs @@ -25,55 +25,17 @@ */ // Locals -use super::{ConfigClient, Popup, SetupActivity}; -use crate::system::environment; +use super::SetupActivity; // Ext use crossterm::terminal::{disable_raw_mode, enable_raw_mode}; use std::env; -use std::path::PathBuf; impl SetupActivity { - /// ### init_config_dir - /// - /// Initialize configuration directory - pub(super) fn init_config_client(&mut self) { - match environment::init_config_dir() { - Ok(config_dir) => match config_dir { - Some(config_dir) => { - // Get paths - let (config_file, ssh_dir): (PathBuf, PathBuf) = - environment::get_config_paths(config_dir.as_path()); - // Create config client - match ConfigClient::new(config_file.as_path(), ssh_dir.as_path()) { - Ok(cli) => self.config_cli = Some(cli), - Err(err) => { - self.popup = Some(Popup::Fatal(format!( - "Could not initialize configuration client: {}", - err - ))) - } - } - } - None => { - self.popup = Some(Popup::Fatal( - "No configuration directory is available on your system".to_string(), - )) - } - }, - Err(err) => { - self.popup = Some(Popup::Fatal(format!( - "Could not initialize configuration directory: {}", - err - ))) - } - } - } - /// ### save_config /// /// Save configuration pub(super) fn save_config(&mut self) -> Result<(), String> { - match &self.config_cli { + match self.context.as_ref().unwrap().config_client.as_ref() { Some(cli) => match cli.write_config() { Ok(_) => Ok(()), Err(err) => Err(format!("Could not save configuration: {}", err)), @@ -87,7 +49,7 @@ impl SetupActivity { /// Reset configuration changes; pratically read config from file, overwriting any change made /// since last write action pub(super) fn reset_config_changes(&mut self) -> Result<(), String> { - match self.config_cli.as_mut() { + match self.context.as_mut().unwrap().config_client.as_mut() { Some(cli) => match cli.read_config() { Ok(_) => Ok(()), Err(err) => Err(format!("Could not restore configuration: {}", err)), @@ -100,7 +62,7 @@ impl SetupActivity { /// /// Delete ssh key from config cli pub(super) fn delete_ssh_key(&mut self, host: &str, username: &str) -> Result<(), String> { - match self.config_cli.as_mut() { + match self.context.as_mut().unwrap().config_client.as_mut() { Some(cli) => match cli.del_ssh_key(host, username) { Ok(_) => Ok(()), Err(err) => Err(format!( @@ -116,58 +78,51 @@ impl SetupActivity { /// /// Edit selected ssh key pub(super) fn edit_ssh_key(&mut self) -> Result<(), String> { - match self.config_cli.as_ref() { - Some(cli) => { - // Set text editor - env::set_var("EDITOR", cli.get_text_editor()); + match self.context.as_mut() { + None => Ok(()), + Some(ctx) => { + // Set editor if config client exists + if let Some(config_cli) = ctx.config_client.as_ref() { + env::set_var("EDITOR", config_cli.get_text_editor()); + } // Prepare terminal let _ = disable_raw_mode(); // Leave alternate mode - if let Some(ctx) = self.context.as_mut() { - ctx.leave_alternate_screen(); - } - // Check if key exists - match cli.iter_ssh_keys().nth(self.ssh_key_idx) { - Some(key) => { - // Get key path - match cli.get_ssh_key(key) { - Ok(ssh_key) => match ssh_key { - None => Ok(()), - Some((_, _, key_path)) => match edit::edit_file(key_path.as_path()) - { - Ok(_) => { - // Restore terminal - if let Some(ctx) = self.context.as_mut() { - // Clear screen - ctx.clear_screen(); - // Enter alternate mode - ctx.enter_alternate_screen(); + ctx.leave_alternate_screen(); + // Get result + let result: Result<(), String> = match ctx.config_client.as_ref() { + Some(config_cli) => match config_cli.iter_ssh_keys().nth(self.ssh_key_idx) { + Some(key) => { + // Get key path + match config_cli.get_ssh_key(key) { + Ok(ssh_key) => match ssh_key { + None => Ok(()), + Some((_, _, key_path)) => { + match edit::edit_file(key_path.as_path()) { + Ok(_) => Ok(()), + Err(err) => { + Err(format!("Could not edit ssh key: {}", err)) + } } - // Re-enable raw mode - let _ = enable_raw_mode(); - Ok(()) - } - Err(err) => { - // Restore terminal - if let Some(ctx) = self.context.as_mut() { - // Clear screen - ctx.clear_screen(); - // Enter alternate mode - ctx.enter_alternate_screen(); - } - // Re-enable raw mode - let _ = enable_raw_mode(); - Err(format!("Could not edit ssh key: {}", err)) } }, - }, - Err(err) => Err(format!("Could not read ssh key: {}", err)), + Err(err) => Err(format!("Could not read ssh key: {}", err)), + } } - } + None => Ok(()), + }, None => Ok(()), - } + }; + // Restore terminal + // Clear screen + ctx.clear_screen(); + // Enter alternate mode + ctx.enter_alternate_screen(); + // Re-enable raw mode + let _ = enable_raw_mode(); + // Return result + result } - None => Ok(()), } } @@ -180,7 +135,7 @@ impl SetupActivity { username: &str, rsa_key: &str, ) -> Result<(), String> { - match self.config_cli.as_mut() { + match self.context.as_mut().unwrap().config_client.as_mut() { Some(cli) => { // Add key to client match cli.add_ssh_key(host, username, rsa_key) { diff --git a/src/ui/activities/setup_activity/input.rs b/src/ui/activities/setup_activity/input.rs index 7fee6cc..c52fc4e 100644 --- a/src/ui/activities/setup_activity/input.rs +++ b/src/ui/activities/setup_activity/input.rs @@ -76,7 +76,8 @@ impl SetupActivity { self.tab = SetupTab::UserInterface(UserInterfaceInputField::DefaultProtocol) } // Switch tab to user interface config KeyCode::Up => { - if let Some(config_cli) = self.config_cli.as_ref() { + if let Some(config_cli) = self.context.as_ref().unwrap().config_client.as_ref() + { // Move ssh key index up let ssh_key_size: usize = config_cli.iter_ssh_keys().count(); if self.ssh_key_idx > 0 { @@ -89,7 +90,8 @@ impl SetupActivity { } } KeyCode::Down => { - if let Some(config_cli) = self.config_cli.as_ref() { + if let Some(config_cli) = self.context.as_ref().unwrap().config_client.as_ref() + { // Move ssh key index down let ssh_key_size: usize = config_cli.iter_ssh_keys().count(); if self.ssh_key_idx + 1 < ssh_key_size { @@ -180,7 +182,8 @@ impl SetupActivity { KeyCode::Tab => self.tab = SetupTab::SshConfig, // Switch tab to ssh config KeyCode::Backspace => { // Pop character from selected input - if let Some(config_cli) = self.config_cli.as_mut() { + if let Some(config_cli) = self.context.as_mut().unwrap().config_client.as_mut() + { match field { UserInterfaceInputField::TextEditor => { // Pop from text editor @@ -207,7 +210,8 @@ impl SetupActivity { } KeyCode::Left => { // Move left on fields which are tabs - if let Some(config_cli) = self.config_cli.as_mut() { + if let Some(config_cli) = self.context.as_mut().unwrap().config_client.as_mut() + { match field { UserInterfaceInputField::DefaultProtocol => { // Move left @@ -248,7 +252,8 @@ impl SetupActivity { } KeyCode::Right => { // Move right on fields which are tabs - if let Some(config_cli) = self.config_cli.as_mut() { + if let Some(config_cli) = self.context.as_mut().unwrap().config_client.as_mut() + { match field { UserInterfaceInputField::DefaultProtocol => { // Move left @@ -354,7 +359,9 @@ impl SetupActivity { } } else { // Push character to input field - if let Some(config_cli) = self.config_cli.as_mut() { + if let Some(config_cli) = + self.context.as_mut().unwrap().config_client.as_mut() + { // NOTE: change to match if other fields are added match field { UserInterfaceInputField::TextEditor => { diff --git a/src/ui/activities/setup_activity/layout.rs b/src/ui/activities/setup_activity/layout.rs index 003e917..ab5bc1c 100644 --- a/src/ui/activities/setup_activity/layout.rs +++ b/src/ui/activities/setup_activity/layout.rs @@ -30,6 +30,7 @@ use super::{ }; use crate::filetransfer::FileTransferProtocol; use crate::fs::explorer::GroupDirs; +use crate::system::config_client::ConfigClient; use crate::utils::fmt::align_text_center; // Ext use tui::{ @@ -46,6 +47,7 @@ impl SetupActivity { /// Draw UI pub(super) fn draw(&mut self) { let mut ctx: Context = self.context.take().unwrap(); + let config_client: Option<&ConfigClient> = ctx.config_client.as_ref(); let _ = ctx.terminal.draw(|f| { // Prepare main chunks let chunks = Layout::default() @@ -71,7 +73,7 @@ impl SetupActivity { .direction(Direction::Vertical) .constraints([Constraint::Percentage(100)].as_ref()) .split(chunks[1]); - if let Some(ssh_key_tab) = self.draw_ssh_keys_list() { + if let Some(ssh_key_tab) = self.draw_ssh_keys_list(config_client) { // Create ssh list state let mut ssh_key_state: ListState = ListState::default(); ssh_key_state.select(Some(self.ssh_key_idx)); @@ -97,26 +99,26 @@ impl SetupActivity { ) .split(chunks[1]); // Render input forms - if let Some(field) = self.draw_text_editor_input() { + if let Some(field) = self.draw_text_editor_input(config_client) { f.render_widget(field, ui_cfg_chunks[0]); } - if let Some(tab) = self.draw_default_protocol_tab() { + if let Some(tab) = self.draw_default_protocol_tab(config_client) { f.render_widget(tab, ui_cfg_chunks[1]); } - if let Some(tab) = self.draw_hidden_files_tab() { + if let Some(tab) = self.draw_hidden_files_tab(config_client) { f.render_widget(tab, ui_cfg_chunks[2]); } - if let Some(tab) = self.draw_check_for_updates_tab() { + if let Some(tab) = self.draw_check_for_updates_tab(config_client) { f.render_widget(tab, ui_cfg_chunks[3]); } - if let Some(tab) = self.draw_default_group_dirs_tab() { + if let Some(tab) = self.draw_default_group_dirs_tab(config_client) { f.render_widget(tab, ui_cfg_chunks[4]); } - if let Some(tab) = self.draw_file_fmt_input() { + if let Some(tab) = self.draw_file_fmt_input(config_client) { f.render_widget(tab, ui_cfg_chunks[5]); } // Set cursor - if let Some(cli) = &self.config_cli { + if let Some(cli) = config_client { match form_field { UserInterfaceInputField::TextEditor => { let editor_text: String = @@ -129,8 +131,8 @@ impl SetupActivity { UserInterfaceInputField::FileFmt => { let file_fmt: String = cli.get_file_fmt().unwrap_or_default(); f.set_cursor( - ui_cfg_chunks[4].x + file_fmt.width() as u16 + 1, - ui_cfg_chunks[4].y + 1, + ui_cfg_chunks[5].x + file_fmt.width() as u16 + 1, + ui_cfg_chunks[5].y + 1, ); } _ => { /* Not a text field */ } @@ -247,8 +249,8 @@ impl SetupActivity { /// ### draw_text_editor_input /// /// Draw input text field for text editor parameter - fn draw_text_editor_input(&self) -> Option { - match &self.config_cli { + fn draw_text_editor_input(&self, config_cli: Option<&ConfigClient>) -> Option { + match config_cli.as_ref() { Some(cli) => Some( Paragraph::new(String::from( cli.get_text_editor().as_path().to_string_lossy(), @@ -274,9 +276,9 @@ impl SetupActivity { /// ### draw_default_protocol_tab /// /// Draw default protocol input tab - fn draw_default_protocol_tab(&self) -> Option { + fn draw_default_protocol_tab(&self, config_cli: Option<&ConfigClient>) -> Option { // Check if config client is some - match &self.config_cli { + match config_cli.as_ref() { Some(cli) => { let choices: Vec = vec![ Spans::from("SFTP"), @@ -324,9 +326,9 @@ impl SetupActivity { /// ### draw_hidden_files_tab /// /// Draw default hidden files tab - fn draw_hidden_files_tab(&self) -> Option { + fn draw_hidden_files_tab(&self, config_cli: Option<&ConfigClient>) -> Option { // Check if config client is some - match &self.config_cli { + match config_cli.as_ref() { Some(cli) => { let choices: Vec = vec![Spans::from("Yes"), Spans::from("No")]; let index: usize = match cli.get_show_hidden_files() { @@ -365,9 +367,9 @@ impl SetupActivity { /// ### draw_check_for_updates_tab /// /// Draw check for updates tab - fn draw_check_for_updates_tab(&self) -> Option { + fn draw_check_for_updates_tab(&self, config_cli: Option<&ConfigClient>) -> Option { // Check if config client is some - match &self.config_cli { + match config_cli.as_ref() { Some(cli) => { let choices: Vec = vec![Spans::from("Yes"), Spans::from("No")]; let index: usize = match cli.get_check_for_updates() { @@ -406,9 +408,9 @@ impl SetupActivity { /// ### draw_default_group_dirs_tab /// /// Draw group dirs input tab - fn draw_default_group_dirs_tab(&self) -> Option { + fn draw_default_group_dirs_tab(&self, config_cli: Option<&ConfigClient>) -> Option { // Check if config client is some - match &self.config_cli { + match config_cli.as_ref() { Some(cli) => { let choices: Vec = vec![ Spans::from("Display First"), @@ -454,8 +456,8 @@ impl SetupActivity { /// ### draw_file_fmt_input /// /// Draw input text field for file fmt - fn draw_file_fmt_input(&self) -> Option { - match &self.config_cli { + fn draw_file_fmt_input(&self, config_cli: Option<&ConfigClient>) -> Option { + match config_cli.as_ref() { Some(cli) => Some( Paragraph::new(cli.get_file_fmt().unwrap_or_default()) .style(Style::default().fg(match &self.tab { @@ -479,9 +481,9 @@ impl SetupActivity { /// ### draw_ssh_keys_list /// /// Draw ssh keys list - fn draw_ssh_keys_list(&self) -> Option { + fn draw_ssh_keys_list(&self, config_cli: Option<&ConfigClient>) -> Option { // Check if config client is some - match &self.config_cli { + match config_cli.as_ref() { Some(cli) => { // Iterate over ssh keys let mut ssh_keys: Vec = Vec::with_capacity(cli.iter_ssh_keys().count()); diff --git a/src/ui/activities/setup_activity/mod.rs b/src/ui/activities/setup_activity/mod.rs index 6e7bc9b..f09f036 100644 --- a/src/ui/activities/setup_activity/mod.rs +++ b/src/ui/activities/setup_activity/mod.rs @@ -37,7 +37,6 @@ extern crate tui; // Locals use super::{Activity, Context}; -use crate::system::config_client::ConfigClient; // Ext use crossterm::event::Event as InputEvent; use crossterm::terminal::{disable_raw_mode, enable_raw_mode}; @@ -106,7 +105,6 @@ enum Popup { pub struct SetupActivity { pub quit: bool, // Becomes true when user requests the activity to terminate context: Option, // Context holder - config_cli: Option, // Config client tab: SetupTab, // Current setup tab popup: Option, // Active popup user_input: Vec, // User input holder @@ -127,7 +125,6 @@ impl Default for SetupActivity { SetupActivity { quit: false, context: None, - config_cli: None, tab: SetupTab::UserInterface(UserInterfaceInputField::TextEditor), popup: None, user_input: user_input_buffer, // Max 16 @@ -153,9 +150,9 @@ impl Activity for SetupActivity { self.context.as_mut().unwrap().clear_screen(); // Put raw mode on enabled let _ = enable_raw_mode(); - // Initialize config client - if self.config_cli.is_none() { - self.init_config_client(); + // Verify error state from context + if let Some(err) = self.context.as_mut().unwrap().get_error() { + self.popup = Some(Popup::Fatal(err)); } } diff --git a/src/ui/context.rs b/src/ui/context.rs index 01842bc..9ffda58 100644 --- a/src/ui/context.rs +++ b/src/ui/context.rs @@ -30,6 +30,7 @@ extern crate tui; // Locals use super::input::InputHandler; use crate::host::Localhost; +use crate::system::config_client::ConfigClient; // Includes use crossterm::event::DisableMouseCapture; @@ -44,25 +45,52 @@ use tui::Terminal; /// Context holds data structures used by the ui pub struct Context { pub local: Localhost, + pub(crate) config_client: Option, pub(crate) input_hnd: InputHandler, pub(crate) terminal: Terminal>, + error: Option, } impl Context { /// ### new /// /// Instantiates a new Context - pub fn new(local: Localhost) -> Context { + pub fn new( + local: Localhost, + config_client: Option, + error: Option, + ) -> Context { // Create terminal let mut stdout = stdout(); assert!(execute!(stdout, EnterAlternateScreen).is_ok()); Context { local, + config_client, input_hnd: InputHandler::new(), terminal: Terminal::new(CrosstermBackend::new(stdout)).unwrap(), + error, } } + /* NOTE: in case is necessary + /// ### set_error + /// + /// Set context error + pub fn set_error(&mut self, err: String) { + self.error = Some(err); + } + */ + + /// ### get_error + /// + /// Get error message and remove it from the context + pub fn get_error(&mut self) -> Option { + self.error.take() + } + + /// ### enter_alternate_screen + /// + /// Enter alternate screen (gui window) pub fn enter_alternate_screen(&mut self) { let _ = execute!( self.terminal.backend_mut(), @@ -71,6 +99,9 @@ impl Context { ); } + /// ### leave_alternate_screen + /// + /// Go back to normal screen (gui window) pub fn leave_alternate_screen(&mut self) { let _ = execute!( self.terminal.backend_mut(), @@ -79,6 +110,9 @@ impl Context { ); } + /// ### clear_screen + /// + /// Clear terminal screen pub fn clear_screen(&mut self) { let _ = self.terminal.clear(); }