Detailed changes
@@ -2233,6 +2233,43 @@ impl Editor {
cx.notify();
}
+ pub fn sync_selections(
+ &mut self,
+ other: Entity<Editor>,
+ cx: &mut Context<Self>,
+ ) -> gpui::Subscription {
+ let other_selections = other.read(cx).selections.disjoint.to_vec();
+ self.selections.change_with(cx, |selections| {
+ selections.select_anchors(other_selections);
+ });
+
+ let other_subscription =
+ cx.subscribe(&other, |this, other, other_evt, cx| match other_evt {
+ EditorEvent::SelectionsChanged { local: true } => {
+ let other_selections = other.read(cx).selections.disjoint.to_vec();
+ this.selections.change_with(cx, |selections| {
+ selections.select_anchors(other_selections);
+ });
+ }
+ _ => {}
+ });
+
+ let this_subscription =
+ cx.subscribe_self::<EditorEvent>(move |this, this_evt, cx| match this_evt {
+ EditorEvent::SelectionsChanged { local: true } => {
+ let these_selections = this.selections.disjoint.to_vec();
+ other.update(cx, |other_editor, cx| {
+ other_editor.selections.change_with(cx, |selections| {
+ selections.select_anchors(these_selections);
+ })
+ });
+ }
+ _ => {}
+ });
+
+ Subscription::join(other_subscription, this_subscription)
+ }
+
pub fn change_selections<R>(
&mut self,
autoscroll: Option<Autoscroll>,
@@ -115,27 +115,9 @@ impl CommitModal {
return;
};
- let (can_open_commit_editor, conflict) = git_panel.update(cx, |git_panel, cx| {
- let can_open_commit_editor = git_panel.can_open_commit_editor();
- let conflict = git_panel.has_unstaged_conflicts();
- if can_open_commit_editor {
- git_panel.set_modal_open(true, cx);
- }
- (can_open_commit_editor, conflict)
+ git_panel.update(cx, |git_panel, cx| {
+ git_panel.set_modal_open(true, cx);
});
- if !can_open_commit_editor {
- let message = if conflict {
- "There are still conflicts. You must stage these before committing."
- } else {
- "No changes to commit."
- };
- let prompt = window.prompt(PromptLevel::Warning, message, None, &["Ok"], cx);
- cx.spawn(|_, _| async move {
- prompt.await.ok();
- })
- .detach();
- return;
- }
let dock = workspace.dock_at_position(git_panel.position(window, cx));
let is_open = dock.read(cx).is_open();
@@ -168,8 +150,16 @@ impl CommitModal {
let commit_editor = git_panel.update(cx, |git_panel, cx| {
git_panel.set_modal_open(true, cx);
let buffer = git_panel.commit_message_buffer(cx).clone();
+ let panel_editor = git_panel.commit_editor.clone();
let project = git_panel.project.clone();
- cx.new(|cx| commit_message_editor(buffer, None, project.clone(), false, window, cx))
+
+ cx.new(|cx| {
+ let mut editor =
+ commit_message_editor(buffer, None, project.clone(), false, window, cx);
+ editor.sync_selections(panel_editor, cx).detach();
+
+ editor
+ })
});
let commit_message = commit_editor.read(cx).text(cx);
@@ -8,6 +8,7 @@ use crate::{
use crate::{picker_prompt, project_diff, ProjectDiff};
use db::kvp::KEY_VALUE_STORE;
use editor::commit_tooltip::CommitTooltip;
+
use editor::{
scroll::ScrollbarAutoHide, Editor, EditorElement, EditorMode, EditorSettings, MultiBuffer,
ShowScrollbar,
@@ -190,7 +191,7 @@ pub struct GitPanel {
remote_operation_id: u32,
pending_remote_operations: RemoteOperations,
pub(crate) active_repository: Option<Entity<Repository>>,
- commit_editor: Entity<Editor>,
+ pub(crate) commit_editor: Entity<Editor>,
conflicted_count: usize,
conflicted_staged_count: usize,
current_modifiers: Modifiers,
@@ -1934,7 +1935,7 @@ impl GitPanel {
})
}
- pub fn can_open_commit_editor(&self) -> bool {
+ pub fn can_commit(&self) -> bool {
(self.has_staged_changes() || self.has_tracked_changes()) && !self.has_unstaged_conflicts()
}
@@ -2013,7 +2014,6 @@ impl GitPanel {
cx: &mut Context<Self>,
) -> Option<impl IntoElement> {
let active_repository = self.active_repository.clone()?;
- let can_open_commit_editor = self.can_open_commit_editor();
let (can_commit, tooltip) = self.configure_commit_button(cx);
let project = self.project.clone().read(cx);
let panel_editor_style = panel_editor_style(true, window, cx);
@@ -2108,7 +2108,6 @@ impl GitPanel {
.icon_size(IconSize::Small)
.style(ButtonStyle::Transparent)
.width(expand_button_size.into())
- .disabled(!can_open_commit_editor)
.on_click(cx.listener({
move |_, _, window, cx| {
window.dispatch_action(
@@ -257,14 +257,12 @@ impl ProjectDiff {
}
}
}
- let mut can_open_commit_editor = false;
let mut stage_all = false;
let mut unstage_all = false;
self.workspace
.read_with(cx, |workspace, cx| {
if let Some(git_panel) = workspace.panel::<GitPanel>(cx) {
let git_panel = git_panel.read(cx);
- can_open_commit_editor = git_panel.can_open_commit_editor();
stage_all = git_panel.can_stage_all();
unstage_all = git_panel.can_unstage_all();
}
@@ -276,7 +274,6 @@ impl ProjectDiff {
unstage: has_staged_hunks,
prev_next,
selection,
- can_open_commit_editor,
stage_all,
unstage_all,
};
@@ -773,7 +770,6 @@ struct ButtonStates {
selection: bool,
stage_all: bool,
unstage_all: bool,
- can_open_commit_editor: bool,
}
impl Render for ProjectDiffToolbar {
@@ -917,7 +913,6 @@ impl Render for ProjectDiffToolbar {
)
.child(
Button::new("commit", "Commit")
- .disabled(!button_states.can_open_commit_editor)
.tooltip(Tooltip::for_action_title_in(
"Commit",
&ShowCommitEditor,
@@ -90,6 +90,21 @@ impl<'a, T: 'static> Context<'a, T> {
})
}
+ /// Subscribe to an event type from ourself
+ pub fn subscribe_self<Evt>(
+ &mut self,
+ mut on_event: impl FnMut(&mut T, &Evt, &mut Context<'_, T>) + 'static,
+ ) -> Subscription
+ where
+ T: 'static + EventEmitter<Evt>,
+ Evt: 'static,
+ {
+ let this = self.entity();
+ self.app.subscribe(&this, move |this, evt, cx| {
+ this.update(cx, |this, cx| on_event(this, evt, cx))
+ })
+ }
+
/// Register a callback to be invoked when GPUI releases this entity.
pub fn on_release(&self, on_release: impl FnOnce(&mut T, &mut App) + 'static) -> Subscription
where
@@ -168,6 +168,23 @@ impl Subscription {
pub fn detach(mut self) {
self.unsubscribe.take();
}
+
+ /// Joins two subscriptions into a single subscription. Detach will
+ /// detach both interior subscriptions.
+ pub fn join(mut subscription_a: Self, mut subscription_b: Self) -> Self {
+ let a_unsubscribe = subscription_a.unsubscribe.take();
+ let b_unsubscribe = subscription_b.unsubscribe.take();
+ Self {
+ unsubscribe: Some(Box::new(move || {
+ if let Some(self_unsubscribe) = a_unsubscribe {
+ self_unsubscribe();
+ }
+ if let Some(other_unsubscribe) = b_unsubscribe {
+ other_unsubscribe();
+ }
+ })),
+ }
+ }
}
impl Drop for Subscription {