Removed filetransfer module; migrated to remotefs crate

This commit is contained in:
veeso
2021-12-09 18:07:36 +01:00
committed by Christian Visintin
parent 25dd1b9b0a
commit df7a4381c4
60 changed files with 1185 additions and 6814 deletions

View File

@@ -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 {

View File

@@ -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

View File

@@ -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(

View File

@@ -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
),
);

View File

@@ -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!(

View File

@@ -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) => {

View File

@@ -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);

View File

@@ -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));

View File

@@ -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)

View File

@@ -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,

View File

@@ -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![],

View File

@@ -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
),

View File

@@ -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
}
}

View File

@@ -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,
}
}
}

View File

@@ -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
///

View File

@@ -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()),
}
}

View File

@@ -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
///

View File

@@ -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));

View File

@@ -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
)
}

View File

@@ -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(),

View File

@@ -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
}

View File

@@ -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"),

View File

@@ -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(

View File

@@ -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};

View File

@@ -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 {

View File

@@ -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