Find dialog in view
This commit is contained in:
parent
8a22259eba
commit
08b855e779
|
@ -32,6 +32,7 @@ Released on FIXME: date
|
|||
- Fixed a bug causing termscp to show two equal bookmarks when overwriting one.
|
||||
- Dependencies:
|
||||
- Removed `unicode-width`
|
||||
- Added `wildmatch 1.0.13`
|
||||
- For developers:
|
||||
- Activity refactoring
|
||||
- Developed an internal library used to create components, components are then nested inside a View
|
||||
|
|
|
@ -127,6 +127,13 @@ impl FileExplorer {
|
|||
self.sort();
|
||||
}
|
||||
|
||||
/// ### del_entry
|
||||
///
|
||||
/// Delete file at provided index
|
||||
pub fn del_entry(&mut self, idx: usize) {
|
||||
self.files.remove(idx);
|
||||
}
|
||||
|
||||
/*
|
||||
/// ### count
|
||||
///
|
||||
|
@ -627,6 +634,23 @@ mod tests {
|
|||
assert!(GroupDirs::from_str("omar").is_err());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_fs_explorer_del_entry() {
|
||||
let mut explorer: FileExplorer = FileExplorer::default();
|
||||
// Create files (files are then sorted by name)
|
||||
explorer.set_files(vec![
|
||||
make_fs_entry("CONTRIBUTING.md", false),
|
||||
make_fs_entry("docs/", true),
|
||||
make_fs_entry("src/", true),
|
||||
make_fs_entry("README.md", false),
|
||||
]);
|
||||
explorer.del_entry(0);
|
||||
assert_eq!(explorer.files.len(), 3);
|
||||
assert_eq!(explorer.files[0].get_name(), "docs/");
|
||||
explorer.del_entry(5);
|
||||
assert_eq!(explorer.files.len(), 3);
|
||||
}
|
||||
|
||||
fn make_fs_entry(name: &str, is_dir: bool) -> FsEntry {
|
||||
let t_now: SystemTime = SystemTime::now();
|
||||
match is_dir {
|
||||
|
|
|
@ -24,7 +24,7 @@
|
|||
*/
|
||||
|
||||
// locals
|
||||
use super::{FileTransferActivity, FsEntry, LogLevel};
|
||||
use super::{FileExplorerTab, FileTransferActivity, FsEntry, LogLevel};
|
||||
use crate::ui::layout::Payload;
|
||||
// externals
|
||||
use std::path::PathBuf;
|
||||
|
@ -485,6 +485,124 @@ impl FileTransferActivity {
|
|||
}
|
||||
}
|
||||
|
||||
pub(super) fn action_local_find(&mut self, input: String) -> Result<Vec<FsEntry>, String> {
|
||||
match self.context.as_mut().unwrap().local.find(input.as_str()) {
|
||||
Ok(entries) => Ok(entries),
|
||||
Err(err) => Err(format!("Could not search for files: {}", err)),
|
||||
}
|
||||
}
|
||||
|
||||
pub(super) fn action_remote_find(&mut self, input: String) -> Result<Vec<FsEntry>, String> {
|
||||
match self.client.as_mut().find(input.as_str()) {
|
||||
Ok(entries) => Ok(entries),
|
||||
Err(err) => Err(format!("Could not search for files: {}", err)),
|
||||
}
|
||||
}
|
||||
|
||||
pub(super) fn action_find_changedir(&mut self, idx: usize) {
|
||||
// Match entry
|
||||
if let Some(entry) = self.found.as_ref().unwrap().get(idx) {
|
||||
// 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.clone(),
|
||||
FsEntry::File(file) => match file.abs_path.parent() {
|
||||
None => PathBuf::from("."),
|
||||
Some(p) => p.to_path_buf(),
|
||||
},
|
||||
};
|
||||
// Change directory
|
||||
match self.tab {
|
||||
FileExplorerTab::FindLocal | FileExplorerTab::Local => {
|
||||
self.local_changedir(path.as_path(), true)
|
||||
}
|
||||
FileExplorerTab::FindRemote | FileExplorerTab::Remote => {
|
||||
self.remote_changedir(path.as_path(), true)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub(super) fn action_find_transfer(&mut self, idx: usize, name: Option<String>) {
|
||||
let entry: Option<FsEntry> = match self.found.as_ref().unwrap().get(idx) {
|
||||
None => None,
|
||||
Some(e) => Some(e.clone()),
|
||||
};
|
||||
if let Some(entry) = entry {
|
||||
// Download file
|
||||
match self.tab {
|
||||
FileExplorerTab::FindLocal | FileExplorerTab::Local => {
|
||||
let wrkdir: PathBuf = self.remote.wrkdir.clone();
|
||||
self.filetransfer_send(&entry.get_realfile(), wrkdir.as_path(), name);
|
||||
}
|
||||
FileExplorerTab::FindRemote | FileExplorerTab::Remote => {
|
||||
let wrkdir: PathBuf = self.local.wrkdir.clone();
|
||||
self.filetransfer_recv(&entry.get_realfile(), wrkdir.as_path(), name);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub(super) fn action_find_delete(&mut self, idx: usize) {
|
||||
let entry: Option<FsEntry> = match self.found.as_ref().unwrap().get(idx) {
|
||||
None => None,
|
||||
Some(e) => Some(e.clone()),
|
||||
};
|
||||
if let Some(entry) = entry {
|
||||
// Download file
|
||||
match self.tab {
|
||||
FileExplorerTab::FindLocal | FileExplorerTab::Local => {
|
||||
let full_path: PathBuf = entry.get_abs_path();
|
||||
// Delete file or directory and report status as popup
|
||||
match self.context.as_mut().unwrap().local.remove(&entry) {
|
||||
Ok(_) => {
|
||||
// Reload files
|
||||
let p: PathBuf = self.local.wrkdir.clone();
|
||||
self.local_scan(p.as_path());
|
||||
// Log
|
||||
self.log(
|
||||
LogLevel::Info,
|
||||
format!("Removed file \"{}\"", full_path.display()).as_ref(),
|
||||
);
|
||||
}
|
||||
Err(err) => {
|
||||
self.log_and_alert(
|
||||
LogLevel::Error,
|
||||
format!(
|
||||
"Could not delete file \"{}\": {}",
|
||||
full_path.display(),
|
||||
err
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
FileExplorerTab::FindRemote | FileExplorerTab::Remote => {
|
||||
let full_path: PathBuf = entry.get_abs_path();
|
||||
// Delete file
|
||||
match self.client.remove(&entry) {
|
||||
Ok(_) => {
|
||||
self.reload_remote_dir();
|
||||
self.log(
|
||||
LogLevel::Info,
|
||||
format!("Removed file \"{}\"", full_path.display()).as_ref(),
|
||||
);
|
||||
}
|
||||
Err(err) => {
|
||||
self.log_and_alert(
|
||||
LogLevel::Error,
|
||||
format!(
|
||||
"Could not delete file \"{}\": {}",
|
||||
full_path.display(),
|
||||
err
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// ### get_local_file_entry
|
||||
///
|
||||
/// Get local file entry
|
||||
|
|
|
@ -111,6 +111,19 @@ impl FileTransferActivity {
|
|||
}
|
||||
}
|
||||
|
||||
/// ### build_found_explorer
|
||||
///
|
||||
/// Build explorer reading from `ConfigClient`, for found result (has some differences)
|
||||
pub(super) fn build_found_explorer() -> FileExplorer {
|
||||
FileExplorerBuilder::new()
|
||||
.with_file_sorting(FileSorting::ByName)
|
||||
.with_group_dirs(Some(GroupDirs::First))
|
||||
.with_hidden_files(true)
|
||||
.with_stack_size(0)
|
||||
.with_formatter(Some("{NAME} {SYMLINK}"))
|
||||
.build()
|
||||
}
|
||||
|
||||
/// ### setup_text_editor
|
||||
///
|
||||
/// Set text editor to use
|
||||
|
|
|
@ -63,23 +63,25 @@ const STORAGE_LOGBOX_WIDTH: &str = "LOGBOX_WIDTH";
|
|||
|
||||
const COMPONENT_EXPLORER_LOCAL: &str = "EXPLORER_LOCAL";
|
||||
const COMPONENT_EXPLORER_REMOTE: &str = "EXPLORER_REMOTE";
|
||||
const COMPONENT_EXPLORER_FIND: &str = "EXPLORER_FIND";
|
||||
const COMPONENT_LOG_BOX: &str = "LOG_BOX";
|
||||
const COMPONENT_PROGRESS_BAR: &str = "PROGRESS_BAR";
|
||||
const COMPONENT_TEXT_HELP: &str = "TEXT_HELP";
|
||||
const COMPONENT_TEXT_ERROR: &str = "TEXT_ERROR";
|
||||
const COMPONENT_TEXT_WAIT: &str = "TEXT_WAIT";
|
||||
const COMPONENT_TEXT_FATAL: &str = "TEXT_FATAL";
|
||||
const COMPONENT_TEXT_HELP: &str = "TEXT_HELP";
|
||||
const COMPONENT_TEXT_WAIT: &str = "TEXT_WAIT";
|
||||
const COMPONENT_INPUT_COPY: &str = "INPUT_COPY";
|
||||
const COMPONENT_INPUT_EXEC: &str = "INPUT_EXEC";
|
||||
const COMPONENT_INPUT_MKDIR: &str = "INPUT_MKDIR";
|
||||
const COMPONENT_INPUT_FIND: &str = "INPUT_FIND";
|
||||
const COMPONENT_INPUT_GOTO: &str = "INPUT_GOTO";
|
||||
const COMPONENT_INPUT_SAVEAS: &str = "INPUT_SAVEAS";
|
||||
const COMPONENT_INPUT_MKDIR: &str = "INPUT_MKDIR";
|
||||
const COMPONENT_INPUT_NEWFILE: &str = "INPUT_NEWFILE";
|
||||
const COMPONENT_INPUT_RENAME: &str = "INPUT_RENAME";
|
||||
const COMPONENT_RADIO_QUIT: &str = "RADIO_QUIT";
|
||||
const COMPONENT_RADIO_DISCONNECT: &str = "RADIO_DISCONNECT";
|
||||
const COMPONENT_RADIO_SORTING: &str = "RADIO_SORTING";
|
||||
const COMPONENT_INPUT_SAVEAS: &str = "INPUT_SAVEAS";
|
||||
const COMPONENT_RADIO_DELETE: &str = "RADIO_DELETE";
|
||||
const COMPONENT_RADIO_DISCONNECT: &str = "RADIO_DISCONNECT";
|
||||
const COMPONENT_RADIO_QUIT: &str = "RADIO_QUIT";
|
||||
const COMPONENT_RADIO_SORTING: &str = "RADIO_SORTING";
|
||||
const COMPONENT_LIST_FILEINFO: &str = "LIST_FILEINFO";
|
||||
|
||||
/// ## FileExplorerTab
|
||||
|
@ -88,6 +90,8 @@ const COMPONENT_LIST_FILEINFO: &str = "LIST_FILEINFO";
|
|||
enum FileExplorerTab {
|
||||
Local,
|
||||
Remote,
|
||||
FindLocal, // Find result tab
|
||||
FindRemote, // Find result tab
|
||||
}
|
||||
|
||||
/// ## LogLevel
|
||||
|
@ -206,6 +210,7 @@ pub struct FileTransferActivity {
|
|||
client: Box<dyn FileTransfer>, // File transfer client
|
||||
local: FileExplorer, // Local File explorer state
|
||||
remote: FileExplorer, // Remote File explorer state
|
||||
found: Option<FileExplorer>, // File explorer for find result
|
||||
tab: FileExplorerTab, // Current selected tab
|
||||
log_index: usize, // Current log index entry selected
|
||||
log_records: VecDeque<LogRecord>, // Log records
|
||||
|
@ -235,6 +240,7 @@ impl FileTransferActivity {
|
|||
},
|
||||
local: Self::build_explorer(config_client.as_ref()),
|
||||
remote: Self::build_explorer(config_client.as_ref()),
|
||||
found: None,
|
||||
tab: FileExplorerTab::Local,
|
||||
log_index: 0,
|
||||
log_records: VecDeque::with_capacity(256), // 256 events is enough I guess
|
||||
|
|
|
@ -27,9 +27,10 @@
|
|||
extern crate bytesize;
|
||||
// locals
|
||||
use super::{
|
||||
FileExplorerTab, FileTransferActivity, LogLevel, COMPONENT_EXPLORER_LOCAL,
|
||||
COMPONENT_EXPLORER_REMOTE, COMPONENT_INPUT_COPY, COMPONENT_INPUT_EXEC, COMPONENT_INPUT_GOTO,
|
||||
COMPONENT_INPUT_MKDIR, COMPONENT_INPUT_NEWFILE, COMPONENT_INPUT_RENAME, COMPONENT_INPUT_SAVEAS,
|
||||
FileExplorerTab, FileTransferActivity, LogLevel, COMPONENT_EXPLORER_FIND,
|
||||
COMPONENT_EXPLORER_LOCAL, COMPONENT_EXPLORER_REMOTE, COMPONENT_INPUT_COPY,
|
||||
COMPONENT_INPUT_EXEC, COMPONENT_INPUT_FIND, COMPONENT_INPUT_GOTO, COMPONENT_INPUT_MKDIR,
|
||||
COMPONENT_INPUT_NEWFILE, COMPONENT_INPUT_RENAME, COMPONENT_INPUT_SAVEAS,
|
||||
COMPONENT_LIST_FILEINFO, COMPONENT_LOG_BOX, COMPONENT_PROGRESS_BAR, COMPONENT_RADIO_DELETE,
|
||||
COMPONENT_RADIO_DISCONNECT, COMPONENT_RADIO_QUIT, COMPONENT_RADIO_SORTING,
|
||||
COMPONENT_TEXT_ERROR, COMPONENT_TEXT_FATAL, COMPONENT_TEXT_HELP,
|
||||
|
@ -37,7 +38,9 @@ use super::{
|
|||
use crate::fs::explorer::FileSorting;
|
||||
use crate::fs::FsEntry;
|
||||
use crate::ui::activities::keymap::*;
|
||||
use crate::ui::layout::props::{PropValue, TableBuilder, TextParts, TextSpan, TextSpanBuilder};
|
||||
use crate::ui::layout::props::{
|
||||
PropValue, PropsBuilder, TableBuilder, TextParts, TextSpan, TextSpanBuilder,
|
||||
};
|
||||
use crate::ui::layout::{Msg, Payload};
|
||||
// externals
|
||||
use bytesize::ByteSize;
|
||||
|
@ -314,6 +317,11 @@ impl FileTransferActivity {
|
|||
self.mount_mkdir();
|
||||
None
|
||||
}
|
||||
(COMPONENT_EXPLORER_LOCAL, &MSG_KEY_CHAR_F)
|
||||
| (COMPONENT_EXPLORER_REMOTE, &MSG_KEY_CHAR_F) => {
|
||||
self.mount_find_input();
|
||||
None
|
||||
}
|
||||
(COMPONENT_EXPLORER_LOCAL, &MSG_KEY_CHAR_G)
|
||||
| (COMPONENT_EXPLORER_REMOTE, &MSG_KEY_CHAR_G) => {
|
||||
self.mount_goto();
|
||||
|
@ -342,7 +350,8 @@ impl FileTransferActivity {
|
|||
None
|
||||
}
|
||||
(COMPONENT_EXPLORER_LOCAL, &MSG_KEY_CHAR_S)
|
||||
| (COMPONENT_EXPLORER_REMOTE, &MSG_KEY_CHAR_S) => {
|
||||
| (COMPONENT_EXPLORER_REMOTE, &MSG_KEY_CHAR_S)
|
||||
| (COMPONENT_EXPLORER_FIND, &MSG_KEY_CHAR_S) => {
|
||||
// Mount save as
|
||||
self.mount_saveas();
|
||||
None
|
||||
|
@ -362,10 +371,50 @@ impl FileTransferActivity {
|
|||
(COMPONENT_EXPLORER_LOCAL, &MSG_KEY_DEL)
|
||||
| (COMPONENT_EXPLORER_LOCAL, &MSG_KEY_CHAR_E)
|
||||
| (COMPONENT_EXPLORER_REMOTE, &MSG_KEY_DEL)
|
||||
| (COMPONENT_EXPLORER_REMOTE, &MSG_KEY_CHAR_E) => {
|
||||
| (COMPONENT_EXPLORER_REMOTE, &MSG_KEY_CHAR_E)
|
||||
| (COMPONENT_EXPLORER_FIND, &MSG_KEY_DEL)
|
||||
| (COMPONENT_EXPLORER_FIND, &MSG_KEY_CHAR_E) => {
|
||||
self.mount_radio_delete();
|
||||
None
|
||||
}
|
||||
// -- find result explorer
|
||||
(COMPONENT_EXPLORER_FIND, &MSG_KEY_ESC) => {
|
||||
// Umount find
|
||||
self.umount_find();
|
||||
// Finalize find
|
||||
self.finalize_find();
|
||||
None
|
||||
}
|
||||
(COMPONENT_EXPLORER_FIND, Msg::OnSubmit(Payload::Unsigned(idx))) => {
|
||||
// Find changedir
|
||||
self.action_find_changedir(*idx);
|
||||
// Umount find
|
||||
self.umount_find();
|
||||
// Finalize find
|
||||
self.finalize_find();
|
||||
// Reload files
|
||||
match self.tab {
|
||||
FileExplorerTab::Local => self.update_local_filelist(),
|
||||
FileExplorerTab::Remote => self.update_remote_filelist(),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
(COMPONENT_EXPLORER_FIND, &MSG_KEY_SPACE) => {
|
||||
// Get entry
|
||||
match self.view.get_value(COMPONENT_EXPLORER_FIND) {
|
||||
Some(Payload::Unsigned(idx)) => {
|
||||
self.action_find_transfer(idx, None);
|
||||
// Reload files
|
||||
match self.tab {
|
||||
// NOTE: swapped by purpose
|
||||
FileExplorerTab::FindLocal => self.update_remote_filelist(),
|
||||
FileExplorerTab::FindRemote => self.update_local_filelist(),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
// -- switch to log
|
||||
(COMPONENT_EXPLORER_LOCAL, &MSG_KEY_TAB)
|
||||
| (COMPONENT_EXPLORER_REMOTE, &MSG_KEY_TAB) => {
|
||||
|
@ -387,12 +436,14 @@ impl FileTransferActivity {
|
|||
match self.tab {
|
||||
FileExplorerTab::Local => self.action_local_copy(input.to_string()),
|
||||
FileExplorerTab::Remote => self.action_remote_copy(input.to_string()),
|
||||
_ => panic!("Found tab doesn't support COPY"),
|
||||
}
|
||||
self.umount_copy();
|
||||
// Reload files
|
||||
match self.tab {
|
||||
FileExplorerTab::Local => self.update_local_filelist(),
|
||||
FileExplorerTab::Remote => self.update_remote_filelist(),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
// -- exec popup
|
||||
|
@ -405,14 +456,53 @@ impl FileTransferActivity {
|
|||
match self.tab {
|
||||
FileExplorerTab::Local => self.action_local_exec(input.to_string()),
|
||||
FileExplorerTab::Remote => self.action_remote_exec(input.to_string()),
|
||||
_ => panic!("Found tab doesn't support EXEC"),
|
||||
}
|
||||
self.umount_exec();
|
||||
// Reload files
|
||||
match self.tab {
|
||||
FileExplorerTab::Local => self.update_local_filelist(),
|
||||
FileExplorerTab::Remote => self.update_remote_filelist(),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
// -- find popup
|
||||
(COMPONENT_INPUT_FIND, &MSG_KEY_ESC) => {
|
||||
self.umount_find_input();
|
||||
None
|
||||
}
|
||||
(COMPONENT_INPUT_FIND, Msg::OnSubmit(Payload::Text(input))) => {
|
||||
self.umount_find_input();
|
||||
// Find
|
||||
let res: Result<Vec<FsEntry>, String> = match self.tab {
|
||||
FileExplorerTab::Local => self.action_local_find(input.to_string()),
|
||||
FileExplorerTab::Remote => self.action_remote_find(input.to_string()),
|
||||
_ => panic!("Trying to search for files, while already in a find result"),
|
||||
};
|
||||
// Match result
|
||||
match res {
|
||||
Err(err) => {
|
||||
// Mount error
|
||||
self.mount_error(err.as_str());
|
||||
}
|
||||
Ok(files) => {
|
||||
// Create explorer and load files
|
||||
let mut explorer = Self::build_found_explorer();
|
||||
explorer.set_files(files);
|
||||
self.found = Some(explorer);
|
||||
// Mount result widget
|
||||
self.mount_find(input);
|
||||
self.update_find_list();
|
||||
// Initialize tab
|
||||
self.tab = match self.tab {
|
||||
FileExplorerTab::Local => FileExplorerTab::FindLocal,
|
||||
FileExplorerTab::Remote => FileExplorerTab::FindRemote,
|
||||
_ => FileExplorerTab::FindLocal,
|
||||
};
|
||||
}
|
||||
}
|
||||
None
|
||||
}
|
||||
// -- goto popup
|
||||
(COMPONENT_INPUT_GOTO, &MSG_KEY_ESC) => {
|
||||
self.umount_goto();
|
||||
|
@ -422,6 +512,7 @@ impl FileTransferActivity {
|
|||
match self.tab {
|
||||
FileExplorerTab::Local => self.action_change_local_dir(input.to_string()),
|
||||
FileExplorerTab::Remote => self.action_change_remote_dir(input.to_string()),
|
||||
_ => panic!("Found tab doesn't support GOTO"),
|
||||
}
|
||||
// Umount
|
||||
self.umount_goto();
|
||||
|
@ -429,6 +520,7 @@ impl FileTransferActivity {
|
|||
match self.tab {
|
||||
FileExplorerTab::Local => self.update_local_filelist(),
|
||||
FileExplorerTab::Remote => self.update_remote_filelist(),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
// -- make directory
|
||||
|
@ -440,12 +532,14 @@ impl FileTransferActivity {
|
|||
match self.tab {
|
||||
FileExplorerTab::Local => self.action_local_mkdir(input.to_string()),
|
||||
FileExplorerTab::Remote => self.action_remote_mkdir(input.to_string()),
|
||||
_ => panic!("Found tab doesn't support MKDIR"),
|
||||
}
|
||||
self.umount_mkdir();
|
||||
// Reload files
|
||||
match self.tab {
|
||||
FileExplorerTab::Local => self.update_local_filelist(),
|
||||
FileExplorerTab::Remote => self.update_remote_filelist(),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
// -- new file
|
||||
|
@ -457,12 +551,14 @@ impl FileTransferActivity {
|
|||
match self.tab {
|
||||
FileExplorerTab::Local => self.action_local_newfile(input.to_string()),
|
||||
FileExplorerTab::Remote => self.action_remote_newfile(input.to_string()),
|
||||
_ => panic!("Found tab doesn't support NEWFILE"),
|
||||
}
|
||||
self.umount_newfile();
|
||||
// Reload files
|
||||
match self.tab {
|
||||
FileExplorerTab::Local => self.update_local_filelist(),
|
||||
FileExplorerTab::Remote => self.update_remote_filelist(),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
// -- rename
|
||||
|
@ -474,12 +570,14 @@ impl FileTransferActivity {
|
|||
match self.tab {
|
||||
FileExplorerTab::Local => self.action_local_rename(input.to_string()),
|
||||
FileExplorerTab::Remote => self.action_remote_rename(input.to_string()),
|
||||
_ => panic!("Found tab doesn't support RENAME"),
|
||||
}
|
||||
self.umount_rename();
|
||||
// Reload files
|
||||
match self.tab {
|
||||
FileExplorerTab::Local => self.update_local_filelist(),
|
||||
FileExplorerTab::Remote => self.update_remote_filelist(),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
// -- save as
|
||||
|
@ -491,6 +589,14 @@ impl FileTransferActivity {
|
|||
match self.tab {
|
||||
FileExplorerTab::Local => self.action_local_saveas(input.to_string()),
|
||||
FileExplorerTab::Remote => self.action_remote_saveas(input.to_string()),
|
||||
FileExplorerTab::FindLocal | FileExplorerTab::FindRemote => {
|
||||
// Get entry
|
||||
if let Some(Payload::Unsigned(idx)) =
|
||||
self.view.get_value(COMPONENT_EXPLORER_FIND)
|
||||
{
|
||||
self.action_find_transfer(idx, Some(input.to_string()));
|
||||
}
|
||||
}
|
||||
}
|
||||
self.umount_saveas();
|
||||
// Reload files
|
||||
|
@ -498,6 +604,8 @@ impl FileTransferActivity {
|
|||
// NOTE: Swapped is intentional
|
||||
FileExplorerTab::Local => self.update_remote_filelist(),
|
||||
FileExplorerTab::Remote => self.update_local_filelist(),
|
||||
FileExplorerTab::FindLocal => self.update_remote_filelist(),
|
||||
FileExplorerTab::FindRemote => self.update_local_filelist(),
|
||||
}
|
||||
}
|
||||
// -- fileinfo
|
||||
|
@ -517,12 +625,25 @@ impl FileTransferActivity {
|
|||
match self.tab {
|
||||
FileExplorerTab::Local => self.action_local_delete(),
|
||||
FileExplorerTab::Remote => self.action_remote_delete(),
|
||||
FileExplorerTab::FindLocal | FileExplorerTab::FindRemote => {
|
||||
// Get entry
|
||||
if let Some(Payload::Unsigned(idx)) =
|
||||
self.view.get_value(COMPONENT_EXPLORER_FIND)
|
||||
{
|
||||
self.action_find_delete(idx);
|
||||
// Reload entries
|
||||
self.found.as_mut().unwrap().del_entry(idx);
|
||||
self.update_find_list();
|
||||
}
|
||||
}
|
||||
}
|
||||
self.umount_radio_delete();
|
||||
// Reload files
|
||||
match self.tab {
|
||||
FileExplorerTab::Local => self.update_local_filelist(),
|
||||
FileExplorerTab::Remote => self.update_remote_filelist(),
|
||||
FileExplorerTab::FindLocal => self.update_local_filelist(),
|
||||
FileExplorerTab::FindRemote => self.update_remote_filelist(),
|
||||
}
|
||||
}
|
||||
// -- disconnect
|
||||
|
@ -547,6 +668,7 @@ impl FileTransferActivity {
|
|||
self.umount_quit();
|
||||
None
|
||||
}
|
||||
// -- sorting
|
||||
(COMPONENT_RADIO_SORTING, &MSG_KEY_ESC) => {
|
||||
self.umount_file_sorting();
|
||||
None
|
||||
|
@ -562,12 +684,14 @@ impl FileTransferActivity {
|
|||
match self.tab {
|
||||
FileExplorerTab::Local => self.local.sort_by(sorting),
|
||||
FileExplorerTab::Remote => self.remote.sort_by(sorting),
|
||||
_ => panic!("Found result doesn't support SORTING"),
|
||||
}
|
||||
self.umount_file_sorting();
|
||||
// Reload files
|
||||
match self.tab {
|
||||
FileExplorerTab::Local => self.update_local_filelist(),
|
||||
FileExplorerTab::Remote => self.update_remote_filelist(),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
// -- error
|
||||
|
@ -809,6 +933,43 @@ impl FileTransferActivity {
|
|||
}
|
||||
}
|
||||
|
||||
/// ### finalize_find
|
||||
///
|
||||
/// Finalize find process
|
||||
fn finalize_find(&mut self) {
|
||||
// Set found to none
|
||||
self.found = None;
|
||||
// Restore tab
|
||||
self.tab = match self.tab {
|
||||
FileExplorerTab::FindLocal => FileExplorerTab::Local,
|
||||
FileExplorerTab::FindRemote => FileExplorerTab::Remote,
|
||||
_ => FileExplorerTab::Local,
|
||||
};
|
||||
}
|
||||
|
||||
fn update_find_list(&mut self) -> Option<(String, Msg)> {
|
||||
match self.view.get_props(COMPONENT_EXPLORER_FIND).as_mut() {
|
||||
None => None,
|
||||
Some(props) => {
|
||||
let props = props.build();
|
||||
let title: String = props.texts.title.clone().unwrap_or(String::new());
|
||||
let mut props = PropsBuilder::from(props.clone());
|
||||
// Prepare files
|
||||
let file_texts: Vec<TextSpan> = self
|
||||
.found
|
||||
.as_ref()
|
||||
.unwrap()
|
||||
.iter_files()
|
||||
.map(|x: &FsEntry| TextSpan::from(self.found.as_ref().unwrap().fmt_file(x)))
|
||||
.collect();
|
||||
let props = props
|
||||
.with_texts(TextParts::new(Some(title), Some(file_texts)))
|
||||
.build();
|
||||
self.view.update(COMPONENT_EXPLORER_FIND, props)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// ### elide_wrkdir_path
|
||||
///
|
||||
/// Elide working directory path if longer than width + host.len
|
||||
|
|
|
@ -33,7 +33,7 @@ use super::{Context, FileExplorerTab, FileTransferActivity};
|
|||
use crate::fs::explorer::FileSorting;
|
||||
use crate::fs::FsEntry;
|
||||
use crate::ui::layout::components::{
|
||||
msgbox::MsgBox, file_list::FileList, input::Input, logbox::LogBox, progress_bar::ProgressBar,
|
||||
file_list::FileList, input::Input, logbox::LogBox, msgbox::MsgBox, progress_bar::ProgressBar,
|
||||
radio_group::RadioGroup, table::Table,
|
||||
};
|
||||
use crate::ui::layout::props::{
|
||||
|
@ -138,6 +138,14 @@ impl FileTransferActivity {
|
|||
// Draw log box
|
||||
self.view.render(super::COMPONENT_LOG_BOX, f, chunks[1]);
|
||||
// Draw popups
|
||||
if let Some(mut props) = self.view.get_props(super::COMPONENT_EXPLORER_FIND) {
|
||||
if props.build().visible {
|
||||
let popup = draw_area_in(f.size(), 60, 80);
|
||||
f.render_widget(Clear, popup);
|
||||
// make popup
|
||||
self.view.render(super::COMPONENT_EXPLORER_FIND, f, popup);
|
||||
}
|
||||
}
|
||||
if let Some(mut props) = self.view.get_props(super::COMPONENT_INPUT_COPY) {
|
||||
if props.build().visible {
|
||||
let popup = draw_area_in(f.size(), 40, 10);
|
||||
|
@ -146,6 +154,14 @@ impl FileTransferActivity {
|
|||
self.view.render(super::COMPONENT_INPUT_COPY, f, popup);
|
||||
}
|
||||
}
|
||||
if let Some(mut props) = self.view.get_props(super::COMPONENT_INPUT_FIND) {
|
||||
if props.build().visible {
|
||||
let popup = draw_area_in(f.size(), 40, 10);
|
||||
f.render_widget(Clear, popup);
|
||||
// make popup
|
||||
self.view.render(super::COMPONENT_INPUT_FIND, f, popup);
|
||||
}
|
||||
}
|
||||
if let Some(mut props) = self.view.get_props(super::COMPONENT_INPUT_GOTO) {
|
||||
if props.build().visible {
|
||||
let popup = draw_area_in(f.size(), 40, 10);
|
||||
|
@ -435,6 +451,55 @@ impl FileTransferActivity {
|
|||
self.view.umount(super::COMPONENT_INPUT_EXEC);
|
||||
}
|
||||
|
||||
pub(super) fn mount_find(&mut self, search: &str) {
|
||||
// Get color
|
||||
let color: Color = match self.tab {
|
||||
FileExplorerTab::Local | FileExplorerTab::FindLocal => Color::Yellow,
|
||||
FileExplorerTab::Remote | FileExplorerTab::FindRemote => Color::LightBlue,
|
||||
};
|
||||
// Mount component
|
||||
self.view.mount(
|
||||
super::COMPONENT_EXPLORER_FIND,
|
||||
Box::new(FileList::new(
|
||||
PropsBuilder::default()
|
||||
.with_texts(TextParts::new(
|
||||
Some(format!("Search results for \"{}\"", search)),
|
||||
Some(vec![]),
|
||||
))
|
||||
.with_background(color)
|
||||
.with_foreground(color)
|
||||
.build(),
|
||||
)),
|
||||
);
|
||||
// Give focus to explorer findd
|
||||
self.view.active(super::COMPONENT_EXPLORER_FIND);
|
||||
}
|
||||
|
||||
pub(super) fn umount_find(&mut self) {
|
||||
self.view.umount(super::COMPONENT_EXPLORER_FIND);
|
||||
}
|
||||
|
||||
pub(super) fn mount_find_input(&mut self) {
|
||||
self.view.mount(
|
||||
super::COMPONENT_INPUT_FIND,
|
||||
Box::new(Input::new(
|
||||
PropsBuilder::default()
|
||||
.with_texts(TextParts::new(
|
||||
Some(String::from("Search files by name")),
|
||||
None,
|
||||
))
|
||||
.build(),
|
||||
)),
|
||||
);
|
||||
// Give focus to input find
|
||||
self.view.active(super::COMPONENT_INPUT_FIND);
|
||||
}
|
||||
|
||||
pub(super) fn umount_find_input(&mut self) {
|
||||
// Umount input find
|
||||
self.view.umount(super::COMPONENT_INPUT_FIND);
|
||||
}
|
||||
|
||||
pub(super) fn mount_goto(&mut self) {
|
||||
self.view.mount(
|
||||
super::COMPONENT_INPUT_GOTO,
|
||||
|
@ -543,6 +608,7 @@ impl FileTransferActivity {
|
|||
let sorting: FileSorting = match self.tab {
|
||||
FileExplorerTab::Local => self.local.get_file_sorting(),
|
||||
FileExplorerTab::Remote => self.remote.get_file_sorting(),
|
||||
_ => panic!("You can't mount file sorting when in found result"),
|
||||
};
|
||||
let index: usize = match sorting {
|
||||
FileSorting::ByCreationTime => 2,
|
||||
|
|
|
@ -91,12 +91,10 @@ pub const MSG_KEY_CHAR_E: Msg = Msg::OnKey(KeyEvent {
|
|||
code: KeyCode::Char('e'),
|
||||
modifiers: KeyModifiers::NONE,
|
||||
});
|
||||
/*
|
||||
pub const MSG_KEY_CHAR_F: Msg = Msg::OnKey(KeyEvent {
|
||||
code: KeyCode::Char('f'),
|
||||
modifiers: KeyModifiers::NONE,
|
||||
});
|
||||
*/
|
||||
pub const MSG_KEY_CHAR_G: Msg = Msg::OnKey(KeyEvent {
|
||||
code: KeyCode::Char('g'),
|
||||
modifiers: KeyModifiers::NONE,
|
||||
|
|
Loading…
Reference in a new issue