Follow-up tweaks to new git panel footer (#25832)

- Use a popover for the branch picker
- Don't deploy a repository selector if there's only one repo

Release Notes:

- N/A
This commit is contained in:
Cole Miller 2025-02-28 19:05:43 -05:00 committed by GitHub
parent 1c4c568068
commit eb648dd096
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 64 additions and 28 deletions

View file

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

View file

@ -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( fn handle_project_git_event(
&mut self, &mut self,
git_store: &Entity<GitStore>, git_store: &Entity<GitStore>,