Project panel faster (#35634)
- **Use a struct instead of a thruple for visible worktree entries** - **Try some telemetry** Closes #ISSUE Release Notes: - N/A --------- Co-authored-by: Piotr Osiewicz <24362066+osiewicz@users.noreply.github.com>
This commit is contained in:
parent
0097d89672
commit
bc32b5a976
4 changed files with 122 additions and 78 deletions
1
Cargo.lock
generated
1
Cargo.lock
generated
|
@ -12653,6 +12653,7 @@ dependencies = [
|
||||||
"serde_json",
|
"serde_json",
|
||||||
"settings",
|
"settings",
|
||||||
"smallvec",
|
"smallvec",
|
||||||
|
"telemetry",
|
||||||
"theme",
|
"theme",
|
||||||
"ui",
|
"ui",
|
||||||
"util",
|
"util",
|
||||||
|
|
|
@ -110,11 +110,7 @@ impl<'a> GitTraversal<'a> {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn advance(&mut self) -> bool {
|
pub fn advance(&mut self) -> bool {
|
||||||
self.advance_by(1)
|
let found = self.traversal.advance_by(1);
|
||||||
}
|
|
||||||
|
|
||||||
pub fn advance_by(&mut self, count: usize) -> bool {
|
|
||||||
let found = self.traversal.advance_by(count);
|
|
||||||
self.synchronize_statuses(false);
|
self.synchronize_statuses(false);
|
||||||
found
|
found
|
||||||
}
|
}
|
||||||
|
|
|
@ -41,6 +41,7 @@ worktree.workspace = true
|
||||||
workspace.workspace = true
|
workspace.workspace = true
|
||||||
language.workspace = true
|
language.workspace = true
|
||||||
zed_actions.workspace = true
|
zed_actions.workspace = true
|
||||||
|
telemetry.workspace = true
|
||||||
workspace-hack.workspace = true
|
workspace-hack.workspace = true
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
|
|
|
@ -44,7 +44,7 @@ use schemars::JsonSchema;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use settings::{Settings, SettingsStore, update_settings_file};
|
use settings::{Settings, SettingsStore, update_settings_file};
|
||||||
use smallvec::SmallVec;
|
use smallvec::SmallVec;
|
||||||
use std::any::TypeId;
|
use std::{any::TypeId, time::Instant};
|
||||||
use std::{
|
use std::{
|
||||||
cell::OnceCell,
|
cell::OnceCell,
|
||||||
cmp,
|
cmp,
|
||||||
|
@ -74,6 +74,12 @@ use zed_actions::OpenRecent;
|
||||||
const PROJECT_PANEL_KEY: &str = "ProjectPanel";
|
const PROJECT_PANEL_KEY: &str = "ProjectPanel";
|
||||||
const NEW_ENTRY_ID: ProjectEntryId = ProjectEntryId::MAX;
|
const NEW_ENTRY_ID: ProjectEntryId = ProjectEntryId::MAX;
|
||||||
|
|
||||||
|
struct VisibleEntriesForWorktree {
|
||||||
|
worktree_id: WorktreeId,
|
||||||
|
entries: Vec<GitEntry>,
|
||||||
|
index: OnceCell<HashSet<Arc<Path>>>,
|
||||||
|
}
|
||||||
|
|
||||||
pub struct ProjectPanel {
|
pub struct ProjectPanel {
|
||||||
project: Entity<Project>,
|
project: Entity<Project>,
|
||||||
fs: Arc<dyn Fs>,
|
fs: Arc<dyn Fs>,
|
||||||
|
@ -82,7 +88,7 @@ pub struct ProjectPanel {
|
||||||
// An update loop that keeps incrementing/decrementing scroll offset while there is a dragged entry that's
|
// An update loop that keeps incrementing/decrementing scroll offset while there is a dragged entry that's
|
||||||
// hovered over the start/end of a list.
|
// hovered over the start/end of a list.
|
||||||
hover_scroll_task: Option<Task<()>>,
|
hover_scroll_task: Option<Task<()>>,
|
||||||
visible_entries: Vec<(WorktreeId, Vec<GitEntry>, OnceCell<HashSet<Arc<Path>>>)>,
|
visible_entries: Vec<VisibleEntriesForWorktree>,
|
||||||
/// Maps from leaf project entry ID to the currently selected ancestor.
|
/// Maps from leaf project entry ID to the currently selected ancestor.
|
||||||
/// Relevant only for auto-fold dirs, where a single project panel entry may actually consist of several
|
/// Relevant only for auto-fold dirs, where a single project panel entry may actually consist of several
|
||||||
/// project entries (and all non-leaf nodes are guaranteed to be directories).
|
/// project entries (and all non-leaf nodes are guaranteed to be directories).
|
||||||
|
@ -116,6 +122,7 @@ pub struct ProjectPanel {
|
||||||
hover_expand_task: Option<Task<()>>,
|
hover_expand_task: Option<Task<()>>,
|
||||||
previous_drag_position: Option<Point<Pixels>>,
|
previous_drag_position: Option<Point<Pixels>>,
|
||||||
sticky_items_count: usize,
|
sticky_items_count: usize,
|
||||||
|
last_reported_update: Instant,
|
||||||
}
|
}
|
||||||
|
|
||||||
struct DragTargetEntry {
|
struct DragTargetEntry {
|
||||||
|
@ -631,6 +638,7 @@ impl ProjectPanel {
|
||||||
hover_expand_task: None,
|
hover_expand_task: None,
|
||||||
previous_drag_position: None,
|
previous_drag_position: None,
|
||||||
sticky_items_count: 0,
|
sticky_items_count: 0,
|
||||||
|
last_reported_update: Instant::now(),
|
||||||
};
|
};
|
||||||
this.update_visible_entries(None, cx);
|
this.update_visible_entries(None, cx);
|
||||||
|
|
||||||
|
@ -1266,15 +1274,19 @@ impl ProjectPanel {
|
||||||
entry_ix -= 1;
|
entry_ix -= 1;
|
||||||
} else if worktree_ix > 0 {
|
} else if worktree_ix > 0 {
|
||||||
worktree_ix -= 1;
|
worktree_ix -= 1;
|
||||||
entry_ix = self.visible_entries[worktree_ix].1.len() - 1;
|
entry_ix = self.visible_entries[worktree_ix].entries.len() - 1;
|
||||||
} else {
|
} else {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
let (worktree_id, worktree_entries, _) = &self.visible_entries[worktree_ix];
|
let VisibleEntriesForWorktree {
|
||||||
|
worktree_id,
|
||||||
|
entries,
|
||||||
|
..
|
||||||
|
} = &self.visible_entries[worktree_ix];
|
||||||
let selection = SelectedEntry {
|
let selection = SelectedEntry {
|
||||||
worktree_id: *worktree_id,
|
worktree_id: *worktree_id,
|
||||||
entry_id: worktree_entries[entry_ix].id,
|
entry_id: entries[entry_ix].id,
|
||||||
};
|
};
|
||||||
self.selection = Some(selection);
|
self.selection = Some(selection);
|
||||||
if window.modifiers().shift {
|
if window.modifiers().shift {
|
||||||
|
@ -2005,7 +2017,9 @@ impl ProjectPanel {
|
||||||
if let Some(selection) = self.selection {
|
if let Some(selection) = self.selection {
|
||||||
let (mut worktree_ix, mut entry_ix, _) =
|
let (mut worktree_ix, mut entry_ix, _) =
|
||||||
self.index_for_selection(selection).unwrap_or_default();
|
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).map(|v| &v.entries)
|
||||||
|
{
|
||||||
if entry_ix + 1 < worktree_entries.len() {
|
if entry_ix + 1 < worktree_entries.len() {
|
||||||
entry_ix += 1;
|
entry_ix += 1;
|
||||||
} else {
|
} else {
|
||||||
|
@ -2014,9 +2028,13 @@ impl ProjectPanel {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some((worktree_id, worktree_entries, _)) = self.visible_entries.get(worktree_ix)
|
if let Some(VisibleEntriesForWorktree {
|
||||||
|
worktree_id,
|
||||||
|
entries,
|
||||||
|
..
|
||||||
|
}) = self.visible_entries.get(worktree_ix)
|
||||||
{
|
{
|
||||||
if let Some(entry) = worktree_entries.get(entry_ix) {
|
if let Some(entry) = entries.get(entry_ix) {
|
||||||
let selection = SelectedEntry {
|
let selection = SelectedEntry {
|
||||||
worktree_id: *worktree_id,
|
worktree_id: *worktree_id,
|
||||||
entry_id: entry.id,
|
entry_id: entry.id,
|
||||||
|
@ -2252,8 +2270,13 @@ impl ProjectPanel {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn select_first(&mut self, _: &SelectFirst, window: &mut Window, cx: &mut Context<Self>) {
|
fn select_first(&mut self, _: &SelectFirst, window: &mut Window, cx: &mut Context<Self>) {
|
||||||
if let Some((worktree_id, visible_worktree_entries, _)) = self.visible_entries.first() {
|
if let Some(VisibleEntriesForWorktree {
|
||||||
if let Some(entry) = visible_worktree_entries.first() {
|
worktree_id,
|
||||||
|
entries,
|
||||||
|
..
|
||||||
|
}) = self.visible_entries.first()
|
||||||
|
{
|
||||||
|
if let Some(entry) = entries.first() {
|
||||||
let selection = SelectedEntry {
|
let selection = SelectedEntry {
|
||||||
worktree_id: *worktree_id,
|
worktree_id: *worktree_id,
|
||||||
entry_id: entry.id,
|
entry_id: entry.id,
|
||||||
|
@ -2269,9 +2292,14 @@ impl ProjectPanel {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn select_last(&mut self, _: &SelectLast, _: &mut Window, cx: &mut Context<Self>) {
|
fn select_last(&mut self, _: &SelectLast, _: &mut Window, cx: &mut Context<Self>) {
|
||||||
if let Some((worktree_id, visible_worktree_entries, _)) = self.visible_entries.last() {
|
if let Some(VisibleEntriesForWorktree {
|
||||||
|
worktree_id,
|
||||||
|
entries,
|
||||||
|
..
|
||||||
|
}) = self.visible_entries.last()
|
||||||
|
{
|
||||||
let worktree = self.project.read(cx).worktree_for_id(*worktree_id, cx);
|
let worktree = self.project.read(cx).worktree_for_id(*worktree_id, cx);
|
||||||
if let (Some(worktree), Some(entry)) = (worktree, visible_worktree_entries.last()) {
|
if let (Some(worktree), Some(entry)) = (worktree, entries.last()) {
|
||||||
let worktree = worktree.read(cx);
|
let worktree = worktree.read(cx);
|
||||||
if let Some(entry) = worktree.entry_for_id(entry.id) {
|
if let Some(entry) = worktree.entry_for_id(entry.id) {
|
||||||
let selection = SelectedEntry {
|
let selection = SelectedEntry {
|
||||||
|
@ -2960,6 +2988,7 @@ impl ProjectPanel {
|
||||||
new_selected_entry: Option<(WorktreeId, ProjectEntryId)>,
|
new_selected_entry: Option<(WorktreeId, ProjectEntryId)>,
|
||||||
cx: &mut Context<Self>,
|
cx: &mut Context<Self>,
|
||||||
) {
|
) {
|
||||||
|
let now = Instant::now();
|
||||||
let settings = ProjectPanelSettings::get_global(cx);
|
let settings = ProjectPanelSettings::get_global(cx);
|
||||||
let auto_collapse_dirs = settings.auto_fold_dirs;
|
let auto_collapse_dirs = settings.auto_fold_dirs;
|
||||||
let hide_gitignore = settings.hide_gitignore;
|
let hide_gitignore = settings.hide_gitignore;
|
||||||
|
@ -3157,19 +3186,23 @@ impl ProjectPanel {
|
||||||
|
|
||||||
project::sort_worktree_entries(&mut visible_worktree_entries);
|
project::sort_worktree_entries(&mut visible_worktree_entries);
|
||||||
|
|
||||||
self.visible_entries
|
self.visible_entries.push(VisibleEntriesForWorktree {
|
||||||
.push((worktree_id, visible_worktree_entries, OnceCell::new()));
|
worktree_id,
|
||||||
|
entries: visible_worktree_entries,
|
||||||
|
index: OnceCell::new(),
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some((project_entry_id, worktree_id, _)) = max_width_item {
|
if let Some((project_entry_id, worktree_id, _)) = max_width_item {
|
||||||
let mut visited_worktrees_length = 0;
|
let mut visited_worktrees_length = 0;
|
||||||
let index = self.visible_entries.iter().find_map(|(id, entries, _)| {
|
let index = self.visible_entries.iter().find_map(|visible_entries| {
|
||||||
if worktree_id == *id {
|
if worktree_id == visible_entries.worktree_id {
|
||||||
entries
|
visible_entries
|
||||||
|
.entries
|
||||||
.iter()
|
.iter()
|
||||||
.position(|entry| entry.id == project_entry_id)
|
.position(|entry| entry.id == project_entry_id)
|
||||||
} else {
|
} else {
|
||||||
visited_worktrees_length += entries.len();
|
visited_worktrees_length += visible_entries.entries.len();
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -3183,6 +3216,18 @@ impl ProjectPanel {
|
||||||
entry_id,
|
entry_id,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
let elapsed = now.elapsed();
|
||||||
|
if self.last_reported_update.elapsed() > Duration::from_secs(3600) {
|
||||||
|
telemetry::event!(
|
||||||
|
"Project Panel Updated",
|
||||||
|
elapsed_ms = elapsed.as_millis() as u64,
|
||||||
|
worktree_entries = self
|
||||||
|
.visible_entries
|
||||||
|
.iter()
|
||||||
|
.map(|worktree| worktree.entries.len())
|
||||||
|
.sum::<usize>(),
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn expand_entry(
|
fn expand_entry(
|
||||||
|
@ -3396,15 +3441,14 @@ impl ProjectPanel {
|
||||||
worktree_id: WorktreeId,
|
worktree_id: WorktreeId,
|
||||||
) -> Option<(usize, usize, usize)> {
|
) -> Option<(usize, usize, usize)> {
|
||||||
let mut total_ix = 0;
|
let mut total_ix = 0;
|
||||||
for (worktree_ix, (current_worktree_id, visible_worktree_entries, _)) in
|
for (worktree_ix, visible) in self.visible_entries.iter().enumerate() {
|
||||||
self.visible_entries.iter().enumerate()
|
if worktree_id != visible.worktree_id {
|
||||||
{
|
total_ix += visible.entries.len();
|
||||||
if worktree_id != *current_worktree_id {
|
|
||||||
total_ix += visible_worktree_entries.len();
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
return visible_worktree_entries
|
return visible
|
||||||
|
.entries
|
||||||
.iter()
|
.iter()
|
||||||
.enumerate()
|
.enumerate()
|
||||||
.find(|(_, entry)| entry.id == entry_id)
|
.find(|(_, entry)| entry.id == entry_id)
|
||||||
|
@ -3415,12 +3459,13 @@ impl ProjectPanel {
|
||||||
|
|
||||||
fn entry_at_index(&self, index: usize) -> Option<(WorktreeId, GitEntryRef<'_>)> {
|
fn entry_at_index(&self, index: usize) -> Option<(WorktreeId, GitEntryRef<'_>)> {
|
||||||
let mut offset = 0;
|
let mut offset = 0;
|
||||||
for (worktree_id, visible_worktree_entries, _) in &self.visible_entries {
|
for worktree in &self.visible_entries {
|
||||||
let current_len = visible_worktree_entries.len();
|
let current_len = worktree.entries.len();
|
||||||
if index < offset + current_len {
|
if index < offset + current_len {
|
||||||
return visible_worktree_entries
|
return worktree
|
||||||
|
.entries
|
||||||
.get(index - offset)
|
.get(index - offset)
|
||||||
.map(|entry| (*worktree_id, entry.to_ref()));
|
.map(|entry| (worktree.worktree_id, entry.to_ref()));
|
||||||
}
|
}
|
||||||
offset += current_len;
|
offset += current_len;
|
||||||
}
|
}
|
||||||
|
@ -3441,26 +3486,23 @@ impl ProjectPanel {
|
||||||
),
|
),
|
||||||
) {
|
) {
|
||||||
let mut ix = 0;
|
let mut ix = 0;
|
||||||
for (_, visible_worktree_entries, entries_paths) in &self.visible_entries {
|
for visible in &self.visible_entries {
|
||||||
if ix >= range.end {
|
if ix >= range.end {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ix + visible_worktree_entries.len() <= range.start {
|
if ix + visible.entries.len() <= range.start {
|
||||||
ix += visible_worktree_entries.len();
|
ix += visible.entries.len();
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
let end_ix = range.end.min(ix + visible_worktree_entries.len());
|
let end_ix = range.end.min(ix + visible.entries.len());
|
||||||
let entry_range = range.start.saturating_sub(ix)..end_ix - ix;
|
let entry_range = range.start.saturating_sub(ix)..end_ix - ix;
|
||||||
let entries = entries_paths.get_or_init(|| {
|
let entries = visible
|
||||||
visible_worktree_entries
|
.index
|
||||||
.iter()
|
.get_or_init(|| visible.entries.iter().map(|e| (e.path.clone())).collect());
|
||||||
.map(|e| (e.path.clone()))
|
|
||||||
.collect()
|
|
||||||
});
|
|
||||||
let base_index = ix + entry_range.start;
|
let base_index = ix + entry_range.start;
|
||||||
for (i, entry) in visible_worktree_entries[entry_range].iter().enumerate() {
|
for (i, entry) in visible.entries[entry_range].iter().enumerate() {
|
||||||
let global_index = base_index + i;
|
let global_index = base_index + i;
|
||||||
callback(&entry, global_index, entries, window, cx);
|
callback(&entry, global_index, entries, window, cx);
|
||||||
}
|
}
|
||||||
|
@ -3476,40 +3518,41 @@ impl ProjectPanel {
|
||||||
mut callback: impl FnMut(ProjectEntryId, EntryDetails, &mut Window, &mut Context<ProjectPanel>),
|
mut callback: impl FnMut(ProjectEntryId, EntryDetails, &mut Window, &mut Context<ProjectPanel>),
|
||||||
) {
|
) {
|
||||||
let mut ix = 0;
|
let mut ix = 0;
|
||||||
for (worktree_id, visible_worktree_entries, entries_paths) in &self.visible_entries {
|
for visible in &self.visible_entries {
|
||||||
if ix >= range.end {
|
if ix >= range.end {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ix + visible_worktree_entries.len() <= range.start {
|
if ix + visible.entries.len() <= range.start {
|
||||||
ix += visible_worktree_entries.len();
|
ix += visible.entries.len();
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
let end_ix = range.end.min(ix + visible_worktree_entries.len());
|
let end_ix = range.end.min(ix + visible.entries.len());
|
||||||
let git_status_setting = {
|
let git_status_setting = {
|
||||||
let settings = ProjectPanelSettings::get_global(cx);
|
let settings = ProjectPanelSettings::get_global(cx);
|
||||||
settings.git_status
|
settings.git_status
|
||||||
};
|
};
|
||||||
if let Some(worktree) = self.project.read(cx).worktree_for_id(*worktree_id, cx) {
|
if let Some(worktree) = self
|
||||||
|
.project
|
||||||
|
.read(cx)
|
||||||
|
.worktree_for_id(visible.worktree_id, cx)
|
||||||
|
{
|
||||||
let snapshot = worktree.read(cx).snapshot();
|
let snapshot = worktree.read(cx).snapshot();
|
||||||
let root_name = OsStr::new(snapshot.root_name());
|
let root_name = OsStr::new(snapshot.root_name());
|
||||||
|
|
||||||
let entry_range = range.start.saturating_sub(ix)..end_ix - ix;
|
let entry_range = range.start.saturating_sub(ix)..end_ix - ix;
|
||||||
let entries = entries_paths.get_or_init(|| {
|
let entries = visible
|
||||||
visible_worktree_entries
|
.index
|
||||||
.iter()
|
.get_or_init(|| visible.entries.iter().map(|e| (e.path.clone())).collect());
|
||||||
.map(|e| (e.path.clone()))
|
for entry in visible.entries[entry_range].iter() {
|
||||||
.collect()
|
|
||||||
});
|
|
||||||
for entry in visible_worktree_entries[entry_range].iter() {
|
|
||||||
let status = git_status_setting
|
let status = git_status_setting
|
||||||
.then_some(entry.git_summary)
|
.then_some(entry.git_summary)
|
||||||
.unwrap_or_default();
|
.unwrap_or_default();
|
||||||
|
|
||||||
let mut details = self.details_for_entry(
|
let mut details = self.details_for_entry(
|
||||||
entry,
|
entry,
|
||||||
*worktree_id,
|
visible.worktree_id,
|
||||||
root_name,
|
root_name,
|
||||||
entries,
|
entries,
|
||||||
status,
|
status,
|
||||||
|
@ -3595,9 +3638,9 @@ impl ProjectPanel {
|
||||||
let entries = self
|
let entries = self
|
||||||
.visible_entries
|
.visible_entries
|
||||||
.iter()
|
.iter()
|
||||||
.find_map(|(tree_id, entries, _)| {
|
.find_map(|visible| {
|
||||||
if worktree_id == *tree_id {
|
if worktree_id == visible.worktree_id {
|
||||||
Some(entries)
|
Some(&visible.entries)
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
@ -3636,7 +3679,7 @@ impl ProjectPanel {
|
||||||
let mut worktree_ids: Vec<_> = self
|
let mut worktree_ids: Vec<_> = self
|
||||||
.visible_entries
|
.visible_entries
|
||||||
.iter()
|
.iter()
|
||||||
.map(|(worktree_id, _, _)| *worktree_id)
|
.map(|worktree| worktree.worktree_id)
|
||||||
.collect();
|
.collect();
|
||||||
let repo_snapshots = self
|
let repo_snapshots = self
|
||||||
.project
|
.project
|
||||||
|
@ -3752,7 +3795,7 @@ impl ProjectPanel {
|
||||||
let mut worktree_ids: Vec<_> = self
|
let mut worktree_ids: Vec<_> = self
|
||||||
.visible_entries
|
.visible_entries
|
||||||
.iter()
|
.iter()
|
||||||
.map(|(worktree_id, _, _)| *worktree_id)
|
.map(|worktree| worktree.worktree_id)
|
||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
let mut last_found: Option<SelectedEntry> = None;
|
let mut last_found: Option<SelectedEntry> = None;
|
||||||
|
@ -3761,8 +3804,8 @@ impl ProjectPanel {
|
||||||
let entries = self
|
let entries = self
|
||||||
.visible_entries
|
.visible_entries
|
||||||
.iter()
|
.iter()
|
||||||
.find(|(worktree_id, _, _)| *worktree_id == start.worktree_id)
|
.find(|worktree| worktree.worktree_id == start.worktree_id)
|
||||||
.map(|(_, entries, _)| entries)?;
|
.map(|worktree| &worktree.entries)?;
|
||||||
|
|
||||||
let mut start_idx = entries
|
let mut start_idx = entries
|
||||||
.iter()
|
.iter()
|
||||||
|
@ -4914,7 +4957,7 @@ impl ProjectPanel {
|
||||||
|
|
||||||
let (active_indent_range, depth) = {
|
let (active_indent_range, depth) = {
|
||||||
let (worktree_ix, child_offset, ix) = self.index_for_entry(entry.id, worktree.id())?;
|
let (worktree_ix, child_offset, ix) = self.index_for_entry(entry.id, worktree.id())?;
|
||||||
let child_paths = &self.visible_entries[worktree_ix].1;
|
let child_paths = &self.visible_entries[worktree_ix].entries;
|
||||||
let mut child_count = 0;
|
let mut child_count = 0;
|
||||||
let depth = entry.path.ancestors().count();
|
let depth = entry.path.ancestors().count();
|
||||||
while let Some(entry) = child_paths.get(child_offset + child_count + 1) {
|
while let Some(entry) = child_paths.get(child_offset + child_count + 1) {
|
||||||
|
@ -4927,9 +4970,14 @@ impl ProjectPanel {
|
||||||
let start = ix + 1;
|
let start = ix + 1;
|
||||||
let end = start + child_count;
|
let end = start + child_count;
|
||||||
|
|
||||||
let (_, entries, paths) = &self.visible_entries[worktree_ix];
|
let visible_worktree = &self.visible_entries[worktree_ix];
|
||||||
let visible_worktree_entries =
|
let visible_worktree_entries = visible_worktree.index.get_or_init(|| {
|
||||||
paths.get_or_init(|| entries.iter().map(|e| (e.path.clone())).collect());
|
visible_worktree
|
||||||
|
.entries
|
||||||
|
.iter()
|
||||||
|
.map(|e| (e.path.clone()))
|
||||||
|
.collect()
|
||||||
|
});
|
||||||
|
|
||||||
// Calculate the actual depth of the entry, taking into account that directories can be auto-folded.
|
// Calculate the actual depth of the entry, taking into account that directories can be auto-folded.
|
||||||
let (depth, _) = Self::calculate_depth_and_difference(entry, visible_worktree_entries);
|
let (depth, _) = Self::calculate_depth_and_difference(entry, visible_worktree_entries);
|
||||||
|
@ -4964,10 +5012,10 @@ impl ProjectPanel {
|
||||||
return SmallVec::new();
|
return SmallVec::new();
|
||||||
};
|
};
|
||||||
|
|
||||||
let Some((_, visible_worktree_entries, entries_paths)) = self
|
let Some(visible) = self
|
||||||
.visible_entries
|
.visible_entries
|
||||||
.iter()
|
.iter()
|
||||||
.find(|(id, _, _)| *id == worktree_id)
|
.find(|worktree| worktree.worktree_id == worktree_id)
|
||||||
else {
|
else {
|
||||||
return SmallVec::new();
|
return SmallVec::new();
|
||||||
};
|
};
|
||||||
|
@ -4977,12 +5025,9 @@ impl ProjectPanel {
|
||||||
};
|
};
|
||||||
let worktree = worktree.read(cx).snapshot();
|
let worktree = worktree.read(cx).snapshot();
|
||||||
|
|
||||||
let paths = entries_paths.get_or_init(|| {
|
let paths = visible
|
||||||
visible_worktree_entries
|
.index
|
||||||
.iter()
|
.get_or_init(|| visible.entries.iter().map(|e| e.path.clone()).collect());
|
||||||
.map(|e| e.path.clone())
|
|
||||||
.collect()
|
|
||||||
});
|
|
||||||
|
|
||||||
let mut sticky_parents = Vec::new();
|
let mut sticky_parents = Vec::new();
|
||||||
let mut current_path = entry_ref.path.clone();
|
let mut current_path = entry_ref.path.clone();
|
||||||
|
@ -5012,7 +5057,8 @@ impl ProjectPanel {
|
||||||
let root_name = OsStr::new(worktree.root_name());
|
let root_name = OsStr::new(worktree.root_name());
|
||||||
|
|
||||||
let git_summaries_by_id = if git_status_enabled {
|
let git_summaries_by_id = if git_status_enabled {
|
||||||
visible_worktree_entries
|
visible
|
||||||
|
.entries
|
||||||
.iter()
|
.iter()
|
||||||
.map(|e| (e.id, e.git_summary))
|
.map(|e| (e.id, e.git_summary))
|
||||||
.collect::<HashMap<_, _>>()
|
.collect::<HashMap<_, _>>()
|
||||||
|
@ -5110,7 +5156,7 @@ impl Render for ProjectPanel {
|
||||||
let item_count = self
|
let item_count = self
|
||||||
.visible_entries
|
.visible_entries
|
||||||
.iter()
|
.iter()
|
||||||
.map(|(_, worktree_entries, _)| worktree_entries.len())
|
.map(|worktree| worktree.entries.len())
|
||||||
.sum();
|
.sum();
|
||||||
|
|
||||||
fn handle_drag_move<T: 'static>(
|
fn handle_drag_move<T: 'static>(
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue