Git commit modal branch list (#26417)
Closes #26273 Release Notes: - git: Fixes opening the branch selector in the commit modal with cmd-option-b - git: Truncates the branch selector in the commit modal
This commit is contained in:
parent
bf11b888c3
commit
c2e4fdf63d
4 changed files with 39 additions and 53 deletions
|
@ -12,9 +12,7 @@ use project::git::Repository;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use time::OffsetDateTime;
|
use time::OffsetDateTime;
|
||||||
use time_format::format_local_timestamp;
|
use time_format::format_local_timestamp;
|
||||||
use ui::{
|
use ui::{prelude::*, HighlightedLabel, KeyBinding, ListItem, ListItemSpacing, Tooltip};
|
||||||
prelude::*, HighlightedLabel, KeyBinding, ListItem, ListItemSpacing, PopoverMenuHandle, Tooltip,
|
|
||||||
};
|
|
||||||
use util::ResultExt;
|
use util::ResultExt;
|
||||||
use workspace::notifications::DetachAndPromptErr;
|
use workspace::notifications::DetachAndPromptErr;
|
||||||
use workspace::{ModalView, Workspace};
|
use workspace::{ModalView, Workspace};
|
||||||
|
@ -79,7 +77,6 @@ enum BranchListStyle {
|
||||||
|
|
||||||
pub struct BranchList {
|
pub struct BranchList {
|
||||||
width: Rems,
|
width: Rems,
|
||||||
pub popover_handle: PopoverMenuHandle<Self>,
|
|
||||||
pub picker: Entity<Picker<BranchListDelegate>>,
|
pub picker: Entity<Picker<BranchListDelegate>>,
|
||||||
_subscription: Subscription,
|
_subscription: Subscription,
|
||||||
}
|
}
|
||||||
|
@ -92,7 +89,6 @@ impl BranchList {
|
||||||
window: &mut Window,
|
window: &mut Window,
|
||||||
cx: &mut Context<Self>,
|
cx: &mut Context<Self>,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
let popover_handle = PopoverMenuHandle::default();
|
|
||||||
let all_branches_request = repository
|
let all_branches_request = repository
|
||||||
.clone()
|
.clone()
|
||||||
.map(|repository| repository.read(cx).branches());
|
.map(|repository| repository.read(cx).branches());
|
||||||
|
@ -130,7 +126,6 @@ impl BranchList {
|
||||||
Self {
|
Self {
|
||||||
picker,
|
picker,
|
||||||
width,
|
width,
|
||||||
popover_handle,
|
|
||||||
_subscription,
|
_subscription,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,7 +4,7 @@ use crate::branch_picker::{self, BranchList};
|
||||||
use crate::git_panel::{commit_message_editor, GitPanel};
|
use crate::git_panel::{commit_message_editor, GitPanel};
|
||||||
use git::{Commit, GenerateCommitMessage};
|
use git::{Commit, GenerateCommitMessage};
|
||||||
use panel::{panel_button, panel_editor_style, panel_filled_button};
|
use panel::{panel_button, panel_editor_style, panel_filled_button};
|
||||||
use ui::{prelude::*, KeybindingHint, PopoverMenu, Tooltip};
|
use ui::{prelude::*, KeybindingHint, PopoverMenu, PopoverMenuHandle, Tooltip};
|
||||||
|
|
||||||
use editor::{Editor, EditorElement};
|
use editor::{Editor, EditorElement};
|
||||||
use gpui::*;
|
use gpui::*;
|
||||||
|
@ -65,11 +65,11 @@ pub fn init(cx: &mut App) {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct CommitModal {
|
pub struct CommitModal {
|
||||||
branch_list: Entity<BranchList>,
|
|
||||||
git_panel: Entity<GitPanel>,
|
git_panel: Entity<GitPanel>,
|
||||||
commit_editor: Entity<Editor>,
|
commit_editor: Entity<Editor>,
|
||||||
restore_dock: RestoreDock,
|
restore_dock: RestoreDock,
|
||||||
properties: ModalContainerProperties,
|
properties: ModalContainerProperties,
|
||||||
|
branch_list_handle: PopoverMenuHandle<BranchList>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Focusable for CommitModal {
|
impl Focusable for CommitModal {
|
||||||
|
@ -146,7 +146,6 @@ impl CommitModal {
|
||||||
cx: &mut Context<Self>,
|
cx: &mut Context<Self>,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
let panel = git_panel.read(cx);
|
let panel = git_panel.read(cx);
|
||||||
let active_repository = panel.active_repository.clone();
|
|
||||||
let suggested_commit_message = panel.suggest_commit_message();
|
let suggested_commit_message = panel.suggest_commit_message();
|
||||||
|
|
||||||
let commit_editor = git_panel.update(cx, |git_panel, cx| {
|
let commit_editor = git_panel.update(cx, |git_panel, cx| {
|
||||||
|
@ -177,11 +176,7 @@ impl CommitModal {
|
||||||
let focus_handle = commit_editor.focus_handle(cx);
|
let focus_handle = commit_editor.focus_handle(cx);
|
||||||
|
|
||||||
cx.on_focus_out(&focus_handle, window, |this, _, window, cx| {
|
cx.on_focus_out(&focus_handle, window, |this, _, window, cx| {
|
||||||
if !this
|
if !this.branch_list_handle.is_focused(window, cx) {
|
||||||
.branch_list
|
|
||||||
.focus_handle(cx)
|
|
||||||
.contains_focused(window, cx)
|
|
||||||
{
|
|
||||||
cx.emit(DismissEvent);
|
cx.emit(DismissEvent);
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
@ -190,11 +185,11 @@ impl CommitModal {
|
||||||
let properties = ModalContainerProperties::new(window, 50);
|
let properties = ModalContainerProperties::new(window, 50);
|
||||||
|
|
||||||
Self {
|
Self {
|
||||||
branch_list: branch_picker::popover(active_repository.clone(), window, cx),
|
|
||||||
git_panel,
|
git_panel,
|
||||||
commit_editor,
|
commit_editor,
|
||||||
restore_dock,
|
restore_dock,
|
||||||
properties,
|
properties,
|
||||||
|
branch_list_handle: PopoverMenuHandle::default(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -232,32 +227,29 @@ impl CommitModal {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn render_footer(&self, window: &mut Window, cx: &mut Context<Self>) -> impl IntoElement {
|
pub fn render_footer(&self, window: &mut Window, cx: &mut Context<Self>) -> impl IntoElement {
|
||||||
let (branch, can_commit, tooltip, commit_label, co_authors, generate_commit_message) =
|
let (can_commit, tooltip, commit_label, co_authors, generate_commit_message, active_repo) =
|
||||||
self.git_panel.update(cx, |git_panel, cx| {
|
self.git_panel.update(cx, |git_panel, cx| {
|
||||||
let branch = git_panel
|
|
||||||
.active_repository
|
|
||||||
.as_ref()
|
|
||||||
.and_then(|repo| {
|
|
||||||
repo.read(cx)
|
|
||||||
.repository_entry
|
|
||||||
.branch()
|
|
||||||
.map(|b| b.name.clone())
|
|
||||||
})
|
|
||||||
.unwrap_or_else(|| "<no branch>".into());
|
|
||||||
let (can_commit, tooltip) = git_panel.configure_commit_button(cx);
|
let (can_commit, tooltip) = git_panel.configure_commit_button(cx);
|
||||||
let title = git_panel.commit_button_title();
|
let title = git_panel.commit_button_title();
|
||||||
let co_authors = git_panel.render_co_authors(cx);
|
let co_authors = git_panel.render_co_authors(cx);
|
||||||
let generate_commit_message = git_panel.render_generate_commit_message_button(cx);
|
let generate_commit_message = git_panel.render_generate_commit_message_button(cx);
|
||||||
|
let active_repo = git_panel.active_repository.clone();
|
||||||
(
|
(
|
||||||
branch,
|
|
||||||
can_commit,
|
can_commit,
|
||||||
tooltip,
|
tooltip,
|
||||||
title,
|
title,
|
||||||
co_authors,
|
co_authors,
|
||||||
generate_commit_message,
|
generate_commit_message,
|
||||||
|
active_repo,
|
||||||
)
|
)
|
||||||
});
|
});
|
||||||
|
|
||||||
|
let branch = active_repo
|
||||||
|
.as_ref()
|
||||||
|
.and_then(|repo| repo.read(cx).repository_entry.branch())
|
||||||
|
.map(|b| b.name.clone())
|
||||||
|
.unwrap_or_else(|| "<no branch>".into());
|
||||||
|
|
||||||
let branch_picker_button = panel_button(branch)
|
let branch_picker_button = panel_button(branch)
|
||||||
.icon(IconName::GitBranch)
|
.icon(IconName::GitBranch)
|
||||||
.icon_size(IconSize::Small)
|
.icon_size(IconSize::Small)
|
||||||
|
@ -274,10 +266,8 @@ impl CommitModal {
|
||||||
.style(ButtonStyle::Transparent);
|
.style(ButtonStyle::Transparent);
|
||||||
|
|
||||||
let branch_picker = PopoverMenu::new("popover-button")
|
let branch_picker = PopoverMenu::new("popover-button")
|
||||||
.menu({
|
.menu(move |window, cx| Some(branch_picker::popover(active_repo.clone(), window, cx)))
|
||||||
let branch_list = self.branch_list.clone();
|
.with_handle(self.branch_list_handle.clone())
|
||||||
move |_window, _cx| Some(branch_list.clone())
|
|
||||||
})
|
|
||||||
.trigger_with_tooltip(
|
.trigger_with_tooltip(
|
||||||
branch_picker_button,
|
branch_picker_button,
|
||||||
Tooltip::for_action_title("Switch Branch", &zed_actions::git::Branch),
|
Tooltip::for_action_title("Switch Branch", &zed_actions::git::Branch),
|
||||||
|
@ -326,7 +316,14 @@ impl CommitModal {
|
||||||
.child(
|
.child(
|
||||||
h_flex()
|
h_flex()
|
||||||
.gap_1()
|
.gap_1()
|
||||||
.child(branch_picker)
|
.flex_shrink()
|
||||||
|
.overflow_x_hidden()
|
||||||
|
.child(
|
||||||
|
h_flex()
|
||||||
|
.flex_shrink()
|
||||||
|
.overflow_x_hidden()
|
||||||
|
.child(branch_picker),
|
||||||
|
)
|
||||||
.children(generate_commit_message)
|
.children(generate_commit_message)
|
||||||
.children(co_authors),
|
.children(co_authors),
|
||||||
)
|
)
|
||||||
|
@ -353,6 +350,14 @@ impl CommitModal {
|
||||||
.update(cx, |git_panel, cx| git_panel.commit_changes(window, cx));
|
.update(cx, |git_panel, cx| git_panel.commit_changes(window, cx));
|
||||||
cx.emit(DismissEvent);
|
cx.emit(DismissEvent);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn toggle_branch_selector(&mut self, window: &mut Window, cx: &mut Context<Self>) {
|
||||||
|
if self.branch_list_handle.is_focused(window, cx) {
|
||||||
|
self.focus_handle(cx).focus(window)
|
||||||
|
} else {
|
||||||
|
self.branch_list_handle.toggle(window, cx);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Render for CommitModal {
|
impl Render for CommitModal {
|
||||||
|
@ -375,17 +380,17 @@ impl Render for CommitModal {
|
||||||
}))
|
}))
|
||||||
.on_action(
|
.on_action(
|
||||||
cx.listener(|this, _: &zed_actions::git::Branch, window, cx| {
|
cx.listener(|this, _: &zed_actions::git::Branch, window, cx| {
|
||||||
toggle_branch_picker(this, window, cx);
|
this.toggle_branch_selector(window, cx);
|
||||||
}),
|
}),
|
||||||
)
|
)
|
||||||
.on_action(
|
.on_action(
|
||||||
cx.listener(|this, _: &zed_actions::git::CheckoutBranch, window, cx| {
|
cx.listener(|this, _: &zed_actions::git::CheckoutBranch, window, cx| {
|
||||||
toggle_branch_picker(this, window, cx);
|
this.toggle_branch_selector(window, cx);
|
||||||
}),
|
}),
|
||||||
)
|
)
|
||||||
.on_action(
|
.on_action(
|
||||||
cx.listener(|this, _: &zed_actions::git::Switch, window, cx| {
|
cx.listener(|this, _: &zed_actions::git::Switch, window, cx| {
|
||||||
toggle_branch_picker(this, window, cx);
|
this.toggle_branch_selector(window, cx);
|
||||||
}),
|
}),
|
||||||
)
|
)
|
||||||
.elevation_3(cx)
|
.elevation_3(cx)
|
||||||
|
@ -424,13 +429,3 @@ impl Render for CommitModal {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn toggle_branch_picker(
|
|
||||||
this: &mut CommitModal,
|
|
||||||
window: &mut Window,
|
|
||||||
cx: &mut Context<'_, CommitModal>,
|
|
||||||
) {
|
|
||||||
this.branch_list.update(cx, |branch_list, cx| {
|
|
||||||
branch_list.popover_handle.toggle(window, cx);
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
|
@ -2361,10 +2361,7 @@ impl GitPanel {
|
||||||
cx,
|
cx,
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
Tooltip::simple(
|
Tooltip::simple("No changes to commit", cx)
|
||||||
"You must have either staged changes or tracked files to generate a commit message",
|
|
||||||
cx,
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.disabled(!can_commit)
|
.disabled(!can_commit)
|
||||||
|
@ -2414,10 +2411,7 @@ impl GitPanel {
|
||||||
if self.has_unstaged_conflicts() {
|
if self.has_unstaged_conflicts() {
|
||||||
(false, "You must resolve conflicts before committing")
|
(false, "You must resolve conflicts before committing")
|
||||||
} else if !self.has_staged_changes() && !self.has_tracked_changes() {
|
} else if !self.has_staged_changes() && !self.has_tracked_changes() {
|
||||||
(
|
(false, "No changes to commit")
|
||||||
false,
|
|
||||||
"You must have either staged changes or tracked files to commit",
|
|
||||||
)
|
|
||||||
} else if self.pending_commit.is_some() {
|
} else if self.pending_commit.is_some() {
|
||||||
(false, "Commit in progress")
|
(false, "Commit in progress")
|
||||||
} else if self.custom_or_suggested_commit_message(cx).is_none() {
|
} else if self.custom_or_suggested_commit_message(cx).is_none() {
|
||||||
|
@ -3579,6 +3573,7 @@ impl RenderOnce for PanelRepoFooter {
|
||||||
.h(px(36.))
|
.h(px(36.))
|
||||||
.items_center()
|
.items_center()
|
||||||
.justify_between()
|
.justify_between()
|
||||||
|
.gap_1()
|
||||||
.child(
|
.child(
|
||||||
h_flex()
|
h_flex()
|
||||||
.flex_1()
|
.flex_1()
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
use gpui::{AnyView, DismissEvent, Entity, FocusHandle, Focusable as _, ManagedView, Subscription};
|
use gpui::{AnyView, DismissEvent, Entity, FocusHandle, Focusable as _, ManagedView, Subscription};
|
||||||
use ui::prelude::*;
|
use ui::prelude::*;
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
pub enum DismissDecision {
|
pub enum DismissDecision {
|
||||||
Dismiss(bool),
|
Dismiss(bool),
|
||||||
Pending,
|
Pending,
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue