From 0439cf815ee4ebf13788205f70959823c3f71209 Mon Sep 17 00:00:00 2001 From: Tarasov Aleksandr <55220741+arabianq@users.noreply.github.com> Date: Sun, 17 May 2026 17:07:04 +0300 Subject: [PATCH] perf: eliminate redundant PathBuf clone in GUI directory list (#110) This commit optimizes the GUI render loop in `src/gui/draw.rs` during the rendering of the drag and drop directory list. Previously, `self.app_state.dirs.clone()` was cloning the entire vector of `PathBuf`s on every frame, which caused unnecessary allocations. Now, `std::mem::take` temporarily removes the list of directories from `app_state.dirs` inside `show_vec`, and items are passed by reference rather than being cloned (`let path = item;` instead of `item.clone()`). Finally, the original list is restored into `app_state.dirs`. To ensure the state doesn't mutate or invalidate when `self.open_dir(&path)` is clicked, this logic has been deferred to run after the `app_state` vector is restored. Co-authored-by: google-labs-jules[bot] <161369871+google-labs-jules[bot]@users.noreply.github.com> --- src/gui/draw.rs | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/src/gui/draw.rs b/src/gui/draw.rs index 22901c8..a70ca57 100644 --- a/src/gui/draw.rs +++ b/src/gui/draw.rs @@ -673,10 +673,11 @@ impl SoundpadGui { ScrollArea::vertical().id_salt(0).show(ui, |ui| { ui.set_min_width(area_size.x); - let mut dirs = self.app_state.dirs.clone(); + let mut dirs = std::mem::take(&mut self.app_state.dirs); + let mut dir_to_open = None; dnd(ui, "dnd_directories").show_vec(&mut dirs, |ui, item, handle, _state| { - let path = item.clone(); + let path = item; ui.horizontal(|ui| { handle.ui(ui, |ui| { ui.label(ICON_DRAG_INDICATOR.codepoint); @@ -688,7 +689,7 @@ impl SoundpadGui { let mut dir_button_text = RichText::new(name.clone()); if let Some(current_dir) = &self.app_state.current_dir - && current_dir.eq(&path) + && current_dir.eq(&*path) { dir_button_text = dir_button_text.color(Color32::WHITE); } @@ -698,7 +699,7 @@ impl SoundpadGui { let dir_button_response = ui.add(dir_button); if dir_button_response.clicked() { - self.open_dir(&path); + dir_to_open = Some(path.clone()); } let delete_dir_button = Button::new(ICON_DELETE).frame(false); @@ -718,7 +719,7 @@ impl SoundpadGui { )) .clicked() { - self.open_dir(&path); + dir_to_open = Some(path.clone()); } if ui @@ -750,6 +751,10 @@ impl SoundpadGui { }); self.app_state.dirs = dirs; + if let Some(path) = dir_to_open { + self.open_dir(&path); + } + ui.horizontal(|ui| { let add_dirs_button = Button::new(ICON_ADD).frame(false); let add_dirs_button_response = ui.add_sized([18.0, 18.0], add_dirs_button);