From a34f7279135399653c5fa3c60b20562bb9187c7e Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Thu, 15 May 2025 11:30:35 -0600 Subject: [PATCH] Fall back to permanently delete on remote shares, part of #909 --- src/app.rs | 50 +++++++++++++++++++++++++++++++++++++++++++------- src/tab.rs | 4 ++-- 2 files changed, 45 insertions(+), 9 deletions(-) diff --git a/src/app.rs b/src/app.rs index c8fcaeb..c8f9372 100644 --- a/src/app.rs +++ b/src/app.rs @@ -910,6 +910,44 @@ impl App { self.open_tab_entity(location, activate, selection_paths).1 } + // This wrapper ensures that local folders use trash and remote folders permanently delete with a dialog + #[must_use] + fn delete(&mut self, paths: Vec) -> Task { + let mut dialog_paths = Vec::new(); + let mut trash_paths = Vec::new(); + + for path in paths { + //TODO: is there a smarter way to check this? (like checking for trash folders) + let can_trash = match path.metadata() { + Ok(metadata) => match tab::fs_kind(&metadata) { + tab::FsKind::Local => true, + _ => false, + }, + Err(err) => { + log::warn!("failed to get metadata for {:?}: {}", path, err); + false + } + }; + if can_trash { + trash_paths.push(path); + } else { + dialog_paths.push(path); + } + } + + if !dialog_paths.is_empty() { + self.dialog_pages.push_back(DialogPage::PermanentlyDelete { + paths: dialog_paths, + }); + } + + if !trash_paths.is_empty() { + self.operation(Operation::Delete { paths: trash_paths }) + } else { + Task::none() + } + } + #[must_use] fn operation(&mut self, operation: Operation) -> Task { let id = self.pending_operation_id; @@ -2304,9 +2342,9 @@ impl Application for App { } } _ => { - let paths = dbg!(self.selected_paths(entity_opt)); + let paths = self.selected_paths(entity_opt); if !paths.is_empty() { - return self.operation(Operation::Delete { paths }); + return self.delete(paths); } } } @@ -3458,9 +3496,7 @@ impl Application for App { self.update_tab(entity, tab_path, selection_paths), ])); } - tab::Command::Delete(paths) => { - commands.push(self.operation(Operation::Delete { paths })) - } + tab::Command::Delete(paths) => commands.push(self.delete(paths)), tab::Command::DropFiles(to, from) => { commands.push(self.update(Message::PasteContents(to, from))); } @@ -3741,7 +3777,7 @@ impl Application for App { }, )), Location::Trash if matches!(action, DndAction::Move) => { - self.operation(Operation::Delete { paths: data.paths }) + self.delete(data.paths) } _ => { log::warn!("Copy to trash is not supported."); @@ -3801,7 +3837,7 @@ impl Application for App { }, )), Location::Trash if matches!(action, DndAction::Move) => { - self.operation(Operation::Delete { paths: data.paths }) + self.delete(data.paths) } _ => { log::warn!("Copy to trash is not supported."); diff --git a/src/tab.rs b/src/tab.rs index fcd2a38..f74a43a 100644 --- a/src/tab.rs +++ b/src/tab.rs @@ -532,7 +532,7 @@ pub enum FsKind { } #[cfg(target_os = "linux")] -fn fs_kind(metadata: &Metadata) -> FsKind { +pub fn fs_kind(metadata: &Metadata) -> FsKind { //TODO: method to reload remote filesystems dynamically //TODO: fix for https://github.com/eminence/procfs/issues/262 static DEVICES: Lazy> = Lazy::new(|| { @@ -579,7 +579,7 @@ fn fs_kind(metadata: &Metadata) -> FsKind { } #[cfg(not(target_os = "linux"))] -fn fs_kind(_metadata: &Metadata) -> FsKind { +pub fn fs_kind(_metadata: &Metadata) -> FsKind { //TODO: support BSD, macOS, Windows? FsKind::Local }