mirror of
https://github.com/veeso/termscp.git
synced 2025-12-07 09:36:00 -08:00
Abort upload/download pressing Ctrl+C
This commit is contained in:
@@ -9,12 +9,13 @@
|
||||
|
||||
## 0.1.2
|
||||
|
||||
Released on ??
|
||||
Released on 13/12/2020
|
||||
|
||||
- General performance and code improvements
|
||||
- Improved symlinks management
|
||||
- Keybindings:
|
||||
- `E`: Delete file (Same as `DEL`); added because some keyboards don't have `DEL` (hey, that's my MacBook Air's keyboard!)
|
||||
- `Ctrl+C`: Abort transfer process
|
||||
|
||||
## 0.1.1
|
||||
|
||||
|
||||
@@ -202,6 +202,7 @@ Password can be basically provided through 3 ways when address argument is provi
|
||||
| `<R>` | Rename file |
|
||||
| `<U>` | Go to parent directory |
|
||||
| `<DEL>` | Delete file |
|
||||
| `CTRL+C` | Abort file transfer process |
|
||||
|
||||
---
|
||||
|
||||
|
||||
@@ -24,11 +24,32 @@ use super::{
|
||||
InputField, InputMode, LogLevel, OnInputSubmitCallback, PopupType,
|
||||
};
|
||||
|
||||
use crossterm::event::KeyCode;
|
||||
use crossterm::event::{KeyCode, KeyModifiers};
|
||||
use std::path::PathBuf;
|
||||
use tui::style::Color;
|
||||
|
||||
impl FileTransferActivity {
|
||||
|
||||
/// ### read_input_event
|
||||
///
|
||||
/// Read one event.
|
||||
/// Returns whether at least one event has been handled
|
||||
pub(super) fn read_input_event(&mut self) -> bool {
|
||||
if let Ok(event) = self.context.as_ref().unwrap().input_hnd.read_event() {
|
||||
// Iterate over input events
|
||||
if let Some(event) = event {
|
||||
// Handle event
|
||||
self.handle_input_event(&event);
|
||||
// Return true
|
||||
true
|
||||
} else { // No event
|
||||
false
|
||||
}
|
||||
} else { // Error
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
/// ### handle_input_event
|
||||
///
|
||||
/// Handle input event based on current input mode
|
||||
@@ -612,8 +633,16 @@ impl FileTransferActivity {
|
||||
/// ### handle_input_event_mode_explorer_alert
|
||||
///
|
||||
/// Input event handler for popup alert
|
||||
pub(super) fn handle_input_event_mode_popup_progress(&mut self, _ev: &InputEvent) {
|
||||
// There's nothing you can do here I guess... maybe ctrl+c in the future idk
|
||||
pub(super) fn handle_input_event_mode_popup_progress(&mut self, ev: &InputEvent) {
|
||||
if let InputEvent::Key(key) = ev {
|
||||
if let KeyCode::Char(ch) = key.code {
|
||||
// If is 'C' and CTRL
|
||||
if matches!(ch, 'c' | 'C') && key.modifiers.intersects(KeyModifiers::CONTROL) {
|
||||
// Abort transfer
|
||||
self.transfer.aborted = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// ### handle_input_event_mode_explorer_alert
|
||||
|
||||
@@ -342,16 +342,8 @@ impl Activity for FileTransferActivity {
|
||||
// Redraw
|
||||
redraw = true;
|
||||
}
|
||||
// Handle input events
|
||||
if let Ok(event) = self.context.as_ref().unwrap().input_hnd.read_event() {
|
||||
// Iterate over input events
|
||||
if let Some(event) = event {
|
||||
// Handle event
|
||||
self.handle_input_event(&event);
|
||||
// Set redraw to true
|
||||
redraw = true;
|
||||
}
|
||||
}
|
||||
// Handle input events (if false, becomes true; otherwise remains true)
|
||||
redraw |= self.read_input_event();
|
||||
// @! draw interface
|
||||
if redraw {
|
||||
self.draw();
|
||||
|
||||
@@ -23,6 +23,7 @@ use super::{FileTransferActivity, FsEntry, InputMode, LogLevel, PopupType};
|
||||
|
||||
use std::io::{Read, Seek, Write};
|
||||
use std::path::{Path, PathBuf};
|
||||
use std::time::Instant;
|
||||
use tui::style::Color;
|
||||
|
||||
impl FileTransferActivity {
|
||||
@@ -157,7 +158,17 @@ impl FileTransferActivity {
|
||||
// Reset transfer states
|
||||
self.transfer.reset();
|
||||
let mut last_progress_val: f64 = 0.0;
|
||||
while total_bytes_written < file_size {
|
||||
let mut last_input_event_fetch: Instant = Instant::now();
|
||||
// While the entire file hasn't been completely written,
|
||||
// Or filetransfer has been aborted
|
||||
while total_bytes_written < file_size && !self.transfer.aborted {
|
||||
// Handle input events (each 500ms)
|
||||
if last_input_event_fetch.elapsed().as_millis() >= 500 {
|
||||
// Read events
|
||||
self.read_input_event();
|
||||
// Reset instant
|
||||
last_input_event_fetch = Instant::now();
|
||||
}
|
||||
// Read till you can
|
||||
let mut buffer: [u8; 65536] = [0; 65536];
|
||||
match fhnd.read(&mut buffer) {
|
||||
@@ -296,6 +307,10 @@ impl FileTransferActivity {
|
||||
Ok(entries) => {
|
||||
// Iterate over files
|
||||
for entry in entries.iter() {
|
||||
// If aborted; break
|
||||
if self.transfer.aborted {
|
||||
break;
|
||||
}
|
||||
// Send entry; name is always None after first call
|
||||
self.filetransfer_send(&entry, remote_path.as_path(), None);
|
||||
}
|
||||
@@ -347,13 +362,22 @@ impl FileTransferActivity {
|
||||
if let Ok(path) = self.client.pwd() {
|
||||
self.remote_scan(path.as_path());
|
||||
}
|
||||
// If aborted; show popup
|
||||
if self.transfer.aborted {
|
||||
// Show alert
|
||||
self.input_mode = InputMode::Popup(PopupType::Alert(
|
||||
Color::Red,
|
||||
String::from("Upload aborted!"),
|
||||
));
|
||||
// Set aborted to false
|
||||
self.transfer.aborted = false;
|
||||
} else {
|
||||
// @! Successful
|
||||
// Eventually, Reset input mode to explorer (if input mode is wait or progress)
|
||||
if let InputMode::Popup(ptype) = &self.input_mode {
|
||||
match ptype {
|
||||
PopupType::Wait(_) | PopupType::Progress(_) => {
|
||||
if matches!(ptype, PopupType::Wait(_) | PopupType::Progress(_)) {
|
||||
self.input_mode = InputMode::Explorer
|
||||
}
|
||||
_ => { /* Nothing to do */ }
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -410,7 +434,17 @@ impl FileTransferActivity {
|
||||
self.transfer.reset();
|
||||
// Write local file
|
||||
let mut last_progress_val: f64 = 0.0;
|
||||
while total_bytes_written < file.size {
|
||||
let mut last_input_event_fetch: Instant = Instant::now();
|
||||
// While the entire file hasn't been completely read,
|
||||
// Or filetransfer has been aborted
|
||||
while total_bytes_written < file.size && !self.transfer.aborted {
|
||||
// Handle input events (each 500 ms)
|
||||
if last_input_event_fetch.elapsed().as_millis() >= 500 {
|
||||
// Read events
|
||||
self.read_input_event();
|
||||
// Reset instant
|
||||
last_input_event_fetch = Instant::now();
|
||||
}
|
||||
// Read till you can
|
||||
let mut buffer: [u8; 8192] = [0; 8192];
|
||||
match rhnd.read(&mut buffer) {
|
||||
@@ -558,6 +592,10 @@ impl FileTransferActivity {
|
||||
Ok(entries) => {
|
||||
// Iterate over files
|
||||
for entry in entries.iter() {
|
||||
// If transfer has been aborted; break
|
||||
if self.transfer.aborted {
|
||||
break;
|
||||
}
|
||||
// Receive entry; name is always None after first call
|
||||
// Local path becomes local_dir_path
|
||||
self.filetransfer_recv(&entry, local_dir_path.as_path(), None);
|
||||
@@ -600,9 +638,20 @@ impl FileTransferActivity {
|
||||
}
|
||||
// Reload directory on local
|
||||
self.local_scan(local_path);
|
||||
// if aborted; show alert
|
||||
if self.transfer.aborted {
|
||||
// Show alert
|
||||
self.input_mode = InputMode::Popup(PopupType::Alert(
|
||||
Color::Red,
|
||||
String::from("Download aborted!"),
|
||||
));
|
||||
// Reset aborted to false
|
||||
self.transfer.aborted = false;
|
||||
} else {
|
||||
// Eventually, Reset input mode to explorer
|
||||
self.input_mode = InputMode::Explorer;
|
||||
}
|
||||
}
|
||||
|
||||
/// ### local_scan
|
||||
///
|
||||
|
||||
Reference in New Issue
Block a user