mirror of
https://github.com/veeso/termscp.git
synced 2025-12-07 09:36:00 -08:00
Show a 'wait' message when deleting, copying and moving files and when executing commands
This commit is contained in:
@@ -45,6 +45,8 @@ Released on FIXME: ??
|
|||||||
- **Installation script**:
|
- **Installation script**:
|
||||||
- From now on, in case cargo is used to install termscp, all the cargo dependencies will be installed
|
- From now on, in case cargo is used to install termscp, all the cargo dependencies will be installed
|
||||||
- **Start termscp from configuration**: Start termscp with `-c` or `--config` to start termscp from configuration page
|
- **Start termscp from configuration**: Start termscp with `-c` or `--config` to start termscp from configuration page
|
||||||
|
- Enhancements:
|
||||||
|
- Show a "wait" message when deleting, copying and moving files and when executing commands
|
||||||
- Bugfix:
|
- Bugfix:
|
||||||
- Fixed broken input cursor when typing UTF8 characters (tui-realm 0.3.2)
|
- Fixed broken input cursor when typing UTF8 characters (tui-realm 0.3.2)
|
||||||
- Fixed save bookmark dialog: you could switch out from dialog with `<TAB>`
|
- Fixed save bookmark dialog: you could switch out from dialog with `<TAB>`
|
||||||
|
|||||||
@@ -366,12 +366,14 @@ impl Update for FileTransferActivity {
|
|||||||
}
|
}
|
||||||
(COMPONENT_INPUT_COPY, Msg::OnSubmit(Payload::One(Value::Str(input)))) => {
|
(COMPONENT_INPUT_COPY, Msg::OnSubmit(Payload::One(Value::Str(input)))) => {
|
||||||
// Copy file
|
// Copy file
|
||||||
|
self.umount_copy();
|
||||||
|
self.mount_blocking_wait("Copying file(s)…");
|
||||||
match self.browser.tab() {
|
match self.browser.tab() {
|
||||||
FileExplorerTab::Local => self.action_local_copy(input.to_string()),
|
FileExplorerTab::Local => self.action_local_copy(input.to_string()),
|
||||||
FileExplorerTab::Remote => self.action_remote_copy(input.to_string()),
|
FileExplorerTab::Remote => self.action_remote_copy(input.to_string()),
|
||||||
_ => panic!("Found tab doesn't support COPY"),
|
_ => panic!("Found tab doesn't support COPY"),
|
||||||
}
|
}
|
||||||
self.umount_copy();
|
self.umount_wait();
|
||||||
// Reload files
|
// Reload files
|
||||||
match self.browser.tab() {
|
match self.browser.tab() {
|
||||||
FileExplorerTab::Local => self.update_local_filelist(),
|
FileExplorerTab::Local => self.update_local_filelist(),
|
||||||
@@ -387,12 +389,14 @@ impl Update for FileTransferActivity {
|
|||||||
}
|
}
|
||||||
(COMPONENT_INPUT_EXEC, Msg::OnSubmit(Payload::One(Value::Str(input)))) => {
|
(COMPONENT_INPUT_EXEC, Msg::OnSubmit(Payload::One(Value::Str(input)))) => {
|
||||||
// Exex command
|
// Exex command
|
||||||
|
self.umount_exec();
|
||||||
|
self.mount_blocking_wait(format!("Executing '{}'…", input).as_str());
|
||||||
match self.browser.tab() {
|
match self.browser.tab() {
|
||||||
FileExplorerTab::Local => self.action_local_exec(input.to_string()),
|
FileExplorerTab::Local => self.action_local_exec(input.to_string()),
|
||||||
FileExplorerTab::Remote => self.action_remote_exec(input.to_string()),
|
FileExplorerTab::Remote => self.action_remote_exec(input.to_string()),
|
||||||
_ => panic!("Found tab doesn't support EXEC"),
|
_ => panic!("Found tab doesn't support EXEC"),
|
||||||
}
|
}
|
||||||
self.umount_exec();
|
self.umount_wait();
|
||||||
// Reload files
|
// Reload files
|
||||||
match self.browser.tab() {
|
match self.browser.tab() {
|
||||||
FileExplorerTab::Local => self.update_local_filelist(),
|
FileExplorerTab::Local => self.update_local_filelist(),
|
||||||
@@ -532,12 +536,14 @@ impl Update for FileTransferActivity {
|
|||||||
None
|
None
|
||||||
}
|
}
|
||||||
(COMPONENT_INPUT_RENAME, Msg::OnSubmit(Payload::One(Value::Str(input)))) => {
|
(COMPONENT_INPUT_RENAME, Msg::OnSubmit(Payload::One(Value::Str(input)))) => {
|
||||||
|
self.umount_rename();
|
||||||
|
self.mount_blocking_wait("Moving file(s)…");
|
||||||
match self.browser.tab() {
|
match self.browser.tab() {
|
||||||
FileExplorerTab::Local => self.action_local_rename(input.to_string()),
|
FileExplorerTab::Local => self.action_local_rename(input.to_string()),
|
||||||
FileExplorerTab::Remote => self.action_remote_rename(input.to_string()),
|
FileExplorerTab::Remote => self.action_remote_rename(input.to_string()),
|
||||||
_ => panic!("Found tab doesn't support RENAME"),
|
_ => panic!("Found tab doesn't support RENAME"),
|
||||||
}
|
}
|
||||||
self.umount_rename();
|
self.umount_wait();
|
||||||
// Reload files
|
// Reload files
|
||||||
match self.browser.tab() {
|
match self.browser.tab() {
|
||||||
FileExplorerTab::Local => self.update_local_filelist(),
|
FileExplorerTab::Local => self.update_local_filelist(),
|
||||||
@@ -586,6 +592,8 @@ impl Update for FileTransferActivity {
|
|||||||
}
|
}
|
||||||
(COMPONENT_RADIO_DELETE, Msg::OnSubmit(Payload::One(Value::Usize(0)))) => {
|
(COMPONENT_RADIO_DELETE, Msg::OnSubmit(Payload::One(Value::Usize(0)))) => {
|
||||||
// Choice is 'YES'
|
// Choice is 'YES'
|
||||||
|
self.umount_radio_delete();
|
||||||
|
self.mount_blocking_wait("Removing file(s)…");
|
||||||
match self.browser.tab() {
|
match self.browser.tab() {
|
||||||
FileExplorerTab::Local => self.action_local_delete(),
|
FileExplorerTab::Local => self.action_local_delete(),
|
||||||
FileExplorerTab::Remote => self.action_remote_delete(),
|
FileExplorerTab::Remote => self.action_remote_delete(),
|
||||||
@@ -612,7 +620,7 @@ impl Update for FileTransferActivity {
|
|||||||
self.update_find_list();
|
self.update_find_list();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
self.umount_radio_delete();
|
self.umount_wait();
|
||||||
// Reload files
|
// Reload files
|
||||||
match self.browser.tab() {
|
match self.browser.tab() {
|
||||||
FileExplorerTab::Local => self.update_local_filelist(),
|
FileExplorerTab::Local => self.update_local_filelist(),
|
||||||
@@ -906,7 +914,7 @@ impl FileTransferActivity {
|
|||||||
/// ### elide_wrkdir_path
|
/// ### elide_wrkdir_path
|
||||||
///
|
///
|
||||||
/// Elide working directory path if longer than width + host.len
|
/// Elide working directory path if longer than width + host.len
|
||||||
/// In this case, the path is formatted to {ANCESTOR[0]}/.../{PARENT[0]}/{BASENAME}
|
/// In this case, the path is formatted to {ANCESTOR[0]}/…/{PARENT[0]}/{BASENAME}
|
||||||
fn elide_wrkdir_path(wrkdir: &Path, host: &str, width: usize) -> PathBuf {
|
fn elide_wrkdir_path(wrkdir: &Path, host: &str, width: usize) -> PathBuf {
|
||||||
let fmt_path: String = format!("{}", wrkdir.display());
|
let fmt_path: String = format!("{}", wrkdir.display());
|
||||||
// NOTE: +5 is const
|
// NOTE: +5 is const
|
||||||
@@ -921,9 +929,9 @@ impl FileTransferActivity {
|
|||||||
if ancestors_len > 2 {
|
if ancestors_len > 2 {
|
||||||
elided_path.push(ancestors.nth(ancestors_len - 2).unwrap());
|
elided_path.push(ancestors.nth(ancestors_len - 2).unwrap());
|
||||||
}
|
}
|
||||||
// If ancestors_len is bigger than 3, push '...' and parent too
|
// If ancestors_len is bigger than 3, push '…' and parent too
|
||||||
if ancestors_len > 3 {
|
if ancestors_len > 3 {
|
||||||
elided_path.push("...");
|
elided_path.push("…");
|
||||||
if let Some(parent) = wrkdir.ancestors().nth(1) {
|
if let Some(parent) = wrkdir.ancestors().nth(1) {
|
||||||
elided_path.push(parent.file_name().unwrap());
|
elided_path.push(parent.file_name().unwrap());
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -422,17 +422,28 @@ impl FileTransferActivity {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub(super) fn mount_wait(&mut self, text: &str) {
|
pub(super) fn mount_wait(&mut self, text: &str) {
|
||||||
|
self.mount_wait_ex(text, false, Color::Reset);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(super) fn mount_blocking_wait(&mut self, text: &str) {
|
||||||
|
self.mount_wait_ex(text, true, Color::Reset);
|
||||||
|
self.view();
|
||||||
|
}
|
||||||
|
|
||||||
|
fn mount_wait_ex(&mut self, text: &str, blink: bool, color: Color) {
|
||||||
// Mount
|
// Mount
|
||||||
|
let mut builder: MsgBoxPropsBuilder = MsgBoxPropsBuilder::default();
|
||||||
|
builder
|
||||||
|
.with_foreground(color)
|
||||||
|
.with_borders(Borders::ALL, BorderType::Rounded, Color::White)
|
||||||
|
.bold()
|
||||||
|
.with_texts(None, vec![TextSpan::from(text)]);
|
||||||
|
if blink {
|
||||||
|
builder.blink();
|
||||||
|
}
|
||||||
self.view.mount(
|
self.view.mount(
|
||||||
super::COMPONENT_TEXT_WAIT,
|
super::COMPONENT_TEXT_WAIT,
|
||||||
Box::new(MsgBox::new(
|
Box::new(MsgBox::new(builder.build())),
|
||||||
MsgBoxPropsBuilder::default()
|
|
||||||
.with_foreground(Color::White)
|
|
||||||
.with_borders(Borders::ALL, BorderType::Rounded, Color::White)
|
|
||||||
.bold()
|
|
||||||
.with_texts(None, vec![TextSpan::from(text)])
|
|
||||||
.build(),
|
|
||||||
)),
|
|
||||||
);
|
);
|
||||||
// Give focus to info
|
// Give focus to info
|
||||||
self.view.active(super::COMPONENT_TEXT_WAIT);
|
self.view.active(super::COMPONENT_TEXT_WAIT);
|
||||||
|
|||||||
@@ -94,6 +94,13 @@ impl MsgBoxPropsBuilder {
|
|||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn blink(&mut self) -> &mut Self {
|
||||||
|
if let Some(props) = self.props.as_mut() {
|
||||||
|
props.modifiers |= Modifier::SLOW_BLINK;
|
||||||
|
}
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
pub fn with_borders(
|
pub fn with_borders(
|
||||||
&mut self,
|
&mut self,
|
||||||
borders: Borders,
|
borders: Borders,
|
||||||
@@ -221,6 +228,7 @@ mod tests {
|
|||||||
.visible()
|
.visible()
|
||||||
.with_foreground(Color::Red)
|
.with_foreground(Color::Red)
|
||||||
.bold()
|
.bold()
|
||||||
|
.blink()
|
||||||
.with_borders(Borders::ALL, BorderType::Double, Color::Red)
|
.with_borders(Borders::ALL, BorderType::Double, Color::Red)
|
||||||
.with_texts(
|
.with_texts(
|
||||||
None,
|
None,
|
||||||
|
|||||||
Reference in New Issue
Block a user