From 3e34dcf2a7bd313ccaf4c243bab22b5fe561ac23 Mon Sep 17 00:00:00 2001 From: "Joseph T. Lyons" Date: Mon, 20 Jul 2026 13:27:25 -0400 Subject: [PATCH] Keep git panel history entry highlighted while context menu is open (#61354) Also, unifies the naming of the variable naming for the target entry in both the git graph and git panel history tab. Release Notes: - Improved the git panel's history tab to keep an entry highlighted while its context menu is open --- crates/git_ui/src/git_graph.rs | 21 ++++++++++------- crates/git_ui/src/git_panel.rs | 43 +++++++++++++++++++++++++++------- 2 files changed, 47 insertions(+), 17 deletions(-) diff --git a/crates/git_ui/src/git_graph.rs b/crates/git_ui/src/git_graph.rs index 6e1ddd12de..d9fc6bf52c 100644 --- a/crates/git_ui/src/git_graph.rs +++ b/crates/git_ui/src/git_graph.rs @@ -1294,7 +1294,7 @@ fn compute_diff_stats(diff: &CommitDiff) -> (usize, usize) { struct GitGraphContextMenu { menu: Entity, position: Point, - entry_idx: Option, + target_entry_index: Option, _subscription: Subscription, } @@ -2446,7 +2446,7 @@ impl GitGraph { &mut self, context_menu: Entity, position: Point, - entry_idx: Option, + target_entry_index: Option, window: &mut Window, cx: &mut Context, ) { @@ -2471,7 +2471,7 @@ impl GitGraph { self.context_menu = Some(GitGraphContextMenu { menu: context_menu, position, - entry_idx, + target_entry_index, _subscription: subscription, }); cx.notify(); @@ -3205,7 +3205,10 @@ impl GitGraph { let hovered_entry_idx = self.hovered_entry_idx; let selected_entry_idx = self.selected_entry_idx; - let context_menu_entry_idx = self.context_menu.as_ref().and_then(|menu| menu.entry_idx); + let context_menu_target_index = self + .context_menu + .as_ref() + .and_then(|menu| menu.target_entry_index); let is_focused = self.focus_handle.is_focused(window); let graph_canvas_bounds = self.graph_canvas_bounds.clone(); @@ -3229,7 +3232,7 @@ impl GitGraph { let is_hovered = hovered_entry_idx == Some(absolute_row_idx); let is_selected = selected_entry_idx == Some(absolute_row_idx); let is_context_menu_target = - context_menu_entry_idx == Some(absolute_row_idx); + context_menu_target_index == Some(absolute_row_idx); if is_hovered || is_selected || is_context_menu_target { let row_y = bounds.origin.y + visible_row_idx as f32 * row_height @@ -3840,8 +3843,10 @@ impl Render for GitGraph { let row_height = Self::row_height(window, cx); let selected_entry_idx = self.selected_entry_idx; let hovered_entry_idx = self.hovered_entry_idx; - let context_menu_entry_idx = - self.context_menu.as_ref().and_then(|menu| menu.entry_idx); + let context_menu_target_index = self + .context_menu + .as_ref() + .and_then(|menu| menu.target_entry_index); let weak_self = cx.weak_entity(); let focus_handle = self.focus_handle.clone(); let table_focus_handle = @@ -3881,7 +3886,7 @@ impl Render for GitGraph { let is_selected = selected_entry_idx == Some(index); let is_hovered = hovered_entry_idx == Some(index); let is_context_menu_target = - context_menu_entry_idx == Some(index); + context_menu_target_index == Some(index); let table_focus_handle = table_focus_handle.clone(); let is_focused = focus_handle.is_focused(window) || table_focus_handle.is_focused(window); diff --git a/crates/git_ui/src/git_panel.rs b/crates/git_ui/src/git_panel.rs index a5b311fd52..55b1f9ffb2 100644 --- a/crates/git_ui/src/git_panel.rs +++ b/crates/git_ui/src/git_panel.rs @@ -895,6 +895,13 @@ impl TruncatedPatch { } } +struct GitPanelContextMenu { + menu: Entity, + position: Point, + target_entry_index: Option, + _subscription: Subscription, +} + pub struct GitPanel { pub(crate) active_repository: Option>, pub(crate) commit_editor: Entity, @@ -934,7 +941,7 @@ pub struct GitPanel { update_visible_entries_task: Task<()>, reopen_commit_buffer_task: Task<()>, pub(crate) workspace: WeakEntity, - context_menu: Option<(Entity, Point, Subscription)>, + context_menu: Option, modal_open: bool, show_placeholders: bool, // Only read to compute collaborative co-authors, which requires the `call` feature. @@ -6232,7 +6239,7 @@ impl GitPanel { ); self.focused_history_entry = Some(index); self.history_keyboard_nav = false; - self.set_context_menu(context_menu, position, window, cx); + self.set_context_menu(context_menu, position, Some(index), window, cx); } fn activate_changes_tab( @@ -6396,6 +6403,10 @@ impl GitPanel { let is_panel_focused = self.focus_handle.is_focused(window); let show_focus_border = self.history_keyboard_nav; let has_context_menu = self.context_menu.is_some(); + let context_menu_target_index = self + .context_menu + .as_ref() + .and_then(|context_menu| context_menu.target_entry_index); let ahead_count = active_repository .read(cx) @@ -6488,6 +6499,8 @@ impl GitPanel { let is_unpushed = index < ahead_count; let is_focused = focused_history_entry == Some(index); + let is_context_menu_target = + context_menu_target_index == Some(index); let workspace = workspace.clone(); let repo = repo_weak.clone(); let sha_for_click = sha_string; @@ -6517,6 +6530,9 @@ impl GitPanel { }, ) .hover(|s| s.bg(cx.theme().colors().element_hover)) + .when(is_context_menu_target, |this| { + this.bg(cx.theme().colors().element_hover) + }) .child( h_flex() .gap_1() @@ -7174,7 +7190,7 @@ impl GitPanel { }) }); self.selected_entry = Some(ix); - self.set_context_menu(context_menu, position, window, cx); + self.set_context_menu(context_menu, position, None, window, cx); } fn deploy_panel_context_menu( @@ -7199,13 +7215,14 @@ impl GitPanel { window, cx, ); - self.set_context_menu(context_menu, position, window, cx); + self.set_context_menu(context_menu, position, None, window, cx); } fn set_context_menu( &mut self, context_menu: Entity, position: Point, + target_entry_index: Option, window: &mut Window, cx: &mut Context, ) { @@ -7216,7 +7233,10 @@ impl GitPanel { window, |this, _, _: &DismissEvent, window, cx| { if this.context_menu.as_ref().is_some_and(|context_menu| { - context_menu.0.focus_handle(cx).contains_focused(window, cx) + context_menu + .menu + .focus_handle(cx) + .contains_focused(window, cx) }) { cx.focus_self(window); } @@ -7224,7 +7244,12 @@ impl GitPanel { cx.notify(); }, ); - self.context_menu = Some((context_menu, position, subscription)); + self.context_menu = Some(GitPanelContextMenu { + menu: context_menu, + position, + target_entry_index, + _subscription: subscription, + }); cx.notify(); } @@ -8024,12 +8049,12 @@ impl Render for GitPanel { }) .into_any_element(), ) - .children(self.context_menu.as_ref().map(|(menu, position, _)| { + .children(self.context_menu.as_ref().map(|context_menu| { deferred( anchored() - .position(*position) + .position(context_menu.position) .anchor(Anchor::TopLeft) - .child(menu.clone()), + .child(context_menu.menu.clone()), ) .with_priority(1) }))