Add ability to remove files from Recents

This commit is contained in:
Jason Rodney Hansen 2025-07-11 08:18:19 -06:00 committed by Jeremy Soller
parent 5a01fb95ff
commit 54b884e5f8
6 changed files with 63 additions and 3 deletions

3
Cargo.lock generated
View file

@ -6048,8 +6048,7 @@ dependencies = [
[[package]] [[package]]
name = "recently-used-xbel" name = "recently-used-xbel"
version = "1.1.0" version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "git+https://github.com/pop-os/recently-used-xbel.git#eeba9e08b0446175d7dd4f526d21ea867ed37e87"
checksum = "079a81183e41e5cf17fd9ec55db30d6be6cddfad7fd619862efac27f1be28c9b"
dependencies = [ dependencies = [
"chrono", "chrono",
"dirs 5.0.1", "dirs 5.0.1",

View file

@ -63,7 +63,7 @@ i18n-embed = { version = "0.15", features = [
i18n-embed-fl = "0.9" i18n-embed-fl = "0.9"
rust-embed = "8" rust-embed = "8"
slotmap = "1.0.7" slotmap = "1.0.7"
recently-used-xbel = "1.1.0" recently-used-xbel = { git = "https://github.com/pop-os/recently-used-xbel.git" }
zip = "2.2.2" zip = "2.2.2"
uzers = "0.12.1" uzers = "0.12.1"
md-5 = "0.10.6" md-5 = "0.10.6"

View file

@ -245,6 +245,14 @@ permanently-deleted = Permanently deleted {$items} {$items ->
[one] item [one] item
*[other] items *[other] items
} }
removing-from-recents = Removing {$items} {$items ->
[one] item
*[other] items
} from {recents}
removed-from-recents = Removed {$items} {$items ->
[one] item
*[other] items
} from {recents}
renaming = Renaming "{$from}" to "{$to}" renaming = Renaming "{$from}" to "{$to}"
renamed = Renamed "{$from}" to "{$to}" renamed = Renamed "{$from}" to "{$to}"
restoring = Restoring {$items} {$items -> restoring = Restoring {$items} {$items ->
@ -303,6 +311,7 @@ sort-by-name = Sort by name
sort-by-modified = Sort by modified sort-by-modified = Sort by modified
sort-by-size = Sort by size sort-by-size = Sort by size
sort-by-trashed = Sort by delete time sort-by-trashed = Sort by delete time
remove-from-recents = Remove from recents
## Desktop ## Desktop
change-wallpaper = Change wallpaper... change-wallpaper = Change wallpaper...

View file

@ -147,6 +147,7 @@ pub enum Action {
PermanentlyDelete, PermanentlyDelete,
Preview, Preview,
Reload, Reload,
RemoveFromRecents,
Rename, Rename,
RestoreFromTrash, RestoreFromTrash,
SearchActivate, SearchActivate,
@ -217,6 +218,7 @@ impl Action {
Action::PermanentlyDelete => Message::PermanentlyDelete(entity_opt), Action::PermanentlyDelete => Message::PermanentlyDelete(entity_opt),
Action::Preview => Message::Preview(entity_opt), Action::Preview => Message::Preview(entity_opt),
Action::Reload => Message::TabMessage(entity_opt, tab::Message::Reload), Action::Reload => Message::TabMessage(entity_opt, tab::Message::Reload),
Action::RemoveFromRecents => Message::RemoveFromRecents(entity_opt),
Action::Rename => Message::Rename(entity_opt), Action::Rename => Message::Rename(entity_opt),
Action::RestoreFromTrash => Message::RestoreFromTrash(entity_opt), Action::RestoreFromTrash => Message::RestoreFromTrash(entity_opt),
Action::SearchActivate => Message::SearchActivate, Action::SearchActivate => Message::SearchActivate,
@ -360,6 +362,7 @@ pub enum Message {
PermanentlyDelete(Option<Entity>), PermanentlyDelete(Option<Entity>),
Preview(Option<Entity>), Preview(Option<Entity>),
RescanTrash, RescanTrash,
RemoveFromRecents(Option<Entity>),
Rename(Option<Entity>), Rename(Option<Entity>),
ReplaceResult(ReplaceResult), ReplaceResult(ReplaceResult),
RestoreFromTrash(Option<Entity>), RestoreFromTrash(Option<Entity>),
@ -1117,6 +1120,23 @@ impl App {
Task::batch(commands) Task::batch(commands)
} }
fn rescan_recents(&mut self) -> Task<Message> {
let mut needs_reload = Vec::new();
for entity in self.tab_model.iter() {
if let Some(tab) = self.tab_model.data::<Tab>(entity) {
if let Location::Recents = &tab.location {
needs_reload.push((entity, Location::Recents));
}
}
}
let mut commands = Vec::with_capacity(needs_reload.len());
for (entity, location) in needs_reload {
commands.push(self.update_tab(entity, location, None));
}
Task::batch(commands)
}
fn search_get(&self) -> Option<&str> { fn search_get(&self) -> Option<&str> {
let entity = self.tab_model.active(); let entity = self.tab_model.active();
let tab = self.tab_model.data::<Tab>(entity)?; let tab = self.tab_model.data::<Tab>(entity)?;
@ -3152,6 +3172,10 @@ impl Application for App {
} }
} }
if matches!(op, Operation::RemoveFromRecents { .. }) {
commands.push(self.rescan_recents());
}
self.complete_operations.insert(id, op); self.complete_operations.insert(id, op);
} }
// Close progress notification if all relevant operations are finished // Close progress notification if all relevant operations are finished
@ -3168,6 +3192,7 @@ impl Application for App {
commands.push(self.rescan_operation_selection(op_sel)); commands.push(self.rescan_operation_selection(op_sel));
// Manually rescan any trash tabs after any operation is completed // Manually rescan any trash tabs after any operation is completed
commands.push(self.rescan_trash()); commands.push(self.rescan_trash());
return Task::batch(commands); return Task::batch(commands);
} }
Message::PendingDismiss => { Message::PendingDismiss => {
@ -3268,6 +3293,10 @@ impl Application for App {
} }
} }
} }
Message::RemoveFromRecents(entity_opt) => {
let paths = self.selected_paths(entity_opt);
return self.operation(Operation::RemoveFromRecents { paths });
}
Message::RescanTrash => { Message::RescanTrash => {
// Update trash icon if empty/full // Update trash icon if empty/full
let maybe_entity = self.nav_model.iter().find(|&entity| { let maybe_entity = self.nav_model.iter().find(|&entity| {

View file

@ -239,6 +239,12 @@ pub fn context_menu<'a>(
children.push(menu_item(fl!("add-to-sidebar"), Action::AddToSidebar).into()); children.push(menu_item(fl!("add-to-sidebar"), Action::AddToSidebar).into());
} }
children.push(divider::horizontal::light().into()); children.push(divider::horizontal::light().into());
if matches!(tab.location, Location::Recents) {
children.push(
menu_item(fl!("remove-from-recents"), Action::RemoveFromRecents).into(),
);
children.push(divider::horizontal::light().into());
}
if selected_mount_point == 0 { if selected_mount_point == 0 {
if modifiers.shift() && !modifiers.control() { if modifiers.shift() && !modifiers.control() {
children.push( children.push(

View file

@ -523,6 +523,9 @@ pub enum Operation {
PermanentlyDelete { PermanentlyDelete {
paths: Vec<PathBuf>, paths: Vec<PathBuf>,
}, },
RemoveFromRecents {
paths: Vec<PathBuf>,
},
Rename { Rename {
from: PathBuf, from: PathBuf,
to: PathBuf, to: PathBuf,
@ -635,6 +638,7 @@ impl Operation {
Self::Rename { from, to } => { Self::Rename { from, to } => {
fl!("renaming", from = file_name(from), to = file_name(to)) fl!("renaming", from = file_name(from), to = file_name(to))
} }
Self::RemoveFromRecents { paths } => fl!("removing-from-recents", items = paths.len()),
Self::Restore { items } => fl!("restoring", items = items.len(), progress = progress()), Self::Restore { items } => fl!("restoring", items = items.len(), progress = progress()),
Self::SetExecutableAndLaunch { path } => { Self::SetExecutableAndLaunch { path } => {
fl!("setting-executable-and-launching", name = file_name(path)) fl!("setting-executable-and-launching", name = file_name(path))
@ -698,6 +702,7 @@ impl Operation {
parent = parent_name(path) parent = parent_name(path)
), ),
Self::PermanentlyDelete { paths } => fl!("permanently-deleted", items = paths.len()), Self::PermanentlyDelete { paths } => fl!("permanently-deleted", items = paths.len()),
Self::RemoveFromRecents { paths } => fl!("removed-from-recents", items = paths.len()),
Self::Rename { from, to } => fl!("renamed", from = file_name(from), to = file_name(to)), Self::Rename { from, to } => fl!("renamed", from = file_name(from), to = file_name(to)),
Self::Restore { items } => fl!("restored", items = items.len()), Self::Restore { items } => fl!("restored", items = items.len()),
Self::SetExecutableAndLaunch { path } => { Self::SetExecutableAndLaunch { path } => {
@ -727,6 +732,7 @@ impl Operation {
| Self::Restore { .. } => true, | Self::Restore { .. } => true,
Self::NewFile { .. } Self::NewFile { .. }
| Self::NewFolder { .. } | Self::NewFolder { .. }
| Self::RemoveFromRecents { .. }
| Self::Rename { .. } | Self::Rename { .. }
| Self::SetExecutableAndLaunch { .. } | Self::SetExecutableAndLaunch { .. }
| Self::SetPermissions { .. } => false, | Self::SetPermissions { .. } => false,
@ -1154,6 +1160,17 @@ impl Operation {
Ok(OperationSelection::default()) Ok(OperationSelection::default())
} }
Self::RemoveFromRecents { paths } => {
tokio::task::spawn_blocking(move || {
let path_refs = paths.iter().map(|p| p.as_ref()).collect::<Vec<&Path>>();
recently_used_xbel::remove_recently_used(&path_refs)
})
.await
.map_err(OperationError::from_str)?
.map_err(OperationError::from_str)?;
Ok(OperationSelection::default())
}
Self::Rename { from, to } => compio::runtime::spawn(async move { Self::Rename { from, to } => compio::runtime::spawn(async move {
controller.check().await.map_err(OperationError::from_str)?; controller.check().await.map_err(OperationError::from_str)?;
compio::fs::rename(&from, &to) compio::fs::rename(&from, &to)