diff --git a/src/activity_manager.rs b/src/activity_manager.rs index 6d0ecfb..13c425c 100644 --- a/src/activity_manager.rs +++ b/src/activity_manager.rs @@ -32,9 +32,9 @@ 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, + setup_activity::SetupActivity, Activity, }; -use crate::ui::context::Context; +use crate::ui::context::{Context, FileTransferParams}; // Namespaces use std::thread::sleep; @@ -54,7 +54,6 @@ pub enum NextActivity { /// The activity manager takes care of running activities and handling them until the application has ended pub struct ActivityManager { context: Option, - ftparams: Option, interval: Duration, } @@ -77,7 +76,6 @@ impl ActivityManager { let ctx: Context = Context::new(host, config_client, error); Ok(ActivityManager { context: Some(ctx), - ftparams: None, interval, }) } @@ -94,7 +92,8 @@ impl ActivityManager { password: Option, entry_directory: Option, ) { - self.ftparams = Some(FileTransferParams { + // Put params into the context + self.context.as_mut().unwrap().ft_params = Some(FileTransferParams { address, port, protocol, @@ -161,21 +160,6 @@ impl ActivityManager { if activity.submit { // User submitted, set next activity result = Some(NextActivity::FileTransfer); - // Get params - self.ftparams = Some(FileTransferParams { - address: activity.address.clone(), - port: activity.port.parse::().ok().unwrap(), - username: match activity.username.len() { - 0 => None, - _ => Some(activity.username.clone()), - }, - password: match activity.password.len() { - 0 => None, - _ => Some(activity.password.clone()), - }, - protocol: activity.protocol, - entry_directory: None, // Has use only when accessing with address - }); break; } // Sleep for ticks @@ -192,19 +176,21 @@ impl ActivityManager { /// Returns when activity terminates. /// Returns the next activity to run fn run_filetransfer(&mut self) -> Option { - if self.ftparams.is_none() { - return Some(NextActivity::Authentication); - } - // Prepare activity - let mut activity: FileTransferActivity = - FileTransferActivity::new(self.ftparams.take().unwrap()); - // Prepare result - let result: Option; // Get context let ctx: Context = match self.context.take() { Some(ctx) => ctx, None => return None, }; + // If ft params is None, return None + let ft_params: &FileTransferParams = match ctx.ft_params.as_ref() { + Some(ft_params) => &ft_params, + None => return None, + }; + // Prepare activity + let protocol: FileTransferProtocol = ft_params.protocol; + let mut activity: FileTransferActivity = FileTransferActivity::new(protocol); + // Prepare result + let result: Option; // Create activity activity.on_create(ctx); loop { diff --git a/src/ui/activities/auth_activity/mod.rs b/src/ui/activities/auth_activity/mod.rs index 633b895..1d5275e 100644 --- a/src/ui/activities/auth_activity/mod.rs +++ b/src/ui/activities/auth_activity/mod.rs @@ -36,6 +36,7 @@ extern crate tui; use super::{Activity, Context}; use crate::filetransfer::FileTransferProtocol; use crate::system::bookmarks_client::BookmarksClient; +use crate::ui::context::FileTransferParams; use crate::ui::layout::view::View; use crate::utils::git; @@ -68,11 +69,6 @@ const STORE_KEY_LATEST_VERSION: &str = "AUTH_LATEST_VERSION"; /// /// AuthActivity is the data holder for the authentication activity pub struct AuthActivity { - pub address: String, - pub port: String, - pub protocol: FileTransferProtocol, - pub username: String, - pub password: String, pub submit: bool, // becomes true after user has submitted fields pub quit: bool, // Becomes true if user has pressed esc pub setup: bool, // Becomes true if user has requested setup @@ -96,11 +92,6 @@ impl AuthActivity { /// Instantiates a new AuthActivity pub fn new() -> AuthActivity { AuthActivity { - address: String::new(), - port: String::from("22"), - protocol: FileTransferProtocol::Sftp, - username: String::new(), - password: String::new(), submit: false, quit: false, setup: false, @@ -157,7 +148,9 @@ impl Activity for AuthActivity { /// `on_create` is the function which must be called to initialize the activity. /// `on_create` must initialize all the data structures used by the activity /// Context is taken from activity manager and will be released only when activity is destroyed - fn on_create(&mut self, context: Context) { + fn on_create(&mut self, mut context: Context) { + // Initialize file transfer params + context.ft_params = Some(FileTransferParams::default()); // Set context self.context = Some(context); // Clear terminal diff --git a/src/ui/activities/auth_activity/update.rs b/src/ui/activities/auth_activity/update.rs index 5272ad0..833ebb3 100644 --- a/src/ui/activities/auth_activity/update.rs +++ b/src/ui/activities/auth_activity/update.rs @@ -25,11 +25,12 @@ // locals use super::{ - AuthActivity, COMPONENT_BOOKMARKS_LIST, COMPONENT_INPUT_ADDR, COMPONENT_INPUT_BOOKMARK_NAME, - COMPONENT_INPUT_PASSWORD, COMPONENT_INPUT_PORT, COMPONENT_INPUT_USERNAME, - COMPONENT_RADIO_BOOKMARK_DEL_BOOKMARK, COMPONENT_RADIO_BOOKMARK_DEL_RECENT, - COMPONENT_RADIO_BOOKMARK_SAVE_PWD, COMPONENT_RADIO_PROTOCOL, COMPONENT_RADIO_QUIT, - COMPONENT_RECENTS_LIST, COMPONENT_TEXT_ERROR, COMPONENT_TEXT_HELP, + AuthActivity, FileTransferParams, COMPONENT_BOOKMARKS_LIST, COMPONENT_INPUT_ADDR, + COMPONENT_INPUT_BOOKMARK_NAME, COMPONENT_INPUT_PASSWORD, COMPONENT_INPUT_PORT, + COMPONENT_INPUT_USERNAME, COMPONENT_RADIO_BOOKMARK_DEL_BOOKMARK, + COMPONENT_RADIO_BOOKMARK_DEL_RECENT, COMPONENT_RADIO_BOOKMARK_SAVE_PWD, + COMPONENT_RADIO_PROTOCOL, COMPONENT_RADIO_QUIT, COMPONENT_RECENTS_LIST, COMPONENT_TEXT_ERROR, + COMPONENT_TEXT_HELP, }; use crate::ui::activities::keymap::*; use crate::ui::layout::{Msg, Payload}; @@ -319,12 +320,20 @@ impl AuthActivity { // Match key for all other components self.save_recent(); let (address, port, protocol, username, password) = self.get_input(); - // TOREM: remove this after removing states - self.address = address; - self.port = port.to_string(); - self.protocol = protocol; - self.username = username; - self.password = password; + // Set file transfer params to context + let mut ft_params: &mut FileTransferParams = + &mut self.context.as_mut().unwrap().ft_params.as_mut().unwrap(); + ft_params.address = address; + ft_params.port = port; + ft_params.protocol = protocol; + ft_params.username = match username.is_empty() { + true => None, + false => Some(username), + }; + ft_params.password = match password.is_empty() { + true => None, + false => Some(password), + }; // Submit true self.submit = true; // Return None diff --git a/src/ui/activities/filetransfer_activity/mod.rs b/src/ui/activities/filetransfer_activity/mod.rs index 9b095c3..83ef365 100644 --- a/src/ui/activities/filetransfer_activity/mod.rs +++ b/src/ui/activities/filetransfer_activity/mod.rs @@ -81,18 +81,6 @@ const COMPONENT_RADIO_SORTING: &str = "RADIO_SORTING"; const COMPONENT_RADIO_DELETE: &str = "RADIO_DELETE"; const COMPONENT_LIST_FILEINFO: &str = "LIST_FILEINFO"; -/// ### FileTransferParams -/// -/// Holds connection parameters for file transfers -pub struct FileTransferParams { - pub address: String, - pub port: u16, - pub protocol: FileTransferProtocol, - pub username: Option, - pub password: Option, - pub entry_directory: Option, -} - /// ## FileExplorerTab /// /// File explorer tab @@ -215,7 +203,6 @@ pub struct FileTransferActivity { pub quit: bool, // Has quit term scp? context: Option, // Context holder view: View, // View - params: FileTransferParams, // FT connection params client: Box, // File transfer client local: FileExplorer, // Local File explorer state remote: FileExplorer, // Remote File explorer state @@ -230,8 +217,7 @@ impl FileTransferActivity { /// ### new /// /// Instantiates a new FileTransferActivity - pub fn new(params: FileTransferParams) -> FileTransferActivity { - let protocol: FileTransferProtocol = params.protocol; + pub fn new(protocol: FileTransferProtocol) -> FileTransferActivity { // Get config client let config_client: Option = Self::init_config_client(); FileTransferActivity { @@ -248,7 +234,6 @@ impl FileTransferActivity { Self::make_ssh_storage(config_client.as_ref()), )), }, - params, local: Self::build_explorer(config_client.as_ref()), remote: Self::build_explorer(config_client.as_ref()), tab: FileExplorerTab::Local, @@ -306,14 +291,10 @@ impl Activity for FileTransferActivity { } // Check if connected (popup must be None, otherwise would try reconnecting in loop in case of error) if !self.client.is_connected() && self.view.get_props(COMPONENT_TEXT_FATAL).is_none() { + let params = self.context.as_ref().unwrap().ft_params.as_ref().unwrap(); + let msg: String = format!("Connecting to {}:{}...", params.address, params.port); // Set init state to connecting popup - self.mount_wait( - format!( - "Connecting to {}:{}...", - self.params.address, self.params.port - ) - .as_str(), - ); + self.mount_wait(msg.as_str()); // Force ui draw self.view(); // Connect to remote diff --git a/src/ui/activities/filetransfer_activity/session.rs b/src/ui/activities/filetransfer_activity/session.rs index ea49f6b..c9b639d 100644 --- a/src/ui/activities/filetransfer_activity/session.rs +++ b/src/ui/activities/filetransfer_activity/session.rs @@ -47,28 +47,27 @@ impl FileTransferActivity { /// /// Connect to remote pub(super) fn connect(&mut self) { + let params = self.context.as_ref().unwrap().ft_params.as_ref().unwrap(); + let addr: String = params.address.clone(); + let entry_dir: Option = params.entry_directory.clone(); // Connect to remote match self.client.connect( - self.params.address.clone(), - self.params.port, - self.params.username.clone(), - self.params.password.clone(), + params.address.clone(), + params.port, + params.username.clone(), + params.password.clone(), ) { Ok(welcome) => { if let Some(banner) = welcome { // Log welcome self.log( LogLevel::Info, - format!( - "Established connection with '{}': \"{}\"", - self.params.address, banner - ) - .as_ref(), + format!("Established connection with '{}': \"{}\"", addr, banner).as_ref(), ); } // Try to change directory to entry directory let mut remote_chdir: Option = None; - if let Some(entry_directory) = &self.params.entry_directory { + if let Some(entry_directory) = &entry_dir { remote_chdir = Some(entry_directory.clone()); } if let Some(entry_directory) = remote_chdir { @@ -92,8 +91,10 @@ impl FileTransferActivity { /// /// disconnect from remote pub(super) fn disconnect(&mut self) { + let params = self.context.as_ref().unwrap().ft_params.as_ref().unwrap(); + let msg: String = format!("Disconnecting from {}...", params.address); // Show popup disconnecting - self.mount_wait(format!("Disconnecting from {}...", self.params.address).as_str()); + self.mount_wait(msg.as_str()); // Disconnect let _ = self.client.disconnect(); // Quit diff --git a/src/ui/activities/filetransfer_activity/update.rs b/src/ui/activities/filetransfer_activity/update.rs index b0ab8d8..11f050a 100644 --- a/src/ui/activities/filetransfer_activity/update.rs +++ b/src/ui/activities/filetransfer_activity/update.rs @@ -649,12 +649,13 @@ impl FileTransferActivity { Some(val) => val, None => 256, // Default }; + let params = self.context.as_ref().unwrap().ft_params.as_ref().unwrap(); let hostname: String = format!( "{}:{} ", - self.params.address, + params.address, FileTransferActivity::elide_wrkdir_path( self.remote.wrkdir.as_path(), - self.params.address.as_str(), + params.address.as_str(), width ) .display() diff --git a/src/ui/context.rs b/src/ui/context.rs index b0ee027..3a9911b 100644 --- a/src/ui/context.rs +++ b/src/ui/context.rs @@ -30,6 +30,7 @@ extern crate tui; // Locals use super::input::InputHandler; use super::store::Store; +use crate::filetransfer::FileTransferProtocol; use crate::host::Localhost; use crate::system::config_client::ConfigClient; @@ -38,6 +39,7 @@ use crossterm::event::DisableMouseCapture; use crossterm::execute; use crossterm::terminal::{EnterAlternateScreen, LeaveAlternateScreen}; use std::io::{stdout, Stdout}; +use std::path::PathBuf; use tui::backend::CrosstermBackend; use tui::Terminal; @@ -46,6 +48,7 @@ use tui::Terminal; /// Context holds data structures used by the ui pub struct Context { pub local: Localhost, + pub ft_params: Option, pub(crate) config_client: Option, pub(crate) store: Store, pub(crate) input_hnd: InputHandler, @@ -53,6 +56,18 @@ pub struct Context { error: Option, } +/// ### FileTransferParams +/// +/// Holds connection parameters for file transfers +pub struct FileTransferParams { + pub address: String, + pub port: u16, + pub protocol: FileTransferProtocol, + pub username: Option, + pub password: Option, + pub entry_directory: Option, +} + impl Context { /// ### new /// @@ -67,6 +82,7 @@ impl Context { assert!(execute!(stdout, EnterAlternateScreen).is_ok()); Context { local, + ft_params: None, config_client, store: Store::init(), input_hnd: InputHandler::new(), @@ -132,14 +148,38 @@ impl Drop for Context { } } -/* +impl Default for FileTransferParams { + fn default() -> Self { + Self { + address: String::new(), + port: 22, + protocol: FileTransferProtocol::Sftp, + username: None, + password: None, + entry_directory: None, + } + } +} + #[cfg(test)] mod tests { use super::*; - use crate::filetransfer::sftp_transfer::SftpFileTransfer; - use std::path::PathBuf; + #[test] + fn test_ui_context_ft_params() { + let params: FileTransferParams = FileTransferParams::default(); + assert_eq!(params.address.as_str(), ""); + assert_eq!(params.port, 22); + assert_eq!(params.protocol, FileTransferProtocol::Sftp); + assert!(params.username.is_none()); + assert!(params.password.is_none()); + } + + //use crate::filetransfer::sftp_transfer::SftpFileTransfer; + //use std::path::PathBuf; + + /* #[test] fn test_ui_context_new() { // Prepare stuff @@ -162,5 +202,5 @@ mod tests { .is_ok()); Box::new(sftp_client) } + */ } -*/