diff --git a/crates/git_ui/src/git_panel.rs b/crates/git_ui/src/git_panel.rs index cecd4411e3482bb65564336ae782a1cc09c649d0..83f4edf3e9cc2b379d2e6833b9acdd855425ed44 100644 --- a/crates/git_ui/src/git_panel.rs +++ b/crates/git_ui/src/git_panel.rs @@ -1,3 +1,4 @@ +use crate::branch_picker::{self, BranchList}; use crate::git_panel_settings::StatusStyle; use crate::repository_selector::RepositorySelectorPopoverMenu; use crate::{ @@ -39,7 +40,7 @@ use strum::{IntoEnumIterator, VariantNames}; use time::OffsetDateTime; use ui::{ prelude::*, ButtonLike, Checkbox, ContextMenu, ElevationIndex, ListItem, ListItemSpacing, - PopoverMenu, Scrollbar, ScrollbarState, Tooltip, + PopoverButton, PopoverMenu, Scrollbar, ScrollbarState, Tooltip, }; use util::{maybe, post_inc, ResultExt, TryFutureExt}; use workspace::{ @@ -1887,7 +1888,7 @@ impl GitPanel { }; let editor_focus_handle = self.commit_editor.focus_handle(cx); - let branch = active_repo.read(cx).current_branch()?; + let branch = active_repo.read(cx).current_branch()?.clone(); let footer_size = px(32.); let gap = px(8.0); @@ -1903,12 +1904,14 @@ impl GitPanel { .display_name(project, cx) .trim_end_matches("/"), )); + let branches = branch_picker::popover(self.project.clone(), window, cx); let footer = v_flex() - .child(PanelRepoHeader::new( - "header-button", + .child(PanelRepoFooter::new( + "footer-button", display_name, - Some(branch.clone()), + Some(branch), Some(git_panel), + Some(branches), )) .child( panel_editor_container(window, cx) @@ -2851,7 +2854,7 @@ fn render_git_action_menu(id: impl Into) -> impl IntoElement { #[derive(IntoElement, IntoComponent)] #[component(scope = "git_panel")] -pub struct PanelRepoHeader { +pub struct PanelRepoFooter { id: SharedString, active_repository: SharedString, branch: Option, @@ -2859,20 +2862,23 @@ pub struct PanelRepoHeader { // // For now just take an option here, and we won't bind handlers to buttons in previews. git_panel: Option>, + branches: Option>, } -impl PanelRepoHeader { +impl PanelRepoFooter { pub fn new( id: impl Into, active_repository: SharedString, branch: Option, git_panel: Option>, + branches: Option>, ) -> Self { Self { id: id.into(), active_repository, branch, git_panel, + branches, } } @@ -2886,6 +2892,7 @@ impl PanelRepoHeader { active_repository, branch, git_panel: None, + branches: None, } } @@ -3067,22 +3074,32 @@ impl PanelRepoHeader { } } -impl RenderOnce for PanelRepoHeader { - fn render(self, _: &mut Window, cx: &mut App) -> impl IntoElement { +impl RenderOnce for PanelRepoFooter { + fn render(self, window: &mut Window, cx: &mut App) -> impl IntoElement { let active_repo = self.active_repository.clone(); let overflow_menu_id: SharedString = format!("overflow-menu-{}", active_repo).into(); let repo_selector = if let Some(panel) = self.git_panel.clone() { - RepositorySelectorPopoverMenu::new( - panel.read(cx).repository_selector.clone(), - Button::new("repo-selector", active_repo.clone()) - .style(ButtonStyle::Transparent) - .size(ButtonSize::None) - .label_size(LabelSize::Small) - .color(Color::Muted), - Tooltip::text("Choose a repository"), - ) - .into_any_element() + let repo_selector = panel.read(cx).repository_selector.clone(); + let repo_count = repo_selector.read(cx).repositories_len(cx); + if repo_count > 1 { + RepositorySelectorPopoverMenu::new( + panel.read(cx).repository_selector.clone(), + Button::new("repo-selector", active_repo) + .style(ButtonStyle::Transparent) + .size(ButtonSize::None) + .label_size(LabelSize::Small) + .color(Color::Muted), + Tooltip::text("Choose a repository"), + ) + .into_any_element() + } else { + Label::new(active_repo) + .size(LabelSize::Small) + .color(Color::Muted) + .line_height_style(LineHeightStyle::UiLabel) + .into_any_element() + } } else { Button::new("repo-selector", active_repo.clone()) .style(ButtonStyle::Transparent) @@ -3097,7 +3114,9 @@ impl RenderOnce for PanelRepoHeader { .as_ref() .map_or("".into(), |branch| branch.name.clone()); - let branch_selector = Button::new("branch-selector", branch_name) + let branches = self.branches.clone(); + + let branch_selector_button = Button::new("branch-selector", branch_name) .style(ButtonStyle::Transparent) .size(ButtonSize::None) .label_size(LabelSize::Small) @@ -3109,6 +3128,19 @@ impl RenderOnce for PanelRepoHeader { window.dispatch_action(zed_actions::git::Branch.boxed_clone(), cx); }); + let branch_selector = if let Some(branches) = branches { + PopoverButton::new( + branches, + Corner::BottomLeft, + branch_selector_button, + Tooltip::for_action_title("Switch Branch", &zed_actions::git::Branch), + ) + .render(window, cx) + .into_any_element() + } else { + branch_selector_button.into_any_element() + }; + let spinner = self .git_panel .as_ref() @@ -3162,7 +3194,7 @@ impl RenderOnce for PanelRepoHeader { } } -impl ComponentPreview for PanelRepoHeader { +impl ComponentPreview for PanelRepoFooter { fn preview(_window: &mut Window, _cx: &mut App) -> AnyElement { let unknown_upstream = None; let no_remote_upstream = Some(UpstreamTracking::Gone); @@ -3225,7 +3257,7 @@ impl ComponentPreview for PanelRepoHeader { "No Branch", div() .w(px(180.)) - .child(PanelRepoHeader::new_preview( + .child(PanelRepoFooter::new_preview( "no-branch", active_repository(1).clone(), None, @@ -3236,7 +3268,7 @@ impl ComponentPreview for PanelRepoHeader { "Remote status unknown", div() .w(px(180.)) - .child(PanelRepoHeader::new_preview( + .child(PanelRepoFooter::new_preview( "unknown-upstream", active_repository(2).clone(), Some(branch(unknown_upstream)), @@ -3247,7 +3279,7 @@ impl ComponentPreview for PanelRepoHeader { "No Remote Upstream", div() .w(px(180.)) - .child(PanelRepoHeader::new_preview( + .child(PanelRepoFooter::new_preview( "no-remote-upstream", active_repository(3).clone(), Some(branch(no_remote_upstream)), @@ -3258,7 +3290,7 @@ impl ComponentPreview for PanelRepoHeader { "Not Ahead or Behind", div() .w(px(180.)) - .child(PanelRepoHeader::new_preview( + .child(PanelRepoFooter::new_preview( "not-ahead-or-behind", active_repository(4).clone(), Some(branch(not_ahead_or_behind_upstream)), @@ -3269,7 +3301,7 @@ impl ComponentPreview for PanelRepoHeader { "Behind remote", div() .w(px(180.)) - .child(PanelRepoHeader::new_preview( + .child(PanelRepoFooter::new_preview( "behind-remote", active_repository(5).clone(), Some(branch(behind_upstream)), @@ -3280,7 +3312,7 @@ impl ComponentPreview for PanelRepoHeader { "Ahead of remote", div() .w(px(180.)) - .child(PanelRepoHeader::new_preview( + .child(PanelRepoFooter::new_preview( "ahead-of-remote", active_repository(6).clone(), Some(branch(ahead_of_upstream)), @@ -3291,7 +3323,7 @@ impl ComponentPreview for PanelRepoHeader { "Ahead and behind remote", div() .w(px(180.)) - .child(PanelRepoHeader::new_preview( + .child(PanelRepoFooter::new_preview( "ahead-and-behind", active_repository(7).clone(), Some(branch(ahead_and_behind_upstream)), diff --git a/crates/git_ui/src/repository_selector.rs b/crates/git_ui/src/repository_selector.rs index 36af1189b5fdddbf1f564a67aefefc47124a6ee9..a67860f3ba48e663a3d849cb535a46a87d7b8c20 100644 --- a/crates/git_ui/src/repository_selector.rs +++ b/crates/git_ui/src/repository_selector.rs @@ -47,6 +47,10 @@ impl RepositorySelector { } } + pub(crate) fn repositories_len(&self, cx: &App) -> usize { + self.picker.read(cx).delegate.repository_entries.len() + } + fn handle_project_git_event( &mut self, git_store: &Entity,