Sync browsing prompts to create dir (#85)

This commit is contained in:
Christian Visintin
2021-12-12 20:41:10 +01:00
parent a93dbde0c8
commit 54c23079be
16 changed files with 361 additions and 82 deletions

View File

@@ -62,6 +62,8 @@ Released on FIXME:
- **Less verbose logging**:
- By default the log level is now set to `INFO`
- It is now possible to enable the `TRACE` level with the `-D` CLI option.
- **Synchronized browsing**:
- From now on, if synchronized browsing is *enabled* and you try to enter a directory that doesn't exist on the other host, you will be asked whether you'd like to create the directory.
- Dependencies:
- Updated `tui-realm` to `1.3.0`
- Updated `tui-realm-stdlib` to `1.1.4`

View File

@@ -201,8 +201,6 @@ All the actions are available when working with multiple files, but be aware tha
When enabled, synchronized browsing, will allow you to synchronize the navigation between the two panels.
This means that whenever you'll change the working directory on one panel, the same action will be reproduced on the other panel. If you want to enable synchronized browsing just press `<Y>`; press twice to disable. While enabled, the synchronized browsing state will be reported on the status bar on `ON`.
> ❗ at the moment, whenever you try to access an unexisting directory, you won't be prompted to create it. This might change in a future update.
### Open and Open With 🚪
Open and open with commands are powered by [open-rs](https://docs.rs/crate/open/1.7.0).

View File

@@ -201,8 +201,6 @@ Todas las acciones están disponibles cuando se trabaja con varios archivos, per
Cuando está habilitada, la navegación sincronizada le permitirá sincronizar la navegación entre los dos paneles.
Esto significa que siempre que cambie el directorio de trabajo en un panel, la misma acción se reproducirá en el otro panel. Si desea habilitar la navegación sincronizada, simplemente presione `<Y>`; presione dos veces para deshabilitar. Mientras está habilitado, el estado de navegación sincronizada se informará en la barra de estado en "ON".
> ❗ Por el momento, cada vez que intente acceder a un directorio que no existe, no se le pedirá que lo cree. Esto podría cambiar en una actualización futura.
### Abierta y abierta con 🚪
Al abrir archivos con el comando Ver (`<V>`), se utilizará la aplicación predeterminada del sistema para el tipo de archivo. Para hacerlo, se utilizará el servicio del sistema operativo predeterminado, así que asegúrese de tener al menos uno de estos instalado en su sistema:

View File

@@ -199,8 +199,6 @@ Toutes les actions sont disponibles lorsque vous travaillez avec plusieurs fichi
Lorsqu'elle est activée, la navigation synchronisée vous permettra de synchroniser la navigation entre les deux panneaux.
Cela signifie que chaque fois que vous changerez de répertoire de travail sur un panneau, la même action sera reproduite sur l'autre panneau. Si vous souhaitez activer la navigation synchronisée, appuyez simplement sur `<Y>` ; appuyez deux fois pour désactiver. Lorsqu'il est activé, l'état de navigation synchronisé sera signalé dans la barre d'état sur `ON`
> ❗ pour le moment, chaque fois que vous essayez d'accéder à un répertoire inexistant, vous ne serez pas invité à le créer. Cela pourrait changer dans une future mise à jour.
### Ouvrir et ouvrir avec 🚪
Lors de l'ouverture de fichiers avec la commande Afficher (`<V>`), l'application par défaut du système pour le type de fichier sera utilisée. Pour ce faire, le service du système d'exploitation par défaut sera utilisé, alors assurez-vous d'avoir au moins l'un de ceux-ci installé sur votre système :

View File

@@ -195,8 +195,6 @@ Tutte le azioni sono disponibili quando si lavora sulle selezioni, ma occhio, ch
Quando abilitato, ti permetterà di sincronizzare la navigazione tra i due pannelli.
Ciò comporta che quando cambierai directory in uno dei due pannelli, lo stesso verrà fatto nell'altro. Per abilitare la modalità è sufficiente premere `<Y>`; fai lo stesso per disabilitarlo. Mentre abilitato, sull'interfaccia dovrebbe essere visualizzato `Sync Browsing: ON` nella barra di stato.
> ❗ Al momento, se provi ad accedere ad una cartella non esistente su uno dei due host, mentre il sync browsing è attivo, non ti verrà chiesto di crearla, ma semplicemente fallirà. Questo sarà risolto in un aggiornamento futuro.
### Apri e apri con 🚪
I comandi "apri" e "apri con" sono forniti da [open-rs](https://docs.rs/crate/open/2.1.0).

View File

@@ -199,8 +199,6 @@ All the actions are available when working with multiple files, but be aware tha
When enabled, synchronized browsing, will allow you to synchronize the navigation between the two panels.
This means that whenever you'll change the working directory on one panel, the same action will be reproduced on the other panel. If you want to enable synchronized browsing just press `<Y>`; press twice to disable. While enabled, the synchronized browsing state will be reported on the status bar on `ON`.
> ❗ at the moment, whenever you try to access an unexisting directory, you won't be prompted to create it. This might change in a future update.
### Open and Open With 🚪
Open and open with commands are powered by [open-rs](https://docs.rs/crate/open/1.7.0).

View File

@@ -193,8 +193,6 @@ termscp中的文件资源管理器是指你与远程建立连接后可以看到
启用时,同步浏览将允许你在两个面板之间同步导航操作。这意味着,每当你在一个面板上改变工作目录时,同样的动作会在另一个面板上重现。如果你想启用同步浏览,只需按下`<Y>`;按两次就可以禁用。当启用时,同步浏览的状态将在状态栏上显示为`ON`。
> ❗ 目前,每当你试图访问一个不存在的目录,你不会被提示创建它。这点可能会在未来的更新中改进。
### 打开/打开方式
打开和打开方式的功能是由 [open-rs](https://docs.rs/crate/open/2.1.0)提供的。

View File

@@ -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
}
}
}

View File

@@ -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;

View 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();
}
}
}
}

View File

@@ -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)
}
}
}

View File

@@ -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};

View File

@@ -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,

View File

@@ -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,

View File

@@ -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();
}

View File

@@ -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,
)))),
)),
)),
)),
)),