mirror of
https://github.com/veeso/termscp.git
synced 2025-12-07 09:36:00 -08:00
Removed progress callback (not a priority atm)
This commit is contained in:
@@ -23,17 +23,14 @@
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
use std::path::{Path, PathBuf};
|
|
||||||
use std::fs::File;
|
use std::fs::File;
|
||||||
|
use std::path::{Path, PathBuf};
|
||||||
|
|
||||||
use crate::fs::FsEntry;
|
use crate::fs::FsEntry;
|
||||||
|
|
||||||
// Transfers
|
// Transfers
|
||||||
pub mod sftp_transfer;
|
pub mod sftp_transfer;
|
||||||
|
|
||||||
// Types
|
|
||||||
pub type ProgressCallback = dyn Fn(usize, usize);
|
|
||||||
|
|
||||||
/// ## FileTransferProtocol
|
/// ## FileTransferProtocol
|
||||||
///
|
///
|
||||||
/// This enum defines the different transfer protocol available in TermSCP
|
/// This enum defines the different transfer protocol available in TermSCP
|
||||||
@@ -65,7 +62,9 @@ pub enum FileTransferError {
|
|||||||
impl std::fmt::Display for FileTransferError {
|
impl std::fmt::Display for FileTransferError {
|
||||||
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
|
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
|
||||||
let err: String = match self {
|
let err: String = match self {
|
||||||
FileTransferError::AuthenticationFailed => String::from("Authentication failed: bad credentials"),
|
FileTransferError::AuthenticationFailed => {
|
||||||
|
String::from("Authentication failed: bad credentials")
|
||||||
|
}
|
||||||
FileTransferError::BadAddress => String::from("Bad address syntax"),
|
FileTransferError::BadAddress => String::from("Bad address syntax"),
|
||||||
FileTransferError::ConnectionError => String::from("Connection error"),
|
FileTransferError::ConnectionError => String::from("Connection error"),
|
||||||
FileTransferError::DirStatFailed => String::from("Could not stat directory"),
|
FileTransferError::DirStatFailed => String::from("Could not stat directory"),
|
||||||
@@ -82,71 +81,75 @@ impl std::fmt::Display for FileTransferError {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// ## FileTransfer
|
/// ## FileTransfer
|
||||||
///
|
///
|
||||||
/// File transfer trait must be implemented by all the file transfers and defines the method used by a generic file transfer
|
/// File transfer trait must be implemented by all the file transfers and defines the method used by a generic file transfer
|
||||||
|
|
||||||
pub trait FileTransfer {
|
pub trait FileTransfer {
|
||||||
|
|
||||||
/// ### connect
|
/// ### connect
|
||||||
///
|
///
|
||||||
/// Connect to the remote server
|
/// Connect to the remote server
|
||||||
|
|
||||||
fn connect(&mut self, address: String, port: u16, username: Option<String>, password: Option<String>) -> Result<(), FileTransferError>;
|
fn connect(
|
||||||
|
&mut self,
|
||||||
|
address: String,
|
||||||
|
port: u16,
|
||||||
|
username: Option<String>,
|
||||||
|
password: Option<String>,
|
||||||
|
) -> Result<(), FileTransferError>;
|
||||||
|
|
||||||
/// ### disconnect
|
/// ### disconnect
|
||||||
///
|
///
|
||||||
/// Disconnect from the remote server
|
/// Disconnect from the remote server
|
||||||
|
|
||||||
fn disconnect(&mut self) -> Result<(), FileTransferError>;
|
fn disconnect(&mut self) -> Result<(), FileTransferError>;
|
||||||
|
|
||||||
/// ### is_connected
|
/// ### is_connected
|
||||||
///
|
///
|
||||||
/// Indicates whether the client is connected to remote
|
/// Indicates whether the client is connected to remote
|
||||||
fn is_connected(&self) -> bool;
|
fn is_connected(&self) -> bool;
|
||||||
|
|
||||||
/// ### pwd
|
/// ### pwd
|
||||||
///
|
///
|
||||||
/// Print working directory
|
/// Print working directory
|
||||||
|
|
||||||
fn pwd(&self) -> Result<PathBuf, FileTransferError>;
|
fn pwd(&self) -> Result<PathBuf, FileTransferError>;
|
||||||
|
|
||||||
/// ### change_dir
|
/// ### change_dir
|
||||||
///
|
///
|
||||||
/// Change working directory
|
/// Change working directory
|
||||||
|
|
||||||
fn change_dir(&mut self, dir: &Path) -> Result<PathBuf, FileTransferError>;
|
fn change_dir(&mut self, dir: &Path) -> Result<PathBuf, FileTransferError>;
|
||||||
|
|
||||||
/// ### list_dir
|
/// ### list_dir
|
||||||
///
|
///
|
||||||
/// List directory entries
|
/// List directory entries
|
||||||
|
|
||||||
fn list_dir(&self, path: &Path) -> Result<Vec<FsEntry>, FileTransferError>;
|
fn list_dir(&self, path: &Path) -> Result<Vec<FsEntry>, FileTransferError>;
|
||||||
|
|
||||||
/// ### mkdir
|
/// ### mkdir
|
||||||
///
|
///
|
||||||
/// Make directory
|
/// Make directory
|
||||||
fn mkdir(&self, dir: &Path) -> Result<(), FileTransferError>;
|
fn mkdir(&self, dir: &Path) -> Result<(), FileTransferError>;
|
||||||
|
|
||||||
/// ### remove
|
/// ### remove
|
||||||
///
|
///
|
||||||
/// Remove a file or a directory
|
/// Remove a file or a directory
|
||||||
fn remove(&self, file: &FsEntry) -> Result<(), FileTransferError>;
|
fn remove(&self, file: &FsEntry) -> Result<(), FileTransferError>;
|
||||||
|
|
||||||
/// ### rename
|
/// ### rename
|
||||||
///
|
///
|
||||||
/// Rename file or a directory
|
/// Rename file or a directory
|
||||||
fn rename(&self, file: &FsEntry, dst: &Path) -> Result<(), FileTransferError>;
|
fn rename(&self, file: &FsEntry, dst: &Path) -> Result<(), FileTransferError>;
|
||||||
|
|
||||||
/// ### send_file
|
/// ### send_file
|
||||||
///
|
///
|
||||||
/// Send file to remote
|
/// Send file to remote
|
||||||
/// File name is referred to the name of the file as it will be saved
|
/// File name is referred to the name of the file as it will be saved
|
||||||
/// Data contains the file data
|
/// Data contains the file data
|
||||||
fn send_file(&self, file_name: &Path, file: &mut File, prog_cb: Option<Box<ProgressCallback>>) -> Result<(), FileTransferError>;
|
fn send_file(&self, file_name: &Path, file: &mut File) -> Result<(), FileTransferError>;
|
||||||
|
|
||||||
/// ### recv_file
|
/// ### recv_file
|
||||||
///
|
///
|
||||||
/// Receive file from remote with provided name
|
/// Receive file from remote with provided name
|
||||||
fn recv_file(&self, file_name: &Path, dest_file: &mut File, prog_cb: Option<Box<ProgressCallback>>) -> Result<(), FileTransferError>;
|
fn recv_file(&self, file_name: &Path, dest_file: &mut File) -> Result<(), FileTransferError>;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -27,7 +27,7 @@
|
|||||||
extern crate ssh2;
|
extern crate ssh2;
|
||||||
|
|
||||||
// Locals
|
// Locals
|
||||||
use super::{FileTransfer, FileTransferError, ProgressCallback};
|
use super::{FileTransfer, FileTransferError};
|
||||||
use crate::fs::{FsDirectory, FsEntry, FsFile};
|
use crate::fs::{FsDirectory, FsEntry, FsFile};
|
||||||
|
|
||||||
// Includes
|
// Includes
|
||||||
@@ -178,7 +178,7 @@ impl FileTransfer for SftpFileTransfer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// ### is_connected
|
/// ### is_connected
|
||||||
///
|
///
|
||||||
/// Indicates whether the client is connected to remote
|
/// Indicates whether the client is connected to remote
|
||||||
fn is_connected(&self) -> bool {
|
fn is_connected(&self) -> bool {
|
||||||
self.session.is_some()
|
self.session.is_some()
|
||||||
@@ -369,7 +369,7 @@ impl FileTransfer for SftpFileTransfer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// ### rename
|
/// ### rename
|
||||||
///
|
///
|
||||||
/// Rename file or a directory
|
/// Rename file or a directory
|
||||||
fn rename(&self, file: &FsEntry, dst: &Path) -> Result<(), FileTransferError> {
|
fn rename(&self, file: &FsEntry, dst: &Path) -> Result<(), FileTransferError> {
|
||||||
match self.sftp.as_ref() {
|
match self.sftp.as_ref() {
|
||||||
@@ -380,11 +380,11 @@ impl FileTransfer for SftpFileTransfer {
|
|||||||
// Get abs path of entry
|
// Get abs path of entry
|
||||||
let abs_src: PathBuf = match file {
|
let abs_src: PathBuf = match file {
|
||||||
FsEntry::Directory(dir) => dir.abs_path.clone(),
|
FsEntry::Directory(dir) => dir.abs_path.clone(),
|
||||||
FsEntry::File(file) => file.abs_path.clone()
|
FsEntry::File(file) => file.abs_path.clone(),
|
||||||
};
|
};
|
||||||
match sftp.rename(abs_src.as_path(), abs_dst.as_path(), None) {
|
match sftp.rename(abs_src.as_path(), abs_dst.as_path(), None) {
|
||||||
Ok(_) => Ok(()),
|
Ok(_) => Ok(()),
|
||||||
Err(_) => Err(FileTransferError::FileCreateDenied)
|
Err(_) => Err(FileTransferError::FileCreateDenied),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -395,18 +395,13 @@ impl FileTransfer for SftpFileTransfer {
|
|||||||
/// Send file to remote
|
/// Send file to remote
|
||||||
/// File name is referred to the name of the file as it will be saved
|
/// File name is referred to the name of the file as it will be saved
|
||||||
/// Data contains the file data
|
/// Data contains the file data
|
||||||
fn send_file(
|
fn send_file(&self, file_name: &Path, file: &mut File) -> Result<(), FileTransferError> {
|
||||||
&self,
|
|
||||||
file_name: &Path,
|
|
||||||
file: &mut File,
|
|
||||||
prog_cb: Option<Box<ProgressCallback>>,
|
|
||||||
) -> Result<(), FileTransferError> {
|
|
||||||
match self.sftp.as_ref() {
|
match self.sftp.as_ref() {
|
||||||
None => Err(FileTransferError::UninitializedSession),
|
None => Err(FileTransferError::UninitializedSession),
|
||||||
Some(sftp) => {
|
Some(sftp) => {
|
||||||
let remote_path: PathBuf = self.get_abs_path(file_name);
|
let remote_path: PathBuf = self.get_abs_path(file_name);
|
||||||
// Get file size
|
// Get file size
|
||||||
let file_size: usize = file.seek(std::io::SeekFrom::End(0)).unwrap_or(0) as usize;
|
//let file_size: usize = file.seek(std::io::SeekFrom::End(0)).unwrap_or(0) as usize;
|
||||||
// rewind
|
// rewind
|
||||||
if let Err(err) = file.seek(std::io::SeekFrom::Start(0)) {
|
if let Err(err) = file.seek(std::io::SeekFrom::Start(0)) {
|
||||||
return Err(FileTransferError::IoErr(err));
|
return Err(FileTransferError::IoErr(err));
|
||||||
@@ -414,13 +409,13 @@ impl FileTransfer for SftpFileTransfer {
|
|||||||
// Open remote file
|
// Open remote file
|
||||||
match sftp.create(remote_path.as_path()) {
|
match sftp.create(remote_path.as_path()) {
|
||||||
Ok(mut rhnd) => {
|
Ok(mut rhnd) => {
|
||||||
let mut total_bytes_written: usize = 0;
|
//let mut total_bytes_written: usize = 0;
|
||||||
loop {
|
loop {
|
||||||
// Read till you can
|
// Read till you can
|
||||||
let mut buffer: [u8; 8192] = [0; 8192];
|
let mut buffer: [u8; 8192] = [0; 8192];
|
||||||
match file.read(&mut buffer) {
|
match file.read(&mut buffer) {
|
||||||
Ok(bytes_read) => {
|
Ok(bytes_read) => {
|
||||||
total_bytes_written += bytes_read;
|
//total_bytes_written += bytes_read;
|
||||||
if bytes_read == 0 {
|
if bytes_read == 0 {
|
||||||
break;
|
break;
|
||||||
} else {
|
} else {
|
||||||
@@ -428,10 +423,6 @@ impl FileTransfer for SftpFileTransfer {
|
|||||||
if let Err(err) = rhnd.write(&buffer) {
|
if let Err(err) = rhnd.write(&buffer) {
|
||||||
return Err(FileTransferError::IoErr(err));
|
return Err(FileTransferError::IoErr(err));
|
||||||
}
|
}
|
||||||
// Call callback
|
|
||||||
if let Some(ref cb) = prog_cb {
|
|
||||||
cb(total_bytes_written, file_size);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Err(err) => return Err(FileTransferError::IoErr(err)),
|
Err(err) => return Err(FileTransferError::IoErr(err)),
|
||||||
@@ -448,12 +439,7 @@ impl FileTransfer for SftpFileTransfer {
|
|||||||
/// ### recv_file
|
/// ### recv_file
|
||||||
///
|
///
|
||||||
/// Receive file from remote with provided name
|
/// Receive file from remote with provided name
|
||||||
fn recv_file(
|
fn recv_file(&self, file_name: &Path, dest_file: &mut File) -> Result<(), FileTransferError> {
|
||||||
&self,
|
|
||||||
file_name: &Path,
|
|
||||||
dest_file: &mut File,
|
|
||||||
prog_cb: Option<Box<ProgressCallback>>,
|
|
||||||
) -> Result<(), FileTransferError> {
|
|
||||||
match self.sftp.as_ref() {
|
match self.sftp.as_ref() {
|
||||||
None => Err(FileTransferError::UninitializedSession),
|
None => Err(FileTransferError::UninitializedSession),
|
||||||
Some(sftp) => {
|
Some(sftp) => {
|
||||||
@@ -465,20 +451,19 @@ impl FileTransfer for SftpFileTransfer {
|
|||||||
// Open remote file
|
// Open remote file
|
||||||
match sftp.open(remote_path.as_path()) {
|
match sftp.open(remote_path.as_path()) {
|
||||||
Ok(mut rhnd) => {
|
Ok(mut rhnd) => {
|
||||||
let file_size: usize =
|
// let file_size: usize = rhnd.seek(std::io::SeekFrom::End(0)).unwrap_or(0) as usize;
|
||||||
rhnd.seek(std::io::SeekFrom::End(0)).unwrap_or(0) as usize;
|
|
||||||
// rewind
|
// rewind
|
||||||
if let Err(err) = rhnd.seek(std::io::SeekFrom::Start(0)) {
|
if let Err(err) = rhnd.seek(std::io::SeekFrom::Start(0)) {
|
||||||
return Err(FileTransferError::IoErr(err));
|
return Err(FileTransferError::IoErr(err));
|
||||||
};
|
};
|
||||||
// Write local file
|
// Write local file
|
||||||
let mut total_bytes_written: usize = 0;
|
// let mut total_bytes_written: usize = 0;
|
||||||
loop {
|
loop {
|
||||||
// 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) {
|
||||||
Ok(bytes_read) => {
|
Ok(bytes_read) => {
|
||||||
total_bytes_written += bytes_read;
|
// total_bytes_written += bytes_read;
|
||||||
if bytes_read == 0 {
|
if bytes_read == 0 {
|
||||||
break;
|
break;
|
||||||
} else {
|
} else {
|
||||||
@@ -486,10 +471,6 @@ impl FileTransfer for SftpFileTransfer {
|
|||||||
if let Err(err) = dest_file.write(&buffer) {
|
if let Err(err) = dest_file.write(&buffer) {
|
||||||
return Err(FileTransferError::IoErr(err));
|
return Err(FileTransferError::IoErr(err));
|
||||||
}
|
}
|
||||||
// Call callback
|
|
||||||
if let Some(ref cb) = prog_cb {
|
|
||||||
cb(total_bytes_written, file_size);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Err(err) => return Err(FileTransferError::IoErr(err)),
|
Err(err) => return Err(FileTransferError::IoErr(err)),
|
||||||
@@ -696,11 +677,7 @@ mod tests {
|
|||||||
.unwrap();
|
.unwrap();
|
||||||
// Receive file
|
// Receive file
|
||||||
assert!(client
|
assert!(client
|
||||||
.recv_file(
|
.recv_file(PathBuf::from("readme.txt").as_path(), &mut dst_file_hnd)
|
||||||
PathBuf::from("readme.txt").as_path(),
|
|
||||||
&mut dst_file_hnd,
|
|
||||||
Some(Box::new(progress_callback))
|
|
||||||
)
|
|
||||||
.is_ok());
|
.is_ok());
|
||||||
// Disconnect
|
// Disconnect
|
||||||
assert!(client.disconnect().is_ok());
|
assert!(client.disconnect().is_ok());
|
||||||
@@ -730,11 +707,7 @@ mod tests {
|
|||||||
.unwrap();
|
.unwrap();
|
||||||
// Receive file
|
// Receive file
|
||||||
assert!(client
|
assert!(client
|
||||||
.recv_file(
|
.recv_file(PathBuf::from("omar.txt").as_path(), &mut dst_file_hnd)
|
||||||
PathBuf::from("omar.txt").as_path(),
|
|
||||||
&mut dst_file_hnd,
|
|
||||||
Some(Box::new(progress_callback))
|
|
||||||
)
|
|
||||||
.is_err());
|
.is_err());
|
||||||
// Disconnect
|
// Disconnect
|
||||||
assert!(client.disconnect().is_ok());
|
assert!(client.disconnect().is_ok());
|
||||||
@@ -767,11 +740,7 @@ mod tests {
|
|||||||
let mut dst_file_hnd: File = OpenOptions::new().read(true).open(dst_file.path()).unwrap();
|
let mut dst_file_hnd: File = OpenOptions::new().read(true).open(dst_file.path()).unwrap();
|
||||||
// Receive file
|
// Receive file
|
||||||
assert!(client
|
assert!(client
|
||||||
.recv_file(
|
.recv_file(PathBuf::from("readme.txt").as_path(), &mut dst_file_hnd)
|
||||||
PathBuf::from("readme.txt").as_path(),
|
|
||||||
&mut dst_file_hnd,
|
|
||||||
Some(Box::new(progress_callback))
|
|
||||||
)
|
|
||||||
.is_err());
|
.is_err());
|
||||||
// Disconnect
|
// Disconnect
|
||||||
assert!(client.disconnect().is_ok());
|
assert!(client.disconnect().is_ok());
|
||||||
@@ -794,8 +763,4 @@ mod tests {
|
|||||||
assert!(client.disconnect().is_ok());
|
assert!(client.disconnect().is_ok());
|
||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
fn progress_callback(it: usize, max: usize) {
|
|
||||||
assert!(it <= max);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -34,7 +34,7 @@ use crate::filetransfer::FileTransferProtocol;
|
|||||||
|
|
||||||
// File transfer
|
// File transfer
|
||||||
use crate::filetransfer::sftp_transfer::SftpFileTransfer;
|
use crate::filetransfer::sftp_transfer::SftpFileTransfer;
|
||||||
use crate::filetransfer::{FileTransfer, ProgressCallback};
|
use crate::filetransfer::FileTransfer;
|
||||||
use crate::fs::FsEntry;
|
use crate::fs::FsEntry;
|
||||||
|
|
||||||
// Includes
|
// Includes
|
||||||
@@ -55,9 +55,6 @@ use tui::{
|
|||||||
};
|
};
|
||||||
use unicode_width::UnicodeWidthStr;
|
use unicode_width::UnicodeWidthStr;
|
||||||
|
|
||||||
// Holder for current upload progress
|
|
||||||
static mut UPLOAD_PROGRESS: f64 = 0.0; // VERY VERY BAD CODING
|
|
||||||
|
|
||||||
// Types
|
// Types
|
||||||
type DialogCallback = fn(&mut FileTransferActivity);
|
type DialogCallback = fn(&mut FileTransferActivity);
|
||||||
type OnInputSubmitCallback = fn(&mut FileTransferActivity, String);
|
type OnInputSubmitCallback = fn(&mut FileTransferActivity, String);
|
||||||
@@ -315,22 +312,15 @@ impl FileTransferActivity {
|
|||||||
FsEntry::Directory(dir) => dir.name.clone(),
|
FsEntry::Directory(dir) => dir.name.clone(),
|
||||||
FsEntry::File(file) => file.name.clone(),
|
FsEntry::File(file) => file.name.clone(),
|
||||||
};
|
};
|
||||||
self.input_mode = InputMode::Popup(PopupType::Progress(format!(
|
self.input_mode =
|
||||||
"Uploading \"{}\"...",
|
InputMode::Popup(PopupType::Wait(format!("Uploading \"{}\"...", file_name)));
|
||||||
file_name
|
// Draw
|
||||||
)));
|
self.draw();
|
||||||
|
// Get remote path
|
||||||
let remote_path: PathBuf = match dst_name {
|
let remote_path: PathBuf = match dst_name {
|
||||||
Some(s) => PathBuf::from(s.as_str()),
|
Some(s) => PathBuf::from(s.as_str()),
|
||||||
None => PathBuf::from(file_name.as_str()),
|
None => PathBuf::from(file_name.as_str()),
|
||||||
};
|
};
|
||||||
let prog_cb: Box<ProgressCallback> = Box::new(|c, sz| {
|
|
||||||
// Progress callback
|
|
||||||
let percentage: f64 = ((c as f64) * 100.0) / (sz as f64);
|
|
||||||
unsafe {
|
|
||||||
UPLOAD_PROGRESS = percentage;
|
|
||||||
}
|
|
||||||
// FIXME: can't draw here...
|
|
||||||
});
|
|
||||||
// Match entry
|
// Match entry
|
||||||
match entry {
|
match entry {
|
||||||
FsEntry::File(file) => {
|
FsEntry::File(file) => {
|
||||||
@@ -343,31 +333,26 @@ impl FileTransferActivity {
|
|||||||
.local
|
.local
|
||||||
.open_file_read(file.abs_path.as_path())
|
.open_file_read(file.abs_path.as_path())
|
||||||
{
|
{
|
||||||
Ok(mut f) => {
|
Ok(mut f) => match self.client.send_file(remote_path.as_path(), &mut f) {
|
||||||
match self
|
Ok(_) => self.log(
|
||||||
.client
|
LogLevel::Info,
|
||||||
.send_file(remote_path.as_path(), &mut f, Some(prog_cb))
|
format!(
|
||||||
{
|
"Saved file \"{}\" to \"{}\"",
|
||||||
Ok(_) => self.log(
|
file.abs_path.display(),
|
||||||
LogLevel::Info,
|
remote_path.display()
|
||||||
format!(
|
)
|
||||||
"Saved file \"{}\" to \"{}\"",
|
.as_ref(),
|
||||||
file.abs_path.display(),
|
),
|
||||||
remote_path.display()
|
Err(err) => self.log(
|
||||||
)
|
LogLevel::Error,
|
||||||
.as_ref(),
|
format!(
|
||||||
),
|
"Failed to upload file \"{}\": {}",
|
||||||
Err(err) => self.log(
|
file.abs_path.display(),
|
||||||
LogLevel::Error,
|
err
|
||||||
format!(
|
)
|
||||||
"Failed to upload file \"{}\": {}",
|
.as_ref(),
|
||||||
file.abs_path.display(),
|
),
|
||||||
err
|
},
|
||||||
)
|
|
||||||
.as_ref(),
|
|
||||||
),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
// Report error
|
// Report error
|
||||||
self.log(
|
self.log(
|
||||||
@@ -441,18 +426,10 @@ impl FileTransferActivity {
|
|||||||
FsEntry::Directory(dir) => dir.name.clone(),
|
FsEntry::Directory(dir) => dir.name.clone(),
|
||||||
FsEntry::File(file) => file.name.clone(),
|
FsEntry::File(file) => file.name.clone(),
|
||||||
};
|
};
|
||||||
self.input_mode = InputMode::Popup(PopupType::Progress(format!(
|
self.input_mode =
|
||||||
"Downloading \"{}\"...",
|
InputMode::Popup(PopupType::Wait(format!("Downloading \"{}\"...", file_name)));
|
||||||
file_name
|
// Draw
|
||||||
)));
|
self.draw();
|
||||||
let prog_cb: Box<ProgressCallback> = Box::new(|c, sz| {
|
|
||||||
// Progress callback
|
|
||||||
let percentage: f64 = ((c as f64) * 100.0) / (sz as f64);
|
|
||||||
unsafe {
|
|
||||||
UPLOAD_PROGRESS = percentage;
|
|
||||||
}
|
|
||||||
// FIXME: can't draw here...
|
|
||||||
});
|
|
||||||
// Match entry
|
// Match entry
|
||||||
match entry {
|
match entry {
|
||||||
FsEntry::File(file) => {
|
FsEntry::File(file) => {
|
||||||
@@ -473,11 +450,10 @@ impl FileTransferActivity {
|
|||||||
{
|
{
|
||||||
Ok(mut local_file) => {
|
Ok(mut local_file) => {
|
||||||
// Download file from remote
|
// Download file from remote
|
||||||
match self.client.recv_file(
|
match self
|
||||||
file.abs_path.as_path(),
|
.client
|
||||||
&mut local_file,
|
.recv_file(file.abs_path.as_path(), &mut local_file)
|
||||||
Some(prog_cb),
|
{
|
||||||
) {
|
|
||||||
Ok(_) => self.log(
|
Ok(_) => self.log(
|
||||||
LogLevel::Info,
|
LogLevel::Info,
|
||||||
format!(
|
format!(
|
||||||
|
|||||||
Reference in New Issue
Block a user