Abort upload/download pressing Ctrl+C

This commit is contained in:
ChristianVisintin
2020-12-12 22:00:12 +01:00
parent 3e72787625
commit a8a9cb9d2e
5 changed files with 95 additions and 23 deletions

View File

@@ -9,12 +9,13 @@
## 0.1.2 ## 0.1.2
Released on ?? Released on 13/12/2020
- General performance and code improvements - General performance and code improvements
- Improved symlinks management - Improved symlinks management
- Keybindings: - Keybindings:
- `E`: Delete file (Same as `DEL`); added because some keyboards don't have `DEL` (hey, that's my MacBook Air's keyboard!) - `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 ## 0.1.1

View File

@@ -202,6 +202,7 @@ Password can be basically provided through 3 ways when address argument is provi
| `<R>` | Rename file | | `<R>` | Rename file |
| `<U>` | Go to parent directory | | `<U>` | Go to parent directory |
| `<DEL>` | Delete file | | `<DEL>` | Delete file |
| `CTRL+C` | Abort file transfer process |
--- ---

View File

@@ -24,11 +24,32 @@ use super::{
InputField, InputMode, LogLevel, OnInputSubmitCallback, PopupType, InputField, InputMode, LogLevel, OnInputSubmitCallback, PopupType,
}; };
use crossterm::event::KeyCode; use crossterm::event::{KeyCode, KeyModifiers};
use std::path::PathBuf; use std::path::PathBuf;
use tui::style::Color; use tui::style::Color;
impl FileTransferActivity { 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
/// ///
/// Handle input event based on current input mode /// Handle input event based on current input mode
@@ -612,8 +633,16 @@ impl FileTransferActivity {
/// ### handle_input_event_mode_explorer_alert /// ### handle_input_event_mode_explorer_alert
/// ///
/// Input event handler for popup alert /// Input event handler for popup alert
pub(super) fn handle_input_event_mode_popup_progress(&mut self, _ev: &InputEvent) { 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 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 /// ### handle_input_event_mode_explorer_alert

View File

@@ -342,16 +342,8 @@ impl Activity for FileTransferActivity {
// Redraw // Redraw
redraw = true; redraw = true;
} }
// Handle input events // Handle input events (if false, becomes true; otherwise remains true)
if let Ok(event) = self.context.as_ref().unwrap().input_hnd.read_event() { redraw |= self.read_input_event();
// Iterate over input events
if let Some(event) = event {
// Handle event
self.handle_input_event(&event);
// Set redraw to true
redraw = true;
}
}
// @! draw interface // @! draw interface
if redraw { if redraw {
self.draw(); self.draw();

View File

@@ -23,6 +23,7 @@ use super::{FileTransferActivity, FsEntry, InputMode, LogLevel, PopupType};
use std::io::{Read, Seek, Write}; use std::io::{Read, Seek, Write};
use std::path::{Path, PathBuf}; use std::path::{Path, PathBuf};
use std::time::Instant;
use tui::style::Color; use tui::style::Color;
impl FileTransferActivity { impl FileTransferActivity {
@@ -157,7 +158,17 @@ impl FileTransferActivity {
// Reset transfer states // Reset transfer states
self.transfer.reset(); self.transfer.reset();
let mut last_progress_val: f64 = 0.0; 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 // Read till you can
let mut buffer: [u8; 65536] = [0; 65536]; let mut buffer: [u8; 65536] = [0; 65536];
match fhnd.read(&mut buffer) { match fhnd.read(&mut buffer) {
@@ -296,6 +307,10 @@ impl FileTransferActivity {
Ok(entries) => { Ok(entries) => {
// Iterate over files // Iterate over files
for entry in entries.iter() { for entry in entries.iter() {
// If aborted; break
if self.transfer.aborted {
break;
}
// Send entry; name is always None after first call // Send entry; name is always None after first call
self.filetransfer_send(&entry, remote_path.as_path(), None); self.filetransfer_send(&entry, remote_path.as_path(), None);
} }
@@ -347,13 +362,22 @@ impl FileTransferActivity {
if let Ok(path) = self.client.pwd() { if let Ok(path) = self.client.pwd() {
self.remote_scan(path.as_path()); self.remote_scan(path.as_path());
} }
// Eventually, Reset input mode to explorer (if input mode is wait or progress) // If aborted; show popup
if let InputMode::Popup(ptype) = &self.input_mode { if self.transfer.aborted {
match ptype { // Show alert
PopupType::Wait(_) | PopupType::Progress(_) => { 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 {
if matches!(ptype, PopupType::Wait(_) | PopupType::Progress(_)) {
self.input_mode = InputMode::Explorer self.input_mode = InputMode::Explorer
} }
_ => { /* Nothing to do */ }
} }
} }
} }
@@ -410,7 +434,17 @@ impl FileTransferActivity {
self.transfer.reset(); self.transfer.reset();
// Write local file // Write local file
let mut last_progress_val: f64 = 0.0; 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 // Read till you can
let mut buffer: [u8; 8192] = [0; 8192]; let mut buffer: [u8; 8192] = [0; 8192];
match rhnd.read(&mut buffer) { match rhnd.read(&mut buffer) {
@@ -558,6 +592,10 @@ impl FileTransferActivity {
Ok(entries) => { Ok(entries) => {
// Iterate over files // Iterate over files
for entry in entries.iter() { 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 // Receive entry; name is always None after first call
// Local path becomes local_dir_path // Local path becomes local_dir_path
self.filetransfer_recv(&entry, local_dir_path.as_path(), None); self.filetransfer_recv(&entry, local_dir_path.as_path(), None);
@@ -600,8 +638,19 @@ impl FileTransferActivity {
} }
// Reload directory on local // Reload directory on local
self.local_scan(local_path); self.local_scan(local_path);
// Eventually, Reset input mode to explorer // if aborted; show alert
self.input_mode = InputMode::Explorer; 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 /// ### local_scan