mirror of
https://github.com/veeso/termscp.git
synced 2025-12-07 09:36:00 -08:00
Removed filetransfer module; migrated to remotefs crate
This commit is contained in:
committed by
Christian Visintin
parent
25dd1b9b0a
commit
df7a4381c4
@@ -52,19 +52,11 @@ use tuirealm::{Component, MockComponent};
|
||||
|
||||
// -- global listener
|
||||
|
||||
#[derive(MockComponent)]
|
||||
#[derive(Default, MockComponent)]
|
||||
pub struct GlobalListener {
|
||||
component: Phantom,
|
||||
}
|
||||
|
||||
impl Default for GlobalListener {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
component: Phantom::default(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Component<Msg, NoUserEvent> for GlobalListener {
|
||||
fn on(&mut self, ev: Event<NoUserEvent>) -> Option<Msg> {
|
||||
match ev {
|
||||
|
||||
@@ -26,7 +26,9 @@
|
||||
* SOFTWARE.
|
||||
*/
|
||||
// locals
|
||||
use super::{FileTransferActivity, FsEntry};
|
||||
use super::FileTransferActivity;
|
||||
|
||||
use remotefs::Directory;
|
||||
use std::path::PathBuf;
|
||||
|
||||
impl FileTransferActivity {
|
||||
@@ -34,70 +36,24 @@ 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, entry: FsEntry, block_sync: bool) -> bool {
|
||||
match entry {
|
||||
FsEntry::Directory(dir) => {
|
||||
self.local_changedir(dir.abs_path.as_path(), true);
|
||||
if self.browser.sync_browsing && !block_sync {
|
||||
self.action_change_remote_dir(dir.name, true);
|
||||
}
|
||||
true
|
||||
}
|
||||
FsEntry::File(file) => {
|
||||
match &file.symlink {
|
||||
Some(symlink_entry) => {
|
||||
// If symlink and is directory, point to symlink
|
||||
match &**symlink_entry {
|
||||
FsEntry::Directory(dir) => {
|
||||
self.local_changedir(dir.abs_path.as_path(), true);
|
||||
// Check whether to sync
|
||||
if self.browser.sync_browsing && !block_sync {
|
||||
self.action_change_remote_dir(dir.name.clone(), true);
|
||||
}
|
||||
true
|
||||
}
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
None => false,
|
||||
}
|
||||
}
|
||||
pub(crate) fn action_enter_local_dir(&mut self, dir: Directory, block_sync: bool) -> bool {
|
||||
self.local_changedir(dir.path.as_path(), true);
|
||||
if self.browser.sync_browsing && !block_sync {
|
||||
self.action_change_remote_dir(dir.name, true);
|
||||
}
|
||||
true
|
||||
}
|
||||
|
||||
/// ### action_enter_remote_dir
|
||||
///
|
||||
/// Enter a directory on local host from entry
|
||||
/// Return true whether the directory changed
|
||||
pub(crate) fn action_enter_remote_dir(&mut self, entry: FsEntry, block_sync: bool) -> bool {
|
||||
match entry {
|
||||
FsEntry::Directory(dir) => {
|
||||
self.remote_changedir(dir.abs_path.as_path(), true);
|
||||
if self.browser.sync_browsing && !block_sync {
|
||||
self.action_change_local_dir(dir.name, true);
|
||||
}
|
||||
true
|
||||
}
|
||||
FsEntry::File(file) => {
|
||||
match &file.symlink {
|
||||
Some(symlink_entry) => {
|
||||
// If symlink and is directory, point to symlink
|
||||
match &**symlink_entry {
|
||||
FsEntry::Directory(dir) => {
|
||||
self.remote_changedir(dir.abs_path.as_path(), true);
|
||||
// Check whether to sync
|
||||
if self.browser.sync_browsing && !block_sync {
|
||||
self.action_change_local_dir(dir.name.clone(), true);
|
||||
}
|
||||
true
|
||||
}
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
None => false,
|
||||
}
|
||||
}
|
||||
pub(crate) fn action_enter_remote_dir(&mut self, dir: Directory, block_sync: bool) -> bool {
|
||||
self.remote_changedir(dir.path.as_path(), true);
|
||||
if self.browser.sync_browsing && !block_sync {
|
||||
self.action_change_local_dir(dir.name, true);
|
||||
}
|
||||
true
|
||||
}
|
||||
|
||||
/// ### action_change_local_dir
|
||||
|
||||
@@ -26,9 +26,9 @@
|
||||
* SOFTWARE.
|
||||
*/
|
||||
// locals
|
||||
use super::{FileTransferActivity, FsEntry, LogLevel, SelectedEntry, TransferPayload};
|
||||
use crate::filetransfer::FileTransferErrorType;
|
||||
use crate::fs::FsFile;
|
||||
use super::{FileTransferActivity, LogLevel, SelectedEntry, TransferPayload};
|
||||
|
||||
use remotefs::{Entry, RemoteErrorType};
|
||||
use std::path::{Path, PathBuf};
|
||||
|
||||
impl FileTransferActivity {
|
||||
@@ -49,7 +49,7 @@ impl FileTransferActivity {
|
||||
// Iter files
|
||||
for entry in entries.iter() {
|
||||
let mut dest_path: PathBuf = base_path.clone();
|
||||
dest_path.push(entry.get_name());
|
||||
dest_path.push(entry.name());
|
||||
self.local_copy_file(entry, dest_path.as_path());
|
||||
}
|
||||
// Reload entries
|
||||
@@ -76,7 +76,7 @@ impl FileTransferActivity {
|
||||
// Iter files
|
||||
for entry in entries.into_iter() {
|
||||
let mut dest_path: PathBuf = base_path.clone();
|
||||
dest_path.push(entry.get_name());
|
||||
dest_path.push(entry.name());
|
||||
self.remote_copy_file(entry, dest_path.as_path());
|
||||
}
|
||||
// Reload entries
|
||||
@@ -86,14 +86,14 @@ impl FileTransferActivity {
|
||||
}
|
||||
}
|
||||
|
||||
fn local_copy_file(&mut self, entry: &FsEntry, dest: &Path) {
|
||||
fn local_copy_file(&mut self, entry: &Entry, dest: &Path) {
|
||||
match self.host.copy(entry, dest) {
|
||||
Ok(_) => {
|
||||
self.log(
|
||||
LogLevel::Info,
|
||||
format!(
|
||||
"Copied \"{}\" to \"{}\"",
|
||||
entry.get_abs_path().display(),
|
||||
entry.path().display(),
|
||||
dest.display()
|
||||
),
|
||||
);
|
||||
@@ -102,7 +102,7 @@ impl FileTransferActivity {
|
||||
LogLevel::Error,
|
||||
format!(
|
||||
"Could not copy \"{}\" to \"{}\": {}",
|
||||
entry.get_abs_path().display(),
|
||||
entry.path().display(),
|
||||
dest.display(),
|
||||
err
|
||||
),
|
||||
@@ -110,20 +110,20 @@ impl FileTransferActivity {
|
||||
}
|
||||
}
|
||||
|
||||
fn remote_copy_file(&mut self, entry: FsEntry, dest: &Path) {
|
||||
match self.client.as_mut().copy(&entry, dest) {
|
||||
fn remote_copy_file(&mut self, entry: Entry, dest: &Path) {
|
||||
match self.client.as_mut().copy(entry.path(), dest) {
|
||||
Ok(_) => {
|
||||
self.log(
|
||||
LogLevel::Info,
|
||||
format!(
|
||||
"Copied \"{}\" to \"{}\"",
|
||||
entry.get_abs_path().display(),
|
||||
entry.path().display(),
|
||||
dest.display()
|
||||
),
|
||||
);
|
||||
}
|
||||
Err(err) => match err.kind() {
|
||||
FileTransferErrorType::UnsupportedFeature => {
|
||||
Err(err) => match err.kind {
|
||||
RemoteErrorType::UnsupportedFeature => {
|
||||
// If copy is not supported, perform the tricky copy
|
||||
let _ = self.tricky_copy(entry, dest);
|
||||
}
|
||||
@@ -131,7 +131,7 @@ impl FileTransferActivity {
|
||||
LogLevel::Error,
|
||||
format!(
|
||||
"Could not copy \"{}\" to \"{}\": {}",
|
||||
entry.get_abs_path().display(),
|
||||
entry.path().display(),
|
||||
dest.display(),
|
||||
err
|
||||
),
|
||||
@@ -143,12 +143,12 @@ impl FileTransferActivity {
|
||||
/// ### tricky_copy
|
||||
///
|
||||
/// Tricky copy will be used whenever copy command is not available on remote host
|
||||
pub(super) fn tricky_copy(&mut self, entry: FsEntry, dest: &Path) -> Result<(), String> {
|
||||
pub(super) fn tricky_copy(&mut self, entry: Entry, dest: &Path) -> Result<(), String> {
|
||||
// NOTE: VERY IMPORTANT; wait block must be umounted or something really bad will happen
|
||||
self.umount_wait();
|
||||
// match entry
|
||||
match entry {
|
||||
FsEntry::File(entry) => {
|
||||
Entry::File(entry) => {
|
||||
// Create tempfile
|
||||
let tmpfile: tempfile::NamedTempFile = match tempfile::NamedTempFile::new() {
|
||||
Ok(f) => f,
|
||||
@@ -162,7 +162,7 @@ impl FileTransferActivity {
|
||||
};
|
||||
// Download file
|
||||
let name = entry.name.clone();
|
||||
let entry_path = entry.abs_path.clone();
|
||||
let entry_path = entry.path.clone();
|
||||
if let Err(err) =
|
||||
self.filetransfer_recv(TransferPayload::File(entry), tmpfile.path(), Some(name))
|
||||
{
|
||||
@@ -173,7 +173,7 @@ impl FileTransferActivity {
|
||||
return Err(err);
|
||||
}
|
||||
// Get local fs entry
|
||||
let tmpfile_entry: FsFile = match self.host.stat(tmpfile.path()) {
|
||||
let tmpfile_entry = match self.host.stat(tmpfile.path()) {
|
||||
Ok(e) => e.unwrap_file(),
|
||||
Err(err) => {
|
||||
self.log_and_alert(
|
||||
@@ -206,7 +206,7 @@ impl FileTransferActivity {
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
FsEntry::Directory(_) => {
|
||||
Entry::Directory(_) => {
|
||||
let tempdir: tempfile::TempDir = match tempfile::TempDir::new() {
|
||||
Ok(d) => d,
|
||||
Err(err) => {
|
||||
@@ -219,7 +219,7 @@ impl FileTransferActivity {
|
||||
};
|
||||
// Get path of dest
|
||||
let mut tempdir_path: PathBuf = tempdir.path().to_path_buf();
|
||||
tempdir_path.push(entry.get_name());
|
||||
tempdir_path.push(entry.name());
|
||||
// Download file
|
||||
if let Err(err) =
|
||||
self.filetransfer_recv(TransferPayload::Any(entry), tempdir.path(), None)
|
||||
@@ -231,7 +231,7 @@ impl FileTransferActivity {
|
||||
return Err(err);
|
||||
}
|
||||
// Stat dir
|
||||
let tempdir_entry: FsEntry = match self.host.stat(tempdir_path.as_path()) {
|
||||
let tempdir_entry = match self.host.stat(tempdir_path.as_path()) {
|
||||
Ok(e) => e,
|
||||
Err(err) => {
|
||||
self.log_and_alert(
|
||||
|
||||
@@ -26,7 +26,9 @@
|
||||
* SOFTWARE.
|
||||
*/
|
||||
// locals
|
||||
use super::{FileTransferActivity, FsEntry, LogLevel, SelectedEntry};
|
||||
use super::{FileTransferActivity, LogLevel, SelectedEntry};
|
||||
|
||||
use remotefs::Entry;
|
||||
|
||||
impl FileTransferActivity {
|
||||
pub(crate) fn action_local_delete(&mut self) {
|
||||
@@ -71,13 +73,13 @@ impl FileTransferActivity {
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn local_remove_file(&mut self, entry: &FsEntry) {
|
||||
pub(crate) fn local_remove_file(&mut self, entry: &Entry) {
|
||||
match self.host.remove(entry) {
|
||||
Ok(_) => {
|
||||
// Log
|
||||
self.log(
|
||||
LogLevel::Info,
|
||||
format!("Removed file \"{}\"", entry.get_abs_path().display()),
|
||||
format!("Removed file \"{}\"", entry.path().display()),
|
||||
);
|
||||
}
|
||||
Err(err) => {
|
||||
@@ -85,7 +87,7 @@ impl FileTransferActivity {
|
||||
LogLevel::Error,
|
||||
format!(
|
||||
"Could not delete file \"{}\": {}",
|
||||
entry.get_abs_path().display(),
|
||||
entry.path().display(),
|
||||
err
|
||||
),
|
||||
);
|
||||
@@ -93,12 +95,12 @@ impl FileTransferActivity {
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn remote_remove_file(&mut self, entry: &FsEntry) {
|
||||
match self.client.remove(entry) {
|
||||
pub(crate) fn remote_remove_file(&mut self, entry: &Entry) {
|
||||
match self.client.remove_dir_all(entry.path()) {
|
||||
Ok(_) => {
|
||||
self.log(
|
||||
LogLevel::Info,
|
||||
format!("Removed file \"{}\"", entry.get_abs_path().display()),
|
||||
format!("Removed file \"{}\"", entry.path().display()),
|
||||
);
|
||||
}
|
||||
Err(err) => {
|
||||
@@ -106,7 +108,7 @@ impl FileTransferActivity {
|
||||
LogLevel::Error,
|
||||
format!(
|
||||
"Could not delete file \"{}\": {}",
|
||||
entry.get_abs_path().display(),
|
||||
entry.path().display(),
|
||||
err
|
||||
),
|
||||
);
|
||||
|
||||
@@ -26,9 +26,10 @@
|
||||
* SOFTWARE.
|
||||
*/
|
||||
// locals
|
||||
use super::{FileTransferActivity, FsEntry, LogLevel, SelectedEntry, TransferPayload};
|
||||
use crate::fs::FsFile;
|
||||
use super::{FileTransferActivity, LogLevel, SelectedEntry, TransferPayload};
|
||||
|
||||
// ext
|
||||
use remotefs::{Entry, File};
|
||||
use std::fs::OpenOptions;
|
||||
use std::io::Read;
|
||||
use std::path::{Path, PathBuf};
|
||||
@@ -36,7 +37,7 @@ use std::time::SystemTime;
|
||||
|
||||
impl FileTransferActivity {
|
||||
pub(crate) fn action_edit_local_file(&mut self) {
|
||||
let entries: Vec<FsEntry> = match self.get_local_selected_entries() {
|
||||
let entries: Vec<Entry> = match self.get_local_selected_entries() {
|
||||
SelectedEntry::One(entry) => vec![entry],
|
||||
SelectedEntry::Many(entries) => entries,
|
||||
SelectedEntry::None => vec![],
|
||||
@@ -47,10 +48,10 @@ impl FileTransferActivity {
|
||||
if entry.is_file() {
|
||||
self.log(
|
||||
LogLevel::Info,
|
||||
format!("Opening file \"{}\"…", entry.get_abs_path().display()),
|
||||
format!("Opening file \"{}\"…", entry.path().display()),
|
||||
);
|
||||
// Edit file
|
||||
if let Err(err) = self.edit_local_file(entry.get_abs_path().as_path()) {
|
||||
if let Err(err) = self.edit_local_file(entry.path()) {
|
||||
self.log_and_alert(LogLevel::Error, err);
|
||||
}
|
||||
}
|
||||
@@ -60,7 +61,7 @@ impl FileTransferActivity {
|
||||
}
|
||||
|
||||
pub(crate) fn action_edit_remote_file(&mut self) {
|
||||
let entries: Vec<FsEntry> = match self.get_remote_selected_entries() {
|
||||
let entries: Vec<Entry> = match self.get_remote_selected_entries() {
|
||||
SelectedEntry::One(entry) => vec![entry],
|
||||
SelectedEntry::Many(entries) => entries,
|
||||
SelectedEntry::None => vec![],
|
||||
@@ -68,10 +69,10 @@ impl FileTransferActivity {
|
||||
// Edit all entries
|
||||
for entry in entries.into_iter() {
|
||||
// Check if file
|
||||
if let FsEntry::File(file) = entry {
|
||||
if let Entry::File(file) = entry {
|
||||
self.log(
|
||||
LogLevel::Info,
|
||||
format!("Opening file \"{}\"…", file.abs_path.display()),
|
||||
format!("Opening file \"{}\"…", file.path.display()),
|
||||
);
|
||||
// Edit file
|
||||
if let Err(err) = self.edit_remote_file(file) {
|
||||
@@ -149,7 +150,7 @@ impl FileTransferActivity {
|
||||
/// ### edit_remote_file
|
||||
///
|
||||
/// Edit file on remote host
|
||||
fn edit_remote_file(&mut self, file: FsFile) -> Result<(), String> {
|
||||
fn edit_remote_file(&mut self, file: File) -> Result<(), String> {
|
||||
// Create temp file
|
||||
let tmpfile: PathBuf = match self.download_file_as_temp(&file) {
|
||||
Ok(p) => p,
|
||||
@@ -157,7 +158,7 @@ impl FileTransferActivity {
|
||||
};
|
||||
// Download file
|
||||
let file_name = file.name.clone();
|
||||
let file_path = file.abs_path.clone();
|
||||
let file_path = file.path.clone();
|
||||
if let Err(err) = self.filetransfer_recv(
|
||||
TransferPayload::File(file),
|
||||
tmpfile.as_path(),
|
||||
@@ -167,7 +168,7 @@ impl FileTransferActivity {
|
||||
}
|
||||
// Get current file modification time
|
||||
let prev_mtime: SystemTime = match self.host.stat(tmpfile.as_path()) {
|
||||
Ok(e) => e.get_last_change_time(),
|
||||
Ok(e) => e.metadata().mtime,
|
||||
Err(err) => {
|
||||
return Err(format!(
|
||||
"Could not stat \"{}\": {}",
|
||||
@@ -181,7 +182,7 @@ impl FileTransferActivity {
|
||||
return Err(err);
|
||||
}
|
||||
// Get local fs entry
|
||||
let tmpfile_entry: FsEntry = match self.host.stat(tmpfile.as_path()) {
|
||||
let tmpfile_entry: Entry = match self.host.stat(tmpfile.as_path()) {
|
||||
Ok(e) => e,
|
||||
Err(err) => {
|
||||
return Err(format!(
|
||||
@@ -192,7 +193,7 @@ impl FileTransferActivity {
|
||||
}
|
||||
};
|
||||
// Check if file has changed
|
||||
match prev_mtime != tmpfile_entry.get_last_change_time() {
|
||||
match prev_mtime != tmpfile_entry.metadata().mtime {
|
||||
true => {
|
||||
self.log(
|
||||
LogLevel::Info,
|
||||
@@ -202,7 +203,7 @@ impl FileTransferActivity {
|
||||
),
|
||||
);
|
||||
// Get local fs entry
|
||||
let tmpfile_entry: FsFile = match self.host.stat(tmpfile.as_path()) {
|
||||
let tmpfile_entry = match self.host.stat(tmpfile.as_path()) {
|
||||
Ok(e) => e.unwrap_file(),
|
||||
Err(err) => {
|
||||
return Err(format!(
|
||||
|
||||
@@ -49,9 +49,12 @@ impl FileTransferActivity {
|
||||
|
||||
pub(crate) fn action_remote_exec(&mut self, input: String) {
|
||||
match self.client.as_mut().exec(input.as_str()) {
|
||||
Ok(output) => {
|
||||
Ok((rc, output)) => {
|
||||
// Reload files
|
||||
self.log(LogLevel::Info, format!("\"{}\": {}", input, output));
|
||||
self.log(
|
||||
LogLevel::Info,
|
||||
format!("\"{}\" (exitcode: {}): {}", input, rc, output),
|
||||
);
|
||||
self.reload_remote_dir();
|
||||
}
|
||||
Err(err) => {
|
||||
|
||||
@@ -27,21 +27,19 @@
|
||||
*/
|
||||
// locals
|
||||
use super::super::browser::FileExplorerTab;
|
||||
use super::{
|
||||
FileTransferActivity, FsEntry, LogLevel, SelectedEntry, TransferOpts, TransferPayload,
|
||||
};
|
||||
use super::{Entry, FileTransferActivity, LogLevel, SelectedEntry, TransferOpts, TransferPayload};
|
||||
|
||||
use std::path::PathBuf;
|
||||
|
||||
impl FileTransferActivity {
|
||||
pub(crate) fn action_local_find(&mut self, input: String) -> Result<Vec<FsEntry>, String> {
|
||||
pub(crate) fn action_local_find(&mut self, input: String) -> Result<Vec<Entry>, String> {
|
||||
match self.host.find(input.as_str()) {
|
||||
Ok(entries) => Ok(entries),
|
||||
Err(err) => Err(format!("Could not search for files: {}", err)),
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn action_remote_find(&mut self, input: String) -> Result<Vec<FsEntry>, String> {
|
||||
pub(crate) fn action_remote_find(&mut self, input: String) -> Result<Vec<Entry>, String> {
|
||||
match self.client.as_mut().find(input.as_str()) {
|
||||
Ok(entries) => Ok(entries),
|
||||
Err(err) => Err(format!("Could not search for files: {}", err)),
|
||||
@@ -53,8 +51,8 @@ impl FileTransferActivity {
|
||||
if let SelectedEntry::One(entry) = self.get_found_selected_entries() {
|
||||
// Get path: if a directory, use directory path; if it is a File, get parent path
|
||||
let path: PathBuf = match entry {
|
||||
FsEntry::Directory(dir) => dir.abs_path,
|
||||
FsEntry::File(file) => match file.abs_path.parent() {
|
||||
Entry::Directory(dir) => dir.path,
|
||||
Entry::File(file) => match file.path.parent() {
|
||||
None => PathBuf::from("."),
|
||||
Some(p) => p.to_path_buf(),
|
||||
},
|
||||
@@ -86,10 +84,10 @@ impl FileTransferActivity {
|
||||
{
|
||||
// Save pending transfer
|
||||
self.set_pending_transfer(
|
||||
opts.save_as.as_deref().unwrap_or_else(|| entry.get_name()),
|
||||
opts.save_as.as_deref().unwrap_or_else(|| entry.name()),
|
||||
);
|
||||
} else if let Err(err) = self.filetransfer_send(
|
||||
TransferPayload::Any(entry.get_realfile()),
|
||||
TransferPayload::Any(entry),
|
||||
wrkdir.as_path(),
|
||||
opts.save_as,
|
||||
) {
|
||||
@@ -107,10 +105,10 @@ impl FileTransferActivity {
|
||||
{
|
||||
// Save pending transfer
|
||||
self.set_pending_transfer(
|
||||
opts.save_as.as_deref().unwrap_or_else(|| entry.get_name()),
|
||||
opts.save_as.as_deref().unwrap_or_else(|| entry.name()),
|
||||
);
|
||||
} else if let Err(err) = self.filetransfer_recv(
|
||||
TransferPayload::Any(entry.get_realfile()),
|
||||
TransferPayload::Any(entry),
|
||||
wrkdir.as_path(),
|
||||
opts.save_as,
|
||||
) {
|
||||
@@ -128,12 +126,11 @@ impl FileTransferActivity {
|
||||
dest_path.push(save_as);
|
||||
}
|
||||
// Iter files
|
||||
let entries: Vec<FsEntry> = entries.iter().map(|x| x.get_realfile()).collect();
|
||||
match self.browser.tab() {
|
||||
FileExplorerTab::FindLocal | FileExplorerTab::Local => {
|
||||
if opts.check_replace && self.config().get_prompt_on_file_replace() {
|
||||
// Check which file would be replaced
|
||||
let existing_files: Vec<&FsEntry> = entries
|
||||
let existing_files: Vec<&Entry> = entries
|
||||
.iter()
|
||||
.filter(|x| {
|
||||
self.remote_file_exists(
|
||||
@@ -166,7 +163,7 @@ impl FileTransferActivity {
|
||||
FileExplorerTab::FindRemote | FileExplorerTab::Remote => {
|
||||
if opts.check_replace && self.config().get_prompt_on_file_replace() {
|
||||
// Check which file would be replaced
|
||||
let existing_files: Vec<&FsEntry> = entries
|
||||
let existing_files: Vec<&Entry> = entries
|
||||
.iter()
|
||||
.filter(|x| {
|
||||
self.local_file_exists(
|
||||
@@ -218,7 +215,7 @@ impl FileTransferActivity {
|
||||
}
|
||||
}
|
||||
|
||||
fn remove_found_file(&mut self, entry: &FsEntry) {
|
||||
fn remove_found_file(&mut self, entry: &Entry) {
|
||||
match self.browser.tab() {
|
||||
FileExplorerTab::FindLocal | FileExplorerTab::Local => {
|
||||
self.local_remove_file(entry);
|
||||
@@ -263,7 +260,7 @@ impl FileTransferActivity {
|
||||
}
|
||||
}
|
||||
|
||||
fn open_found_file(&mut self, entry: &FsEntry, with: Option<&str>) {
|
||||
fn open_found_file(&mut self, entry: &Entry, with: Option<&str>) {
|
||||
match self.browser.tab() {
|
||||
FileExplorerTab::FindLocal | FileExplorerTab::Local => {
|
||||
self.action_open_local_file(entry, with);
|
||||
|
||||
@@ -27,6 +27,7 @@
|
||||
*/
|
||||
// locals
|
||||
use super::{FileTransferActivity, LogLevel};
|
||||
use remotefs::fs::UnixPex;
|
||||
use std::path::PathBuf;
|
||||
|
||||
impl FileTransferActivity {
|
||||
@@ -48,11 +49,10 @@ impl FileTransferActivity {
|
||||
}
|
||||
}
|
||||
pub(crate) fn action_remote_mkdir(&mut self, input: String) {
|
||||
match self
|
||||
.client
|
||||
.as_mut()
|
||||
.mkdir(PathBuf::from(input.as_str()).as_path())
|
||||
{
|
||||
match self.client.as_mut().create_dir(
|
||||
PathBuf::from(input.as_str()).as_path(),
|
||||
UnixPex::from(0o755),
|
||||
) {
|
||||
Ok(_) => {
|
||||
// Reload files
|
||||
self.log(LogLevel::Info, format!("Created directory \"{}\"", input));
|
||||
|
||||
@@ -26,9 +26,9 @@
|
||||
* SOFTWARE.
|
||||
*/
|
||||
pub(self) use super::{
|
||||
browser::FileExplorerTab, FileTransferActivity, FsEntry, Id, LogLevel, TransferOpts,
|
||||
TransferPayload,
|
||||
browser::FileExplorerTab, FileTransferActivity, Id, LogLevel, TransferOpts, TransferPayload,
|
||||
};
|
||||
pub(self) use remotefs::Entry;
|
||||
use tuirealm::{State, StateValue};
|
||||
|
||||
// actions
|
||||
@@ -47,8 +47,8 @@ pub(crate) mod submit;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub(crate) enum SelectedEntry {
|
||||
One(FsEntry),
|
||||
Many(Vec<FsEntry>),
|
||||
One(Entry),
|
||||
Many(Vec<Entry>),
|
||||
None,
|
||||
}
|
||||
|
||||
@@ -59,8 +59,8 @@ enum SelectedEntryIndex {
|
||||
None,
|
||||
}
|
||||
|
||||
impl From<Option<&FsEntry>> for SelectedEntry {
|
||||
fn from(opt: Option<&FsEntry>) -> Self {
|
||||
impl From<Option<&Entry>> for SelectedEntry {
|
||||
fn from(opt: Option<&Entry>) -> Self {
|
||||
match opt {
|
||||
Some(e) => SelectedEntry::One(e.clone()),
|
||||
None => SelectedEntry::None,
|
||||
@@ -68,8 +68,8 @@ impl From<Option<&FsEntry>> for SelectedEntry {
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Vec<&FsEntry>> for SelectedEntry {
|
||||
fn from(files: Vec<&FsEntry>) -> Self {
|
||||
impl From<Vec<&Entry>> for SelectedEntry {
|
||||
fn from(files: Vec<&Entry>) -> Self {
|
||||
SelectedEntry::Many(files.into_iter().cloned().collect())
|
||||
}
|
||||
}
|
||||
@@ -82,9 +82,9 @@ impl FileTransferActivity {
|
||||
match self.get_selected_index(&Id::ExplorerLocal) {
|
||||
SelectedEntryIndex::One(idx) => SelectedEntry::from(self.local().get(idx)),
|
||||
SelectedEntryIndex::Many(files) => {
|
||||
let files: Vec<&FsEntry> = files
|
||||
let files: Vec<&Entry> = files
|
||||
.iter()
|
||||
.map(|x| self.local().get(*x)) // Usize to Option<FsEntry>
|
||||
.map(|x| self.local().get(*x)) // Usize to Option<Entry>
|
||||
.flatten()
|
||||
.collect();
|
||||
SelectedEntry::from(files)
|
||||
@@ -100,9 +100,9 @@ impl FileTransferActivity {
|
||||
match self.get_selected_index(&Id::ExplorerRemote) {
|
||||
SelectedEntryIndex::One(idx) => SelectedEntry::from(self.remote().get(idx)),
|
||||
SelectedEntryIndex::Many(files) => {
|
||||
let files: Vec<&FsEntry> = files
|
||||
let files: Vec<&Entry> = files
|
||||
.iter()
|
||||
.map(|x| self.remote().get(*x)) // Usize to Option<FsEntry>
|
||||
.map(|x| self.remote().get(*x)) // Usize to Option<Entry>
|
||||
.flatten()
|
||||
.collect();
|
||||
SelectedEntry::from(files)
|
||||
@@ -120,9 +120,9 @@ impl FileTransferActivity {
|
||||
SelectedEntry::from(self.found().as_ref().unwrap().get(idx))
|
||||
}
|
||||
SelectedEntryIndex::Many(files) => {
|
||||
let files: Vec<&FsEntry> = files
|
||||
let files: Vec<&Entry> = files
|
||||
.iter()
|
||||
.map(|x| self.found().as_ref().unwrap().get(*x)) // Usize to Option<FsEntry>
|
||||
.map(|x| self.found().as_ref().unwrap().get(*x)) // Usize to Option<Entry>
|
||||
.flatten()
|
||||
.collect();
|
||||
SelectedEntry::from(files)
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
* SOFTWARE.
|
||||
*/
|
||||
// locals
|
||||
use super::{FileTransferActivity, FsEntry, LogLevel};
|
||||
use super::{Entry, FileTransferActivity, LogLevel};
|
||||
use std::fs::File;
|
||||
use std::path::PathBuf;
|
||||
|
||||
@@ -35,7 +35,7 @@ impl FileTransferActivity {
|
||||
// Check if file exists
|
||||
let mut file_exists: bool = false;
|
||||
for file in self.local().iter_files_all() {
|
||||
if input == file.get_name() {
|
||||
if input == file.name() {
|
||||
file_exists = true;
|
||||
}
|
||||
}
|
||||
@@ -67,7 +67,7 @@ impl FileTransferActivity {
|
||||
// Check if file exists
|
||||
let mut file_exists: bool = false;
|
||||
for file in self.remote().iter_files_all() {
|
||||
if input == file.get_name() {
|
||||
if input == file.name() {
|
||||
file_exists = true;
|
||||
}
|
||||
}
|
||||
@@ -88,7 +88,7 @@ impl FileTransferActivity {
|
||||
),
|
||||
Ok(tfile) => {
|
||||
// Stat tempfile
|
||||
let local_file: FsEntry = match self.host.stat(tfile.path()) {
|
||||
let local_file: Entry = match self.host.stat(tfile.path()) {
|
||||
Err(err) => {
|
||||
self.log_and_alert(
|
||||
LogLevel::Error,
|
||||
@@ -98,7 +98,7 @@ impl FileTransferActivity {
|
||||
}
|
||||
Ok(f) => f,
|
||||
};
|
||||
if let FsEntry::File(local_file) = local_file {
|
||||
if let Entry::File(local_file) = local_file {
|
||||
// Create file
|
||||
let reader = Box::new(match File::open(tfile.path()) {
|
||||
Ok(f) => f,
|
||||
@@ -112,7 +112,7 @@ impl FileTransferActivity {
|
||||
});
|
||||
match self
|
||||
.client
|
||||
.send_file_wno_stream(&local_file, file_path.as_path(), reader)
|
||||
.create_file(file_path.as_path(), &local_file.metadata, reader)
|
||||
{
|
||||
Err(err) => self.log_and_alert(
|
||||
LogLevel::Error,
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
* SOFTWARE.
|
||||
*/
|
||||
// locals
|
||||
use super::{FileTransferActivity, FsEntry, LogLevel, SelectedEntry, TransferPayload};
|
||||
use super::{Entry, FileTransferActivity, LogLevel, SelectedEntry, TransferPayload};
|
||||
// ext
|
||||
use std::path::{Path, PathBuf};
|
||||
|
||||
@@ -35,7 +35,7 @@ impl FileTransferActivity {
|
||||
///
|
||||
/// Open local file
|
||||
pub(crate) fn action_open_local(&mut self) {
|
||||
let entries: Vec<FsEntry> = match self.get_local_selected_entries() {
|
||||
let entries: Vec<Entry> = match self.get_local_selected_entries() {
|
||||
SelectedEntry::One(entry) => vec![entry],
|
||||
SelectedEntry::Many(entries) => entries,
|
||||
SelectedEntry::None => vec![],
|
||||
@@ -49,7 +49,7 @@ impl FileTransferActivity {
|
||||
///
|
||||
/// Open local file
|
||||
pub(crate) fn action_open_remote(&mut self) {
|
||||
let entries: Vec<FsEntry> = match self.get_remote_selected_entries() {
|
||||
let entries: Vec<Entry> = match self.get_remote_selected_entries() {
|
||||
SelectedEntry::One(entry) => vec![entry],
|
||||
SelectedEntry::Many(entries) => entries,
|
||||
SelectedEntry::None => vec![],
|
||||
@@ -62,25 +62,22 @@ impl FileTransferActivity {
|
||||
/// ### action_open_local_file
|
||||
///
|
||||
/// Perform open lopcal file
|
||||
pub(crate) fn action_open_local_file(&mut self, entry: &FsEntry, open_with: Option<&str>) {
|
||||
let entry: FsEntry = entry.get_realfile();
|
||||
self.open_path_with(entry.get_abs_path().as_path(), open_with);
|
||||
pub(crate) fn action_open_local_file(&mut self, entry: &Entry, open_with: Option<&str>) {
|
||||
self.open_path_with(entry.path(), open_with);
|
||||
}
|
||||
|
||||
/// ### action_open_local
|
||||
///
|
||||
/// Open remote file. The file is first downloaded to a temporary directory on localhost
|
||||
pub(crate) fn action_open_remote_file(&mut self, entry: &FsEntry, open_with: Option<&str>) {
|
||||
let entry: FsEntry = entry.get_realfile();
|
||||
pub(crate) fn action_open_remote_file(&mut self, entry: &Entry, open_with: Option<&str>) {
|
||||
// Download file
|
||||
let tmpfile: String =
|
||||
match self.get_cache_tmp_name(entry.get_name(), entry.get_ftype().as_deref()) {
|
||||
None => {
|
||||
self.log(LogLevel::Error, String::from("Could not create tempdir"));
|
||||
return;
|
||||
}
|
||||
Some(p) => p,
|
||||
};
|
||||
let tmpfile: String = match self.get_cache_tmp_name(entry.name(), entry.extension()) {
|
||||
None => {
|
||||
self.log(LogLevel::Error, String::from("Could not create tempdir"));
|
||||
return;
|
||||
}
|
||||
Some(p) => p,
|
||||
};
|
||||
let cache: PathBuf = match self.cache.as_ref() {
|
||||
None => {
|
||||
self.log(LogLevel::Error, String::from("Could not create tempdir"));
|
||||
@@ -89,7 +86,7 @@ impl FileTransferActivity {
|
||||
Some(p) => p.path().to_path_buf(),
|
||||
};
|
||||
match self.filetransfer_recv(
|
||||
TransferPayload::Any(entry),
|
||||
TransferPayload::Any(entry.clone()),
|
||||
cache.as_path(),
|
||||
Some(tmpfile.clone()),
|
||||
) {
|
||||
@@ -114,7 +111,7 @@ impl FileTransferActivity {
|
||||
///
|
||||
/// Open selected file with provided application
|
||||
pub(crate) fn action_local_open_with(&mut self, with: &str) {
|
||||
let entries: Vec<FsEntry> = match self.get_local_selected_entries() {
|
||||
let entries: Vec<Entry> = match self.get_local_selected_entries() {
|
||||
SelectedEntry::One(entry) => vec![entry],
|
||||
SelectedEntry::Many(entries) => entries,
|
||||
SelectedEntry::None => vec![],
|
||||
@@ -129,7 +126,7 @@ impl FileTransferActivity {
|
||||
///
|
||||
/// Open selected file with provided application
|
||||
pub(crate) fn action_remote_open_with(&mut self, with: &str) {
|
||||
let entries: Vec<FsEntry> = match self.get_remote_selected_entries() {
|
||||
let entries: Vec<Entry> = match self.get_remote_selected_entries() {
|
||||
SelectedEntry::One(entry) => vec![entry],
|
||||
SelectedEntry::Many(entries) => entries,
|
||||
SelectedEntry::None => vec![],
|
||||
|
||||
@@ -26,8 +26,9 @@
|
||||
* SOFTWARE.
|
||||
*/
|
||||
// locals
|
||||
use super::{FileTransferActivity, FsEntry, LogLevel, SelectedEntry};
|
||||
use crate::filetransfer::FileTransferErrorType;
|
||||
use super::{Entry, FileTransferActivity, LogLevel, SelectedEntry};
|
||||
|
||||
use remotefs::RemoteErrorType;
|
||||
use std::path::{Path, PathBuf};
|
||||
|
||||
impl FileTransferActivity {
|
||||
@@ -45,7 +46,7 @@ impl FileTransferActivity {
|
||||
// Iter files
|
||||
for entry in entries.iter() {
|
||||
let mut dest_path: PathBuf = base_path.clone();
|
||||
dest_path.push(entry.get_name());
|
||||
dest_path.push(entry.name());
|
||||
self.local_rename_file(entry, dest_path.as_path());
|
||||
}
|
||||
// Reload entries
|
||||
@@ -69,7 +70,7 @@ impl FileTransferActivity {
|
||||
// Iter files
|
||||
for entry in entries.iter() {
|
||||
let mut dest_path: PathBuf = base_path.clone();
|
||||
dest_path.push(entry.get_name());
|
||||
dest_path.push(entry.name());
|
||||
self.remote_rename_file(entry, dest_path.as_path());
|
||||
}
|
||||
// Reload entries
|
||||
@@ -79,14 +80,14 @@ impl FileTransferActivity {
|
||||
}
|
||||
}
|
||||
|
||||
fn local_rename_file(&mut self, entry: &FsEntry, dest: &Path) {
|
||||
fn local_rename_file(&mut self, entry: &Entry, dest: &Path) {
|
||||
match self.host.rename(entry, dest) {
|
||||
Ok(_) => {
|
||||
self.log(
|
||||
LogLevel::Info,
|
||||
format!(
|
||||
"Moved \"{}\" to \"{}\"",
|
||||
entry.get_abs_path().display(),
|
||||
entry.path().display(),
|
||||
dest.display()
|
||||
),
|
||||
);
|
||||
@@ -95,7 +96,7 @@ impl FileTransferActivity {
|
||||
LogLevel::Error,
|
||||
format!(
|
||||
"Could not move \"{}\" to \"{}\": {}",
|
||||
entry.get_abs_path().display(),
|
||||
entry.path().display(),
|
||||
dest.display(),
|
||||
err
|
||||
),
|
||||
@@ -103,26 +104,26 @@ impl FileTransferActivity {
|
||||
}
|
||||
}
|
||||
|
||||
fn remote_rename_file(&mut self, entry: &FsEntry, dest: &Path) {
|
||||
match self.client.as_mut().rename(entry, dest) {
|
||||
fn remote_rename_file(&mut self, entry: &Entry, dest: &Path) {
|
||||
match self.client.as_mut().mov(entry.path(), dest) {
|
||||
Ok(_) => {
|
||||
self.log(
|
||||
LogLevel::Info,
|
||||
format!(
|
||||
"Moved \"{}\" to \"{}\"",
|
||||
entry.get_abs_path().display(),
|
||||
entry.path().display(),
|
||||
dest.display()
|
||||
),
|
||||
);
|
||||
}
|
||||
Err(err) if err.kind() == FileTransferErrorType::UnsupportedFeature => {
|
||||
Err(err) if err.kind == RemoteErrorType::UnsupportedFeature => {
|
||||
self.tricky_move(entry, dest);
|
||||
}
|
||||
Err(err) => self.log_and_alert(
|
||||
LogLevel::Error,
|
||||
format!(
|
||||
"Could not move \"{}\" to \"{}\": {}",
|
||||
entry.get_abs_path().display(),
|
||||
entry.path().display(),
|
||||
dest.display(),
|
||||
err
|
||||
),
|
||||
@@ -134,21 +135,21 @@ impl FileTransferActivity {
|
||||
///
|
||||
/// Tricky move will be used whenever copy command is not available on remote host.
|
||||
/// It basically uses the tricky_copy function, then it just deletes the previous entry (`entry`)
|
||||
fn tricky_move(&mut self, entry: &FsEntry, dest: &Path) {
|
||||
fn tricky_move(&mut self, entry: &Entry, dest: &Path) {
|
||||
debug!(
|
||||
"Using tricky-move to move entry {} to {}",
|
||||
entry.get_abs_path().display(),
|
||||
entry.path().display(),
|
||||
dest.display()
|
||||
);
|
||||
if self.tricky_copy(entry.clone(), dest).is_ok() {
|
||||
// Delete remote existing entry
|
||||
debug!("Tricky-copy worked; removing existing remote entry");
|
||||
match self.client.remove(entry) {
|
||||
match self.client.remove_dir_all(entry.path()) {
|
||||
Ok(_) => self.log(
|
||||
LogLevel::Info,
|
||||
format!(
|
||||
"Moved \"{}\" to \"{}\"",
|
||||
entry.get_abs_path().display(),
|
||||
entry.path().display(),
|
||||
dest.display()
|
||||
),
|
||||
),
|
||||
@@ -156,7 +157,7 @@ impl FileTransferActivity {
|
||||
LogLevel::Error,
|
||||
format!(
|
||||
"Copied \"{}\" to \"{}\"; but failed to remove src: {}",
|
||||
entry.get_abs_path().display(),
|
||||
entry.path().display(),
|
||||
dest.display(),
|
||||
err
|
||||
),
|
||||
|
||||
@@ -27,7 +27,7 @@
|
||||
*/
|
||||
// locals
|
||||
use super::{
|
||||
super::STORAGE_PENDING_TRANSFER, FileExplorerTab, FileTransferActivity, FsEntry, LogLevel,
|
||||
super::STORAGE_PENDING_TRANSFER, Entry, FileExplorerTab, FileTransferActivity, LogLevel,
|
||||
SelectedEntry, TransferOpts, TransferPayload,
|
||||
};
|
||||
use std::path::{Path, PathBuf};
|
||||
@@ -101,10 +101,10 @@ impl FileTransferActivity {
|
||||
{
|
||||
// Save pending transfer
|
||||
self.set_pending_transfer(
|
||||
opts.save_as.as_deref().unwrap_or_else(|| entry.get_name()),
|
||||
opts.save_as.as_deref().unwrap_or_else(|| entry.name()),
|
||||
);
|
||||
} else if let Err(err) = self.filetransfer_send(
|
||||
TransferPayload::Any(entry.get_realfile()),
|
||||
TransferPayload::Any(entry.clone()),
|
||||
wrkdir.as_path(),
|
||||
opts.save_as,
|
||||
) {
|
||||
@@ -123,10 +123,9 @@ impl FileTransferActivity {
|
||||
dest_path.push(save_as);
|
||||
}
|
||||
// Iter files
|
||||
let entries: Vec<FsEntry> = entries.iter().map(|x| x.get_realfile()).collect();
|
||||
if opts.check_replace && self.config().get_prompt_on_file_replace() {
|
||||
// Check which file would be replaced
|
||||
let existing_files: Vec<&FsEntry> = entries
|
||||
let existing_files: Vec<&Entry> = entries
|
||||
.iter()
|
||||
.filter(|x| {
|
||||
self.remote_file_exists(
|
||||
@@ -171,10 +170,10 @@ impl FileTransferActivity {
|
||||
{
|
||||
// Save pending transfer
|
||||
self.set_pending_transfer(
|
||||
opts.save_as.as_deref().unwrap_or_else(|| entry.get_name()),
|
||||
opts.save_as.as_deref().unwrap_or_else(|| entry.name()),
|
||||
);
|
||||
} else if let Err(err) = self.filetransfer_recv(
|
||||
TransferPayload::Any(entry.get_realfile()),
|
||||
TransferPayload::Any(entry.clone()),
|
||||
wrkdir.as_path(),
|
||||
opts.save_as,
|
||||
) {
|
||||
@@ -193,10 +192,9 @@ impl FileTransferActivity {
|
||||
dest_path.push(save_as);
|
||||
}
|
||||
// Iter files
|
||||
let entries: Vec<FsEntry> = entries.iter().map(|x| x.get_realfile()).collect();
|
||||
if opts.check_replace && self.config().get_prompt_on_file_replace() {
|
||||
// Check which file would be replaced
|
||||
let existing_files: Vec<&FsEntry> = entries
|
||||
let existing_files: Vec<&Entry> = entries
|
||||
.iter()
|
||||
.filter(|x| {
|
||||
self.local_file_exists(
|
||||
@@ -244,8 +242,8 @@ impl FileTransferActivity {
|
||||
/// ### set_pending_transfer_many
|
||||
///
|
||||
/// Set pending transfer for many files into storage and mount radio
|
||||
pub(crate) fn set_pending_transfer_many(&mut self, files: Vec<&FsEntry>, dest_path: &str) {
|
||||
let file_names: Vec<&str> = files.iter().map(|x| x.get_name()).collect();
|
||||
pub(crate) fn set_pending_transfer_many(&mut self, files: Vec<&Entry>, dest_path: &str) {
|
||||
let file_names: Vec<&str> = files.iter().map(|x| x.name()).collect();
|
||||
self.mount_radio_replace_many(file_names.as_slice());
|
||||
self.context_mut()
|
||||
.store_mut()
|
||||
@@ -255,16 +253,16 @@ impl FileTransferActivity {
|
||||
/// ### file_to_check
|
||||
///
|
||||
/// Get file to check for path
|
||||
pub(crate) fn file_to_check(e: &FsEntry, alt: Option<&String>) -> PathBuf {
|
||||
pub(crate) fn file_to_check(e: &Entry, alt: Option<&String>) -> PathBuf {
|
||||
match alt {
|
||||
Some(s) => PathBuf::from(s),
|
||||
None => PathBuf::from(e.get_name()),
|
||||
None => PathBuf::from(e.name()),
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn file_to_check_many(e: &FsEntry, wrkdir: &Path) -> PathBuf {
|
||||
pub(crate) fn file_to_check_many(e: &Entry, wrkdir: &Path) -> PathBuf {
|
||||
let mut p = wrkdir.to_path_buf();
|
||||
p.push(e.get_name());
|
||||
p.push(e.name());
|
||||
p
|
||||
}
|
||||
}
|
||||
|
||||
@@ -26,7 +26,9 @@
|
||||
* SOFTWARE.
|
||||
*/
|
||||
// locals
|
||||
use super::{FileTransferActivity, FsEntry};
|
||||
use super::{Entry, FileTransferActivity};
|
||||
|
||||
use remotefs::fs::{File, Metadata};
|
||||
|
||||
enum SubmitAction {
|
||||
ChangeDir,
|
||||
@@ -38,25 +40,41 @@ 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: FsEntry) -> bool {
|
||||
let action: SubmitAction = match &entry {
|
||||
FsEntry::Directory(_) => SubmitAction::ChangeDir,
|
||||
FsEntry::File(file) => {
|
||||
match &file.symlink {
|
||||
Some(symlink_entry) => {
|
||||
// If symlink and is directory, point to symlink
|
||||
match &**symlink_entry {
|
||||
FsEntry::Directory(_) => SubmitAction::ChangeDir,
|
||||
_ => SubmitAction::None,
|
||||
}
|
||||
pub(crate) fn action_submit_local(&mut self, entry: Entry) -> bool {
|
||||
let (action, entry) = match &entry {
|
||||
Entry::Directory(_) => (SubmitAction::ChangeDir, entry),
|
||||
Entry::File(File {
|
||||
path,
|
||||
metadata:
|
||||
Metadata {
|
||||
symlink: Some(symlink),
|
||||
..
|
||||
},
|
||||
..
|
||||
}) => {
|
||||
// Stat file
|
||||
let stat_file = match self.host.stat(symlink.as_path()) {
|
||||
Ok(e) => e,
|
||||
Err(err) => {
|
||||
warn!(
|
||||
"Could not stat file pointed by {} ({}): {}",
|
||||
path.display(),
|
||||
symlink.display(),
|
||||
err
|
||||
);
|
||||
entry
|
||||
}
|
||||
None => SubmitAction::None,
|
||||
}
|
||||
};
|
||||
(SubmitAction::ChangeDir, stat_file)
|
||||
}
|
||||
Entry::File(_) => (SubmitAction::None, entry),
|
||||
};
|
||||
match action {
|
||||
SubmitAction::ChangeDir => self.action_enter_local_dir(entry, false),
|
||||
SubmitAction::None => false,
|
||||
match (action, entry) {
|
||||
(SubmitAction::ChangeDir, Entry::Directory(dir)) => {
|
||||
self.action_enter_local_dir(dir, false)
|
||||
}
|
||||
(SubmitAction::ChangeDir, _) => false,
|
||||
(SubmitAction::None, _) => false,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -64,25 +82,41 @@ impl FileTransferActivity {
|
||||
///
|
||||
/// 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: FsEntry) -> bool {
|
||||
let action: SubmitAction = match &entry {
|
||||
FsEntry::Directory(_) => SubmitAction::ChangeDir,
|
||||
FsEntry::File(file) => {
|
||||
match &file.symlink {
|
||||
Some(symlink_entry) => {
|
||||
// If symlink and is directory, point to symlink
|
||||
match &**symlink_entry {
|
||||
FsEntry::Directory(_) => SubmitAction::ChangeDir,
|
||||
_ => SubmitAction::None,
|
||||
}
|
||||
pub(crate) fn action_submit_remote(&mut self, entry: Entry) -> bool {
|
||||
let (action, entry) = match &entry {
|
||||
Entry::Directory(_) => (SubmitAction::ChangeDir, entry),
|
||||
Entry::File(File {
|
||||
path,
|
||||
metadata:
|
||||
Metadata {
|
||||
symlink: Some(symlink),
|
||||
..
|
||||
},
|
||||
..
|
||||
}) => {
|
||||
// Stat file
|
||||
let stat_file = match self.client.stat(symlink.as_path()) {
|
||||
Ok(e) => e,
|
||||
Err(err) => {
|
||||
warn!(
|
||||
"Could not stat file pointed by {} ({}): {}",
|
||||
path.display(),
|
||||
symlink.display(),
|
||||
err
|
||||
);
|
||||
entry
|
||||
}
|
||||
None => SubmitAction::None,
|
||||
}
|
||||
};
|
||||
(SubmitAction::ChangeDir, stat_file)
|
||||
}
|
||||
Entry::File(_) => (SubmitAction::None, entry),
|
||||
};
|
||||
match action {
|
||||
SubmitAction::ChangeDir => self.action_enter_remote_dir(entry, false),
|
||||
SubmitAction::None => false,
|
||||
match (action, entry) {
|
||||
(SubmitAction::ChangeDir, Entry::Directory(dir)) => {
|
||||
self.action_enter_remote_dir(dir, false)
|
||||
}
|
||||
(SubmitAction::ChangeDir, _) => false,
|
||||
(SubmitAction::None, _) => false,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -225,21 +225,12 @@ impl Component<Msg, NoUserEvent> for Log {
|
||||
/// ## OwnStates
|
||||
///
|
||||
/// OwnStates contains states for this component
|
||||
#[derive(Clone)]
|
||||
#[derive(Clone, Default)]
|
||||
struct OwnStates {
|
||||
list_index: usize, // Index of selected element in list
|
||||
list_len: usize, // Length of file list
|
||||
}
|
||||
|
||||
impl Default for OwnStates {
|
||||
fn default() -> Self {
|
||||
OwnStates {
|
||||
list_index: 0,
|
||||
list_len: 0,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl OwnStates {
|
||||
/// ### set_list_len
|
||||
///
|
||||
|
||||
@@ -27,12 +27,11 @@
|
||||
*/
|
||||
use super::super::Browser;
|
||||
use super::{Msg, TransferMsg, UiMsg};
|
||||
use crate::fs::explorer::FileSorting;
|
||||
use crate::fs::FsEntry;
|
||||
use crate::explorer::FileSorting;
|
||||
use crate::utils::fmt::fmt_time;
|
||||
|
||||
use bytesize::ByteSize;
|
||||
use std::path::PathBuf;
|
||||
use remotefs::Entry;
|
||||
|
||||
use tui_realm_stdlib::{Input, List, Paragraph, ProgressBar, Radio, Span};
|
||||
use tuirealm::command::{Cmd, CmdResult, Direction, Position};
|
||||
@@ -400,38 +399,32 @@ pub struct FileInfoPopup {
|
||||
}
|
||||
|
||||
impl FileInfoPopup {
|
||||
pub fn new(file: &FsEntry) -> Self {
|
||||
pub fn new(file: &Entry) -> Self {
|
||||
let mut texts: TableBuilder = TableBuilder::default();
|
||||
// Abs path
|
||||
let real_path: Option<PathBuf> = {
|
||||
let real_file: FsEntry = file.get_realfile();
|
||||
match real_file.get_abs_path() != file.get_abs_path() {
|
||||
true => Some(real_file.get_abs_path()),
|
||||
false => None,
|
||||
}
|
||||
};
|
||||
let real_path = file.metadata().symlink.as_deref();
|
||||
let path: String = match real_path {
|
||||
Some(symlink) => format!("{} -> {}", file.get_abs_path().display(), symlink.display()),
|
||||
None => format!("{}", file.get_abs_path().display()),
|
||||
Some(symlink) => format!("{} -> {}", file.path().display(), symlink.display()),
|
||||
None => format!("{}", file.path().display()),
|
||||
};
|
||||
// Make texts
|
||||
texts
|
||||
.add_col(TextSpan::from("Path: "))
|
||||
.add_col(TextSpan::new(path.as_str()).fg(Color::Yellow));
|
||||
if let Some(filetype) = file.get_ftype() {
|
||||
if let Some(filetype) = file.extension() {
|
||||
texts
|
||||
.add_row()
|
||||
.add_col(TextSpan::from("File type: "))
|
||||
.add_col(TextSpan::new(filetype.as_str()).fg(Color::LightGreen));
|
||||
.add_col(TextSpan::new(filetype).fg(Color::LightGreen));
|
||||
}
|
||||
let (bsize, size): (ByteSize, usize) = (ByteSize(file.get_size() as u64), file.get_size());
|
||||
let (bsize, size): (ByteSize, u64) = (ByteSize(file.metadata().size), file.metadata().size);
|
||||
texts
|
||||
.add_row()
|
||||
.add_col(TextSpan::from("Size: "))
|
||||
.add_col(TextSpan::new(format!("{} ({})", bsize, size).as_str()).fg(Color::Cyan));
|
||||
let ctime: String = fmt_time(file.get_creation_time(), "%b %d %Y %H:%M:%S");
|
||||
let atime: String = fmt_time(file.get_last_access_time(), "%b %d %Y %H:%M:%S");
|
||||
let mtime: String = fmt_time(file.get_creation_time(), "%b %d %Y %H:%M:%S");
|
||||
let atime: String = fmt_time(file.metadata().atime, "%b %d %Y %H:%M:%S");
|
||||
let ctime: String = fmt_time(file.metadata().ctime, "%b %d %Y %H:%M:%S");
|
||||
let mtime: String = fmt_time(file.metadata().mtime, "%b %d %Y %H:%M:%S");
|
||||
texts
|
||||
.add_row()
|
||||
.add_col(TextSpan::from("Creation time: "))
|
||||
@@ -446,7 +439,7 @@ impl FileInfoPopup {
|
||||
.add_col(TextSpan::new(atime.as_str()).fg(Color::LightRed));
|
||||
// User
|
||||
#[cfg(target_family = "unix")]
|
||||
let username: String = match file.get_user() {
|
||||
let username: String = match file.metadata().uid {
|
||||
Some(uid) => match get_user_by_uid(uid) {
|
||||
Some(user) => user.name().to_string_lossy().to_string(),
|
||||
None => uid.to_string(),
|
||||
@@ -454,10 +447,10 @@ impl FileInfoPopup {
|
||||
None => String::from("0"),
|
||||
};
|
||||
#[cfg(target_os = "windows")]
|
||||
let username: String = format!("{}", file.get_user().unwrap_or(0));
|
||||
let username: String = format!("{}", file.metadata().uid.unwrap_or(0));
|
||||
// Group
|
||||
#[cfg(target_family = "unix")]
|
||||
let group: String = match file.get_group() {
|
||||
let group: String = match file.metadata().gid {
|
||||
Some(gid) => match get_group_by_gid(gid) {
|
||||
Some(group) => group.name().to_string_lossy().to_string(),
|
||||
None => gid.to_string(),
|
||||
@@ -465,7 +458,7 @@ impl FileInfoPopup {
|
||||
None => String::from("0"),
|
||||
};
|
||||
#[cfg(target_os = "windows")]
|
||||
let group: String = format!("{}", file.get_group().unwrap_or(0));
|
||||
let group: String = format!("{}", file.metadata().gid.unwrap_or(0));
|
||||
texts
|
||||
.add_row()
|
||||
.add_col(TextSpan::from("User: "))
|
||||
@@ -478,7 +471,7 @@ impl FileInfoPopup {
|
||||
component: List::default()
|
||||
.borders(Borders::default().modifiers(BorderType::Rounded))
|
||||
.scroll(false)
|
||||
.title(file.get_name(), Alignment::Left)
|
||||
.title(file.name(), Alignment::Left)
|
||||
.rows(texts.build()),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -39,21 +39,12 @@ pub const FILE_LIST_CMD_SELECT_ALL: &str = "A";
|
||||
/// ## OwnStates
|
||||
///
|
||||
/// OwnStates contains states for this component
|
||||
#[derive(Clone)]
|
||||
#[derive(Clone, Default)]
|
||||
struct OwnStates {
|
||||
list_index: usize, // Index of selected element in list
|
||||
selected: Vec<usize>, // Selected files
|
||||
}
|
||||
|
||||
impl Default for OwnStates {
|
||||
fn default() -> Self {
|
||||
OwnStates {
|
||||
list_index: 0,
|
||||
selected: Vec::new(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl OwnStates {
|
||||
/// ### init_list_states
|
||||
///
|
||||
|
||||
@@ -25,10 +25,10 @@
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
use crate::fs::explorer::{builder::FileExplorerBuilder, FileExplorer, FileSorting, GroupDirs};
|
||||
use crate::fs::FsEntry;
|
||||
use crate::explorer::{builder::FileExplorerBuilder, FileExplorer, FileSorting, GroupDirs};
|
||||
use crate::system::config_client::ConfigClient;
|
||||
|
||||
use remotefs::Entry;
|
||||
use std::path::Path;
|
||||
|
||||
/// ## FileExplorerTab
|
||||
@@ -100,7 +100,7 @@ impl Browser {
|
||||
self.found.as_mut().map(|x| &mut x.1)
|
||||
}
|
||||
|
||||
pub fn set_found(&mut self, tab: FoundExplorerTab, files: Vec<FsEntry>, wrkdir: &Path) {
|
||||
pub fn set_found(&mut self, tab: FoundExplorerTab, files: Vec<Entry>, wrkdir: &Path) {
|
||||
let mut explorer = Self::build_found_explorer(wrkdir);
|
||||
explorer.set_files(files);
|
||||
self.found = Some((tab, explorer));
|
||||
|
||||
@@ -29,7 +29,6 @@ use super::{
|
||||
use crate::filetransfer::ProtocolParams;
|
||||
use crate::system::environment;
|
||||
use crate::system::notifications::Notification;
|
||||
use crate::system::sshkey_storage::SshKeyStorage;
|
||||
use crate::utils::fmt::{fmt_millis, fmt_path_elide_ex};
|
||||
use crate::utils::path;
|
||||
// Ext
|
||||
@@ -120,13 +119,6 @@ impl FileTransferActivity {
|
||||
}
|
||||
}
|
||||
|
||||
/// ### make_ssh_storage
|
||||
///
|
||||
/// Make ssh storage from `ConfigClient` if possible, empty otherwise (empty is implicit if degraded)
|
||||
pub(super) fn make_ssh_storage(cli: &ConfigClient) -> SshKeyStorage {
|
||||
SshKeyStorage::storage_from_config(cli)
|
||||
}
|
||||
|
||||
/// ### setup_text_editor
|
||||
///
|
||||
/// Set text editor to use
|
||||
@@ -227,7 +219,7 @@ impl FileTransferActivity {
|
||||
TransferPayload::Any(entry) => {
|
||||
format!(
|
||||
"\"{}\" has been successfully transferred ({})",
|
||||
entry.get_name(),
|
||||
entry.name(),
|
||||
transfer_stats
|
||||
)
|
||||
}
|
||||
|
||||
@@ -37,10 +37,8 @@ mod view;
|
||||
// locals
|
||||
use super::{Activity, Context, ExitReason};
|
||||
use crate::config::themes::Theme;
|
||||
use crate::filetransfer::{FileTransfer, FileTransferProtocol};
|
||||
use crate::filetransfer::{FtpFileTransfer, S3FileTransfer, ScpFileTransfer, SftpFileTransfer};
|
||||
use crate::fs::explorer::{FileExplorer, FileSorting};
|
||||
use crate::fs::FsEntry;
|
||||
use crate::explorer::{FileExplorer, FileSorting};
|
||||
use crate::filetransfer::{Builder, FileTransferParams};
|
||||
use crate::host::Localhost;
|
||||
use crate::system::config_client::ConfigClient;
|
||||
pub(self) use lib::browser;
|
||||
@@ -50,6 +48,7 @@ pub(self) use session::TransferPayload;
|
||||
|
||||
// Includes
|
||||
use chrono::{DateTime, Local};
|
||||
use remotefs::RemoteFs;
|
||||
use std::collections::VecDeque;
|
||||
use std::time::Duration;
|
||||
use tempfile::TempDir;
|
||||
@@ -217,8 +216,8 @@ pub struct FileTransferActivity {
|
||||
redraw: bool,
|
||||
/// Localhost bridge
|
||||
host: Localhost,
|
||||
/// Remote host
|
||||
client: Box<dyn FileTransfer>,
|
||||
/// Remote host client
|
||||
client: Box<dyn RemoteFs>,
|
||||
/// Browser
|
||||
browser: Browser,
|
||||
/// Current log lines
|
||||
@@ -232,7 +231,7 @@ impl FileTransferActivity {
|
||||
/// ### new
|
||||
///
|
||||
/// Instantiates a new FileTransferActivity
|
||||
pub fn new(host: Localhost, protocol: FileTransferProtocol, ticks: Duration) -> Self {
|
||||
pub fn new(host: Localhost, params: &FileTransferParams, ticks: Duration) -> Self {
|
||||
// Get config client
|
||||
let config_client: ConfigClient = Self::init_config_client();
|
||||
Self {
|
||||
@@ -245,16 +244,7 @@ impl FileTransferActivity {
|
||||
),
|
||||
redraw: true,
|
||||
host,
|
||||
client: match protocol {
|
||||
FileTransferProtocol::Sftp => Box::new(SftpFileTransfer::new(
|
||||
Self::make_ssh_storage(&config_client),
|
||||
)),
|
||||
FileTransferProtocol::Ftp(ftps) => Box::new(FtpFileTransfer::new(ftps)),
|
||||
FileTransferProtocol::Scp => {
|
||||
Box::new(ScpFileTransfer::new(Self::make_ssh_storage(&config_client)))
|
||||
}
|
||||
FileTransferProtocol::AwsS3 => Box::new(S3FileTransfer::default()),
|
||||
},
|
||||
client: Builder::build(params.protocol, params.params.clone(), &config_client),
|
||||
browser: Browser::new(&config_client),
|
||||
log_records: VecDeque::with_capacity(256), // 256 events is enough I guess
|
||||
transfer: TransferStates::default(),
|
||||
|
||||
@@ -27,14 +27,14 @@
|
||||
*/
|
||||
// Locals
|
||||
use super::{FileTransferActivity, LogLevel};
|
||||
use crate::filetransfer::{FileTransferError, FileTransferErrorType};
|
||||
use crate::fs::{FsEntry, FsFile};
|
||||
use crate::host::HostError;
|
||||
use crate::utils::fmt::fmt_millis;
|
||||
|
||||
// Ext
|
||||
use bytesize::ByteSize;
|
||||
use std::fs::File;
|
||||
use remotefs::fs::{Entry, File, UnixPex, Welcome};
|
||||
use remotefs::{RemoteError, RemoteErrorType};
|
||||
use std::fs::File as StdFile;
|
||||
use std::io::{Read, Seek, Write};
|
||||
use std::path::{Path, PathBuf};
|
||||
use std::time::Instant;
|
||||
@@ -56,20 +56,20 @@ enum TransferErrorReason {
|
||||
#[error("I/O error on remote: {0}")]
|
||||
RemoteIoError(std::io::Error),
|
||||
#[error("File transfer error: {0}")]
|
||||
FileTransferError(FileTransferError),
|
||||
FileTransferError(RemoteError),
|
||||
}
|
||||
|
||||
/// ## TransferPayload
|
||||
///
|
||||
/// Represents the entity to send or receive during a transfer.
|
||||
/// - File: describes an individual `FsFile` to send
|
||||
/// - Any: Can be any kind of `FsEntry`, but just one
|
||||
/// - Many: a list of `FsEntry`
|
||||
/// - File: describes an individual `File` to send
|
||||
/// - Any: Can be any kind of `Entry`, but just one
|
||||
/// - Many: a list of `Entry`
|
||||
#[derive(Debug)]
|
||||
pub(super) enum TransferPayload {
|
||||
File(FsFile),
|
||||
Any(FsEntry),
|
||||
Many(Vec<FsEntry>),
|
||||
File(File),
|
||||
Any(Entry),
|
||||
Many(Vec<Entry>),
|
||||
}
|
||||
|
||||
impl FileTransferActivity {
|
||||
@@ -78,11 +78,11 @@ impl FileTransferActivity {
|
||||
/// Connect to remote
|
||||
pub(super) fn connect(&mut self) {
|
||||
let ft_params = self.context().ft_params().unwrap().clone();
|
||||
let entry_dir: Option<PathBuf> = ft_params.entry_directory.clone();
|
||||
let entry_dir: Option<PathBuf> = ft_params.entry_directory;
|
||||
// Connect to remote
|
||||
match self.client.connect(&ft_params.params) {
|
||||
Ok(welcome) => {
|
||||
if let Some(banner) = welcome {
|
||||
match self.client.connect() {
|
||||
Ok(Welcome { banner, .. }) => {
|
||||
if let Some(banner) = banner {
|
||||
// Log welcome
|
||||
self.log(
|
||||
LogLevel::Info,
|
||||
@@ -234,17 +234,17 @@ impl FileTransferActivity {
|
||||
/// Send one file to remote at specified path.
|
||||
fn filetransfer_send_file(
|
||||
&mut self,
|
||||
file: &FsFile,
|
||||
file: &File,
|
||||
curr_remote_path: &Path,
|
||||
dst_name: Option<String>,
|
||||
) -> Result<(), String> {
|
||||
// Reset states
|
||||
self.transfer.reset();
|
||||
// Calculate total size of transfer
|
||||
let total_transfer_size: usize = file.size;
|
||||
let total_transfer_size: usize = file.metadata.size as usize;
|
||||
self.transfer.full.init(total_transfer_size);
|
||||
// Mount progress bar
|
||||
self.mount_progress_bar(format!("Uploading {}…", file.abs_path.display()));
|
||||
self.mount_progress_bar(format!("Uploading {}…", file.path.display()));
|
||||
// Get remote path
|
||||
let file_name: String = file.name.clone();
|
||||
let mut remote_path: PathBuf = PathBuf::from(curr_remote_path);
|
||||
@@ -266,7 +266,7 @@ impl FileTransferActivity {
|
||||
/// Send a `TransferPayload` of type `Any`
|
||||
fn filetransfer_send_any(
|
||||
&mut self,
|
||||
entry: &FsEntry,
|
||||
entry: &Entry,
|
||||
curr_remote_path: &Path,
|
||||
dst_name: Option<String>,
|
||||
) -> Result<(), String> {
|
||||
@@ -276,7 +276,7 @@ impl FileTransferActivity {
|
||||
let total_transfer_size: usize = self.get_total_transfer_size_local(entry);
|
||||
self.transfer.full.init(total_transfer_size);
|
||||
// Mount progress bar
|
||||
self.mount_progress_bar(format!("Uploading {}…", entry.get_abs_path().display()));
|
||||
self.mount_progress_bar(format!("Uploading {}…", entry.path().display()));
|
||||
// Send recurse
|
||||
let result = self.filetransfer_send_recurse(entry, curr_remote_path, dst_name);
|
||||
// Umount progress bar
|
||||
@@ -289,7 +289,7 @@ impl FileTransferActivity {
|
||||
/// Send many entries to remote
|
||||
fn filetransfer_send_many(
|
||||
&mut self,
|
||||
entries: &[FsEntry],
|
||||
entries: &[Entry],
|
||||
curr_remote_path: &Path,
|
||||
) -> Result<(), String> {
|
||||
// Reset states
|
||||
@@ -315,14 +315,14 @@ impl FileTransferActivity {
|
||||
|
||||
fn filetransfer_send_recurse(
|
||||
&mut self,
|
||||
entry: &FsEntry,
|
||||
entry: &Entry,
|
||||
curr_remote_path: &Path,
|
||||
dst_name: Option<String>,
|
||||
) -> Result<(), String> {
|
||||
// Write popup
|
||||
let file_name: String = match entry {
|
||||
FsEntry::Directory(dir) => dir.name.clone(),
|
||||
FsEntry::File(file) => file.name.clone(),
|
||||
Entry::Directory(dir) => dir.name.clone(),
|
||||
Entry::File(file) => file.name.clone(),
|
||||
};
|
||||
// Get remote path
|
||||
let mut remote_path: PathBuf = PathBuf::from(curr_remote_path);
|
||||
@@ -333,7 +333,7 @@ impl FileTransferActivity {
|
||||
remote_path.push(remote_file_name);
|
||||
// Match entry
|
||||
let result: Result<(), String> = match entry {
|
||||
FsEntry::File(file) => {
|
||||
Entry::File(file) => {
|
||||
match self.filetransfer_send_one(file, remote_path.as_path(), file_name) {
|
||||
Err(err) => {
|
||||
// If transfer was abrupted or there was an IO error on remote, remove file
|
||||
@@ -352,7 +352,7 @@ impl FileTransferActivity {
|
||||
),
|
||||
),
|
||||
Ok(entry) => {
|
||||
if let Err(err) = self.client.remove(&entry) {
|
||||
if let Err(err) = self.client.remove_file(entry.path()) {
|
||||
self.log(
|
||||
LogLevel::Error,
|
||||
format!(
|
||||
@@ -370,16 +370,19 @@ impl FileTransferActivity {
|
||||
Ok(_) => Ok(()),
|
||||
}
|
||||
}
|
||||
FsEntry::Directory(dir) => {
|
||||
Entry::Directory(dir) => {
|
||||
// Create directory on remote first
|
||||
match self.client.mkdir(remote_path.as_path()) {
|
||||
match self
|
||||
.client
|
||||
.create_dir(remote_path.as_path(), UnixPex::from(0o755))
|
||||
{
|
||||
Ok(_) => {
|
||||
self.log(
|
||||
LogLevel::Info,
|
||||
format!("Created directory \"{}\"", remote_path.display()),
|
||||
);
|
||||
}
|
||||
Err(err) if err.kind() == FileTransferErrorType::DirectoryAlreadyExists => {
|
||||
Err(err) if err.kind == RemoteErrorType::DirectoryAlreadyExists => {
|
||||
self.log(
|
||||
LogLevel::Info,
|
||||
format!(
|
||||
@@ -401,7 +404,7 @@ impl FileTransferActivity {
|
||||
}
|
||||
}
|
||||
// Get files in dir
|
||||
match self.host.scan_dir(dir.abs_path.as_path()) {
|
||||
match self.host.scan_dir(dir.path.as_path()) {
|
||||
Ok(entries) => {
|
||||
// Iterate over files
|
||||
for entry in entries.iter() {
|
||||
@@ -423,7 +426,7 @@ impl FileTransferActivity {
|
||||
LogLevel::Error,
|
||||
format!(
|
||||
"Could not scan directory \"{}\": {}",
|
||||
dir.abs_path.display(),
|
||||
dir.path.display(),
|
||||
err
|
||||
),
|
||||
);
|
||||
@@ -439,7 +442,7 @@ impl FileTransferActivity {
|
||||
// Log abort
|
||||
self.log_and_alert(
|
||||
LogLevel::Warn,
|
||||
format!("Upload aborted for \"{}\"!", entry.get_abs_path().display()),
|
||||
format!("Upload aborted for \"{}\"!", entry.path().display()),
|
||||
);
|
||||
}
|
||||
result
|
||||
@@ -450,18 +453,24 @@ impl FileTransferActivity {
|
||||
/// Send local file and write it to remote path
|
||||
fn filetransfer_send_one(
|
||||
&mut self,
|
||||
local: &FsFile,
|
||||
local: &File,
|
||||
remote: &Path,
|
||||
file_name: String,
|
||||
) -> Result<(), TransferErrorReason> {
|
||||
// Sync file size and attributes before transfer
|
||||
let metadata = self
|
||||
.host
|
||||
.stat(local.path.as_path())
|
||||
.map_err(TransferErrorReason::HostError)
|
||||
.map(|x| x.metadata().clone())?;
|
||||
// Upload file
|
||||
// Try to open local file
|
||||
match self.host.open_file_read(local.abs_path.as_path()) {
|
||||
Ok(fhnd) => match self.client.send_file(local, remote) {
|
||||
match self.host.open_file_read(local.path.as_path()) {
|
||||
Ok(fhnd) => match self.client.create(remote, &metadata) {
|
||||
Ok(rhnd) => {
|
||||
self.filetransfer_send_one_with_stream(local, remote, file_name, fhnd, rhnd)
|
||||
}
|
||||
Err(err) if err.kind() == FileTransferErrorType::UnsupportedFeature => {
|
||||
Err(err) if err.kind == RemoteErrorType::UnsupportedFeature => {
|
||||
self.filetransfer_send_one_wno_stream(local, remote, file_name, fhnd)
|
||||
}
|
||||
Err(err) => Err(TransferErrorReason::FileTransferError(err)),
|
||||
@@ -475,10 +484,10 @@ impl FileTransferActivity {
|
||||
/// Send file to remote using stream
|
||||
fn filetransfer_send_one_with_stream(
|
||||
&mut self,
|
||||
local: &FsFile,
|
||||
local: &File,
|
||||
remote: &Path,
|
||||
file_name: String,
|
||||
mut reader: File,
|
||||
mut reader: StdFile,
|
||||
mut writer: Box<dyn Write>,
|
||||
) -> Result<(), TransferErrorReason> {
|
||||
// Write file
|
||||
@@ -548,7 +557,7 @@ impl FileTransferActivity {
|
||||
}
|
||||
}
|
||||
// Finalize stream
|
||||
if let Err(err) = self.client.on_sent(writer) {
|
||||
if let Err(err) = self.client.on_written(writer) {
|
||||
self.log(
|
||||
LogLevel::Warn,
|
||||
format!("Could not finalize remote stream: \"{}\"", err),
|
||||
@@ -562,7 +571,7 @@ impl FileTransferActivity {
|
||||
LogLevel::Info,
|
||||
format!(
|
||||
"Saved file \"{}\" to \"{}\" (took {} seconds; at {}/s)",
|
||||
local.abs_path.display(),
|
||||
local.path.display(),
|
||||
remote.display(),
|
||||
fmt_millis(self.transfer.partial.started().elapsed()),
|
||||
ByteSize(self.transfer.partial.calc_bytes_per_second()),
|
||||
@@ -573,14 +582,20 @@ impl FileTransferActivity {
|
||||
|
||||
/// ### filetransfer_send_one_wno_stream
|
||||
///
|
||||
/// Send an `FsFile` to remote without using streams.
|
||||
/// Send an `File` to remote without using streams.
|
||||
fn filetransfer_send_one_wno_stream(
|
||||
&mut self,
|
||||
local: &FsFile,
|
||||
local: &File,
|
||||
remote: &Path,
|
||||
file_name: String,
|
||||
mut reader: File,
|
||||
mut reader: StdFile,
|
||||
) -> Result<(), TransferErrorReason> {
|
||||
// Sync file size and attributes before transfer
|
||||
let metadata = self
|
||||
.host
|
||||
.stat(local.path.as_path())
|
||||
.map_err(TransferErrorReason::HostError)
|
||||
.map(|x| x.metadata().clone())?;
|
||||
// Write file
|
||||
let file_size: usize = reader.seek(std::io::SeekFrom::End(0)).unwrap_or(0) as usize;
|
||||
// Init transfer
|
||||
@@ -593,10 +608,7 @@ impl FileTransferActivity {
|
||||
self.update_progress_bar(format!("Uploading \"{}\"…", file_name));
|
||||
self.view();
|
||||
// Send file
|
||||
if let Err(err) = self
|
||||
.client
|
||||
.send_file_wno_stream(local, remote, Box::new(reader))
|
||||
{
|
||||
if let Err(err) = self.client.create_file(remote, &metadata, Box::new(reader)) {
|
||||
return Err(TransferErrorReason::FileTransferError(err));
|
||||
}
|
||||
// Set transfer size ok
|
||||
@@ -610,7 +622,7 @@ impl FileTransferActivity {
|
||||
LogLevel::Info,
|
||||
format!(
|
||||
"Saved file \"{}\" to \"{}\" (took {} seconds; at {}/s)",
|
||||
local.abs_path.display(),
|
||||
local.path.display(),
|
||||
remote.display(),
|
||||
fmt_millis(self.transfer.partial.started().elapsed()),
|
||||
ByteSize(self.transfer.partial.calc_bytes_per_second()),
|
||||
@@ -656,7 +668,7 @@ impl FileTransferActivity {
|
||||
/// If entry is a directory, this applies to directory only
|
||||
fn filetransfer_recv_any(
|
||||
&mut self,
|
||||
entry: &FsEntry,
|
||||
entry: &Entry,
|
||||
local_path: &Path,
|
||||
dst_name: Option<String>,
|
||||
) -> Result<(), String> {
|
||||
@@ -666,7 +678,7 @@ impl FileTransferActivity {
|
||||
let total_transfer_size: usize = self.get_total_transfer_size_remote(entry);
|
||||
self.transfer.full.init(total_transfer_size);
|
||||
// Mount progress bar
|
||||
self.mount_progress_bar(format!("Downloading {}…", entry.get_abs_path().display()));
|
||||
self.mount_progress_bar(format!("Downloading {}…", entry.path().display()));
|
||||
// Receive
|
||||
let result = self.filetransfer_recv_recurse(entry, local_path, dst_name);
|
||||
// Umount progress bar
|
||||
@@ -677,14 +689,14 @@ impl FileTransferActivity {
|
||||
/// ### filetransfer_recv_file
|
||||
///
|
||||
/// Receive a single file from remote.
|
||||
fn filetransfer_recv_file(&mut self, entry: &FsFile, local_path: &Path) -> Result<(), String> {
|
||||
fn filetransfer_recv_file(&mut self, entry: &File, local_path: &Path) -> Result<(), String> {
|
||||
// Reset states
|
||||
self.transfer.reset();
|
||||
// Calculate total transfer size
|
||||
let total_transfer_size: usize = entry.size;
|
||||
let total_transfer_size: usize = entry.metadata.size as usize;
|
||||
self.transfer.full.init(total_transfer_size);
|
||||
// Mount progress bar
|
||||
self.mount_progress_bar(format!("Downloading {}…", entry.abs_path.display()));
|
||||
self.mount_progress_bar(format!("Downloading {}…", entry.path.display()));
|
||||
// Receive
|
||||
let result = self.filetransfer_recv_one(local_path, entry, entry.name.clone());
|
||||
// Umount progress bar
|
||||
@@ -698,7 +710,7 @@ impl FileTransferActivity {
|
||||
/// Send many entries to remote
|
||||
fn filetransfer_recv_many(
|
||||
&mut self,
|
||||
entries: &[FsEntry],
|
||||
entries: &[Entry],
|
||||
curr_remote_path: &Path,
|
||||
) -> Result<(), String> {
|
||||
// Reset states
|
||||
@@ -724,18 +736,18 @@ impl FileTransferActivity {
|
||||
|
||||
fn filetransfer_recv_recurse(
|
||||
&mut self,
|
||||
entry: &FsEntry,
|
||||
entry: &Entry,
|
||||
local_path: &Path,
|
||||
dst_name: Option<String>,
|
||||
) -> Result<(), String> {
|
||||
// Write popup
|
||||
let file_name: String = match entry {
|
||||
FsEntry::Directory(dir) => dir.name.clone(),
|
||||
FsEntry::File(file) => file.name.clone(),
|
||||
Entry::Directory(dir) => dir.name.clone(),
|
||||
Entry::File(file) => file.name.clone(),
|
||||
};
|
||||
// Match entry
|
||||
let result: Result<(), String> = match entry {
|
||||
FsEntry::File(file) => {
|
||||
Entry::File(file) => {
|
||||
// Get local file
|
||||
let mut local_file_path: PathBuf = PathBuf::from(local_path);
|
||||
let local_file_name: String = match dst_name {
|
||||
@@ -781,7 +793,7 @@ impl FileTransferActivity {
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
FsEntry::Directory(dir) => {
|
||||
Entry::Directory(dir) => {
|
||||
// Get dir name
|
||||
let mut local_dir_path: PathBuf = PathBuf::from(local_path);
|
||||
match dst_name {
|
||||
@@ -797,16 +809,13 @@ impl FileTransferActivity {
|
||||
target_os = "macos",
|
||||
target_os = "linux"
|
||||
))]
|
||||
if let Some((owner, group, others)) = dir.unix_pex {
|
||||
if let Err(err) = self.host.chmod(
|
||||
local_dir_path.as_path(),
|
||||
(owner.as_byte(), group.as_byte(), others.as_byte()),
|
||||
) {
|
||||
if let Some(mode) = dir.metadata.mode {
|
||||
if let Err(err) = self.host.chmod(local_dir_path.as_path(), mode) {
|
||||
self.log(
|
||||
LogLevel::Error,
|
||||
format!(
|
||||
"Could not apply file mode {:?} to \"{}\": {}",
|
||||
(owner.as_byte(), group.as_byte(), others.as_byte()),
|
||||
"Could not apply file mode {:o} to \"{}\": {}",
|
||||
u32::from(mode),
|
||||
local_dir_path.display(),
|
||||
err
|
||||
),
|
||||
@@ -818,7 +827,7 @@ impl FileTransferActivity {
|
||||
format!("Created directory \"{}\"", local_dir_path.display()),
|
||||
);
|
||||
// Get files in dir
|
||||
match self.client.list_dir(dir.abs_path.as_path()) {
|
||||
match self.client.list_dir(dir.path.as_path()) {
|
||||
Ok(entries) => {
|
||||
// Iterate over files
|
||||
for entry in entries.iter() {
|
||||
@@ -843,7 +852,7 @@ impl FileTransferActivity {
|
||||
LogLevel::Error,
|
||||
format!(
|
||||
"Could not scan directory \"{}\": {}",
|
||||
dir.abs_path.display(),
|
||||
dir.path.display(),
|
||||
err
|
||||
),
|
||||
);
|
||||
@@ -872,10 +881,7 @@ impl FileTransferActivity {
|
||||
// Log abort
|
||||
self.log_and_alert(
|
||||
LogLevel::Warn,
|
||||
format!(
|
||||
"Download aborted for \"{}\"!",
|
||||
entry.get_abs_path().display()
|
||||
),
|
||||
format!("Download aborted for \"{}\"!", entry.path().display()),
|
||||
);
|
||||
}
|
||||
result
|
||||
@@ -887,18 +893,18 @@ impl FileTransferActivity {
|
||||
fn filetransfer_recv_one(
|
||||
&mut self,
|
||||
local: &Path,
|
||||
remote: &FsFile,
|
||||
remote: &File,
|
||||
file_name: String,
|
||||
) -> Result<(), TransferErrorReason> {
|
||||
// Try to open local file
|
||||
match self.host.open_file_write(local) {
|
||||
Ok(local_file) => {
|
||||
// Download file from remote
|
||||
match self.client.recv_file(remote) {
|
||||
match self.client.open(remote.path.as_path()) {
|
||||
Ok(rhnd) => self.filetransfer_recv_one_with_stream(
|
||||
local, remote, file_name, rhnd, local_file,
|
||||
),
|
||||
Err(err) if err.kind() == FileTransferErrorType::UnsupportedFeature => {
|
||||
Err(err) if err.kind == RemoteErrorType::UnsupportedFeature => {
|
||||
self.filetransfer_recv_one_wno_stream(local, remote, file_name)
|
||||
}
|
||||
Err(err) => Err(TransferErrorReason::FileTransferError(err)),
|
||||
@@ -910,24 +916,24 @@ impl FileTransferActivity {
|
||||
|
||||
/// ### filetransfer_recv_one_with_stream
|
||||
///
|
||||
/// Receive an `FsEntry` from remote using stream
|
||||
/// Receive an `Entry` from remote using stream
|
||||
fn filetransfer_recv_one_with_stream(
|
||||
&mut self,
|
||||
local: &Path,
|
||||
remote: &FsFile,
|
||||
remote: &File,
|
||||
file_name: String,
|
||||
mut reader: Box<dyn Read>,
|
||||
mut writer: File,
|
||||
mut writer: StdFile,
|
||||
) -> Result<(), TransferErrorReason> {
|
||||
let mut total_bytes_written: usize = 0;
|
||||
// Init transfer
|
||||
self.transfer.partial.init(remote.size);
|
||||
self.transfer.partial.init(remote.metadata.size as usize);
|
||||
// Write local file
|
||||
let mut last_progress_val: f64 = 0.0;
|
||||
let mut last_input_event_fetch: Option<Instant> = None;
|
||||
// While the entire file hasn't been completely read,
|
||||
// Or filetransfer has been aborted
|
||||
while total_bytes_written < remote.size && !self.transfer.aborted() {
|
||||
while total_bytes_written < remote.metadata.size as usize && !self.transfer.aborted() {
|
||||
// Handle input events (each 500 ms) or is None
|
||||
if last_input_event_fetch.is_none()
|
||||
|| last_input_event_fetch
|
||||
@@ -978,7 +984,7 @@ impl FileTransferActivity {
|
||||
}
|
||||
}
|
||||
// Finalize stream
|
||||
if let Err(err) = self.client.on_recv(reader) {
|
||||
if let Err(err) = self.client.on_read(reader) {
|
||||
self.log(
|
||||
LogLevel::Warn,
|
||||
format!("Could not finalize remote stream: \"{}\"", err),
|
||||
@@ -990,16 +996,13 @@ impl FileTransferActivity {
|
||||
}
|
||||
// Apply file mode to file
|
||||
#[cfg(target_family = "unix")]
|
||||
if let Some((owner, group, others)) = remote.unix_pex {
|
||||
if let Err(err) = self
|
||||
.host
|
||||
.chmod(local, (owner.as_byte(), group.as_byte(), others.as_byte()))
|
||||
{
|
||||
if let Some(mode) = remote.metadata.mode {
|
||||
if let Err(err) = self.host.chmod(local, mode) {
|
||||
self.log(
|
||||
LogLevel::Error,
|
||||
format!(
|
||||
"Could not apply file mode {:?} to \"{}\": {}",
|
||||
(owner.as_byte(), group.as_byte(), others.as_byte()),
|
||||
"Could not apply file mode {:o} to \"{}\": {}",
|
||||
u32::from(mode),
|
||||
local.display(),
|
||||
err
|
||||
),
|
||||
@@ -1011,7 +1014,7 @@ impl FileTransferActivity {
|
||||
LogLevel::Info,
|
||||
format!(
|
||||
"Saved file \"{}\" to \"{}\" (took {} seconds; at {}/s)",
|
||||
remote.abs_path.display(),
|
||||
remote.path.display(),
|
||||
local.display(),
|
||||
fmt_millis(self.transfer.partial.started().elapsed()),
|
||||
ByteSize(self.transfer.partial.calc_bytes_per_second()),
|
||||
@@ -1022,40 +1025,47 @@ impl FileTransferActivity {
|
||||
|
||||
/// ### filetransfer_recv_one_with_stream
|
||||
///
|
||||
/// Receive an `FsEntry` from remote without using stream
|
||||
/// Receive an `Entry` from remote without using stream
|
||||
fn filetransfer_recv_one_wno_stream(
|
||||
&mut self,
|
||||
local: &Path,
|
||||
remote: &FsFile,
|
||||
remote: &File,
|
||||
file_name: String,
|
||||
) -> Result<(), TransferErrorReason> {
|
||||
// Open local file
|
||||
let reader = self
|
||||
.host
|
||||
.open_file_write(local)
|
||||
.map_err(TransferErrorReason::HostError)
|
||||
.map(Box::new)?;
|
||||
// Init transfer
|
||||
self.transfer.partial.init(remote.size);
|
||||
self.transfer.partial.init(remote.metadata.size as usize);
|
||||
// Draw before transfer
|
||||
self.update_progress_bar(format!("Downloading \"{}\"", file_name));
|
||||
self.view();
|
||||
// recv wno stream
|
||||
if let Err(err) = self.client.recv_file_wno_stream(remote, local) {
|
||||
if let Err(err) = self.client.open_file(remote.path.as_path(), reader) {
|
||||
return Err(TransferErrorReason::FileTransferError(err));
|
||||
}
|
||||
// Update progress at the end
|
||||
self.transfer.partial.update_progress(remote.size);
|
||||
self.transfer.full.update_progress(remote.size);
|
||||
self.transfer
|
||||
.partial
|
||||
.update_progress(remote.metadata.size as usize);
|
||||
self.transfer
|
||||
.full
|
||||
.update_progress(remote.metadata.size as usize);
|
||||
// Draw after transfer
|
||||
self.update_progress_bar(format!("Downloading \"{}\"", file_name));
|
||||
self.view();
|
||||
// Apply file mode to file
|
||||
#[cfg(target_family = "unix")]
|
||||
if let Some((owner, group, others)) = remote.unix_pex {
|
||||
if let Err(err) = self
|
||||
.host
|
||||
.chmod(local, (owner.as_byte(), group.as_byte(), others.as_byte()))
|
||||
{
|
||||
if let Some(mode) = remote.metadata.mode {
|
||||
if let Err(err) = self.host.chmod(local, mode) {
|
||||
self.log(
|
||||
LogLevel::Error,
|
||||
format!(
|
||||
"Could not apply file mode {:?} to \"{}\": {}",
|
||||
(owner.as_byte(), group.as_byte(), others.as_byte()),
|
||||
"Could not apply file mode {:o} to \"{}\": {}",
|
||||
u32::from(mode),
|
||||
local.display(),
|
||||
err
|
||||
),
|
||||
@@ -1067,7 +1077,7 @@ impl FileTransferActivity {
|
||||
LogLevel::Info,
|
||||
format!(
|
||||
"Saved file \"{}\" to \"{}\" (took {} seconds; at {}/s)",
|
||||
remote.abs_path.display(),
|
||||
remote.path.display(),
|
||||
local.display(),
|
||||
fmt_millis(self.transfer.partial.started().elapsed()),
|
||||
ByteSize(self.transfer.partial.calc_bytes_per_second()),
|
||||
@@ -1136,7 +1146,7 @@ impl FileTransferActivity {
|
||||
/// ### download_file_as_temp
|
||||
///
|
||||
/// Download provided file as a temporary file
|
||||
pub(super) fn download_file_as_temp(&mut self, file: &FsFile) -> Result<PathBuf, String> {
|
||||
pub(super) fn download_file_as_temp(&mut self, file: &File) -> Result<PathBuf, String> {
|
||||
let tmpfile: PathBuf = match self.cache.as_ref() {
|
||||
Some(cache) => {
|
||||
let mut p: PathBuf = cache.path().to_path_buf();
|
||||
@@ -1157,7 +1167,7 @@ impl FileTransferActivity {
|
||||
) {
|
||||
Err(err) => Err(format!(
|
||||
"Could not download {} to temporary file: {}",
|
||||
file.abs_path.display(),
|
||||
file.path.display(),
|
||||
err
|
||||
)),
|
||||
Ok(()) => Ok(tmpfile),
|
||||
@@ -1169,12 +1179,12 @@ impl FileTransferActivity {
|
||||
/// ### get_total_transfer_size_local
|
||||
///
|
||||
/// Get total size of transfer for localhost
|
||||
fn get_total_transfer_size_local(&mut self, entry: &FsEntry) -> usize {
|
||||
fn get_total_transfer_size_local(&mut self, entry: &Entry) -> usize {
|
||||
match entry {
|
||||
FsEntry::File(file) => file.size,
|
||||
FsEntry::Directory(dir) => {
|
||||
Entry::File(file) => file.metadata.size as usize,
|
||||
Entry::Directory(dir) => {
|
||||
// List dir
|
||||
match self.host.scan_dir(dir.abs_path.as_path()) {
|
||||
match self.host.scan_dir(dir.path.as_path()) {
|
||||
Ok(files) => files
|
||||
.iter()
|
||||
.map(|x| self.get_total_transfer_size_local(x))
|
||||
@@ -1182,11 +1192,7 @@ impl FileTransferActivity {
|
||||
Err(err) => {
|
||||
self.log(
|
||||
LogLevel::Error,
|
||||
format!(
|
||||
"Could not list directory {}: {}",
|
||||
dir.abs_path.display(),
|
||||
err
|
||||
),
|
||||
format!("Could not list directory {}: {}", dir.path.display(), err),
|
||||
);
|
||||
0
|
||||
}
|
||||
@@ -1198,12 +1204,12 @@ impl FileTransferActivity {
|
||||
/// ### get_total_transfer_size_remote
|
||||
///
|
||||
/// Get total size of transfer for remote host
|
||||
fn get_total_transfer_size_remote(&mut self, entry: &FsEntry) -> usize {
|
||||
fn get_total_transfer_size_remote(&mut self, entry: &Entry) -> usize {
|
||||
match entry {
|
||||
FsEntry::File(file) => file.size,
|
||||
FsEntry::Directory(dir) => {
|
||||
Entry::File(file) => file.metadata.size as usize,
|
||||
Entry::Directory(dir) => {
|
||||
// List directory
|
||||
match self.client.list_dir(dir.abs_path.as_path()) {
|
||||
match self.client.list_dir(dir.path.as_path()) {
|
||||
Ok(files) => files
|
||||
.iter()
|
||||
.map(|x| self.get_total_transfer_size_remote(x))
|
||||
@@ -1211,11 +1217,7 @@ impl FileTransferActivity {
|
||||
Err(err) => {
|
||||
self.log(
|
||||
LogLevel::Error,
|
||||
format!(
|
||||
"Could not list directory {}: {}",
|
||||
dir.abs_path.display(),
|
||||
err
|
||||
),
|
||||
format!("Could not list directory {}: {}", dir.path.display(), err),
|
||||
);
|
||||
0
|
||||
}
|
||||
|
||||
@@ -31,8 +31,8 @@ use super::{
|
||||
browser::{FileExplorerTab, FoundExplorerTab},
|
||||
ExitReason, FileTransferActivity, Id, Msg, TransferMsg, TransferOpts, UiMsg,
|
||||
};
|
||||
use crate::fs::FsEntry;
|
||||
// externals
|
||||
use remotefs::fs::Entry;
|
||||
use tuirealm::{
|
||||
props::{AttrValue, Attribute},
|
||||
State, StateValue, Update,
|
||||
@@ -282,7 +282,7 @@ impl FileTransferActivity {
|
||||
// Mount wait
|
||||
self.mount_blocking_wait(format!(r#"Searching for "{}"…"#, search).as_str());
|
||||
// Find
|
||||
let res: Result<Vec<FsEntry>, String> = match self.browser.tab() {
|
||||
let res: Result<Vec<Entry>, String> = match self.browser.tab() {
|
||||
FileExplorerTab::Local => self.action_local_find(search.clone()),
|
||||
FileExplorerTab::Remote => self.action_remote_find(search.clone()),
|
||||
_ => panic!("Trying to search for files, while already in a find result"),
|
||||
|
||||
@@ -30,11 +30,11 @@ use super::{
|
||||
browser::{FileExplorerTab, FoundExplorerTab},
|
||||
components, Context, FileTransferActivity, Id,
|
||||
};
|
||||
use crate::fs::explorer::FileSorting;
|
||||
use crate::fs::FsEntry;
|
||||
use crate::explorer::FileSorting;
|
||||
use crate::ui::store::Store;
|
||||
use crate::utils::ui::draw_area_in;
|
||||
// Ext
|
||||
use remotefs::fs::Entry;
|
||||
use tuirealm::event::{Key, KeyEvent, KeyModifiers};
|
||||
use tuirealm::tui::layout::{Constraint, Direction, Layout};
|
||||
use tuirealm::tui::widgets::Clear;
|
||||
@@ -747,7 +747,7 @@ impl FileTransferActivity {
|
||||
let _ = self.app.umount(&Id::ReplacingFilesListPopup); // NOTE: replace anyway
|
||||
}
|
||||
|
||||
pub(super) fn mount_file_info(&mut self, file: &FsEntry) {
|
||||
pub(super) fn mount_file_info(&mut self, file: &Entry) {
|
||||
assert!(self
|
||||
.app
|
||||
.remount(
|
||||
|
||||
@@ -26,8 +26,8 @@
|
||||
* SOFTWARE.
|
||||
*/
|
||||
use super::{ConfigMsg, Msg};
|
||||
use crate::explorer::GroupDirs as GroupDirsEnum;
|
||||
use crate::filetransfer::FileTransferProtocol;
|
||||
use crate::fs::explorer::GroupDirs as GroupDirsEnum;
|
||||
use crate::utils::parser::parse_bytesize;
|
||||
|
||||
use tui_realm_stdlib::{Input, Radio};
|
||||
|
||||
@@ -46,19 +46,11 @@ use tuirealm::{Component, MockComponent};
|
||||
|
||||
// -- global listener
|
||||
|
||||
#[derive(MockComponent)]
|
||||
#[derive(Default, MockComponent)]
|
||||
pub struct GlobalListener {
|
||||
component: Phantom,
|
||||
}
|
||||
|
||||
impl Default for GlobalListener {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
component: Phantom::default(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Component<Msg, NoUserEvent> for GlobalListener {
|
||||
fn on(&mut self, ev: Event<NoUserEvent>) -> Option<Msg> {
|
||||
match ev {
|
||||
|
||||
@@ -28,8 +28,8 @@
|
||||
*/
|
||||
// Locals
|
||||
use super::{components, Context, Id, IdCommon, IdConfig, SetupActivity, ViewLayout};
|
||||
use crate::explorer::GroupDirs;
|
||||
use crate::filetransfer::FileTransferProtocol;
|
||||
use crate::fs::explorer::GroupDirs;
|
||||
use crate::utils::fmt::fmt_bytes;
|
||||
|
||||
// Ext
|
||||
|
||||
Reference in New Issue
Block a user