git_picker: Make the unified version of it available through the title bar (#47151)

Danilo Leal created

The recently-introduced unified Git picker was previously only available
if you reached for the branch, worktree or stash pickers through the
keybinding. Now, if you click on the title bar's branch button, you'll
also be able to quickly view the worktree and stash pickers.

Release Notes:

- N/A

Change summary

crates/git_ui/src/branch_picker.rs   |  6 +++
crates/git_ui/src/git_picker.rs      | 40 +++++++++++++++++++++++++++--
crates/git_ui/src/stash_picker.rs    |  6 +++
crates/git_ui/src/worktree_picker.rs |  6 +++
crates/title_bar/src/title_bar.rs    |  5 ++-
5 files changed, 55 insertions(+), 8 deletions(-)

Detailed changes

crates/git_ui/src/branch_picker.rs 🔗

@@ -232,7 +232,11 @@ impl BranchList {
         .detach_and_log_err(cx);
 
         let delegate = BranchListDelegate::new(workspace, repository, style, cx);
-        let picker = cx.new(|cx| Picker::uniform_list(delegate, window, cx).modal(!embedded));
+        let picker = cx.new(|cx| {
+            Picker::uniform_list(delegate, window, cx)
+                .show_scrollbar(true)
+                .modal(!embedded)
+        });
         let picker_focus_handle = picker.focus_handle(cx);
 
         picker.update(cx, |picker, _| {

crates/git_ui/src/git_picker.rs 🔗

@@ -2,8 +2,8 @@ use std::fmt::Display;
 
 use gpui::{
     App, Context, DismissEvent, Entity, EventEmitter, FocusHandle, Focusable, InteractiveElement,
-    KeyContext, ModifiersChangedEvent, MouseButton, ParentElement, Render, Styled, Subscription,
-    WeakEntity, Window, actions, rems,
+    KeyContext, ModifiersChangedEvent, MouseButton, ParentElement, Rems, Render, Styled,
+    Subscription, WeakEntity, Window, actions, rems,
 };
 use project::git_store::Repository;
 use ui::{
@@ -50,6 +50,7 @@ pub struct GitPicker {
     worktree_list: Option<Entity<WorktreeList>>,
     stash_list: Option<Entity<StashList>>,
     _subscriptions: Vec<Subscription>,
+    popover_style: bool,
 }
 
 impl GitPicker {
@@ -60,6 +61,18 @@ impl GitPicker {
         width: Rems,
         window: &mut Window,
         cx: &mut Context<Self>,
+    ) -> Self {
+        Self::new_internal(workspace, repository, initial_tab, width, false, window, cx)
+    }
+
+    fn new_internal(
+        workspace: WeakEntity<Workspace>,
+        repository: Option<Entity<Repository>>,
+        initial_tab: GitPickerTab,
+        width: Rems,
+        popover_style: bool,
+        window: &mut Window,
+        cx: &mut Context<Self>,
     ) -> Self {
         let mut this = Self {
             tab: initial_tab,
@@ -70,6 +83,7 @@ impl GitPicker {
             worktree_list: None,
             stash_list: None,
             _subscriptions: Vec::new(),
+            popover_style,
         };
 
         this.ensure_active_picker(window, cx);
@@ -454,6 +468,11 @@ impl Render for GitPicker {
             .w(self.width)
             .elevation_3(cx)
             .overflow_hidden()
+            .when(self.popover_style, |el| {
+                el.on_mouse_down_out(cx.listener(|_, _, _, cx| {
+                    cx.emit(DismissEvent);
+                }))
+            })
             .key_context({
                 let mut key_context = KeyContext::new_with_defaults();
                 key_context.add("Pane");
@@ -582,7 +601,22 @@ fn open_with_tab(
     })
 }
 
-/// Register all git picker actions with the workspace.
+pub fn popover(
+    workspace: WeakEntity<Workspace>,
+    repository: Option<Entity<Repository>>,
+    initial_tab: GitPickerTab,
+    width: Rems,
+    window: &mut Window,
+    cx: &mut App,
+) -> Entity<GitPicker> {
+    cx.new(|cx| {
+        let picker =
+            GitPicker::new_internal(workspace, repository, initial_tab, width, true, window, cx);
+        picker.focus_handle(cx).focus(window, cx);
+        picker
+    })
+}
+
 pub fn register(workspace: &mut Workspace) {
     workspace.register_action(|workspace, _: &zed_actions::git::Branch, window, cx| {
         open_with_tab(workspace, GitPickerTab::Branches, window, cx);

crates/git_ui/src/stash_picker.rs 🔗

@@ -125,7 +125,11 @@ impl StashList {
         .detach_and_log_err(cx);
 
         let delegate = StashListDelegate::new(repository, workspace, window, cx);
-        let picker = cx.new(|cx| Picker::uniform_list(delegate, window, cx).modal(!embedded));
+        let picker = cx.new(|cx| {
+            Picker::uniform_list(delegate, window, cx)
+                .show_scrollbar(true)
+                .modal(!embedded)
+        });
         let picker_focus_handle = picker.focus_handle(cx);
         picker.update(cx, |picker, _| {
             picker.delegate.focus_handle = picker_focus_handle.clone();

crates/git_ui/src/worktree_picker.rs 🔗

@@ -112,7 +112,11 @@ impl WorktreeList {
         .detach_and_log_err(cx);
 
         let delegate = WorktreeListDelegate::new(workspace, repository, window, cx);
-        let picker = cx.new(|cx| Picker::uniform_list(delegate, window, cx).modal(!embedded));
+        let picker = cx.new(|cx| {
+            Picker::uniform_list(delegate, window, cx)
+                .show_scrollbar(true)
+                .modal(!embedded)
+        });
         let picker_focus_handle = picker.focus_handle(cx);
         picker.update(cx, |picker, _| {
             picker.delegate.focus_handle = picker_focus_handle.clone();

crates/title_bar/src/title_bar.rs 🔗

@@ -792,10 +792,11 @@ impl TitleBar {
         Some(
             PopoverMenu::new("branch-menu")
                 .menu(move |window, cx| {
-                    Some(git_ui::branch_picker::popover(
+                    Some(git_ui::git_picker::popover(
                         workspace.downgrade(),
-                        true,
                         effective_repository.clone(),
+                        git_ui::git_picker::GitPickerTab::Branches,
+                        gpui::rems(34.),
                         window,
                         cx,
                     ))