diff --git a/CHANGELOG.md b/CHANGELOG.md
index cf6ae61..c54bbc0 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -41,6 +41,7 @@ FIXME: Released on
- `A`: Toggle hidden files
- `N`: New file
- Dependencies:
+ - added `bitflags 1.2.1`
- removed `data-encoding`
- updated `rand` to `0.8.0`
- removed `ring`
diff --git a/Cargo.lock b/Cargo.lock
index 87dfa7d..05aeb57 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -1049,6 +1049,7 @@ dependencies = [
name = "termscp"
version = "0.3.0"
dependencies = [
+ "bitflags",
"bytesize",
"chrono",
"content_inspector",
diff --git a/Cargo.toml b/Cargo.toml
index 783df5f..b0d41c4 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -15,6 +15,7 @@ readme = "README.md"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
+bitflags = "1.2.1"
bytesize = "1.0.1"
chrono = "0.4.19"
content_inspector = "0.2.4"
diff --git a/src/fs/explorer/builder.rs b/src/fs/explorer/builder.rs
new file mode 100644
index 0000000..28ff326
--- /dev/null
+++ b/src/fs/explorer/builder.rs
@@ -0,0 +1,139 @@
+//! ## Builder
+//!
+//! `builder` is the module which provides a builder for FileExplorer
+
+/*
+*
+* Copyright (C) 2020 Christian Visintin - christian.visintin1997@gmail.com
+*
+* This file is part of "TermSCP"
+*
+* TermSCP is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* TermSCP is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with TermSCP. If not, see .
+*
+*/
+
+// Locals
+use super::{ExplorerOpts, FileExplorer};
+// Ext
+use std::collections::VecDeque;
+
+/// ## FileExplorerBuilder
+///
+/// Struct used to create a `FileExplorer`
+pub struct FileExplorerBuilder {
+ explorer: Option,
+}
+
+impl FileExplorerBuilder {
+ /// ### new
+ ///
+ /// Build a new `FileExplorerBuilder`
+ pub fn new() -> Self {
+ FileExplorerBuilder {
+ explorer: Some(FileExplorer::default()),
+ }
+ }
+
+ /// ### build
+ ///
+ /// Take FileExplorer out of builder
+ pub fn build(&mut self) -> FileExplorer {
+ self.explorer.take().unwrap()
+ }
+
+ /// ### with_hidden_files
+ ///
+ /// Enable HIDDEN_FILES option
+ pub fn with_hidden_files(&mut self) -> &mut FileExplorerBuilder {
+ if let Some(e) = self.explorer.as_mut() {
+ e.opts.insert(ExplorerOpts::SHOW_HIDDEN_FILES);
+ }
+ self
+ }
+
+ /// ### sort_by_name
+ ///
+ /// Enable SORT_BY_NAME option
+ pub fn sort_by_name(&mut self) -> &mut FileExplorerBuilder {
+ if let Some(e) = self.explorer.as_mut() {
+ e.opts.insert(ExplorerOpts::SORT_BY_NAME);
+ }
+ self
+ }
+
+ /// ### sort_by_mtime
+ ///
+ /// Enable SORT_BY_MTIME option
+ pub fn sort_by_mtime(&mut self) -> &mut FileExplorerBuilder {
+ if let Some(e) = self.explorer.as_mut() {
+ e.opts.insert(ExplorerOpts::SORT_BY_MTIME);
+ }
+ self
+ }
+
+ /// ### with_dirs_first
+ ///
+ /// Enable DIRS_FIRST option
+ pub fn with_dirs_first(&mut self) -> &mut FileExplorerBuilder {
+ if let Some(e) = self.explorer.as_mut() {
+ e.opts.insert(ExplorerOpts::DIRS_FIRST);
+ }
+ self
+ }
+
+ /// ### with_stack_size
+ ///
+ /// Set stack size for FileExplorer
+ pub fn with_stack_size(&mut self, sz: usize) -> &mut FileExplorerBuilder {
+ if let Some(e) = self.explorer.as_mut() {
+ e.stack_size = sz;
+ e.dirstack = VecDeque::with_capacity(sz);
+ }
+ self
+ }
+}
+
+#[cfg(test)]
+mod tests {
+
+ use super::*;
+
+ #[test]
+ fn test_fs_explorer_builder_new_default() {
+ let explorer: FileExplorer = FileExplorerBuilder::new().build();
+ // Verify
+ assert!(!explorer.opts.intersects(ExplorerOpts::SHOW_HIDDEN_FILES));
+ assert!(!explorer.opts.intersects(ExplorerOpts::SORT_BY_MTIME));
+ assert!(!explorer.opts.intersects(ExplorerOpts::SORT_BY_NAME));
+ assert!(!explorer.opts.intersects(ExplorerOpts::DIRS_FIRST));
+ assert_eq!(explorer.stack_size, 16);
+ }
+
+ #[test]
+ fn test_fs_explorer_builder_new_all() {
+ let explorer: FileExplorer = FileExplorerBuilder::new()
+ .sort_by_mtime()
+ .sort_by_name()
+ .with_dirs_first()
+ .with_hidden_files()
+ .with_stack_size(24)
+ .build();
+ // Verify
+ assert!(explorer.opts.intersects(ExplorerOpts::SHOW_HIDDEN_FILES));
+ assert!(explorer.opts.intersects(ExplorerOpts::SORT_BY_MTIME));
+ assert!(explorer.opts.intersects(ExplorerOpts::SORT_BY_NAME));
+ assert!(explorer.opts.intersects(ExplorerOpts::DIRS_FIRST));
+ assert_eq!(explorer.stack_size, 24);
+ }
+}
diff --git a/src/ui/activities/filetransfer_activity/explorer.rs b/src/fs/explorer/mod.rs
similarity index 68%
rename from src/ui/activities/filetransfer_activity/explorer.rs
rename to src/fs/explorer/mod.rs
index cc5a481..07e40fe 100644
--- a/src/ui/activities/filetransfer_activity/explorer.rs
+++ b/src/fs/explorer/mod.rs
@@ -1,6 +1,6 @@
-//! ## FileTransferActivity
+//! ## Explorer
//!
-//! `filetransfer_activiy` is the module which implements the Filetransfer activity, which is the main activity afterall
+//! `explorer` is the module which provides an Helper in handling Directory status through
/*
*
@@ -23,39 +23,51 @@
*
*/
+// Mods
+pub(crate) mod builder;
+// Deps
+extern crate bitflags;
// Locals
use super::FsEntry;
// Ext
use std::collections::VecDeque;
use std::path::{Path, PathBuf};
+bitflags! {
+ pub(crate) struct ExplorerOpts: u32 {
+ const SHOW_HIDDEN_FILES = 0b00000001;
+ const SORT_BY_NAME = 0b00000010;
+ const SORT_BY_MTIME = 0b00000100;
+ const DIRS_FIRST = 0b00001000;
+ }
+}
+
/// ## FileExplorer
///
/// File explorer states
pub struct FileExplorer {
- pub wrkdir: PathBuf, // Current directory
- index: usize, // Selected file
- files: Vec, // Files in directory
- dirstack: VecDeque, // Stack of visited directory (max 16)
- stack_size: usize, // Directory stack size
- hidden_files: bool, // Should hidden files be shown or not; hidden if false
+ pub wrkdir: PathBuf, // Current directory
+ index: usize, // Selected file
+ files: Vec, // Files in directory
+ pub(crate) dirstack: VecDeque, // Stack of visited directory (max 16)
+ pub(crate) stack_size: usize, // Directory stack size
+ pub(crate) opts: ExplorerOpts, // Explorer options
}
-impl FileExplorer {
- /// ### new
- ///
- /// Instantiates a new FileExplorer
- pub fn new(stack_size: usize) -> FileExplorer {
+impl Default for FileExplorer {
+ fn default() -> Self {
FileExplorer {
wrkdir: PathBuf::from("/"),
index: 0,
files: Vec::new(),
- dirstack: VecDeque::with_capacity(stack_size),
- stack_size,
- hidden_files: false, // Default: don't show hidden files
+ dirstack: VecDeque::with_capacity(16),
+ stack_size: 16,
+ opts: ExplorerOpts::empty(),
}
}
+}
+impl FileExplorer {
/// ### pushd
///
/// push directory to stack
@@ -78,10 +90,13 @@ impl FileExplorer {
/// ### set_files
///
/// Set Explorer files
- /// Index is then moved to first valid `FsEntry` for current setup
+ /// This method will also sort entries based on current options
+ /// Once all sorting have been performed, index is moved to first valid entry.
pub fn set_files(&mut self, files: Vec) {
self.files = files;
- // Set index to first valid entry
+ // Sort
+ self.sort();
+ // Reset index
self.index_at_first();
}
@@ -97,11 +112,17 @@ impl FileExplorer {
/// Iterate over files
/// Filters are applied based on current options (e.g. hidden files not returned)
pub fn iter_files(&self) -> Box + '_> {
- // Match options
- match self.hidden_files {
- false => Box::new(self.files.iter().filter(|x| !x.is_hidden())), // Show only visible files
- true => self.iter_files_all(), // Show all
- }
+ // Filter
+ let opts: ExplorerOpts = self.opts;
+ Box::new(self.files.iter().filter(move |x| {
+ // If true, element IS NOT filtered
+ let mut pass: bool = true;
+ // If hidden files SHOULDN'T be shown, AND pass with not hidden
+ if !opts.intersects(ExplorerOpts::SHOW_HIDDEN_FILES) {
+ pass &= !x.is_hidden();
+ }
+ pass
+ }))
}
/// ### iter_files_all
@@ -118,16 +139,46 @@ impl FileExplorer {
self.files.get(self.index)
}
+ // Sorting
+
+ /// ### sort
+ ///
+ /// Sort files based on Explorer options.
+ fn sort(&mut self) {
+ // Sort by name
+ if self.opts.intersects(ExplorerOpts::SORT_BY_NAME) {
+ self.sort_files_by_name();
+ } else if self.opts.intersects(ExplorerOpts::SORT_BY_MTIME) {
+ // Sort by mtime NOTE: else if cause exclusive
+ self.sort_files_by_name();
+ }
+ // Directories first (MUST COME AFTER NAME)
+ if self.opts.intersects(ExplorerOpts::DIRS_FIRST) {
+ self.sort_files_directories_first();
+ }
+ }
+
/// ### sort_files_by_name
///
/// Sort explorer files by their name. All names are converted to lowercase
- pub fn sort_files_by_name(&mut self) {
- self.files.sort_by_key(|x: &FsEntry| match x {
- FsEntry::Directory(dir) => dir.name.as_str().to_lowercase(),
- FsEntry::File(file) => file.name.as_str().to_lowercase(),
- });
- // Reset index
- self.index_at_first();
+ fn sort_files_by_name(&mut self) {
+ self.files
+ .sort_by_key(|x: &FsEntry| x.get_name().to_lowercase());
+ }
+
+ /// ### sort_files_by_mtime
+ ///
+ /// Sort files by mtime; the newest comes first
+ fn sort_files_by_mtime(&mut self) {
+ self.files
+ .sort_by_key(|x: &FsEntry| x.get_last_change_time());
+ }
+
+ /// ### sort_files_directories_first
+ ///
+ /// Sort files; directories come first
+ fn sort_files_directories_first(&mut self) {
+ self.files.sort_by_key(|x: &FsEntry| x.is_file());
}
/// ### incr_index
@@ -145,7 +196,7 @@ impl FileExplorer {
// Validate
match self.files.get(self.index) {
Some(assoc_entry) => {
- if !self.hidden_files {
+ if !self.opts.intersects(ExplorerOpts::SHOW_HIDDEN_FILES) {
// Check if file is hidden, otherwise increment
if assoc_entry.is_hidden() {
// Check if all files are hidden (NOTE: PREVENT STACK OVERFLOWS)
@@ -194,7 +245,7 @@ impl FileExplorer {
// Validate index
match self.files.get(self.index) {
Some(assoc_entry) => {
- if !self.hidden_files {
+ if !self.opts.intersects(ExplorerOpts::SHOW_HIDDEN_FILES) {
// Check if file is hidden, otherwise increment
if assoc_entry.is_hidden() {
// Check if all files are hidden (NOTE: PREVENT STACK OVERFLOWS)
@@ -238,7 +289,7 @@ impl FileExplorer {
///
/// Return first valid index
fn get_first_valid_index(&self) -> usize {
- match self.hidden_files {
+ match self.opts.intersects(ExplorerOpts::SHOW_HIDDEN_FILES) {
true => 0,
false => {
// Look for first "non-hidden" entry
@@ -302,7 +353,7 @@ impl FileExplorer {
///
/// Enable/disable hidden files
pub fn toggle_hidden_files(&mut self) {
- self.hidden_files = !self.hidden_files;
+ self.opts.toggle(ExplorerOpts::SHOW_HIDDEN_FILES);
// Adjust index
if self.index < self.get_first_valid_index() {
self.index_at_first();
@@ -316,23 +367,26 @@ mod tests {
use super::*;
use crate::fs::{FsDirectory, FsFile};
- use std::time::SystemTime;
+ use std::thread::sleep;
+ use std::time::{Duration, SystemTime};
#[test]
- fn test_ui_filetransfer_activity_explorer_new() {
- let explorer: FileExplorer = FileExplorer::new(16);
+ fn test_fs_explorer_new() {
+ let explorer: FileExplorer = FileExplorer::default();
// Verify
assert_eq!(explorer.dirstack.len(), 0);
assert_eq!(explorer.files.len(), 0);
- assert_eq!(explorer.hidden_files, false);
+ assert_eq!(explorer.opts, ExplorerOpts::empty());
assert_eq!(explorer.wrkdir, PathBuf::from("/"));
assert_eq!(explorer.stack_size, 16);
assert_eq!(explorer.index, 0);
}
#[test]
- fn test_ui_filetransfer_activity_explorer_stack() {
- let mut explorer: FileExplorer = FileExplorer::new(2);
+ fn test_fs_explorer_stack() {
+ let mut explorer: FileExplorer = FileExplorer::default();
+ explorer.stack_size = 2;
+ explorer.dirstack = VecDeque::with_capacity(2);
// Push dir
explorer.pushd(&Path::new("/tmp"));
explorer.pushd(&Path::new("/home/omar"));
@@ -356,10 +410,10 @@ mod tests {
}
#[test]
- fn test_ui_filetransfer_activity_explorer_files() {
- let mut explorer: FileExplorer = FileExplorer::new(16);
- explorer.hidden_files = false;
- // Create files
+ fn test_fs_explorer_files() {
+ let mut explorer: FileExplorer = FileExplorer::default();
+ explorer.opts.remove(ExplorerOpts::SHOW_HIDDEN_FILES); // Don't show hidden files
+ // Create files
explorer.set_files(vec![
make_fs_entry("README.md", false),
make_fs_entry("src/", true),
@@ -391,10 +445,11 @@ mod tests {
}
#[test]
- fn test_ui_filetransfer_activity_explorer_index() {
- let mut explorer: FileExplorer = FileExplorer::new(16);
- explorer.hidden_files = false;
- // Create files
+ fn test_fs_explorer_index() {
+ let mut explorer: FileExplorer = FileExplorer::default();
+ explorer.opts.remove(ExplorerOpts::SHOW_HIDDEN_FILES);
+ explorer.opts.insert(ExplorerOpts::SORT_BY_NAME);
+ // Create files (files are then sorted by name)
explorer.set_files(vec![
make_fs_entry("README.md", false),
make_fs_entry("src/", true),
@@ -409,14 +464,15 @@ mod tests {
make_fs_entry(".gitignore", false),
]);
let sz: usize = explorer.count();
- // Sort by name
- explorer.sort_files_by_name();
// Get first index
assert_eq!(explorer.get_first_valid_index(), 2);
// Index should be 2 now; files hidden; this happens because `index_at_first` is called after loading files
assert_eq!(explorer.get_index(), 2);
assert_eq!(explorer.get_relative_index(), 0); // Relative index should be 0
- assert_eq!(explorer.hidden_files, false);
+ assert_eq!(
+ explorer.opts.intersects(ExplorerOpts::SHOW_HIDDEN_FILES),
+ false
+ );
// Increment index
explorer.incr_index();
// Index should now be 3 (was 0, + 2 + 1); first 2 files are hidden (.git, .gitignore)
@@ -462,7 +518,10 @@ mod tests {
assert_eq!(explorer.get_relative_index(), 0);
// Toggle hidden files
explorer.toggle_hidden_files();
- assert_eq!(explorer.hidden_files, true);
+ assert_eq!(
+ explorer.opts.intersects(ExplorerOpts::SHOW_HIDDEN_FILES),
+ true
+ );
// Move index to 0
explorer.set_index(0);
assert_eq!(explorer.get_index(), 0);
@@ -483,7 +542,10 @@ mod tests {
assert_eq!(explorer.get_relative_index(), 0); // Now relative matches
// Toggle; move at first
explorer.toggle_hidden_files();
- assert_eq!(explorer.hidden_files, false);
+ assert_eq!(
+ explorer.opts.intersects(ExplorerOpts::SHOW_HIDDEN_FILES),
+ false
+ );
explorer.index_at_first();
assert_eq!(explorer.get_index(), 2);
assert_eq!(explorer.get_relative_index(), 0);
@@ -498,6 +560,74 @@ mod tests {
assert_eq!(explorer.get_relative_index(), 0);
}
+ #[test]
+ fn test_fs_explorer_sort_by_name() {
+ let mut explorer: FileExplorer = FileExplorer::default();
+ explorer.opts.insert(ExplorerOpts::SORT_BY_NAME);
+ // Create files (files are then sorted by name)
+ explorer.set_files(vec![
+ make_fs_entry("README.md", false),
+ make_fs_entry("src/", true),
+ make_fs_entry("CONTRIBUTING.md", false),
+ make_fs_entry("CODE_OF_CONDUCT.md", false),
+ make_fs_entry("CHANGELOG.md", false),
+ make_fs_entry("LICENSE", false),
+ make_fs_entry("Cargo.toml", false),
+ make_fs_entry("Cargo.lock", false),
+ make_fs_entry("codecov.yml", false),
+ ]);
+ // First entry should be "Cargo.lock"
+ assert_eq!(explorer.files.get(0).unwrap().get_name(), "Cargo.lock");
+ // Last should be "src/"
+ assert_eq!(explorer.files.get(8).unwrap().get_name(), "src/");
+ }
+
+ #[test]
+ fn test_fs_explorer_sort_by_mtime() {
+ let mut explorer: FileExplorer = FileExplorer::default();
+ explorer.opts.insert(ExplorerOpts::SORT_BY_MTIME);
+ let entry1: FsEntry = make_fs_entry("README.md", false);
+ // Wait 1 sec
+ sleep(Duration::from_secs(1));
+ let entry2: FsEntry = make_fs_entry("CODE_OF_CONDUCT.md", false);
+ // Create files (files are then sorted by name)
+ explorer.set_files(vec![entry1, entry2]);
+ // First entry should be "CODE_OF_CONDUCT.md"
+ assert_eq!(
+ explorer.files.get(0).unwrap().get_name(),
+ "CODE_OF_CONDUCT.md"
+ );
+ // Last should be "src/"
+ assert_eq!(explorer.files.get(1).unwrap().get_name(), "README.md");
+ }
+
+ #[test]
+ fn test_fs_explorer_sort_by_name_and_dir() {
+ let mut explorer: FileExplorer = FileExplorer::default();
+ explorer.opts.insert(ExplorerOpts::SORT_BY_NAME);
+ explorer.opts.insert(ExplorerOpts::DIRS_FIRST);
+ // Create files (files are then sorted by name)
+ explorer.set_files(vec![
+ make_fs_entry("README.md", false),
+ make_fs_entry("src/", true),
+ make_fs_entry("docs/", true),
+ make_fs_entry("CONTRIBUTING.md", false),
+ make_fs_entry("CODE_OF_CONDUCT.md", false),
+ make_fs_entry("CHANGELOG.md", false),
+ make_fs_entry("LICENSE", false),
+ make_fs_entry("Cargo.toml", false),
+ make_fs_entry("Cargo.lock", false),
+ make_fs_entry("codecov.yml", false),
+ ]);
+ // First entry should be "docs"
+ assert_eq!(explorer.files.get(0).unwrap().get_name(), "docs/");
+ assert_eq!(explorer.files.get(1).unwrap().get_name(), "src/");
+ // 3rd is file first for alphabetical order
+ assert_eq!(explorer.files.get(2).unwrap().get_name(), "Cargo.lock");
+ // Last should be "README.md" (last file for alphabetical ordening)
+ assert_eq!(explorer.files.get(9).unwrap().get_name(), "README.md");
+ }
+
fn make_fs_entry(name: &str, is_dir: bool) -> FsEntry {
let t_now: SystemTime = SystemTime::now();
match is_dir {
diff --git a/src/fs/mod.rs b/src/fs/mod.rs
index 0e62298..b66ae1b 100644
--- a/src/fs/mod.rs
+++ b/src/fs/mod.rs
@@ -23,12 +23,16 @@
*
*/
+// Mod
+pub mod explorer;
+
+// Deps
extern crate bytesize;
#[cfg(any(target_os = "unix", target_os = "macos", target_os = "linux"))]
extern crate users;
-
+// Locals
use crate::utils::fmt::{fmt_pex, fmt_time};
-
+// Ext
use bytesize::ByteSize;
use std::path::PathBuf;
use std::time::SystemTime;
diff --git a/src/lib.rs b/src/lib.rs
index 087e803..a779075 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -19,6 +19,8 @@
*
*/
+#[macro_use]
+extern crate bitflags;
#[macro_use]
extern crate lazy_static;
#[macro_use]
diff --git a/src/main.rs b/src/main.rs
index 93eafb5..048c233 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -25,6 +25,8 @@ const TERMSCP_AUTHORS: &str = env!("CARGO_PKG_AUTHORS");
// Crates
extern crate getopts;
#[macro_use]
+extern crate bitflags;
+#[macro_use]
extern crate lazy_static;
#[macro_use]
extern crate magic_crypt;
diff --git a/src/ui/activities/filetransfer_activity/misc.rs b/src/ui/activities/filetransfer_activity/misc.rs
index 9931519..42c0562 100644
--- a/src/ui/activities/filetransfer_activity/misc.rs
+++ b/src/ui/activities/filetransfer_activity/misc.rs
@@ -24,6 +24,7 @@ use super::{
Color, ConfigClient, FileTransferActivity, InputField, InputMode, LogLevel, LogRecord,
PopupType,
};
+use crate::fs::explorer::{builder::FileExplorerBuilder, FileExplorer};
use crate::system::environment;
use crate::system::sshkey_storage::SshKeyStorage;
// Ext
@@ -125,6 +126,17 @@ impl FileTransferActivity {
}
}
+ /// ### build_explorer
+ ///
+ /// Build explorer reading configuration from `ConfigClient`
+ pub(super) fn build_explorer(cli: Option<&ConfigClient>) -> FileExplorer {
+ FileExplorerBuilder::new()
+ .sort_by_name()
+ .with_dirs_first()
+ .with_stack_size(16)
+ .build()
+ }
+
/// ### setup_text_editor
///
/// Set text editor to use
diff --git a/src/ui/activities/filetransfer_activity/mod.rs b/src/ui/activities/filetransfer_activity/mod.rs
index b8a9a77..e727008 100644
--- a/src/ui/activities/filetransfer_activity/mod.rs
+++ b/src/ui/activities/filetransfer_activity/mod.rs
@@ -25,7 +25,6 @@
// This module is split into files, cause it's just too big
mod callbacks;
-mod explorer;
mod input;
mod layout;
mod misc;
@@ -44,9 +43,9 @@ use crate::filetransfer::ftp_transfer::FtpFileTransfer;
use crate::filetransfer::scp_transfer::ScpFileTransfer;
use crate::filetransfer::sftp_transfer::SftpFileTransfer;
use crate::filetransfer::{FileTransfer, FileTransferProtocol};
+use crate::fs::explorer::FileExplorer;
use crate::fs::FsEntry;
use crate::system::config_client::ConfigClient;
-use explorer::FileExplorer;
// Includes
use chrono::{DateTime, Local};
@@ -269,10 +268,10 @@ impl FileTransferActivity {
Self::make_ssh_storage(config_client.as_ref()),
)),
},
- config_cli: config_client,
params,
- local: FileExplorer::new(16),
- remote: FileExplorer::new(16),
+ local: Self::build_explorer(config_client.as_ref()),
+ remote: Self::build_explorer(config_client.as_ref()),
+ config_cli: config_client,
tab: FileExplorerTab::Local,
log_index: 0,
log_records: VecDeque::with_capacity(256), // 256 events is enough I guess
diff --git a/src/ui/activities/filetransfer_activity/session.rs b/src/ui/activities/filetransfer_activity/session.rs
index 3a2c32d..381538e 100644
--- a/src/ui/activities/filetransfer_activity/session.rs
+++ b/src/ui/activities/filetransfer_activity/session.rs
@@ -603,9 +603,8 @@ impl FileTransferActivity {
pub(super) fn local_scan(&mut self, path: &Path) {
match self.context.as_ref().unwrap().local.scan_dir(path) {
Ok(files) => {
+ // Set files and sort (sorting is implicit)
self.local.set_files(files);
- // Sort files
- self.local.sort_files_by_name();
// Set index; keep if possible, otherwise set to last item
self.local.set_index(match self.local.get_current_file() {
Some(_) => self.local.get_index(),
@@ -630,9 +629,8 @@ impl FileTransferActivity {
pub(super) fn remote_scan(&mut self, path: &Path) {
match self.client.list_dir(path) {
Ok(files) => {
+ // Set files and sort (sorting is implicit)
self.remote.set_files(files);
- // Sort files
- self.remote.sort_files_by_name();
// Set index; keep if possible, otherwise set to last item
self.remote.set_index(match self.remote.get_current_file() {
Some(_) => self.remote.get_index(),