feat(file-select): Queueing transfers

the logic of selecting files has been extended!
From now on selecting file will put the files into a transfer queue, which is shown on the bottom panel.
When a file is selected the file is added to the queue with a destination path, which is the **current other explorer path at the moment of selection.
It is possible to navigate to the transfer queue by using `P` and pressing `ENTER` on a file will remove it from the transfer queue.Other commands will work as well on the transfer queue, like `COPY`, `MOVE`, `DELETE`, `RENAME`.

closes #132
This commit is contained in:
veeso
2025-03-22 16:17:59 +01:00
parent 76c5528734
commit 85bb586e8f
11 changed files with 324 additions and 43 deletions

View File

@@ -16,6 +16,7 @@ use super::browser::{FileExplorerTab, FoundExplorerTab};
use super::components::ATTR_FILES;
use super::{Context, FileTransferActivity, Id, components};
use crate::explorer::FileSorting;
use crate::ui::activities::filetransfer::MarkQueue;
use crate::utils::ui::{Popup, Size};
impl FileTransferActivity {
@@ -81,6 +82,8 @@ impl FileTransferActivity {
)
.is_ok()
);
self.refresh_host_bridge_transfer_queue();
self.refresh_remote_transfer_queue();
// Load status bar
self.refresh_local_status_bar();
self.refresh_remote_status_bar();
@@ -138,6 +141,17 @@ impl FileTransferActivity {
.direction(Direction::Horizontal)
.horizontal_margin(1)
.split(bottom_chunks[0]);
let bottom_components = Layout::default()
.constraints(
[
Constraint::Percentage(25),
Constraint::Percentage(25),
Constraint::Percentage(50),
]
.as_ref(),
)
.direction(Direction::Horizontal)
.split(bottom_chunks[1]);
// Draw footer
self.app.view(&Id::FooterBar, f, body[1]);
// Draw explorers
@@ -153,8 +167,13 @@ impl FileTransferActivity {
} else {
self.app.view(&Id::ExplorerRemote, f, tabs_chunks[1]);
}
// draw transfer queues
self.app
.view(&Id::TransferQueueHostBridge, f, bottom_components[0]);
self.app
.view(&Id::TransferQueueRemote, f, bottom_components[1]);
// Draw log box
self.app.view(&Id::Log, f, bottom_chunks[1]);
self.app.view(&Id::Log, f, bottom_components[2]);
// Draw status bar
self.app
.view(&Id::StatusBarHostBridge, f, status_bar_chunks[0]);
@@ -928,6 +947,56 @@ impl FileTransferActivity {
let _ = self.app.umount(&Id::FileInfoPopup);
}
pub(super) fn refresh_host_bridge_transfer_queue(&mut self) {
let enqueued = self
.host_bridge()
.enqueued()
.iter()
.map(|(src, dest)| (src.clone(), dest.clone()))
.collect::<Vec<_>>();
let log_panel = self.theme().transfer_log_window;
assert!(
self.app
.remount(
Id::TransferQueueHostBridge,
Box::new(components::SelectedFilesList::new(
&enqueued,
MarkQueue::Local,
log_panel,
"Host Bridge transfer queue",
)),
vec![]
)
.is_ok()
);
}
pub(super) fn refresh_remote_transfer_queue(&mut self) {
let enqueued = self
.remote()
.enqueued()
.iter()
.map(|(src, dest)| (src.clone(), dest.clone()))
.collect::<Vec<_>>();
let log_panel = self.theme().transfer_log_window;
assert!(
self.app
.remount(
Id::TransferQueueRemote,
Box::new(components::SelectedFilesList::new(
&enqueued,
MarkQueue::Remote,
log_panel,
"Remote transfer queue",
)),
vec![]
)
.is_ok()
);
}
pub(super) fn refresh_local_status_bar(&mut self) {
let sorting_color = self.theme().transfer_status_sorting;
let hidden_color = self.theme().transfer_status_hidden;