diff --git a/src/ui/activities/filetransfer/actions/find.rs b/src/ui/activities/filetransfer/actions/find.rs index d9b844b..c6ffba9 100644 --- a/src/ui/activities/filetransfer/actions/find.rs +++ b/src/ui/activities/filetransfer/actions/find.rs @@ -78,15 +78,16 @@ impl FileTransferActivity { SelectedEntry::One(entry) => match self.browser.tab() { FileExplorerTab::FindLocal | FileExplorerTab::Local => { let file_to_check = Self::file_to_check(&entry, opts.save_as.as_ref()); - if opts.check_replace - && self.config().get_prompt_on_file_replace() + if self.config().get_prompt_on_file_replace() && self.remote_file_exists(file_to_check.as_path()) - { - // Save pending transfer - self.set_pending_transfer( + && !self.should_replace_file( opts.save_as.as_deref().unwrap_or_else(|| entry.name()), - ); - } else if let Err(err) = self.filetransfer_send( + ) + { + // Do not replace + return; + } + if let Err(err) = self.filetransfer_send( TransferPayload::Any(entry), wrkdir.as_path(), opts.save_as, @@ -99,15 +100,16 @@ impl FileTransferActivity { } FileExplorerTab::FindRemote | FileExplorerTab::Remote => { let file_to_check = Self::file_to_check(&entry, opts.save_as.as_ref()); - if opts.check_replace - && self.config().get_prompt_on_file_replace() + if self.config().get_prompt_on_file_replace() && self.local_file_exists(file_to_check.as_path()) - { - // Save pending transfer - self.set_pending_transfer( + && !self.should_replace_file( opts.save_as.as_deref().unwrap_or_else(|| entry.name()), - ); - } else if let Err(err) = self.filetransfer_recv( + ) + { + // Do not replace + return; + } + if let Err(err) = self.filetransfer_recv( TransferPayload::Any(entry), wrkdir.as_path(), opts.save_as, @@ -128,7 +130,7 @@ impl FileTransferActivity { // Iter files match self.browser.tab() { FileExplorerTab::FindLocal | FileExplorerTab::Local => { - if opts.check_replace && self.config().get_prompt_on_file_replace() { + if self.config().get_prompt_on_file_replace() { // Check which file would be replaced let existing_files: Vec<&Entry> = entries .iter() @@ -138,12 +140,10 @@ impl FileTransferActivity { ) }) .collect(); - // Save pending transfer - if !existing_files.is_empty() { - self.set_pending_transfer_many( - existing_files, - &dest_path.to_string_lossy().to_owned(), - ); + // Check whether to replace files + if !existing_files.is_empty() + && !self.should_replace_files(existing_files) + { return; } } @@ -161,7 +161,7 @@ impl FileTransferActivity { } } FileExplorerTab::FindRemote | FileExplorerTab::Remote => { - if opts.check_replace && self.config().get_prompt_on_file_replace() { + if self.config().get_prompt_on_file_replace() { // Check which file would be replaced let existing_files: Vec<&Entry> = entries .iter() @@ -171,13 +171,10 @@ impl FileTransferActivity { ) }) .collect(); - // Save pending transfer - // Save pending transfer - if !existing_files.is_empty() { - self.set_pending_transfer_many( - existing_files, - &dest_path.to_string_lossy().to_owned(), - ); + // Check whether to replace files + if !existing_files.is_empty() + && !self.should_replace_files(existing_files) + { return; } } diff --git a/src/ui/activities/filetransfer/actions/pending.rs b/src/ui/activities/filetransfer/actions/pending.rs index 852ef80..293def5 100644 --- a/src/ui/activities/filetransfer/actions/pending.rs +++ b/src/ui/activities/filetransfer/actions/pending.rs @@ -28,7 +28,7 @@ */ use super::{FileTransferActivity, Msg}; -use tuirealm::PollStrategy; +use tuirealm::{PollStrategy, Update}; impl FileTransferActivity { /// Block execution of activity, preventing ANY kind of message not specified in the `wait_for` argument. @@ -42,12 +42,22 @@ impl FileTransferActivity { loop { // Poll match self.app.tick(PollStrategy::Once) { - Ok(messages) => { + Ok(mut messages) => { if !messages.is_empty() { self.redraw = true; } - if let Some(msg) = messages.into_iter().find(|m| wait_for.contains(m)) { - return msg; + let found = messages.iter().position(|m| wait_for.contains(m)); + // Return if found + if let Some(index) = found { + return messages.remove(index); + } else { + // Update + for msg in messages.into_iter() { + let mut msg = Some(msg); + while msg.is_some() { + msg = self.update(msg); + } + } } } Err(err) => { diff --git a/src/ui/activities/filetransfer/actions/save.rs b/src/ui/activities/filetransfer/actions/save.rs index f71ef83..0b6e70d 100644 --- a/src/ui/activities/filetransfer/actions/save.rs +++ b/src/ui/activities/filetransfer/actions/save.rs @@ -27,8 +27,8 @@ */ // locals use super::{ - super::STORAGE_PENDING_TRANSFER, Entry, FileExplorerTab, FileTransferActivity, LogLevel, - SelectedEntry, TransferOpts, TransferPayload, + Entry, FileTransferActivity, LogLevel, Msg, PendingActionMsg, SelectedEntry, TransferOpts, + TransferPayload, }; use std::path::{Path, PathBuf}; @@ -49,59 +49,21 @@ impl FileTransferActivity { self.remote_recv_file(TransferOpts::default()); } - /// Finalize "pending" transfer. - /// The pending transfer is created after a transfer which required a user action to be completed first. - /// The name of the file to transfer, is contained in the storage at `STORAGE_PENDING_TRANSFER`. - /// NOTE: Panics if `STORAGE_PENDING_TRANSFER` is undefined - pub(crate) fn action_finalize_pending_transfer(&mut self) { - // Retrieve pending transfer - let file_name = self - .context_mut() - .store_mut() - .take_string(STORAGE_PENDING_TRANSFER); - // Send file - match self.browser.tab() { - FileExplorerTab::Local => self.local_send_file( - TransferOpts::default() - .save_as(file_name) - .check_replace(false), - ), - FileExplorerTab::Remote => self.remote_recv_file( - TransferOpts::default() - .save_as(file_name) - .check_replace(false), - ), - FileExplorerTab::FindLocal | FileExplorerTab::FindRemote => self.action_find_transfer( - TransferOpts::default() - .save_as(file_name) - .check_replace(false), - ), - } - // Reload browsers - match self.browser.tab() { - FileExplorerTab::Local | FileExplorerTab::FindLocal => { - self.update_remote_filelist(); - } - FileExplorerTab::Remote | FileExplorerTab::FindRemote => { - self.update_local_filelist(); - } - } - } - fn local_send_file(&mut self, opts: TransferOpts) { let wrkdir: PathBuf = self.remote().wrkdir.clone(); match self.get_local_selected_entries() { SelectedEntry::One(entry) => { let file_to_check = Self::file_to_check(&entry, opts.save_as.as_ref()); - if opts.check_replace - && self.config().get_prompt_on_file_replace() + if self.config().get_prompt_on_file_replace() && self.remote_file_exists(file_to_check.as_path()) - { - // Save pending transfer - self.set_pending_transfer( + && !self.should_replace_file( opts.save_as.as_deref().unwrap_or_else(|| entry.name()), - ); - } else if let Err(err) = self.filetransfer_send( + ) + { + // Do not replace + return; + } + if let Err(err) = self.filetransfer_send( TransferPayload::Any(entry.clone()), wrkdir.as_path(), opts.save_as, @@ -121,7 +83,7 @@ impl FileTransferActivity { dest_path.push(save_as); } // Iter files - if opts.check_replace && self.config().get_prompt_on_file_replace() { + if self.config().get_prompt_on_file_replace() { // Check which file would be replaced let existing_files: Vec<&Entry> = entries .iter() @@ -131,12 +93,8 @@ impl FileTransferActivity { ) }) .collect(); - // Save pending transfer - if !existing_files.is_empty() { - self.set_pending_transfer_many( - existing_files, - &dest_path.to_string_lossy().to_owned(), - ); + // Check whether to replace files + if !existing_files.is_empty() && !self.should_replace_files(existing_files) { return; } } @@ -162,15 +120,15 @@ impl FileTransferActivity { match self.get_remote_selected_entries() { SelectedEntry::One(entry) => { let file_to_check = Self::file_to_check(&entry, opts.save_as.as_ref()); - if opts.check_replace - && self.config().get_prompt_on_file_replace() + if self.config().get_prompt_on_file_replace() && self.local_file_exists(file_to_check.as_path()) - { - // Save pending transfer - self.set_pending_transfer( + && !self.should_replace_file( opts.save_as.as_deref().unwrap_or_else(|| entry.name()), - ); - } else if let Err(err) = self.filetransfer_recv( + ) + { + return; + } + if let Err(err) = self.filetransfer_recv( TransferPayload::Any(entry.clone()), wrkdir.as_path(), opts.save_as, @@ -190,7 +148,7 @@ impl FileTransferActivity { dest_path.push(save_as); } // Iter files - if opts.check_replace && self.config().get_prompt_on_file_replace() { + if self.config().get_prompt_on_file_replace() { // Check which file would be replaced let existing_files: Vec<&Entry> = entries .iter() @@ -200,12 +158,8 @@ impl FileTransferActivity { ) }) .collect(); - // Save pending transfer - if !existing_files.is_empty() { - self.set_pending_transfer_many( - existing_files, - &dest_path.to_string_lossy().to_owned(), - ); + // Check whether to replace files + if !existing_files.is_empty() && !self.should_replace_files(existing_files) { return; } } @@ -227,21 +181,47 @@ impl FileTransferActivity { } /// Set pending transfer into storage - pub(crate) fn set_pending_transfer(&mut self, file_name: &str) { + pub(crate) fn should_replace_file(&mut self, file_name: &str) -> bool { self.mount_radio_replace(file_name); - // Put pending transfer in store - self.context_mut() - .store_mut() - .set_string(STORAGE_PENDING_TRANSFER, file_name.to_string()); + // Wait for answer + trace!("Asking user whether he wants to replace file {}", file_name); + if self.wait_for_pending_msg(&[ + Msg::PendingAction(PendingActionMsg::CloseReplacePopups), + Msg::PendingAction(PendingActionMsg::TransferPendingFile), + ]) == Msg::PendingAction(PendingActionMsg::TransferPendingFile) + { + trace!("User wants to replace file"); + self.umount_radio_replace(); + true + } else { + trace!("The user doesn't want replace file"); + self.umount_radio_replace(); + false + } } /// Set pending transfer for many files into storage and mount radio - pub(crate) fn set_pending_transfer_many(&mut self, files: Vec<&Entry>, dest_path: &str) { + pub(crate) fn should_replace_files(&mut self, files: Vec<&Entry>) -> bool { let file_names: Vec<&str> = files.iter().map(|x| x.name()).collect(); self.mount_radio_replace_many(file_names.as_slice()); - self.context_mut() - .store_mut() - .set_string(STORAGE_PENDING_TRANSFER, dest_path.to_string()); + // Wait for answer + trace!( + "Asking user whether he wants to replace files {:?}", + file_names + ); + if self.wait_for_pending_msg(&[ + Msg::PendingAction(PendingActionMsg::CloseReplacePopups), + Msg::PendingAction(PendingActionMsg::TransferPendingFile), + ]) == Msg::PendingAction(PendingActionMsg::TransferPendingFile) + { + trace!("User wants to replace files"); + self.umount_radio_replace(); + true + } else { + trace!("The user doesn't want replace file"); + self.umount_radio_replace(); + false + } } /// Get file to check for path diff --git a/src/ui/activities/filetransfer/components/popups.rs b/src/ui/activities/filetransfer/components/popups.rs index 0f06026..c0ca5c9 100644 --- a/src/ui/activities/filetransfer/components/popups.rs +++ b/src/ui/activities/filetransfer/components/popups.rs @@ -1343,7 +1343,7 @@ impl Component for ReplacePopup { Some(Msg::None) } Event::Keyboard(KeyEvent { code: Key::Esc, .. }) => { - Some(Msg::Ui(UiMsg::CloseReplacePopups)) + Some(Msg::PendingAction(PendingActionMsg::CloseReplacePopups)) } Event::Keyboard(KeyEvent { code: Key::Enter, .. @@ -1352,9 +1352,9 @@ impl Component for ReplacePopup { self.perform(Cmd::Submit), CmdResult::Submit(State::One(StateValue::Usize(0))) ) { - Some(Msg::Transfer(TransferMsg::TransferPendingFile)) + Some(Msg::PendingAction(PendingActionMsg::TransferPendingFile)) } else { - Some(Msg::Ui(UiMsg::CloseReplacePopups)) + Some(Msg::PendingAction(PendingActionMsg::CloseReplacePopups)) } } _ => None, @@ -1393,7 +1393,7 @@ impl Component for ReplacingFilesListPopup { fn on(&mut self, ev: Event) -> Option { match ev { Event::Keyboard(KeyEvent { code: Key::Esc, .. }) => { - Some(Msg::Ui(UiMsg::CloseReplacePopups)) + Some(Msg::PendingAction(PendingActionMsg::CloseReplacePopups)) } Event::Keyboard(KeyEvent { code: Key::Tab, .. }) => { Some(Msg::Ui(UiMsg::ReplacePopupTabbed)) diff --git a/src/ui/activities/filetransfer/lib/transfer.rs b/src/ui/activities/filetransfer/lib/transfer.rs index 6b1659f..2b60969 100644 --- a/src/ui/activities/filetransfer/lib/transfer.rs +++ b/src/ui/activities/filetransfer/lib/transfer.rs @@ -183,20 +183,10 @@ impl ProgressStates { // -- Options /// Defines the transfer options for transfer actions +#[derive(Default)] pub struct TransferOpts { /// Save file as pub save_as: Option, - /// Whether to check if file is being replaced - pub check_replace: bool, -} - -impl Default for TransferOpts { - fn default() -> Self { - Self { - save_as: None, - check_replace: true, - } - } } impl TransferOpts { @@ -205,12 +195,6 @@ impl TransferOpts { self.save_as = n.map(|x| x.as_ref().to_string()); self } - - /// Set whether to check if the file being transferred will "replace" an existing one - pub fn check_replace(mut self, opt: bool) -> Self { - self.check_replace = opt; - self - } } #[cfg(test)] @@ -289,12 +273,8 @@ mod test { #[test] fn transfer_opts() { let opts = TransferOpts::default(); - assert_eq!(opts.check_replace, true); assert!(opts.save_as.is_none()); - let opts = TransferOpts::default() - .check_replace(false) - .save_as(Some("omar.txt")); + let opts = TransferOpts::default().save_as(Some("omar.txt")); assert_eq!(opts.save_as.as_deref().unwrap(), "omar.txt"); - assert_eq!(opts.check_replace, false); } } diff --git a/src/ui/activities/filetransfer/mod.rs b/src/ui/activities/filetransfer/mod.rs index 07860fa..c64783c 100644 --- a/src/ui/activities/filetransfer/mod.rs +++ b/src/ui/activities/filetransfer/mod.rs @@ -58,8 +58,6 @@ use tuirealm::{Application, EventListenerCfg, NoUserEvent}; /// Stores the explorer width const STORAGE_EXPLORER_WIDTH: &str = "FT_EW"; -/// Stores the filename of the entry to transfer, when the replace file dialog must be shown -const STORAGE_PENDING_TRANSFER: &str = "FT_PT"; // -- components @@ -108,8 +106,10 @@ enum Msg { #[derive(Debug, PartialEq)] enum PendingActionMsg { + CloseReplacePopups, CloseSyncBrowsingMkdirPopup, MakePendingDirectory, + TransferPendingFile, } #[derive(Debug, PartialEq)] @@ -132,7 +132,6 @@ enum TransferMsg { SaveFileAs(String), SearchFile(String), TransferFile, - TransferPendingFile, } #[derive(Debug, PartialEq)] @@ -155,7 +154,6 @@ enum UiMsg { CloseNewFilePopup, CloseOpenWithPopup, CloseQuitPopup, - CloseReplacePopups, CloseRenamePopup, CloseSaveAsPopup, Disconnect, diff --git a/src/ui/activities/filetransfer/update.rs b/src/ui/activities/filetransfer/update.rs index 9bb9315..fefb513 100644 --- a/src/ui/activities/filetransfer/update.rs +++ b/src/ui/activities/filetransfer/update.rs @@ -340,10 +340,6 @@ impl FileTransferActivity { } self.update_browser_file_list_swapped(); } - TransferMsg::TransferPendingFile => { - self.umount_radio_replace(); - self.action_finalize_pending_transfer(); - } } // Force redraw self.redraw = true; @@ -411,9 +407,6 @@ impl FileTransferActivity { UiMsg::CloseOpenWithPopup => self.umount_openwith(), UiMsg::CloseQuitPopup => self.umount_quit(), UiMsg::CloseRenamePopup => self.umount_rename(), - UiMsg::CloseReplacePopups => { - self.umount_radio_replace(); - } UiMsg::CloseSaveAsPopup => self.umount_saveas(), UiMsg::Disconnect => { self.disconnect();