From 08a3ac862035897cef046bc9a482cbf22d9dfd6e Mon Sep 17 00:00:00 2001 From: Jason Rodney Hansen Date: Sat, 8 Mar 2025 14:23:58 -0700 Subject: [PATCH 1/2] Update favorites when dir is renamed or moved --- src/app.rs | 75 +++++++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 72 insertions(+), 3 deletions(-) diff --git a/src/app.rs b/src/app.rs index ab1d7ce..2caecbe 100644 --- a/src/app.rs +++ b/src/app.rs @@ -50,8 +50,7 @@ use slotmap::Key as SlotMapKey; use std::{ any::TypeId, collections::{BTreeMap, BTreeSet, HashMap, HashSet, VecDeque}, - env, - fmt, fs, io, + env, fmt, fs, io, num::NonZeroU16, path::{Path, PathBuf}, process, @@ -1567,6 +1566,57 @@ impl App { ]) .into() } + + // Update favorites based on a rename or a move. + fn update_favorites(&mut self, from: &Path, to: &Path) -> bool { + let mut favorites_changed = false; + let favorites = self + .config + .favorites + .iter() + .cloned() + .map(|favorite| { + if let Favorite::Path(ref path) = favorite { + if path.starts_with(from) { + if let Ok(relative) = path.strip_prefix(from) { + favorites_changed = true; + return Favorite::from_path(to.join(relative)); + } + } + } + favorite + }) + .collect(); + + if favorites_changed { + if let Some(config_handler) = &self.config_handler { + match self.config.set_favorites(config_handler, favorites) { + Ok(updated) => { + if updated { + return true; + } + } + Err(err) => { + log::warn!( + "failed to update favorites after moving {} to {}: {}", + from.display(), + to.display(), + err, + ); + } + }; + } else { + self.config.favorites = favorites; + log::warn!( + "failed to update favorites after moving {} to {}: no config handler", + from.display(), + to.display(), + ); + } + } + + return false; + } } /// Implement [`Application`] to integrate with COSMIC. @@ -2673,8 +2723,8 @@ impl Application for App { } Message::PendingComplete(id, op_sel) => { let mut commands = Vec::with_capacity(4); - // Show toast for some operations if let Some((op, _)) = self.pending_operations.remove(&id) { + // Show toast for some operations if let Some(description) = op.toast() { if let Operation::Delete { ref paths } = op { let paths: Arc<[PathBuf]> = Arc::from(paths.as_slice()); @@ -2690,6 +2740,25 @@ impl Application for App { ); } } + + // If a favorite for a path has been renamed or moved, update it. + if let Operation::Rename { ref from, ref to } = op { + if self.update_favorites(from, to) { + commands.push(self.update_config()); + } + } else if let Operation::Move { ref paths, ref to } = op { + let mut updated = false; + for from in paths { + if let Some(name) = from.file_name() { + let to = to.join(name); + updated |= self.update_favorites(from, &to); + } + } + if updated { + commands.push(self.update_config()); + } + } + self.complete_operations.insert(id, op); } // Close progress notification if all relavent operations are finished From 0d76f7819e2743d4ed6b7c17f134bfa198be691a Mon Sep 17 00:00:00 2001 From: Jason Rodney Hansen Date: Sat, 8 Mar 2025 17:11:34 -0700 Subject: [PATCH 2/2] Improve updating favorites when moving multiple dirs Now update_favorites only needs to be called a single time after moving a bunch of files. --- src/app.rs | 39 ++++++++++++++++++--------------------- 1 file changed, 18 insertions(+), 21 deletions(-) diff --git a/src/app.rs b/src/app.rs index 2caecbe..e469bce 100644 --- a/src/app.rs +++ b/src/app.rs @@ -1567,8 +1567,8 @@ impl App { .into() } - // Update favorites based on a rename or a move. - fn update_favorites(&mut self, from: &Path, to: &Path) -> bool { + // Update favorites based on renaming or moving dirs. + fn update_favorites(&mut self, path_changes: &[(PathBuf, PathBuf)]) -> bool { let mut favorites_changed = false; let favorites = self .config @@ -1577,10 +1577,12 @@ impl App { .cloned() .map(|favorite| { if let Favorite::Path(ref path) = favorite { - if path.starts_with(from) { - if let Ok(relative) = path.strip_prefix(from) { - favorites_changed = true; - return Favorite::from_path(to.join(relative)); + for (from, to) in path_changes { + if path.starts_with(from) { + if let Ok(relative) = path.strip_prefix(from) { + favorites_changed = true; + return Favorite::from_path(to.join(relative)); + } } } } @@ -1598,9 +1600,7 @@ impl App { } Err(err) => { log::warn!( - "failed to update favorites after moving {} to {}: {}", - from.display(), - to.display(), + "failed to update favorites after moving directories: {:?}", err, ); } @@ -1608,9 +1608,7 @@ impl App { } else { self.config.favorites = favorites; log::warn!( - "failed to update favorites after moving {} to {}: no config handler", - from.display(), - to.display(), + "failed to update favorites after moving directories: no config handler", ); } } @@ -2743,18 +2741,17 @@ impl Application for App { // If a favorite for a path has been renamed or moved, update it. if let Operation::Rename { ref from, ref to } = op { - if self.update_favorites(from, to) { + if self.update_favorites(&[(from.clone(), to.clone())]) { commands.push(self.update_config()); } } else if let Operation::Move { ref paths, ref to } = op { - let mut updated = false; - for from in paths { - if let Some(name) = from.file_name() { - let to = to.join(name); - updated |= self.update_favorites(from, &to); - } - } - if updated { + let path_changes: Vec<_> = paths + .iter() + .filter_map(|from| { + from.file_name().map(|name| (from.clone(), to.join(name))) + }) + .collect(); + if self.update_favorites(&path_changes) { commands.push(self.update_config()); } }