mirror of
https://github.com/veeso/termscp.git
synced 2025-12-07 09:36:00 -08:00
Sync browsing prompts to create dir (#85)
This commit is contained in:
@@ -26,84 +26,87 @@
|
||||
* SOFTWARE.
|
||||
*/
|
||||
// locals
|
||||
use super::FileTransferActivity;
|
||||
use super::{FileExplorerTab, FileTransferActivity, LogLevel, Msg, PendingActionMsg};
|
||||
|
||||
use remotefs::Directory;
|
||||
use std::path::PathBuf;
|
||||
|
||||
/// Describes destination for sync browsing
|
||||
enum SyncBrowsingDestination {
|
||||
Path(String),
|
||||
ParentDir,
|
||||
PreviousDir,
|
||||
}
|
||||
|
||||
impl FileTransferActivity {
|
||||
/// Enter a directory on local host from entry
|
||||
/// Return true whether the directory changed
|
||||
pub(crate) fn action_enter_local_dir(&mut self, dir: Directory, block_sync: bool) -> bool {
|
||||
pub(crate) fn action_enter_local_dir(&mut self, dir: Directory) {
|
||||
self.local_changedir(dir.path.as_path(), true);
|
||||
if self.browser.sync_browsing && !block_sync {
|
||||
self.action_change_remote_dir(dir.name, true);
|
||||
if self.browser.sync_browsing {
|
||||
self.synchronize_browsing(SyncBrowsingDestination::Path(dir.name));
|
||||
}
|
||||
true
|
||||
}
|
||||
|
||||
/// Enter a directory on local host from entry
|
||||
/// Return true whether the directory changed
|
||||
pub(crate) fn action_enter_remote_dir(&mut self, dir: Directory, block_sync: bool) -> bool {
|
||||
pub(crate) fn action_enter_remote_dir(&mut self, dir: Directory) {
|
||||
self.remote_changedir(dir.path.as_path(), true);
|
||||
if self.browser.sync_browsing && !block_sync {
|
||||
self.action_change_local_dir(dir.name, true);
|
||||
if self.browser.sync_browsing {
|
||||
self.synchronize_browsing(SyncBrowsingDestination::Path(dir.name));
|
||||
}
|
||||
true
|
||||
}
|
||||
|
||||
/// Change local directory reading value from input
|
||||
pub(crate) fn action_change_local_dir(&mut self, input: String, block_sync: bool) {
|
||||
pub(crate) fn action_change_local_dir(&mut self, input: String) {
|
||||
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 && !block_sync {
|
||||
self.action_change_remote_dir(input, true);
|
||||
if self.browser.sync_browsing {
|
||||
self.synchronize_browsing(SyncBrowsingDestination::Path(input));
|
||||
}
|
||||
}
|
||||
|
||||
/// Change remote directory reading value from input
|
||||
pub(crate) fn action_change_remote_dir(&mut self, input: String, block_sync: bool) {
|
||||
pub(crate) fn action_change_remote_dir(&mut self, input: String) {
|
||||
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 && !block_sync {
|
||||
self.action_change_local_dir(input, true);
|
||||
if self.browser.sync_browsing {
|
||||
self.synchronize_browsing(SyncBrowsingDestination::Path(input));
|
||||
}
|
||||
}
|
||||
|
||||
/// Go to previous directory from localhost
|
||||
pub(crate) fn action_go_to_previous_local_dir(&mut self, block_sync: bool) {
|
||||
pub(crate) fn action_go_to_previous_local_dir(&mut self) {
|
||||
if let Some(d) = self.local_mut().popd() {
|
||||
self.local_changedir(d.as_path(), false);
|
||||
// Check whether to sync
|
||||
if self.browser.sync_browsing && !block_sync {
|
||||
self.action_go_to_previous_remote_dir(true);
|
||||
if self.browser.sync_browsing {
|
||||
self.synchronize_browsing(SyncBrowsingDestination::PreviousDir);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Go to previous directory from remote host
|
||||
pub(crate) fn action_go_to_previous_remote_dir(&mut self, block_sync: bool) {
|
||||
pub(crate) fn action_go_to_previous_remote_dir(&mut self) {
|
||||
if let Some(d) = self.remote_mut().popd() {
|
||||
self.remote_changedir(d.as_path(), false);
|
||||
// Check whether to sync
|
||||
if self.browser.sync_browsing && !block_sync {
|
||||
self.action_go_to_previous_local_dir(true);
|
||||
if self.browser.sync_browsing {
|
||||
self.synchronize_browsing(SyncBrowsingDestination::PreviousDir);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Go to upper directory on local host
|
||||
pub(crate) fn action_go_to_local_upper_dir(&mut self, block_sync: bool) {
|
||||
pub(crate) 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 && !block_sync {
|
||||
self.action_go_to_remote_upper_dir(true);
|
||||
if self.browser.sync_browsing {
|
||||
self.synchronize_browsing(SyncBrowsingDestination::ParentDir);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -111,15 +114,140 @@ impl FileTransferActivity {
|
||||
/// #### action_go_to_remote_upper_dir
|
||||
///
|
||||
/// Go to upper directory on remote host
|
||||
pub(crate) fn action_go_to_remote_upper_dir(&mut self, block_sync: bool) {
|
||||
pub(crate) 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 && !block_sync {
|
||||
self.action_go_to_local_upper_dir(true);
|
||||
if self.browser.sync_browsing {
|
||||
self.synchronize_browsing(SyncBrowsingDestination::ParentDir);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// -- sync browsing
|
||||
|
||||
/// Synchronize browsing on the target browser.
|
||||
/// If destination doesn't exist, then prompt for directory creation.
|
||||
fn synchronize_browsing(&mut self, destination: SyncBrowsingDestination) {
|
||||
// Get destination path
|
||||
let path = match self.resolve_sync_browsing_destination(&destination) {
|
||||
Some(p) => p,
|
||||
None => return,
|
||||
};
|
||||
trace!("Synchronizing browsing to path {}", path.display());
|
||||
// Check whether destination exists on host
|
||||
let exists = match self.browser.tab() {
|
||||
FileExplorerTab::Local => match self.client.exists(path.as_path()) {
|
||||
Ok(e) => e,
|
||||
Err(err) => {
|
||||
error!(
|
||||
"Failed to check whether {} exists on remote: {}",
|
||||
path.display(),
|
||||
err
|
||||
);
|
||||
return;
|
||||
}
|
||||
},
|
||||
FileExplorerTab::Remote => self.host.file_exists(path.as_path()),
|
||||
_ => return,
|
||||
};
|
||||
let name = path
|
||||
.file_name()
|
||||
.map(|x| x.to_string_lossy().to_string())
|
||||
.unwrap();
|
||||
// If file doesn't exist, ask whether to create directory
|
||||
if !exists {
|
||||
trace!("Directory doesn't exist; asking to user if I should create it");
|
||||
// Mount dialog
|
||||
self.mount_sync_browsing_mkdir_popup(&name);
|
||||
// Wait for dialog dismiss
|
||||
if self.wait_for_pending_msg(&[
|
||||
Msg::PendingAction(PendingActionMsg::MakePendingDirectory),
|
||||
Msg::PendingAction(PendingActionMsg::CloseSyncBrowsingMkdirPopup),
|
||||
]) == Msg::PendingAction(PendingActionMsg::MakePendingDirectory)
|
||||
{
|
||||
trace!("User wants to create the unexisting directory");
|
||||
// Make directory
|
||||
match self.browser.tab() {
|
||||
FileExplorerTab::Local => self.action_remote_mkdir(name.clone()),
|
||||
FileExplorerTab::Remote => self.action_local_mkdir(name.clone()),
|
||||
_ => {}
|
||||
}
|
||||
} else {
|
||||
// Do not synchronize, disable sync browsing and return
|
||||
trace!("The user doesn't want to create the directory; disabling synchronized browsing");
|
||||
self.log(
|
||||
LogLevel::Warn,
|
||||
format!(
|
||||
"Refused to create '{}'; synchronized browsing disabled",
|
||||
name
|
||||
),
|
||||
);
|
||||
self.browser.toggle_sync_browsing();
|
||||
self.refresh_remote_status_bar();
|
||||
self.umount_sync_browsing_mkdir_popup();
|
||||
return;
|
||||
}
|
||||
// Umount dialog
|
||||
self.umount_sync_browsing_mkdir_popup();
|
||||
}
|
||||
trace!("Entering on the other explorer directory {}", name);
|
||||
// Enter directory
|
||||
match destination {
|
||||
SyncBrowsingDestination::ParentDir => match self.browser.tab() {
|
||||
FileExplorerTab::Local => self.remote_changedir(path.as_path(), true),
|
||||
FileExplorerTab::Remote => self.local_changedir(path.as_path(), true),
|
||||
_ => {}
|
||||
},
|
||||
SyncBrowsingDestination::Path(_) => match self.browser.tab() {
|
||||
FileExplorerTab::Local => self.remote_changedir(path.as_path(), true),
|
||||
FileExplorerTab::Remote => self.local_changedir(path.as_path(), true),
|
||||
_ => {}
|
||||
},
|
||||
SyncBrowsingDestination::PreviousDir => match self.browser.tab() {
|
||||
FileExplorerTab::Local => self.remote_changedir(path.as_path(), false),
|
||||
FileExplorerTab::Remote => self.local_changedir(path.as_path(), false),
|
||||
_ => {}
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
/// Resolve synchronized browsing destination
|
||||
fn resolve_sync_browsing_destination(
|
||||
&mut self,
|
||||
destination: &SyncBrowsingDestination,
|
||||
) -> Option<PathBuf> {
|
||||
match (destination, self.browser.tab()) {
|
||||
// NOTE: tab and methods are switched on purpose
|
||||
(SyncBrowsingDestination::ParentDir, FileExplorerTab::Local) => {
|
||||
self.remote().wrkdir.parent().map(|x| x.to_path_buf())
|
||||
}
|
||||
(SyncBrowsingDestination::ParentDir, FileExplorerTab::Remote) => {
|
||||
self.local().wrkdir.parent().map(|x| x.to_path_buf())
|
||||
}
|
||||
(SyncBrowsingDestination::PreviousDir, FileExplorerTab::Local) => {
|
||||
if let Some(p) = self.remote_mut().popd() {
|
||||
Some(p)
|
||||
} else {
|
||||
warn!("Cannot synchronize browsing: remote has no previous directory in stack");
|
||||
None
|
||||
}
|
||||
}
|
||||
(SyncBrowsingDestination::PreviousDir, FileExplorerTab::Remote) => {
|
||||
if let Some(p) = self.local_mut().popd() {
|
||||
Some(p)
|
||||
} else {
|
||||
warn!("Cannot synchronize browsing: local has no previous directory in stack");
|
||||
None
|
||||
}
|
||||
}
|
||||
(SyncBrowsingDestination::Path(p), _) => Some(PathBuf::from(p.as_str())),
|
||||
_ => {
|
||||
warn!("Cannot synchronize browsing for current explorer");
|
||||
None
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -26,7 +26,8 @@
|
||||
* SOFTWARE.
|
||||
*/
|
||||
pub(self) use super::{
|
||||
browser::FileExplorerTab, FileTransferActivity, Id, LogLevel, TransferOpts, TransferPayload,
|
||||
browser::FileExplorerTab, FileTransferActivity, Id, LogLevel, Msg, PendingActionMsg,
|
||||
TransferOpts, TransferPayload,
|
||||
};
|
||||
pub(self) use remotefs::Entry;
|
||||
use tuirealm::{State, StateValue};
|
||||
@@ -41,6 +42,7 @@ pub(crate) mod find;
|
||||
pub(crate) mod mkdir;
|
||||
pub(crate) mod newfile;
|
||||
pub(crate) mod open;
|
||||
mod pending;
|
||||
pub(crate) mod rename;
|
||||
pub(crate) mod save;
|
||||
pub(crate) mod submit;
|
||||
|
||||
63
src/ui/activities/filetransfer/actions/pending.rs
Normal file
63
src/ui/activities/filetransfer/actions/pending.rs
Normal file
@@ -0,0 +1,63 @@
|
||||
//! ## Pending actions
|
||||
//!
|
||||
//! this little module exposes the routine to create a pending action on the file transfer activity.
|
||||
//! A pending action is an action which blocks the execution of the application in await of a certain `Msg`.
|
||||
|
||||
/**
|
||||
* MIT License
|
||||
*
|
||||
* termscp - Copyright (c) 2021 Christian Visintin
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
use super::{FileTransferActivity, Msg};
|
||||
|
||||
use tuirealm::PollStrategy;
|
||||
|
||||
impl FileTransferActivity {
|
||||
/// Block execution of activity, preventing ANY kind of message not specified in the `wait_for` argument.
|
||||
/// Once `wait_for` clause is satisfied, the function returns.
|
||||
///
|
||||
/// Returns the message which satisfied the clause
|
||||
///
|
||||
/// NOTE: The view is redrawn as usual
|
||||
pub(super) fn wait_for_pending_msg(&mut self, wait_for: &[Msg]) -> Msg {
|
||||
self.redraw = true;
|
||||
loop {
|
||||
// Poll
|
||||
match self.app.tick(PollStrategy::Once) {
|
||||
Ok(messages) => {
|
||||
if !messages.is_empty() {
|
||||
self.redraw = true;
|
||||
}
|
||||
if let Some(msg) = messages.into_iter().find(|m| wait_for.contains(m)) {
|
||||
return msg;
|
||||
}
|
||||
}
|
||||
Err(err) => {
|
||||
error!("Application error: {}", err);
|
||||
}
|
||||
}
|
||||
// Redraw
|
||||
if self.redraw {
|
||||
self.view();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -38,7 +38,7 @@ enum SubmitAction {
|
||||
impl FileTransferActivity {
|
||||
/// Decides which action to perform on submit for local explorer
|
||||
/// Return true whether the directory changed
|
||||
pub(crate) fn action_submit_local(&mut self, entry: Entry) -> bool {
|
||||
pub(crate) fn action_submit_local(&mut self, entry: Entry) {
|
||||
let (action, entry) = match &entry {
|
||||
Entry::Directory(_) => (SubmitAction::ChangeDir, entry),
|
||||
Entry::File(File {
|
||||
@@ -67,18 +67,14 @@ impl FileTransferActivity {
|
||||
}
|
||||
Entry::File(_) => (SubmitAction::None, entry),
|
||||
};
|
||||
match (action, entry) {
|
||||
(SubmitAction::ChangeDir, Entry::Directory(dir)) => {
|
||||
self.action_enter_local_dir(dir, false)
|
||||
}
|
||||
(SubmitAction::ChangeDir, _) => false,
|
||||
(SubmitAction::None, _) => false,
|
||||
if let (SubmitAction::ChangeDir, Entry::Directory(dir)) = (action, entry) {
|
||||
self.action_enter_local_dir(dir)
|
||||
}
|
||||
}
|
||||
|
||||
/// Decides which action to perform on submit for remote explorer
|
||||
/// Return true whether the directory changed
|
||||
pub(crate) fn action_submit_remote(&mut self, entry: Entry) -> bool {
|
||||
pub(crate) fn action_submit_remote(&mut self, entry: Entry) {
|
||||
let (action, entry) = match &entry {
|
||||
Entry::Directory(_) => (SubmitAction::ChangeDir, entry),
|
||||
Entry::File(File {
|
||||
@@ -107,12 +103,8 @@ impl FileTransferActivity {
|
||||
}
|
||||
Entry::File(_) => (SubmitAction::None, entry),
|
||||
};
|
||||
match (action, entry) {
|
||||
(SubmitAction::ChangeDir, Entry::Directory(dir)) => {
|
||||
self.action_enter_remote_dir(dir, false)
|
||||
}
|
||||
(SubmitAction::ChangeDir, _) => false,
|
||||
(SubmitAction::None, _) => false,
|
||||
if let (SubmitAction::ChangeDir, Entry::Directory(dir)) = (action, entry) {
|
||||
self.action_enter_remote_dir(dir)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -25,7 +25,7 @@
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
use super::{Msg, TransferMsg, UiMsg};
|
||||
use super::{Msg, PendingActionMsg, TransferMsg, UiMsg};
|
||||
|
||||
use tui_realm_stdlib::Phantom;
|
||||
use tuirealm::{
|
||||
@@ -45,7 +45,8 @@ pub use popups::{
|
||||
CopyPopup, DeletePopup, DisconnectPopup, ErrorPopup, ExecPopup, FatalPopup, FileInfoPopup,
|
||||
FindPopup, GoToPopup, KeybindingsPopup, MkdirPopup, NewfilePopup, OpenWithPopup,
|
||||
ProgressBarFull, ProgressBarPartial, QuitPopup, RenamePopup, ReplacePopup,
|
||||
ReplacingFilesListPopup, SaveAsPopup, SortingPopup, StatusBarLocal, StatusBarRemote, WaitPopup,
|
||||
ReplacingFilesListPopup, SaveAsPopup, SortingPopup, StatusBarLocal, StatusBarRemote,
|
||||
SyncBrowsingMkdirPopup, WaitPopup,
|
||||
};
|
||||
pub use transfer::{ExplorerFind, ExplorerLocal, ExplorerRemote};
|
||||
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
* SOFTWARE.
|
||||
*/
|
||||
use super::super::Browser;
|
||||
use super::{Msg, TransferMsg, UiMsg};
|
||||
use super::{Msg, PendingActionMsg, TransferMsg, UiMsg};
|
||||
use crate::explorer::FileSorting;
|
||||
use crate::utils::fmt::fmt_time;
|
||||
|
||||
@@ -1657,6 +1657,70 @@ fn hidden_files_label(visible: bool) -> &'static str {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(MockComponent)]
|
||||
pub struct SyncBrowsingMkdirPopup {
|
||||
component: Radio,
|
||||
}
|
||||
|
||||
impl SyncBrowsingMkdirPopup {
|
||||
pub fn new(color: Color, dir_name: &str) -> Self {
|
||||
Self {
|
||||
component: Radio::default()
|
||||
.borders(
|
||||
Borders::default()
|
||||
.color(color)
|
||||
.modifiers(BorderType::Rounded),
|
||||
)
|
||||
.foreground(color)
|
||||
.choices(&["Yes", "No"])
|
||||
.title(
|
||||
format!(
|
||||
r#"Sync browsing: directory "{}" doesn't exist. Do you want to create it?"#,
|
||||
dir_name
|
||||
),
|
||||
Alignment::Center,
|
||||
),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Component<Msg, NoUserEvent> for SyncBrowsingMkdirPopup {
|
||||
fn on(&mut self, ev: Event<NoUserEvent>) -> Option<Msg> {
|
||||
match ev {
|
||||
Event::Keyboard(KeyEvent {
|
||||
code: Key::Left, ..
|
||||
}) => {
|
||||
self.perform(Cmd::Move(Direction::Left));
|
||||
Some(Msg::None)
|
||||
}
|
||||
Event::Keyboard(KeyEvent {
|
||||
code: Key::Right, ..
|
||||
}) => {
|
||||
self.perform(Cmd::Move(Direction::Right));
|
||||
Some(Msg::None)
|
||||
}
|
||||
Event::Keyboard(KeyEvent { code: Key::Esc, .. }) => Some(Msg::PendingAction(
|
||||
PendingActionMsg::CloseSyncBrowsingMkdirPopup,
|
||||
)),
|
||||
Event::Keyboard(KeyEvent {
|
||||
code: Key::Enter, ..
|
||||
}) => {
|
||||
if matches!(
|
||||
self.perform(Cmd::Submit),
|
||||
CmdResult::Submit(State::One(StateValue::Usize(0)))
|
||||
) {
|
||||
Some(Msg::PendingAction(PendingActionMsg::MakePendingDirectory))
|
||||
} else {
|
||||
Some(Msg::PendingAction(
|
||||
PendingActionMsg::CloseSyncBrowsingMkdirPopup,
|
||||
))
|
||||
}
|
||||
}
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(MockComponent)]
|
||||
pub struct WaitPopup {
|
||||
component: Paragraph,
|
||||
|
||||
@@ -56,8 +56,10 @@ use tuirealm::{Application, EventListenerCfg, NoUserEvent};
|
||||
|
||||
// -- Storage keys
|
||||
|
||||
const STORAGE_EXPLORER_WIDTH: &str = "FILETRANSFER_EXPLORER_WIDTH";
|
||||
const STORAGE_PENDING_TRANSFER: &str = "FILETRANSFER_PENDING_TRANSFER";
|
||||
/// 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
|
||||
|
||||
@@ -92,16 +94,24 @@ enum Id {
|
||||
SortingPopup,
|
||||
StatusBarLocal,
|
||||
StatusBarRemote,
|
||||
SyncBrowsingMkdirPopup,
|
||||
WaitPopup,
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq)]
|
||||
enum Msg {
|
||||
PendingAction(PendingActionMsg),
|
||||
Transfer(TransferMsg),
|
||||
Ui(UiMsg),
|
||||
None,
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq)]
|
||||
enum PendingActionMsg {
|
||||
CloseSyncBrowsingMkdirPopup,
|
||||
MakePendingDirectory,
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq)]
|
||||
enum TransferMsg {
|
||||
AbortTransfer,
|
||||
|
||||
@@ -42,6 +42,10 @@ impl Update<Msg> for FileTransferActivity {
|
||||
fn update(&mut self, msg: Option<Msg>) -> Option<Msg> {
|
||||
match msg.unwrap_or(Msg::None) {
|
||||
Msg::None => None,
|
||||
Msg::PendingAction(_) => {
|
||||
// NOTE: Pending actions must be handled directly in the action
|
||||
None
|
||||
}
|
||||
Msg::Transfer(msg) => self.update_transfer(msg),
|
||||
Msg::Ui(msg) => self.update_ui(msg),
|
||||
}
|
||||
@@ -106,24 +110,22 @@ impl FileTransferActivity {
|
||||
}
|
||||
TransferMsg::EnterDirectory if self.browser.tab() == FileExplorerTab::Local => {
|
||||
if let SelectedEntry::One(entry) = self.get_local_selected_entries() {
|
||||
if self.action_submit_local(entry) {
|
||||
// Update file list if sync
|
||||
if self.browser.sync_browsing {
|
||||
let _ = self.update_remote_filelist();
|
||||
}
|
||||
self.update_local_filelist();
|
||||
self.action_submit_local(entry);
|
||||
// Update file list if sync
|
||||
if self.browser.sync_browsing {
|
||||
let _ = self.update_remote_filelist();
|
||||
}
|
||||
self.update_local_filelist();
|
||||
}
|
||||
}
|
||||
TransferMsg::EnterDirectory if self.browser.tab() == FileExplorerTab::Remote => {
|
||||
if let SelectedEntry::One(entry) = self.get_remote_selected_entries() {
|
||||
if self.action_submit_remote(entry) {
|
||||
// Update file list if sync
|
||||
if self.browser.sync_browsing {
|
||||
let _ = self.update_local_filelist();
|
||||
}
|
||||
self.update_remote_filelist();
|
||||
self.action_submit_remote(entry);
|
||||
// Update file list if sync
|
||||
if self.browser.sync_browsing {
|
||||
let _ = self.update_local_filelist();
|
||||
}
|
||||
self.update_remote_filelist();
|
||||
}
|
||||
}
|
||||
TransferMsg::EnterDirectory => {
|
||||
@@ -152,8 +154,8 @@ impl FileTransferActivity {
|
||||
}
|
||||
TransferMsg::GoTo(dir) => {
|
||||
match self.browser.tab() {
|
||||
FileExplorerTab::Local => self.action_change_local_dir(dir, false),
|
||||
FileExplorerTab::Remote => self.action_change_remote_dir(dir, false),
|
||||
FileExplorerTab::Local => self.action_change_local_dir(dir),
|
||||
FileExplorerTab::Remote => self.action_change_remote_dir(dir),
|
||||
_ => panic!("Found tab doesn't support GOTO"),
|
||||
}
|
||||
// Umount
|
||||
@@ -168,7 +170,7 @@ impl FileTransferActivity {
|
||||
TransferMsg::GoToParentDirectory => {
|
||||
match self.browser.tab() {
|
||||
FileExplorerTab::Local => {
|
||||
self.action_go_to_local_upper_dir(false);
|
||||
self.action_go_to_local_upper_dir();
|
||||
if self.browser.sync_browsing {
|
||||
let _ = self.update_remote_filelist();
|
||||
}
|
||||
@@ -176,7 +178,7 @@ impl FileTransferActivity {
|
||||
self.update_local_filelist()
|
||||
}
|
||||
FileExplorerTab::Remote => {
|
||||
self.action_go_to_remote_upper_dir(false);
|
||||
self.action_go_to_remote_upper_dir();
|
||||
if self.browser.sync_browsing {
|
||||
let _ = self.update_local_filelist();
|
||||
}
|
||||
@@ -189,7 +191,7 @@ impl FileTransferActivity {
|
||||
TransferMsg::GoToPreviousDirectory => {
|
||||
match self.browser.tab() {
|
||||
FileExplorerTab::Local => {
|
||||
self.action_go_to_previous_local_dir(false);
|
||||
self.action_go_to_previous_local_dir();
|
||||
if self.browser.sync_browsing {
|
||||
let _ = self.update_remote_filelist();
|
||||
}
|
||||
@@ -197,7 +199,7 @@ impl FileTransferActivity {
|
||||
self.update_local_filelist()
|
||||
}
|
||||
FileExplorerTab::Remote => {
|
||||
self.action_go_to_previous_remote_dir(false);
|
||||
self.action_go_to_previous_remote_dir();
|
||||
if self.browser.sync_browsing {
|
||||
let _ = self.update_local_filelist();
|
||||
}
|
||||
|
||||
@@ -307,6 +307,11 @@ impl FileTransferActivity {
|
||||
f.render_widget(Clear, popup);
|
||||
// make popup
|
||||
self.app.view(&Id::WaitPopup, f, popup);
|
||||
} else if self.app.mounted(&Id::SyncBrowsingMkdirPopup) {
|
||||
let popup = draw_area_in(f.size(), 60, 10);
|
||||
f.render_widget(Clear, popup);
|
||||
// make popup
|
||||
self.app.view(&Id::SyncBrowsingMkdirPopup, f, popup);
|
||||
} else if self.app.mounted(&Id::KeybindingsPopup) {
|
||||
let popup = draw_area_in(f.size(), 50, 80);
|
||||
f.render_widget(Clear, popup);
|
||||
@@ -798,6 +803,23 @@ impl FileTransferActivity {
|
||||
.is_ok());
|
||||
}
|
||||
|
||||
pub(super) fn mount_sync_browsing_mkdir_popup(&mut self, dir_name: &str) {
|
||||
let color = self.theme().misc_info_dialog;
|
||||
assert!(self
|
||||
.app
|
||||
.remount(
|
||||
Id::SyncBrowsingMkdirPopup,
|
||||
Box::new(components::SyncBrowsingMkdirPopup::new(color, dir_name,)),
|
||||
vec![],
|
||||
)
|
||||
.is_ok());
|
||||
assert!(self.app.active(&Id::SyncBrowsingMkdirPopup).is_ok());
|
||||
}
|
||||
|
||||
pub(super) fn umount_sync_browsing_mkdir_popup(&mut self) {
|
||||
let _ = self.app.umount(&Id::SyncBrowsingMkdirPopup);
|
||||
}
|
||||
|
||||
/// Mount help
|
||||
pub(super) fn mount_help(&mut self) {
|
||||
let key_color = self.theme().misc_keys;
|
||||
@@ -949,9 +971,14 @@ impl FileTransferActivity {
|
||||
Box::new(SubClause::Not(Box::new(SubClause::IsMounted(
|
||||
Id::FindPopup,
|
||||
)))),
|
||||
Box::new(SubClause::Not(Box::new(SubClause::IsMounted(
|
||||
Id::WaitPopup,
|
||||
)))),
|
||||
Box::new(SubClause::And(
|
||||
Box::new(SubClause::Not(Box::new(SubClause::IsMounted(
|
||||
Id::SyncBrowsingMkdirPopup,
|
||||
)))),
|
||||
Box::new(SubClause::Not(Box::new(SubClause::IsMounted(
|
||||
Id::WaitPopup,
|
||||
)))),
|
||||
)),
|
||||
)),
|
||||
)),
|
||||
)),
|
||||
|
||||
Reference in New Issue
Block a user