Cargo.lock 🔗
@@ -7221,6 +7221,7 @@ dependencies = [
"git",
"git_ui",
"gpui",
+ "menu",
"project",
"rand 0.9.2",
"recent_projects",
Remco Smits created
This PR adds basic support for keyboard navigation for the git graph
panel.
**Back and forward**:
https://github.com/user-attachments/assets/5015b0d9-bf83-4944-8c9b-1c5b9badfdb4
**Scrolling**:
https://github.com/user-attachments/assets/451badb5-59df-48a2-aa73-be5188d28dae
- [x] Tests or screenshots needed?
- [x] Code Reviewed
- [x] Manual QA
- Do we need to add keybinds for it, or is falling back to the default
keybindings enough?
**TODO**:
- [x] Add auto scroll when you select the last visible item
Release Notes:
- N/A (no release notes since its behind a feature flag)
Cargo.lock | 1 +
crates/git_graph/Cargo.toml | 1 +
crates/git_graph/src/git_graph.rs | 29 +++++++++++++++++++++++++++--
3 files changed, 29 insertions(+), 2 deletions(-)
@@ -7221,6 +7221,7 @@ dependencies = [
"git",
"git_ui",
"gpui",
+ "menu",
"project",
"rand 0.9.2",
"recent_projects",
@@ -26,6 +26,7 @@ feature_flags.workspace = true
git.workspace = true
git_ui.workspace = true
gpui.workspace = true
+menu.workspace = true
project.workspace = true
settings.workspace = true
smallvec.workspace = true
@@ -9,9 +9,10 @@ use git_ui::commit_tooltip::CommitAvatar;
use gpui::{
AnyElement, App, Bounds, ClipboardItem, Context, Corner, DefiniteLength, ElementId, Entity,
EventEmitter, FocusHandle, Focusable, FontWeight, Hsla, InteractiveElement, ParentElement,
- PathBuilder, Pixels, Point, Render, ScrollWheelEvent, SharedString, Styled, Subscription, Task,
- WeakEntity, Window, actions, anchored, deferred, point, px,
+ PathBuilder, Pixels, Point, Render, ScrollStrategy, ScrollWheelEvent, SharedString, Styled,
+ Subscription, Task, WeakEntity, Window, actions, anchored, deferred, point, px,
};
+use menu::{SelectNext, SelectPrevious};
use project::{
Project,
git_store::{CommitDataState, GitStoreEvent, Repository, RepositoryEvent},
@@ -844,6 +845,22 @@ impl GitGraph {
.collect()
}
+ fn select_prev(&mut self, _: &SelectPrevious, _window: &mut Window, cx: &mut Context<Self>) {
+ if let Some(selected_entry_idx) = &self.selected_entry_idx {
+ self.select_entry(selected_entry_idx.saturating_sub(1), cx);
+ } else {
+ self.select_entry(0, cx);
+ }
+ }
+
+ fn select_next(&mut self, _: &SelectNext, window: &mut Window, cx: &mut Context<Self>) {
+ if let Some(selected_entry_idx) = &self.selected_entry_idx {
+ self.select_entry(selected_entry_idx.saturating_add(1), cx);
+ } else {
+ self.select_prev(&SelectPrevious, window, cx);
+ }
+ }
+
fn select_entry(&mut self, idx: usize, cx: &mut Context<Self>) {
if self.selected_entry_idx == Some(idx) {
return;
@@ -851,6 +868,12 @@ impl GitGraph {
self.selected_entry_idx = Some(idx);
self.selected_commit_diff = None;
+ self.table_interaction_state.update(cx, |state, cx| {
+ state
+ .scroll_handle
+ .scroll_to_item(idx, ScrollStrategy::Nearest);
+ cx.notify();
+ });
let Some(commit) = self.graph_data.commits.get(idx) else {
return;
@@ -1604,6 +1627,8 @@ impl Render for GitGraph {
.bg(cx.theme().colors().editor_background)
.key_context("GitGraph")
.track_focus(&self.focus_handle)
+ .on_action(cx.listener(Self::select_prev))
+ .on_action(cx.listener(Self::select_next))
.child(content)
.children(self.context_menu.as_ref().map(|(menu, position, _)| {
deferred(