project_panel: Fix selection not updating for already-visible gitignored files (#49521)

## Summary
- Keep auto-reveal behavior for ignored files unchanged (no implicit
reveal).
- When an ignored file is already visible in the project panel, mark it
as selected on `ActiveEntryChanged`.
- Add regression coverage for switching back to a visible gitignored
file.

## Testing
- `project_panel_tests::test_autoreveal_and_gitignored_files`
- `project_panel_tests::test_gitignored_and_always_included`
- `project_panel_tests::test_explicit_reveal`

Closes #49515

Release Notes:

- Fixed project panel not updating selection when switching to a
gitignored file that was already visible.
This commit is contained in:
Efe authored and GitHub committed 2026-02-25 23:35:59 +05:30
1 parent 6acc1a3344
commit 706faa973e
2 files changed
+79 -7

No files matched your search

+21 -7
View File
@@ -6053,12 +6053,27 @@ impl ProjectPanel {
.worktree_for_entry(entry_id, cx)
.context("can't reveal a non-existent entry in the project panel")?;
let worktree = worktree.read(cx);
if skip_ignored
&& worktree
.entry_for_id(entry_id)
.is_none_or(|entry| entry.is_ignored && !entry.is_always_included)
{
anyhow::bail!("can't reveal an ignored entry in the project panel");
let worktree_id = worktree.id();
let is_ignored = worktree
.entry_for_id(entry_id)
.is_none_or(|entry| entry.is_ignored && !entry.is_always_included);
if skip_ignored && is_ignored {
if self.index_for_entry(entry_id, worktree_id).is_none() {
anyhow::bail!("can't reveal an ignored entry in the project panel");
}
self.selection = Some(SelectedEntry {
worktree_id,
entry_id,
});
self.marked_entries.clear();
self.marked_entries.push(SelectedEntry {
worktree_id,
entry_id,
});
self.autoscroll(cx);
cx.notify();
return Ok(());
}
let is_active_item_file_diff_view = self
.workspace
@@ -6070,7 +6085,6 @@ impl ProjectPanel {
return Ok(());
}
let worktree_id = worktree.id();
self.expand_entry(worktree_id, entry_id, cx);
self.update_visible_entries(Some((worktree_id, entry_id)), false, true, window, cx);
self.marked_entries.clear();
@@ -4843,6 +4843,64 @@ async fn test_autoreveal_and_gitignored_files(cx: &mut gpui::TestAppContext) {
],
"When a gitignored entry is explicitly revealed, it should be shown in the project tree"
);
panel.update(cx, |panel, cx| {
panel.project.update(cx, |_, cx| {
cx.emit(project::Event::ActiveEntryChanged(Some(dir_2_file)))
})
});
cx.run_until_parked();
assert_eq!(
visible_entries_as_strings(&panel, 0..20, cx),
&[
"v project_root",
" > .git",
" v dir_1",
" v gitignored_dir",
" file_a.py",
" file_b.py",
" file_c.py",
" file_1.py",
" file_2.py",
" file_3.py",
" v dir_2",
" file_1.py <== selected <== marked",
" file_2.py",
" file_3.py",
" .gitignore",
],
"After switching to dir_2_file, it should be selected and marked"
);
panel.update(cx, |panel, cx| {
panel.project.update(cx, |_, cx| {
cx.emit(project::Event::ActiveEntryChanged(Some(
gitignored_dir_file,
)))
})
});
cx.run_until_parked();
assert_eq!(
visible_entries_as_strings(&panel, 0..20, cx),
&[
"v project_root",
" > .git",
" v dir_1",
" v gitignored_dir",
" file_a.py <== selected <== marked",
" file_b.py",
" file_c.py",
" file_1.py",
" file_2.py",
" file_3.py",
" v dir_2",
" file_1.py",
" file_2.py",
" file_3.py",
" .gitignore",
],
"When a gitignored entry is already visible, auto reveal should mark it as selected"
);
}
#[gpui::test]