diff --git a/crates/project_panel/src/project_panel.rs b/crates/project_panel/src/project_panel.rs index 0ca5b6c595..c7e2ee260c 100644 --- a/crates/project_panel/src/project_panel.rs +++ b/crates/project_panel/src/project_panel.rs @@ -22,6 +22,7 @@ use project::{Entry, EntryKind, Fs, Project, ProjectEntryId, ProjectPath, Worktr use project_panel_settings::{ProjectPanelDockPosition, ProjectPanelSettings}; use serde::{Deserialize, Serialize}; use std::{ + cell::OnceCell, collections::HashSet, ffi::OsStr, ops::Range, @@ -46,7 +47,7 @@ pub struct ProjectPanel { fs: Arc, scroll_handle: UniformListScrollHandle, focus_handle: FocusHandle, - visible_entries: Vec<(WorktreeId, Vec)>, + visible_entries: Vec<(WorktreeId, Vec, OnceCell>>)>, last_worktree_root_id: Option, last_external_paths_drag_over_entry: Option, expanded_dir_ids: HashMap>, @@ -675,7 +676,7 @@ impl ProjectPanel { return; } - let (worktree_id, worktree_entries) = &self.visible_entries[worktree_ix]; + let (worktree_id, worktree_entries, _) = &self.visible_entries[worktree_ix]; let selection = SelectedEntry { worktree_id: *worktree_id, entry_id: worktree_entries[entry_ix].id, @@ -1120,7 +1121,7 @@ impl ProjectPanel { if let Some(selection) = self.selection { let (mut worktree_ix, mut entry_ix, _) = self.index_for_selection(selection).unwrap_or_default(); - if let Some((_, worktree_entries)) = self.visible_entries.get(worktree_ix) { + if let Some((_, worktree_entries, _)) = self.visible_entries.get(worktree_ix) { if entry_ix + 1 < worktree_entries.len() { entry_ix += 1; } else { @@ -1129,7 +1130,8 @@ impl ProjectPanel { } } - if let Some((worktree_id, worktree_entries)) = self.visible_entries.get(worktree_ix) { + if let Some((worktree_id, worktree_entries, _)) = self.visible_entries.get(worktree_ix) + { if let Some(entry) = worktree_entries.get(entry_ix) { let selection = SelectedEntry { worktree_id: *worktree_id, @@ -1170,7 +1172,9 @@ impl ProjectPanel { let worktree = self .visible_entries .first() - .and_then(|(worktree_id, _)| self.project.read(cx).worktree_for_id(*worktree_id, cx)); + .and_then(|(worktree_id, _, _)| { + self.project.read(cx).worktree_for_id(*worktree_id, cx) + }); if let Some(worktree) = worktree { let worktree = worktree.read(cx); let worktree_id = worktree.id(); @@ -1190,10 +1194,9 @@ impl ProjectPanel { } fn select_last(&mut self, _: &SelectLast, cx: &mut ViewContext) { - let worktree = self - .visible_entries - .last() - .and_then(|(worktree_id, _)| self.project.read(cx).worktree_for_id(*worktree_id, cx)); + let worktree = self.visible_entries.last().and_then(|(worktree_id, _, _)| { + self.project.read(cx).worktree_for_id(*worktree_id, cx) + }); if let Some(worktree) = worktree { let worktree = worktree.read(cx); let worktree_id = worktree.id(); @@ -1461,7 +1464,7 @@ impl ProjectPanel { fn index_for_selection(&self, selection: SelectedEntry) -> Option<(usize, usize, usize)> { let mut entry_index = 0; let mut visible_entries_index = 0; - for (worktree_index, (worktree_id, worktree_entries)) in + for (worktree_index, (worktree_id, worktree_entries, _)) in self.visible_entries.iter().enumerate() { if *worktree_id == selection.worktree_id { @@ -1623,7 +1626,7 @@ impl ProjectPanel { snapshot.propagate_git_statuses(&mut visible_worktree_entries); project::sort_worktree_entries(&mut visible_worktree_entries); self.visible_entries - .push((worktree_id, visible_worktree_entries)); + .push((worktree_id, visible_worktree_entries, OnceCell::new())); } if let Some((worktree_id, entry_id)) = new_selected_entry { @@ -1794,7 +1797,7 @@ impl ProjectPanel { mut callback: impl FnMut(ProjectEntryId, EntryDetails, &mut ViewContext), ) { let mut ix = 0; - for (worktree_id, visible_worktree_entries) in &self.visible_entries { + for (worktree_id, visible_worktree_entries, entries_paths) in &self.visible_entries { if ix >= range.end { return; } @@ -1823,10 +1826,12 @@ impl ProjectPanel { .unwrap_or(&[]); let entry_range = range.start.saturating_sub(ix)..end_ix - ix; - let entries = visible_worktree_entries - .iter() - .map(|e| (e.path.clone())) - .collect(); + let entries = entries_paths.get_or_init(|| { + visible_worktree_entries + .iter() + .map(|e| (e.path.clone())) + .collect() + }); for entry in visible_worktree_entries[entry_range].iter() { let status = git_status_setting.then(|| entry.git_status).flatten(); let is_expanded = expanded_entry_ids.binary_search(&entry.id).is_ok(); @@ -2298,7 +2303,7 @@ impl Render for ProjectPanel { "entries", self.visible_entries .iter() - .map(|(_, worktree_entries)| worktree_entries.len()) + .map(|(_, worktree_entries, _)| worktree_entries.len()) .sum(), { |this, range, cx| {