git_ui: Fix select previous selects a non-visible item (#49289)

Remco Smits created

This PR fixes that when you are below a header and want to select a
previous item, we would select a non-visible item because we did a -1 of
the newly selected index, which could end up inside a collapsed
directory.

**Note**: This is only an issue for the git tree view mode.

**Before** (See selection is not visible anymore after select previous,
because it's inside the collapsed directory)


https://github.com/user-attachments/assets/bd032768-b947-45f8-b5a1-6185010202cf

**After** (See selection now selects the first visible item in the list
which is the collapsed directory)


https://github.com/user-attachments/assets/47f67237-be7c-4ef5-8b99-6a3a2b016086

Before you mark this PR as ready for review, make sure that you have:
- [x] Added a solid test coverage and/or screenshots from doing manual
testing
- [x] Done a self-review taking into account security and performance
aspects
- [x] Aligned any UI changes with the [UI
checklist](https://github.com/zed-industries/zed/blob/main/CONTRIBUTING.md#uiux-checklist)

Release Notes:

- Git UI: Fix selecting previous item would select a non-visible item if
it's inside a collapsed directory

Change summary

crates/git_ui/src/git_panel.rs | 17 ++++++++++++++++-
1 file changed, 16 insertions(+), 1 deletion(-)

Detailed changes

crates/git_ui/src/git_panel.rs 🔗

@@ -1133,7 +1133,22 @@ impl GitPanel {
         }
 
         if matches!(self.entries.get(new_index), Some(GitListEntry::Header(..))) {
-            self.selected_entry = Some(new_index.saturating_sub(1));
+            self.selected_entry = match &self.view_mode {
+                GitPanelViewMode::Flat => Some(new_index.saturating_sub(1)),
+                GitPanelViewMode::Tree(tree_view_state) => {
+                    maybe!({
+                        let current_logical_index = tree_view_state
+                            .logical_indices
+                            .iter()
+                            .position(|&i| i == new_index)?;
+
+                        tree_view_state
+                            .logical_indices
+                            .get(current_logical_index.saturating_sub(1))
+                            .copied()
+                    })
+                }
+            };
         } else {
             self.selected_entry = Some(new_index);
         }