diff --git a/crates/git_ui/src/git_panel.rs b/crates/git_ui/src/git_panel.rs index 4382af63db..cbe40e24b6 100644 --- a/crates/git_ui/src/git_panel.rs +++ b/crates/git_ui/src/git_panel.rs @@ -3,7 +3,7 @@ use crate::commit_modal::CommitModal; use crate::commit_tooltip::{CommitAvatar, CommitTooltip}; use crate::commit_view::CommitView; use crate::git_panel_settings::GitPanelScrollbarAccessor; -use crate::project_diff::{self, BranchDiff, Diff, ProjectDiff}; +use crate::project_diff::{BranchDiff, Diff, ProjectDiff}; use crate::remote_output::{self, RemoteAction, SuccessMessage}; use crate::solo_diff_view::SoloDiffView; use crate::{branch_picker, picker_prompt, render_remote_button}; @@ -163,53 +163,42 @@ enum TrashCancel { } struct GitMenuState { - has_tracked_changes: bool, - has_staged_changes: bool, - has_unstaged_changes: bool, - has_new_changes: bool, sort_by: GitPanelSortBy, group_by: GitPanelGroupBy, - has_stash_items: bool, tree_view: bool, } fn git_panel_context_menu( + has_tracked_changes: bool, + has_staged_changes: bool, + has_unstaged_changes: bool, + has_new_changes: bool, + has_stash_items: bool, focus_handle: FocusHandle, - state: GitMenuState, window: &mut Window, cx: &mut App, ) -> Entity { - ContextMenu::build(window, cx, move |context_menu, _, _| { + ContextMenu::build(window, cx, |context_menu, _, _| { context_menu - .context(focus_handle) - .action_disabled_when( - !state.has_unstaged_changes, - "Stage All", - StageAll.boxed_clone(), - ) - .action_disabled_when( - !state.has_staged_changes, - "Unstage All", - UnstageAll.boxed_clone(), - ) + .context(focus_handle.clone()) + .action_disabled_when(!has_unstaged_changes, "Stage All", StageAll.boxed_clone()) + .action_disabled_when(!has_staged_changes, "Unstage All", UnstageAll.boxed_clone()) .separator() .action_disabled_when( - !(state.has_new_changes || state.has_tracked_changes), + !(has_new_changes || has_tracked_changes), "Stash All", StashAll.boxed_clone(), ) - .action_disabled_when(!state.has_stash_items, "Stash Pop", StashPop.boxed_clone()) + .action_disabled_when(!has_stash_items, "Stash Pop", StashPop.boxed_clone()) .action("View Stash", zed_actions::git::ViewStash.boxed_clone()) .separator() - .action("Open Diff", project_diff::Diff.boxed_clone()) - .separator() .action_disabled_when( - !state.has_tracked_changes, + !has_tracked_changes, "Discard Tracked Changes", RestoreTrackedFiles.boxed_clone(), ) .action_disabled_when( - !state.has_new_changes, + !has_new_changes, "Trash Untracked Files", TrashUntrackedFiles.boxed_clone(), ) @@ -4410,46 +4399,8 @@ impl GitPanel { path + file_name + depth * 2 } - fn render_ellipsis_menu(&self, id: impl Into) -> impl IntoElement { - let focus_handle = self.focus_handle.clone(); - let has_tracked_changes = self.has_tracked_changes(); - let has_staged_changes = self.has_staged_changes(); - let has_unstaged_changes = self.has_unstaged_changes(); - let has_new_changes = self.new_count > 0; - let has_stash_items = self.stash_entries.entries.len() > 0; - - PopoverMenu::new(id.into()) - .trigger( - IconButton::new("overflow-menu-trigger", IconName::Ellipsis) - .icon_size(IconSize::Small), - ) - .menu(move |window, cx| { - Some(git_panel_context_menu( - focus_handle.clone(), - GitMenuState { - has_tracked_changes, - has_staged_changes, - has_unstaged_changes, - has_new_changes, - sort_by: GitPanelSettings::get_global(cx).sort_by, - group_by: GitPanelSettings::get_global(cx).group_by, - has_stash_items, - tree_view: GitPanelSettings::get_global(cx).tree_view, - }, - window, - cx, - )) - }) - .anchor(Anchor::TopRight) - } - fn render_view_options_menu(&self, id: impl Into) -> impl IntoElement { let focus_handle = self.focus_handle.clone(); - let has_tracked_changes = self.has_tracked_changes(); - let has_staged_changes = self.has_staged_changes(); - let has_unstaged_changes = self.has_unstaged_changes(); - let has_new_changes = self.new_count > 0; - let has_stash_items = self.stash_entries.entries.len() > 0; PopoverMenu::new(id.into()) .trigger( @@ -4461,13 +4412,8 @@ impl GitPanel { Some(git_panel_view_options_menu( focus_handle.clone(), GitMenuState { - has_tracked_changes, - has_staged_changes, - has_unstaged_changes, - has_new_changes, sort_by: GitPanelSettings::get_global(cx).sort_by, group_by: GitPanelSettings::get_global(cx).group_by, - has_stash_items, tree_view: GitPanelSettings::get_global(cx).tree_view, }, window, @@ -4727,6 +4673,78 @@ impl GitPanel { }) } + fn render_git_changes_actions_menu( + &self, + id: impl Into, + _cx: &mut Context, + ) -> impl IntoElement { + let has_tracked_changes = self.has_tracked_changes(); + let has_staged_changes = self.has_staged_changes(); + let has_unstaged_changes = self.has_unstaged_changes(); + let has_new_changes = self.new_count > 0; + let has_stash_items = self.stash_entries.entries.len() > 0; + let focus_handle = self.focus_handle.clone(); + + PopoverMenu::new(id.into()) + .trigger( + ui::ButtonLike::new_rounded_right("git-changes-actions-split-button-right") + .layer(ui::ElevationIndex::ModalSurface) + .size(ButtonSize::None) + .child( + div() + .px_1() + .child(Icon::new(IconName::ChevronDown).size(IconSize::XSmall)), + ), + ) + .menu(move |window, cx| { + Some(git_panel_context_menu( + has_tracked_changes, + has_staged_changes, + has_unstaged_changes, + has_new_changes, + has_stash_items, + focus_handle.clone(), + window, + cx, + )) + }) + .anchor(Anchor::TopRight) + } + + fn render_git_changes_actions_button(&self, cx: &mut Context) -> impl IntoElement { + let (text, action, stage, tooltip) = + if self.total_staged_count() == self.entry_count && self.entry_count > 0 { + ("Unstage All", UnstageAll.boxed_clone(), false, "git reset") + } else { + ("Stage All", StageAll.boxed_clone(), true, "git add --all") + }; + + SplitButton::new( + ButtonLike::new_rounded_left("git-changes-actions-split-button-left") + .layer(ElevationIndex::ModalSurface) + .size(ButtonSize::Compact) + .child(Label::new(text).size(LabelSize::Small).mr_0p5()) + .tooltip(Tooltip::for_action_title_in( + tooltip, + action.as_ref(), + &self.focus_handle, + )) + .disabled(self.entry_count == 0) + .on_click({ + let git_panel = cx.weak_entity(); + move |_, _, cx| { + git_panel + .update(cx, |git_panel, cx| { + git_panel.change_all_files_stage(stage, cx); + }) + .ok(); + } + }), + self.render_git_changes_actions_menu("git-changes-actions-split-button-menu", cx) + .into_any_element(), + ) + } + fn render_changes_header( &self, _window: &mut Window, @@ -4738,13 +4756,6 @@ impl GitPanel { self.active_repository.as_ref()?; - let (text, action, stage, tooltip) = - if self.total_staged_count() == self.entry_count && self.entry_count > 0 { - ("Unstage All", UnstageAll.boxed_clone(), false, "git reset") - } else { - ("Stage All", StageAll.boxed_clone(), true, "git add --all") - }; - let diff_stat_total = self.diff_stat_total; Some( @@ -4796,29 +4807,7 @@ impl GitPanel { h_flex() .gap_1() .child(self.render_view_options_menu("view_options_menu")) - .child(self.render_ellipsis_menu("overflow_menu")) - .child( - Button::new("stage_unstage_all", text) - .label_size(LabelSize::Small) - .layer(ElevationIndex::ModalSurface) - .style(ButtonStyle::Filled) - .tooltip(Tooltip::for_action_title_in( - tooltip, - action.as_ref(), - &self.focus_handle, - )) - .disabled(self.entry_count == 0) - .on_click({ - let git_panel = cx.weak_entity(); - move |_, _, cx| { - git_panel - .update(cx, |git_panel, cx| { - git_panel.change_all_files_stage(stage, cx); - }) - .ok(); - } - }), - ), + .child(self.render_git_changes_actions_button(cx)), ), ) } @@ -6232,18 +6221,19 @@ impl GitPanel { window: &mut Window, cx: &mut Context, ) { + let has_tracked_changes = self.has_tracked_changes(); + let has_staged_changes = self.has_staged_changes(); + let has_unstaged_changes = self.has_unstaged_changes(); + let has_new_changes = self.new_count > 0; + let has_stash_items = self.stash_entries.entries.len() > 0; + let context_menu = git_panel_context_menu( + has_tracked_changes, + has_staged_changes, + has_unstaged_changes, + has_new_changes, + has_stash_items, self.focus_handle.clone(), - GitMenuState { - has_tracked_changes: self.has_tracked_changes(), - has_staged_changes: self.has_staged_changes(), - has_unstaged_changes: self.has_unstaged_changes(), - has_new_changes: self.new_count > 0, - sort_by: GitPanelSettings::get_global(cx).sort_by, - group_by: GitPanelSettings::get_global(cx).group_by, - has_stash_items: self.stash_entries.entries.len() > 0, - tree_view: GitPanelSettings::get_global(cx).tree_view, - }, window, cx, );