From 60269c77776b0f81dfdacd21ee9ccffbff98cf84 Mon Sep 17 00:00:00 2001 From: veeso Date: Sun, 2 May 2021 12:09:50 +0200 Subject: [PATCH 1/7] wip --- docs/man.md | 1 + .../activities/filetransfer_activity/mod.rs | 26 +++++++++++++++++++ src/ui/activities/keymap.rs | 2 +- 3 files changed, 28 insertions(+), 1 deletion(-) diff --git a/docs/man.md b/docs/man.md index b926857..b60b678 100644 --- a/docs/man.md +++ b/docs/man.md @@ -108,6 +108,7 @@ Password can be basically provided through 3 ways when address argument is provi | `` | Save file as... | Save | | `` | Go to parent directory | Upper | | `` | Execute a command | eXecute | +| `` | Toggle synchronized browsing | sYnc | | `` | Delete file | | | `` | Abort file transfer process | | diff --git a/src/ui/activities/filetransfer_activity/mod.rs b/src/ui/activities/filetransfer_activity/mod.rs index dca8952..02f2e91 100644 --- a/src/ui/activities/filetransfer_activity/mod.rs +++ b/src/ui/activities/filetransfer_activity/mod.rs @@ -202,6 +202,30 @@ impl Default for TransferStates { } } +/// ## Browser +/// +/// Browser contains the browser options +struct Browser { + pub sync_browsing: bool, +} + +impl Default for Browser { + fn default() -> Self { + Self { + sync_browsing: false, + } + } +} + +impl Browser { + /// ### toggle_sync_browsing + /// + /// Invert the current state for the sync browsing + pub fn toggle_sync_browsing(&mut self) { + self.sync_browsing = !self.sync_browsing; + } +} + /// ## FileTransferActivity /// /// FileTransferActivity is the data holder for the file transfer activity @@ -217,6 +241,7 @@ pub struct FileTransferActivity { log_records: VecDeque, // Log records log_size: usize, // Log records size (max) transfer: TransferStates, // Transfer states + browser: Browser, // Browser states } impl FileTransferActivity { @@ -246,6 +271,7 @@ impl FileTransferActivity { log_records: VecDeque::with_capacity(256), // 256 events is enough I guess log_size: 256, // Must match with capacity transfer: TransferStates::default(), + browser: Browser::default(), } } } diff --git a/src/ui/activities/keymap.rs b/src/ui/activities/keymap.rs index 4de26bc..0540013 100644 --- a/src/ui/activities/keymap.rs +++ b/src/ui/activities/keymap.rs @@ -179,11 +179,11 @@ pub const MSG_KEY_CHAR_X: Msg = Msg::OnKey(KeyEvent { code: KeyCode::Char('x'), modifiers: KeyModifiers::NONE, }); -/* pub const MSG_KEY_CHAR_Y: Msg = Msg::OnKey(KeyEvent { code: KeyCode::Char('y'), modifiers: KeyModifiers::NONE, }); +/* pub const MSG_KEY_CHAR_Z: Msg = Msg::OnKey(KeyEvent { code: KeyCode::Char('z'), modifiers: KeyModifiers::NONE, From a088c6dbd3ab3cfbf039ca343620ce94b97de9a9 Mon Sep 17 00:00:00 2001 From: veeso Date: Sun, 2 May 2021 14:35:45 +0200 Subject: [PATCH 2/7] key toggle sync browsing --- .../activities/filetransfer_activity/update.rs | 6 ++++++ src/ui/activities/filetransfer_activity/view.rs | 16 ++++++++++++++++ 2 files changed, 22 insertions(+) diff --git a/src/ui/activities/filetransfer_activity/update.rs b/src/ui/activities/filetransfer_activity/update.rs index c5e7b1f..05a43b6 100644 --- a/src/ui/activities/filetransfer_activity/update.rs +++ b/src/ui/activities/filetransfer_activity/update.rs @@ -357,6 +357,12 @@ impl FileTransferActivity { self.mount_exec(); None } + (COMPONENT_EXPLORER_LOCAL, &MSG_KEY_CHAR_Y) + | (COMPONENT_EXPLORER_REMOTE, &MSG_KEY_CHAR_Y) => { + // Toggle browser sync + self.browser.toggle_sync_browsing(); + None + } (COMPONENT_EXPLORER_LOCAL, &MSG_KEY_ESC) | (COMPONENT_EXPLORER_REMOTE, &MSG_KEY_ESC) | (COMPONENT_LOG_BOX, &MSG_KEY_ESC) => { diff --git a/src/ui/activities/filetransfer_activity/view.rs b/src/ui/activities/filetransfer_activity/view.rs index 84d2f58..e4b6aa1 100644 --- a/src/ui/activities/filetransfer_activity/view.rs +++ b/src/ui/activities/filetransfer_activity/view.rs @@ -975,6 +975,22 @@ impl FileTransferActivity { ) .add_col(TextSpan::from(" Go to parent directory")) .add_row() + .add_col( + TextSpanBuilder::new("") + .bold() + .with_foreground(Color::Cyan) + .build(), + ) + .add_col(TextSpan::from(" Execute shell command")) + .add_row() + .add_col( + TextSpanBuilder::new("") + .bold() + .with_foreground(Color::Cyan) + .build(), + ) + .add_col(TextSpan::from(" Toggle synchronized browsing")) + .add_row() .add_col( TextSpanBuilder::new("") .bold() From cbe242bb94d5c02a01e29dd6b145f5fe37c4aca9 Mon Sep 17 00:00:00 2001 From: veeso Date: Sun, 2 May 2021 14:59:21 +0200 Subject: [PATCH 3/7] WIP --- src/ui/activities/filetransfer_activity/session.rs | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/src/ui/activities/filetransfer_activity/session.rs b/src/ui/activities/filetransfer_activity/session.rs index a98f55b..97aeb21 100644 --- a/src/ui/activities/filetransfer_activity/session.rs +++ b/src/ui/activities/filetransfer_activity/session.rs @@ -749,6 +749,12 @@ impl FileTransferActivity { if push { self.local.pushd(prev_dir.as_path()) } + // @! if synchronized browsing is enabled, change directory on remote too ~ since 0.5.0 + if self.browser.sync_browsing { + if let Some(name) = path.file_name() { + self.remote_changedir(PathBuf::from(name).as_path(), push); + } + } } Err(err) => { // Report err @@ -778,6 +784,13 @@ impl FileTransferActivity { if push { self.remote.pushd(prev_dir.as_path()) } + // @! if synchronized browsing is enabled, change directory on local too ~ since 0.5.0 + if self.browser.sync_browsing { + if let Some(name) = path.file_name() { + self.local_changedir(PathBuf::from(name).as_path(), push); + // TODO: move this somewhere else, since it's calling recursively + } + } } Err(err) => { // Report err From 2f0b340fe0797c8b000713da545509c18d06d084 Mon Sep 17 00:00:00 2001 From: veeso Date: Sun, 2 May 2021 21:04:03 +0200 Subject: [PATCH 4/7] Working on sync --- .../filetransfer_activity/actions.rs | 158 +++++++++++++++--- .../activities/filetransfer_activity/misc.rs | 30 +++- .../filetransfer_activity/session.rs | 13 -- .../filetransfer_activity/update.rs | 89 ++++------ 4 files changed, 204 insertions(+), 86 deletions(-) diff --git a/src/ui/activities/filetransfer_activity/actions.rs b/src/ui/activities/filetransfer_activity/actions.rs index c93e885..8dcf9db 100644 --- a/src/ui/activities/filetransfer_activity/actions.rs +++ b/src/ui/activities/filetransfer_activity/actions.rs @@ -32,36 +32,156 @@ use tuirealm::{Payload, Value}; use std::path::PathBuf; impl FileTransferActivity { + /// ### action_enter_local_dir + /// + /// Enter a directory on local host from entry + /// Return true whether the directory changed + pub(super) fn action_enter_local_dir(&mut self, entry: FsEntry) -> bool { + match entry { + FsEntry::Directory(dir) => { + self.remote_changedir(dir.abs_path.as_path(), true); + if self.browser.sync_browsing { + self.action_change_remote_dir(dir.name.clone()); + } + true + } + FsEntry::File(file) => { + match &file.symlink { + Some(symlink_entry) => { + // If symlink and is directory, point to symlink + match &**symlink_entry { + FsEntry::Directory(dir) => { + self.remote_changedir(dir.abs_path.as_path(), true); + // Check whether to sync + if self.browser.sync_browsing { + self.action_change_remote_dir(dir.name.clone()); + } + true + } + _ => false, + } + } + None => false, + } + } + } + } + + /// ### action_enter_remote_dir + /// + /// Enter a directory on local host from entry + /// Return true whether the directory changed + pub(super) fn action_enter_remote_dir(&mut self, entry: FsEntry) -> bool { + match entry { + FsEntry::Directory(dir) => { + self.local_changedir(dir.abs_path.as_path(), true); + if self.browser.sync_browsing { + self.action_change_local_dir(dir.name.clone()); + } + true + } + FsEntry::File(file) => { + match &file.symlink { + Some(symlink_entry) => { + // If symlink and is directory, point to symlink + match &**symlink_entry { + FsEntry::Directory(dir) => { + self.local_changedir(dir.abs_path.as_path(), true); + // Check whether to sync + if self.browser.sync_browsing { + self.action_change_local_dir(dir.name.clone()); + } + true + } + _ => false, + } + } + None => false, + } + } + } + } + /// ### action_change_local_dir /// /// Change local directory reading value from input pub(super) fn action_change_local_dir(&mut self, input: String) { - let dir_path: PathBuf = PathBuf::from(input.as_str()); - let abs_dir_path: PathBuf = match dir_path.is_relative() { - true => { - let mut d: PathBuf = self.local.wrkdir.clone(); - d.push(dir_path); - d - } - false => dir_path, - }; - self.local_changedir(abs_dir_path.as_path(), true); + let dir_path: PathBuf = self.local_to_abs_path(PathBuf::from(input.as_str()).as_path()); + self.local_changedir(dir_path.as_path(), true); + // Check whether to sync + if self.browser.sync_browsing { + self.action_change_remote_dir(input); + } } /// ### action_change_remote_dir /// /// Change remote directory reading value from input pub(super) fn action_change_remote_dir(&mut self, input: String) { - let dir_path: PathBuf = PathBuf::from(input.as_str()); - let abs_dir_path: PathBuf = match dir_path.is_relative() { - true => { - let mut wrkdir: PathBuf = self.remote.wrkdir.clone(); - wrkdir.push(dir_path); - wrkdir + let dir_path: PathBuf = self.remote_to_abs_path(PathBuf::from(input.as_str()).as_path()); + self.remote_changedir(dir_path.as_path(), true); + // Check whether to sync + if self.browser.sync_browsing { + self.action_change_local_dir(input); + } + } + + /// ### action_go_to_previous_local_dir + /// + /// Go to previous directory from localhost + pub(super) fn action_go_to_previous_local_dir(&mut self) { + if let Some(d) = self.local.popd() { + self.local_changedir(d.as_path(), false); + // Check whether to sync + if self.browser.sync_browsing { + self.action_go_to_previous_remote_dir(); } - false => dir_path, - }; - self.remote_changedir(abs_dir_path.as_path(), true); + } + } + + /// ### action_go_to_previous_remote_dir + /// + /// Go to previous directory from remote host + pub(super) fn action_go_to_previous_remote_dir(&mut self) { + if let Some(d) = self.local.popd() { + self.remote_changedir(d.as_path(), false); + // Check whether to sync + if self.browser.sync_browsing { + self.action_go_to_previous_local_dir(); + } + } + } + + /// ### action_go_to_local_upper_dir + /// + /// Go to upper directory on local host + pub(super) fn action_go_to_local_upper_dir(&mut self) { + // Get pwd + let path: PathBuf = self.local.wrkdir.clone(); + // Go to parent directory + if let Some(parent) = path.as_path().parent() { + self.local_changedir(parent, true); + // If sync is enabled update remote too + if self.browser.sync_browsing { + self.action_go_to_remote_upper_dir(); + } + } + } + + /// #### action_go_to_remote_upper_dir + /// + /// Go to upper directory on remote host + pub(super) fn action_go_to_remote_upper_dir(&mut self) { + // Get pwd + let path: PathBuf = self.remote.wrkdir.clone(); + // Go to parent directory + if let Some(parent) = path.as_path().parent() { + self.remote_changedir(parent, true); + // If sync is enabled update local too + if self.browser.sync_browsing { + self.action_go_to_local_upper_dir(); + } + } } /// ### action_local_copy diff --git a/src/ui/activities/filetransfer_activity/misc.rs b/src/ui/activities/filetransfer_activity/misc.rs index cb56463..d30cb4e 100644 --- a/src/ui/activities/filetransfer_activity/misc.rs +++ b/src/ui/activities/filetransfer_activity/misc.rs @@ -28,7 +28,7 @@ use crate::system::environment; use crate::system::sshkey_storage::SshKeyStorage; // Ext use std::env; -use std::path::PathBuf; +use std::path::{Path, PathBuf}; impl FileTransferActivity { /// ### log @@ -175,4 +175,32 @@ impl FileTransferActivity { false } } + + /// ### local_to_abs_path + /// + /// Convert a path to absolute according to local explorer + pub(super) fn local_to_abs_path(&self, path: &Path) -> PathBuf { + match path.is_relative() { + true => { + let mut d: PathBuf = self.local.wrkdir.clone(); + d.push(path); + d + } + false => path.to_path_buf(), + } + } + + /// ### remote_to_abs_path + /// + /// Convert a path to absolute according to remote explorer + pub(super) fn remote_to_abs_path(&self, path: &Path) -> PathBuf { + match path.is_relative() { + true => { + let mut wrkdir: PathBuf = self.remote.wrkdir.clone(); + wrkdir.push(path); + wrkdir + } + false => path.to_path_buf(), + } + } } diff --git a/src/ui/activities/filetransfer_activity/session.rs b/src/ui/activities/filetransfer_activity/session.rs index 97aeb21..a98f55b 100644 --- a/src/ui/activities/filetransfer_activity/session.rs +++ b/src/ui/activities/filetransfer_activity/session.rs @@ -749,12 +749,6 @@ impl FileTransferActivity { if push { self.local.pushd(prev_dir.as_path()) } - // @! if synchronized browsing is enabled, change directory on remote too ~ since 0.5.0 - if self.browser.sync_browsing { - if let Some(name) = path.file_name() { - self.remote_changedir(PathBuf::from(name).as_path(), push); - } - } } Err(err) => { // Report err @@ -784,13 +778,6 @@ impl FileTransferActivity { if push { self.remote.pushd(prev_dir.as_path()) } - // @! if synchronized browsing is enabled, change directory on local too ~ since 0.5.0 - if self.browser.sync_browsing { - if let Some(name) = path.file_name() { - self.local_changedir(PathBuf::from(name).as_path(), push); - // TODO: move this somewhere else, since it's calling recursively - } - } } Err(err) => { // Report err diff --git a/src/ui/activities/filetransfer_activity/update.rs b/src/ui/activities/filetransfer_activity/update.rs index 05a43b6..06a16f0 100644 --- a/src/ui/activities/filetransfer_activity/update.rs +++ b/src/ui/activities/filetransfer_activity/update.rs @@ -73,8 +73,9 @@ impl FileTransferActivity { } (COMPONENT_EXPLORER_LOCAL, &MSG_KEY_BACKSPACE) => { // Go to previous directory - if let Some(d) = self.local.popd() { - self.local_changedir(d.as_path(), false); + self.action_go_to_previous_local_dir(); + if self.browser.sync_browsing { + let _ = self.update_remote_filelist(); } // Reload file list component self.update_local_filelist() @@ -86,25 +87,14 @@ impl FileTransferActivity { entry = Some(e.clone()); } if let Some(entry) = entry { - // If directory, enter directory, otherwise check if symlink - match entry { - FsEntry::Directory(dir) => { - self.local_changedir(dir.abs_path.as_path(), true); - self.update_local_filelist() - } - FsEntry::File(file) => { - // Check if symlink - match &file.symlink { - Some(pointer) => match &**pointer { - FsEntry::Directory(dir) => { - self.local_changedir(dir.abs_path.as_path(), true); - self.update_local_filelist() - } - _ => None, - }, - None => None, - } + if self.action_enter_local_dir(entry) { + // Update file list if sync + if self.browser.sync_browsing { + let _ = self.update_remote_filelist(); } + self.update_local_filelist() + } else { + None } } else { None @@ -170,13 +160,11 @@ impl FileTransferActivity { self.update_local_filelist() } (COMPONENT_EXPLORER_LOCAL, &MSG_KEY_CHAR_U) => { - // Get pwd - let path: PathBuf = self.local.wrkdir.clone(); - // Go to parent directory - if let Some(parent) = path.as_path().parent() { - self.local_changedir(parent, true); - // Reload file list component + self.action_go_to_local_upper_dir(); + if self.browser.sync_browsing { + let _ = self.update_remote_filelist(); } + // Reload file list component self.update_local_filelist() } // -- remote tab @@ -193,27 +181,14 @@ impl FileTransferActivity { entry = Some(e.clone()); } if let Some(entry) = entry { - // If directory, enter directory; if file, check if is symlink - match entry { - FsEntry::Directory(dir) => { - self.remote_changedir(dir.abs_path.as_path(), true); - self.update_remote_filelist() - } - FsEntry::File(file) => { - match &file.symlink { - Some(symlink_entry) => { - // If symlink and is directory, point to symlink - match &**symlink_entry { - FsEntry::Directory(dir) => { - self.remote_changedir(dir.abs_path.as_path(), true); - self.update_remote_filelist() - } - _ => None, - } - } - None => None, - } + if self.action_enter_remote_dir(entry) { + // Update file list if sync + if self.browser.sync_browsing { + let _ = self.update_local_filelist(); } + self.update_remote_filelist() + } else { + None } } else { None @@ -234,8 +209,10 @@ impl FileTransferActivity { } (COMPONENT_EXPLORER_REMOTE, &MSG_KEY_BACKSPACE) => { // Go to previous directory - if let Some(d) = self.remote.popd() { - self.remote_changedir(d.as_path(), false); + self.action_go_to_previous_remote_dir(); + // If sync is enabled update local too + if self.browser.sync_browsing { + let _ = self.update_local_filelist(); } // Reload file list component self.update_remote_filelist() @@ -286,11 +263,9 @@ impl FileTransferActivity { self.update_remote_filelist() } (COMPONENT_EXPLORER_REMOTE, &MSG_KEY_CHAR_U) => { - // Get pwd - let path: PathBuf = self.remote.wrkdir.clone(); - // Go to parent directory - if let Some(parent) = path.as_path().parent() { - self.remote_changedir(parent, true); + self.action_go_to_remote_upper_dir(); + if self.browser.sync_browsing { + let _ = self.update_local_filelist(); } // Reload file list component self.update_remote_filelist() @@ -517,6 +492,14 @@ impl FileTransferActivity { } // Umount self.umount_goto(); + // Reload files if sync + if self.browser.sync_browsing { + match self.tab { + FileExplorerTab::Remote => self.update_local_filelist(), + FileExplorerTab::Local => self.update_remote_filelist(), + _ => None, + }; + } // Reload files match self.tab { FileExplorerTab::Local => self.update_local_filelist(), From a0c29d117451f045cc343c6ed2d4f8f73691ad49 Mon Sep 17 00:00:00 2001 From: veeso Date: Mon, 3 May 2021 18:08:05 +0200 Subject: [PATCH 5/7] Fixed sync browser --- .../filetransfer_activity/actions.rs | 66 +++++++++---------- .../filetransfer_activity/update.rs | 20 +++--- 2 files changed, 45 insertions(+), 41 deletions(-) diff --git a/src/ui/activities/filetransfer_activity/actions.rs b/src/ui/activities/filetransfer_activity/actions.rs index 8dcf9db..e1bdd4a 100644 --- a/src/ui/activities/filetransfer_activity/actions.rs +++ b/src/ui/activities/filetransfer_activity/actions.rs @@ -36,12 +36,12 @@ impl FileTransferActivity { /// /// Enter a directory on local host from entry /// Return true whether the directory changed - pub(super) fn action_enter_local_dir(&mut self, entry: FsEntry) -> bool { + pub(super) fn action_enter_local_dir(&mut self, entry: FsEntry, block_sync: bool) -> bool { match entry { FsEntry::Directory(dir) => { - self.remote_changedir(dir.abs_path.as_path(), true); - if self.browser.sync_browsing { - self.action_change_remote_dir(dir.name.clone()); + self.local_changedir(dir.abs_path.as_path(), true); + if self.browser.sync_browsing && !block_sync { + self.action_change_remote_dir(dir.name, true); } true } @@ -51,10 +51,10 @@ impl FileTransferActivity { // If symlink and is directory, point to symlink match &**symlink_entry { FsEntry::Directory(dir) => { - self.remote_changedir(dir.abs_path.as_path(), true); + self.local_changedir(dir.abs_path.as_path(), true); // Check whether to sync - if self.browser.sync_browsing { - self.action_change_remote_dir(dir.name.clone()); + if self.browser.sync_browsing && !block_sync { + self.action_change_remote_dir(dir.name.clone(), true); } true } @@ -71,12 +71,12 @@ impl FileTransferActivity { /// /// Enter a directory on local host from entry /// Return true whether the directory changed - pub(super) fn action_enter_remote_dir(&mut self, entry: FsEntry) -> bool { + pub(super) fn action_enter_remote_dir(&mut self, entry: FsEntry, block_sync: bool) -> bool { match entry { FsEntry::Directory(dir) => { - self.local_changedir(dir.abs_path.as_path(), true); - if self.browser.sync_browsing { - self.action_change_local_dir(dir.name.clone()); + self.remote_changedir(dir.abs_path.as_path(), true); + if self.browser.sync_browsing && !block_sync { + self.action_change_local_dir(dir.name, true); } true } @@ -86,10 +86,10 @@ impl FileTransferActivity { // If symlink and is directory, point to symlink match &**symlink_entry { FsEntry::Directory(dir) => { - self.local_changedir(dir.abs_path.as_path(), true); + self.remote_changedir(dir.abs_path.as_path(), true); // Check whether to sync - if self.browser.sync_browsing { - self.action_change_local_dir(dir.name.clone()); + if self.browser.sync_browsing && !block_sync { + self.action_change_local_dir(dir.name.clone(), true); } true } @@ -105,36 +105,36 @@ impl FileTransferActivity { /// ### action_change_local_dir /// /// Change local directory reading value from input - pub(super) fn action_change_local_dir(&mut self, input: String) { + pub(super) fn action_change_local_dir(&mut self, input: String, block_sync: bool) { let dir_path: PathBuf = self.local_to_abs_path(PathBuf::from(input.as_str()).as_path()); self.local_changedir(dir_path.as_path(), true); // Check whether to sync - if self.browser.sync_browsing { - self.action_change_remote_dir(input); + if self.browser.sync_browsing && !block_sync { + self.action_change_remote_dir(input, true); } } /// ### action_change_remote_dir /// /// Change remote directory reading value from input - pub(super) fn action_change_remote_dir(&mut self, input: String) { + pub(super) fn action_change_remote_dir(&mut self, input: String, block_sync: bool) { let dir_path: PathBuf = self.remote_to_abs_path(PathBuf::from(input.as_str()).as_path()); self.remote_changedir(dir_path.as_path(), true); // Check whether to sync - if self.browser.sync_browsing { - self.action_change_local_dir(input); + if self.browser.sync_browsing && !block_sync { + self.action_change_local_dir(input, true); } } /// ### action_go_to_previous_local_dir /// /// Go to previous directory from localhost - pub(super) fn action_go_to_previous_local_dir(&mut self) { + pub(super) fn action_go_to_previous_local_dir(&mut self, block_sync: bool) { if let Some(d) = self.local.popd() { self.local_changedir(d.as_path(), false); // Check whether to sync - if self.browser.sync_browsing { - self.action_go_to_previous_remote_dir(); + if self.browser.sync_browsing && !block_sync { + self.action_go_to_previous_remote_dir(true); } } } @@ -142,12 +142,12 @@ impl FileTransferActivity { /// ### action_go_to_previous_remote_dir /// /// Go to previous directory from remote host - pub(super) fn action_go_to_previous_remote_dir(&mut self) { - if let Some(d) = self.local.popd() { + pub(super) fn action_go_to_previous_remote_dir(&mut self, block_sync: bool) { + if let Some(d) = self.remote.popd() { self.remote_changedir(d.as_path(), false); // Check whether to sync - if self.browser.sync_browsing { - self.action_go_to_previous_local_dir(); + if self.browser.sync_browsing && !block_sync { + self.action_go_to_previous_local_dir(true); } } } @@ -155,15 +155,15 @@ impl FileTransferActivity { /// ### action_go_to_local_upper_dir /// /// Go to upper directory on local host - pub(super) fn action_go_to_local_upper_dir(&mut self) { + pub(super) fn action_go_to_local_upper_dir(&mut self, block_sync: bool) { // Get pwd let path: PathBuf = self.local.wrkdir.clone(); // Go to parent directory if let Some(parent) = path.as_path().parent() { self.local_changedir(parent, true); // If sync is enabled update remote too - if self.browser.sync_browsing { - self.action_go_to_remote_upper_dir(); + if self.browser.sync_browsing && !block_sync { + self.action_go_to_remote_upper_dir(true); } } } @@ -171,15 +171,15 @@ impl FileTransferActivity { /// #### action_go_to_remote_upper_dir /// /// Go to upper directory on remote host - pub(super) fn action_go_to_remote_upper_dir(&mut self) { + pub(super) fn action_go_to_remote_upper_dir(&mut self, block_sync: bool) { // Get pwd let path: PathBuf = self.remote.wrkdir.clone(); // Go to parent directory if let Some(parent) = path.as_path().parent() { self.remote_changedir(parent, true); // If sync is enabled update local too - if self.browser.sync_browsing { - self.action_go_to_local_upper_dir(); + if self.browser.sync_browsing && !block_sync { + self.action_go_to_local_upper_dir(true); } } } diff --git a/src/ui/activities/filetransfer_activity/update.rs b/src/ui/activities/filetransfer_activity/update.rs index 06a16f0..71ebb67 100644 --- a/src/ui/activities/filetransfer_activity/update.rs +++ b/src/ui/activities/filetransfer_activity/update.rs @@ -73,7 +73,7 @@ impl FileTransferActivity { } (COMPONENT_EXPLORER_LOCAL, &MSG_KEY_BACKSPACE) => { // Go to previous directory - self.action_go_to_previous_local_dir(); + self.action_go_to_previous_local_dir(false); if self.browser.sync_browsing { let _ = self.update_remote_filelist(); } @@ -87,7 +87,7 @@ impl FileTransferActivity { entry = Some(e.clone()); } if let Some(entry) = entry { - if self.action_enter_local_dir(entry) { + if self.action_enter_local_dir(entry, false) { // Update file list if sync if self.browser.sync_browsing { let _ = self.update_remote_filelist(); @@ -160,7 +160,7 @@ impl FileTransferActivity { self.update_local_filelist() } (COMPONENT_EXPLORER_LOCAL, &MSG_KEY_CHAR_U) => { - self.action_go_to_local_upper_dir(); + self.action_go_to_local_upper_dir(false); if self.browser.sync_browsing { let _ = self.update_remote_filelist(); } @@ -181,7 +181,7 @@ impl FileTransferActivity { entry = Some(e.clone()); } if let Some(entry) = entry { - if self.action_enter_remote_dir(entry) { + if self.action_enter_remote_dir(entry, false) { // Update file list if sync if self.browser.sync_browsing { let _ = self.update_local_filelist(); @@ -209,7 +209,7 @@ impl FileTransferActivity { } (COMPONENT_EXPLORER_REMOTE, &MSG_KEY_BACKSPACE) => { // Go to previous directory - self.action_go_to_previous_remote_dir(); + self.action_go_to_previous_remote_dir(false); // If sync is enabled update local too if self.browser.sync_browsing { let _ = self.update_local_filelist(); @@ -263,7 +263,7 @@ impl FileTransferActivity { self.update_remote_filelist() } (COMPONENT_EXPLORER_REMOTE, &MSG_KEY_CHAR_U) => { - self.action_go_to_remote_upper_dir(); + self.action_go_to_remote_upper_dir(false); if self.browser.sync_browsing { let _ = self.update_local_filelist(); } @@ -486,8 +486,12 @@ impl FileTransferActivity { } (COMPONENT_INPUT_GOTO, Msg::OnSubmit(Payload::One(Value::Str(input)))) => { match self.tab { - FileExplorerTab::Local => self.action_change_local_dir(input.to_string()), - FileExplorerTab::Remote => self.action_change_remote_dir(input.to_string()), + FileExplorerTab::Local => { + self.action_change_local_dir(input.to_string(), false) + } + FileExplorerTab::Remote => { + self.action_change_remote_dir(input.to_string(), false) + } _ => panic!("Found tab doesn't support GOTO"), } // Umount From 4c1fb826be838b43789baeec90a62ec9a3782340 Mon Sep 17 00:00:00 2001 From: veeso Date: Mon, 3 May 2021 22:23:55 +0200 Subject: [PATCH 6/7] Status bar --- .../activities/filetransfer_activity/mod.rs | 1 + .../filetransfer_activity/update.rs | 4 ++ .../activities/filetransfer_activity/view.rs | 64 ++++++++++++++++++- 3 files changed, 67 insertions(+), 2 deletions(-) diff --git a/src/ui/activities/filetransfer_activity/mod.rs b/src/ui/activities/filetransfer_activity/mod.rs index 02f2e91..c0dd44e 100644 --- a/src/ui/activities/filetransfer_activity/mod.rs +++ b/src/ui/activities/filetransfer_activity/mod.rs @@ -84,6 +84,7 @@ const COMPONENT_RADIO_DELETE: &str = "RADIO_DELETE"; const COMPONENT_RADIO_DISCONNECT: &str = "RADIO_DISCONNECT"; const COMPONENT_RADIO_QUIT: &str = "RADIO_QUIT"; const COMPONENT_RADIO_SORTING: &str = "RADIO_SORTING"; +const COMPONENT_SPAN_STATUS_BAR: &str = "STATUS_BAR"; const COMPONENT_LIST_FILEINFO: &str = "LIST_FILEINFO"; /// ## FileExplorerTab diff --git a/src/ui/activities/filetransfer_activity/update.rs b/src/ui/activities/filetransfer_activity/update.rs index 71ebb67..66295de 100644 --- a/src/ui/activities/filetransfer_activity/update.rs +++ b/src/ui/activities/filetransfer_activity/update.rs @@ -336,6 +336,8 @@ impl FileTransferActivity { | (COMPONENT_EXPLORER_REMOTE, &MSG_KEY_CHAR_Y) => { // Toggle browser sync self.browser.toggle_sync_browsing(); + // Update status bar + self.refresh_status_bar(); None } (COMPONENT_EXPLORER_LOCAL, &MSG_KEY_ESC) @@ -675,6 +677,8 @@ impl FileTransferActivity { FileExplorerTab::Remote => self.remote.sort_by(sorting), _ => panic!("Found result doesn't support SORTING"), } + // Update status bar + self.refresh_status_bar(); // Reload files match self.tab { FileExplorerTab::Local => self.update_local_filelist(), diff --git a/src/ui/activities/filetransfer_activity/view.rs b/src/ui/activities/filetransfer_activity/view.rs index e4b6aa1..a0a321e 100644 --- a/src/ui/activities/filetransfer_activity/view.rs +++ b/src/ui/activities/filetransfer_activity/view.rs @@ -49,6 +49,7 @@ use tuirealm::components::{ input::{Input, InputPropsBuilder}, progress_bar::{ProgressBar, ProgressBarPropsBuilder}, radio::{Radio, RadioPropsBuilder}, + span::{Span, SpanPropsBuilder}, table::{Table, TablePropsBuilder}, }; use tuirealm::props::{PropsBuilder, TableBuilder, TextSpan, TextSpanBuilder}; @@ -98,6 +99,13 @@ impl FileTransferActivity { .build(), )), ); + // Mount status bar + self.view.mount( + super::COMPONENT_SPAN_STATUS_BAR, + Box::new(Span::new(SpanPropsBuilder::default().build())), + ); + // Load process bar + self.refresh_status_bar(); // Update components let _ = self.update_local_filelist(); let _ = self.update_remote_filelist(); @@ -131,6 +139,11 @@ impl FileTransferActivity { .constraints([Constraint::Percentage(50), Constraint::Percentage(50)].as_ref()) .direction(Direction::Horizontal) .split(chunks[0]); + // Create log box chunks + let bottom_chunks = Layout::default() + .constraints([Constraint::Length(1), Constraint::Length(10)].as_ref()) + .direction(Direction::Vertical) + .split(chunks[1]); // If width is unset in the storage, set width if !store.isset(super::STORAGE_EXPLORER_WIDTH) { store.set_unsigned(super::STORAGE_EXPLORER_WIDTH, tabs_chunks[0].width as usize); @@ -159,8 +172,11 @@ impl FileTransferActivity { .view .render(super::COMPONENT_EXPLORER_REMOTE, f, tabs_chunks[1]), } - // Draw log box - self.view.render(super::COMPONENT_LOG_BOX, f, chunks[1]); + // Draw log box and status bar + self.view + .render(super::COMPONENT_LOG_BOX, f, bottom_chunks[1]); + self.view + .render(super::COMPONENT_SPAN_STATUS_BAR, f, bottom_chunks[0]); // @! Draw popups if let Some(props) = self.view.get_props(super::COMPONENT_INPUT_COPY) { if props.visible { @@ -793,6 +809,41 @@ impl FileTransferActivity { self.view.umount(super::COMPONENT_LIST_FILEINFO); } + pub(super) fn refresh_status_bar(&mut self) { + let bar_spans: Vec = vec![ + TextSpanBuilder::new("Synchronized Browsing: ") + .with_foreground(Color::LightGreen) + .build(), + TextSpanBuilder::new(match self.browser.sync_browsing { + true => "ON ", + false => "OFF", + }) + .with_foreground(Color::LightGreen) + .reversed() + .build(), + TextSpanBuilder::new(" Localhost file sorting: ") + .with_foreground(Color::LightYellow) + .build(), + TextSpanBuilder::new(Self::get_file_sorting_str(self.local.get_file_sorting())) + .with_foreground(Color::LightYellow) + .reversed() + .build(), + TextSpanBuilder::new(" Remote host file sorting: ") + .with_foreground(Color::LightBlue) + .build(), + TextSpanBuilder::new(Self::get_file_sorting_str(self.remote.get_file_sorting())) + .with_foreground(Color::LightBlue) + .reversed() + .build(), + ]; + if let Some(props) = self.view.get_props(super::COMPONENT_SPAN_STATUS_BAR) { + self.view.update( + super::COMPONENT_SPAN_STATUS_BAR, + SpanPropsBuilder::from(props).with_spans(bar_spans).build(), + ); + } + } + /// ### mount_help /// /// Mount help @@ -1018,4 +1069,13 @@ impl FileTransferActivity { pub(super) fn umount_help(&mut self) { self.view.umount(super::COMPONENT_TEXT_HELP); } + + fn get_file_sorting_str(mode: FileSorting) -> &'static str { + match mode { + FileSorting::ByName => "By name", + FileSorting::ByCreationTime => "By creation time", + FileSorting::ByModifyTime => "By modify time", + FileSorting::BySize => "By size", + } + } } From 42477d6893d61e2cdbb8b0de7770404627f77166 Mon Sep 17 00:00:00 2001 From: veeso Date: Mon, 3 May 2021 22:24:17 +0200 Subject: [PATCH 7/7] tui-realm 0.2.2 --- CHANGELOG.md | 8 +++++++- Cargo.lock | 41 ++++++++--------------------------------- Cargo.toml | 2 +- 3 files changed, 16 insertions(+), 35 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a187358..15182cf 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -21,14 +21,20 @@ Released on FIXME: ?? +- **Synchronized browsing**: + - Added the possibility to enabled the synchronized brower navigation + - when you enter a directory, the same directory will be entered on the other tab + - Enable sync browser with `` - **Remote and Local hosts file formatter**: - Added the possibility to set different formatters for local and remote hosts +- Enhancements + - Added a status bar in the file explorer showing whether the sync browser is enabled and which file sorting mode is selected - Bugfix: - Fixed wrong text wrap in log box - Fixed error message not being shown after an upload failure - [Issue 23](https://github.com/veeso/termscp/issues/23): Remove created file if transfer failed or was abrupted - Dependencies: - - Added `tui-realm 0.2.1` + - Added `tui-realm 0.2.2` - Removed `tui` (as direct dependency) - Updated `regex` to `1.5.3` diff --git a/Cargo.lock b/Cargo.lock index 1859dc2..91ff146 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -219,22 +219,6 @@ dependencies = [ "debug-helper", ] -[[package]] -name = "crossterm" -version = "0.18.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4e86d73f2a0b407b5768d10a8c720cf5d2df49a9efc10ca09176d201ead4b7fb" -dependencies = [ - "bitflags", - "crossterm_winapi 0.6.2", - "lazy_static", - "libc", - "mio", - "parking_lot 0.11.1", - "signal-hook", - "winapi", -] - [[package]] name = "crossterm" version = "0.19.0" @@ -242,7 +226,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7c36c10130df424b2f3552fcc2ddcd9b28a27b1e54b358b45874f88d1ca6888c" dependencies = [ "bitflags", - "crossterm_winapi 0.7.0", + "crossterm_winapi", "lazy_static", "libc", "mio", @@ -251,15 +235,6 @@ dependencies = [ "winapi", ] -[[package]] -name = "crossterm_winapi" -version = "0.6.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c2265c3f8e080075d9b6417aa72293fc71662f34b4af2612d8d1b074d29510db" -dependencies = [ - "winapi", -] - [[package]] name = "crossterm_winapi" version = "0.7.0" @@ -1275,7 +1250,7 @@ dependencies = [ "bytesize", "chrono", "content_inspector", - "crossterm 0.19.0", + "crossterm", "dirs", "edit", "ftp4", @@ -1379,24 +1354,24 @@ dependencies = [ [[package]] name = "tui" -version = "0.14.0" +version = "0.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ced152a8e9295a5b168adc254074525c17ac4a83c90b2716274cc38118bddc9" +checksum = "861d8f3ad314ede6219bcb2ab844054b1de279ee37a9bc38e3d606f9d3fb2a71" dependencies = [ "bitflags", "cassowary", - "crossterm 0.18.2", + "crossterm", "unicode-segmentation", "unicode-width", ] [[package]] name = "tuirealm" -version = "0.2.1" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2cade7d98a40066164d9c8e52bf01f86ecaa4fa810e854855a5a4ec3deca83c2" +checksum = "963c590368d3ab9be44ee0fccb7ad86f3611dfb4536b02be0e25cbc5685d51bb" dependencies = [ - "crossterm 0.19.0", + "crossterm", "textwrap", "tui", "unicode-width", diff --git a/Cargo.toml b/Cargo.toml index 3d39747..00aeb58 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -46,7 +46,7 @@ tempfile = "3.1.0" textwrap = "0.13.4" thiserror = "^1.0.0" toml = "0.5.8" -tuirealm = { version = "0.2.1", features = [ "with-components" ] } +tuirealm = { version = "0.2.2", features = [ "with-components" ] } whoami = "1.1.1" wildmatch = "2.0.0"