sidebar: Fix space not working in the search editor (#52444)

Danilo Leal created

We were using space as an alternative to `enter` for selecting thread
items even while the search editor was focused. The solution here was to
create a dynamic key context based on the search editor focus state.

Release Notes:

- N/A

Change summary

assets/keymaps/default-linux.json   |  8 +++++++-
assets/keymaps/default-macos.json   |  8 +++++++-
assets/keymaps/default-windows.json |  8 +++++++-
crates/sidebar/src/sidebar.rs       | 21 ++++++++++++++++++---
4 files changed, 39 insertions(+), 6 deletions(-)

Detailed changes

assets/keymaps/default-linux.json 🔗

@@ -698,12 +698,18 @@
       "left": "menu::SelectParent",
       "right": "menu::SelectChild",
       "enter": "menu::Confirm",
-      "space": "menu::Confirm",
       "ctrl-f": "agents_sidebar::FocusSidebarFilter",
       "ctrl-g": "agents_sidebar::ToggleArchive",
       "shift-backspace": "agent::RemoveSelectedThread",
     },
   },
+  {
+    "context": "ThreadsSidebar && not_searching",
+    "use_key_equivalents": true,
+    "bindings": {
+      "space": "menu::Confirm",
+    },
+  },
   {
     "context": "Workspace && debugger_running",
     "bindings": {

assets/keymaps/default-macos.json 🔗

@@ -764,12 +764,18 @@
       "left": "menu::SelectParent",
       "right": "menu::SelectChild",
       "enter": "menu::Confirm",
-      "space": "menu::Confirm",
       "cmd-f": "agents_sidebar::FocusSidebarFilter",
       "cmd-g": "agents_sidebar::ToggleArchive",
       "shift-backspace": "agent::RemoveSelectedThread",
     },
   },
+  {
+    "context": "ThreadsSidebar && not_searching",
+    "use_key_equivalents": true,
+    "bindings": {
+      "space": "menu::Confirm",
+    },
+  },
   {
     "context": "Workspace && debugger_running",
     "use_key_equivalents": true,

assets/keymaps/default-windows.json 🔗

@@ -700,12 +700,18 @@
       "left": "menu::SelectParent",
       "right": "menu::SelectChild",
       "enter": "menu::Confirm",
-      "space": "menu::Confirm",
       "ctrl-f": "agents_sidebar::FocusSidebarFilter",
       "ctrl-g": "agents_sidebar::ToggleArchive",
       "shift-backspace": "agent::RemoveSelectedThread",
     },
   },
+  {
+    "context": "ThreadsSidebar && not_searching",
+    "use_key_equivalents": true,
+    "bindings": {
+      "space": "menu::Confirm",
+    },
+  },
   {
     "context": "ApplicationMenu",
     "use_key_equivalents": true,

crates/sidebar/src/sidebar.rs 🔗

@@ -12,8 +12,8 @@ use chrono::Utc;
 use editor::Editor;
 use feature_flags::{AgentV2FeatureFlag, FeatureFlagViewExt as _};
 use gpui::{
-    Action as _, AnyElement, App, Context, Entity, FocusHandle, Focusable, ListState, Pixels,
-    Render, SharedString, WeakEntity, Window, WindowHandle, list, prelude::*, px,
+    Action as _, AnyElement, App, Context, Entity, FocusHandle, Focusable, KeyContext, ListState,
+    Pixels, Render, SharedString, WeakEntity, Window, WindowHandle, list, prelude::*, px,
 };
 use menu::{
     Cancel, Confirm, SelectChild, SelectFirst, SelectLast, SelectNext, SelectParent, SelectPrevious,
@@ -1732,6 +1732,21 @@ impl Sidebar {
         self.update_entries(cx);
     }
 
+    fn dispatch_context(&self, window: &Window, cx: &Context<Self>) -> KeyContext {
+        let mut dispatch_context = KeyContext::new_with_defaults();
+        dispatch_context.add("ThreadsSidebar");
+        dispatch_context.add("menu");
+
+        let identifier = if self.filter_editor.focus_handle(cx).is_focused(window) {
+            "searching"
+        } else {
+            "not_searching"
+        };
+
+        dispatch_context.add(identifier);
+        dispatch_context
+    }
+
     fn focus_in(&mut self, window: &mut Window, cx: &mut Context<Self>) {
         if !self.focus_handle.is_focused(window) {
             return;
@@ -3067,7 +3082,7 @@ impl Render for Sidebar {
 
         v_flex()
             .id("workspace-sidebar")
-            .key_context("ThreadsSidebar")
+            .key_context(self.dispatch_context(window, cx))
             .track_focus(&self.focus_handle)
             .on_action(cx.listener(Self::select_next))
             .on_action(cx.listener(Self::select_previous))