git_ui: Fix select first entry selects the wrong visual first entry when tree view is enabled (#45108)

This PR fixes a bug where the select first didn't select the first
visual entry when the first entry is a collapsed directory.

Follow-up: https://github.com/zed-industries/zed/pull/45030

**Before**:


https://github.com/user-attachments/assets/5e5865cc-ec0f-471d-a81b-9521fb70df41

**After**:


https://github.com/user-attachments/assets/05562572-e43f-4d1e-9638-80e4dccc0998

Release Notes:

- git_ui: Fix select first entry selects the wrong visual first entry
when tree view is enabled
This commit is contained in:
Remco Smits
2025-12-17 16:31:36 +01:00
committed by GitHub
parent a16f0712c8
commit 5b8e4e58c5

View File

@@ -279,6 +279,13 @@ impl GitListEntry {
_ => None,
}
}
fn directory_entry(&self) -> Option<&GitTreeDirEntry> {
match self {
GitListEntry::Directory(entry) => Some(entry),
_ => None,
}
}
}
enum GitPanelViewMode {
@@ -895,12 +902,6 @@ impl GitPanel {
cx.notify();
}
fn first_status_entry_index(&self) -> Option<usize> {
self.entries
.iter()
.position(|entry| entry.status_entry().is_some())
}
fn expand_selected_entry(
&mut self,
_: &ExpandSelectedEntry,
@@ -944,7 +945,21 @@ impl GitPanel {
}
fn select_first(&mut self, _: &SelectFirst, _window: &mut Window, cx: &mut Context<Self>) {
if let Some(first_entry) = self.first_status_entry_index() {
let first_entry = match &self.view_mode {
GitPanelViewMode::Flat => self
.entries
.iter()
.position(|entry| entry.status_entry().is_some()),
GitPanelViewMode::Tree(state) => {
let index = self.entries.iter().position(|entry| {
entry.status_entry().is_some() || entry.directory_entry().is_some()
});
index.map(|index| state.logical_indices[index])
}
};
if let Some(first_entry) = first_entry {
self.selected_entry = Some(first_entry);
self.scroll_to_selected_entry(cx);
}
@@ -1053,15 +1068,13 @@ impl GitPanel {
cx.notify();
}
fn select_first_entry_if_none(&mut self, cx: &mut Context<Self>) {
fn select_first_entry_if_none(&mut self, window: &mut Window, cx: &mut Context<Self>) {
let have_entries = self
.active_repository
.as_ref()
.is_some_and(|active_repository| active_repository.read(cx).status_summary().count > 0);
if have_entries && self.selected_entry.is_none() {
self.selected_entry = self.first_status_entry_index();
self.scroll_to_selected_entry(cx);
cx.notify();
self.select_first(&SelectFirst, window, cx);
}
}
@@ -1071,10 +1084,9 @@ impl GitPanel {
window: &mut Window,
cx: &mut Context<Self>,
) {
self.select_first_entry_if_none(cx);
self.focus_handle.focus(window);
cx.notify();
self.select_first_entry_if_none(window, cx);
}
fn get_selected_entry(&self) -> Option<&GitListEntry> {
@@ -3549,7 +3561,7 @@ impl GitPanel {
self.bulk_staging = bulk_staging;
}
self.select_first_entry_if_none(cx);
self.select_first_entry_if_none(window, cx);
let suggested_commit_message = self.suggest_commit_message(cx);
let placeholder_text = suggested_commit_message.unwrap_or("Enter commit message".into());