diff --git a/crates/assistant/src/inline_assistant.rs b/crates/assistant/src/inline_assistant.rs index a6e71fc40b..2ec7d154e3 100644 --- a/crates/assistant/src/inline_assistant.rs +++ b/crates/assistant/src/inline_assistant.rs @@ -58,6 +58,13 @@ pub fn init( cx: &mut AppContext, ) { cx.set_global(InlineAssistant::new(fs, prompt_builder, telemetry)); + cx.observe_new_views(|_, cx| { + let workspace = cx.view().clone(); + InlineAssistant::update_global(cx, |inline_assistant, cx| { + inline_assistant.register_workspace(&workspace, cx) + }) + }) + .detach(); } const PROMPT_HISTORY_MAX_LEN: usize = 20; @@ -100,6 +107,29 @@ impl InlineAssistant { } } + pub fn register_workspace(&mut self, workspace: &View, cx: &mut WindowContext) { + cx.subscribe(workspace, |_, event, cx| { + Self::update_global(cx, |this, cx| this.handle_workspace_event(event, cx)); + }) + .detach(); + } + + fn handle_workspace_event(&mut self, event: &workspace::Event, cx: &mut WindowContext) { + // When the user manually saves an editor, automatically accepts all finished transformations. + if let workspace::Event::UserSavedItem { item, .. } = event { + if let Some(editor) = item.upgrade().and_then(|item| item.act_as::(cx)) { + if let Some(editor_assists) = self.assists_by_editor.get(&editor.downgrade()) { + for assist_id in editor_assists.assist_ids.clone() { + let assist = &self.assists[&assist_id]; + if let CodegenStatus::Done = &assist.codegen.read(cx).status { + self.finish_assist(assist_id, false, cx) + } + } + } + } + } + } + pub fn assist( &mut self, editor: &View, @@ -558,14 +588,6 @@ impl InlineAssistant { }; match event { - EditorEvent::Saved => { - for assist_id in editor_assists.assist_ids.clone() { - let assist = &self.assists[&assist_id]; - if let CodegenStatus::Done = &assist.codegen.read(cx).status { - self.finish_assist(assist_id, false, cx) - } - } - } EditorEvent::Edited { transaction_id } => { let buffer = editor.read(cx).buffer().read(cx); let edited_ranges = diff --git a/crates/workspace/src/item.rs b/crates/workspace/src/item.rs index 7e66e48358..6ea8be830d 100644 --- a/crates/workspace/src/item.rs +++ b/crates/workspace/src/item.rs @@ -436,6 +436,7 @@ pub trait ItemHandle: 'static + Send { pub trait WeakItemHandle: Send + Sync { fn id(&self) -> EntityId; + fn boxed_clone(&self) -> Box; fn upgrade(&self) -> Option>; } @@ -852,6 +853,10 @@ impl WeakItemHandle for WeakView { self.entity_id() } + fn boxed_clone(&self) -> Box { + Box::new(self.clone()) + } + fn upgrade(&self) -> Option> { self.upgrade().map(|v| Box::new(v) as Box) } diff --git a/crates/workspace/src/pane.rs b/crates/workspace/src/pane.rs index 8ee5ef7a3e..38c368074b 100644 --- a/crates/workspace/src/pane.rs +++ b/crates/workspace/src/pane.rs @@ -166,16 +166,28 @@ impl DeploySearch { const MAX_NAVIGATION_HISTORY_LEN: usize = 1024; pub enum Event { - AddItem { item: Box }, - ActivateItem { local: bool }, + AddItem { + item: Box, + }, + ActivateItem { + local: bool, + }, Remove, - RemoveItem { idx: usize }, - RemovedItem { item_id: EntityId }, + RemoveItem { + idx: usize, + }, + RemovedItem { + item_id: EntityId, + }, Split(SplitDirection), ChangeItemTitle, Focus, ZoomIn, ZoomOut, + UserSavedItem { + item: Box, + save_intent: SaveIntent, + }, } impl fmt::Debug for Event { @@ -203,6 +215,11 @@ impl fmt::Debug for Event { Event::Focus => f.write_str("Focus"), Event::ZoomIn => f.write_str("ZoomIn"), Event::ZoomOut => f.write_str("ZoomOut"), + Event::UserSavedItem { item, save_intent } => f + .debug_struct("UserSavedItem") + .field("item", &item.id()) + .field("save_intent", save_intent) + .finish(), } } } @@ -1494,7 +1511,13 @@ impl Pane { } } - Ok(true) + pane.update(cx, |_, cx| { + cx.emit(Event::UserSavedItem { + item: item.downgrade_item(), + save_intent, + }); + true + }) } fn can_autosave_item(item: &dyn ItemHandle, cx: &AppContext) -> bool { diff --git a/crates/workspace/src/workspace.rs b/crates/workspace/src/workspace.rs index db375d0d31..643473f7dc 100644 --- a/crates/workspace/src/workspace.rs +++ b/crates/workspace/src/workspace.rs @@ -40,7 +40,7 @@ use gpui::{ }; use item::{ FollowableItem, FollowableItemHandle, Item, ItemHandle, ItemSettings, PreviewTabsSettings, - ProjectItem, SerializableItem, SerializableItemHandle, + ProjectItem, SerializableItem, SerializableItemHandle, WeakItemHandle, }; use itertools::Itertools; use language::{LanguageRegistry, Rope}; @@ -670,6 +670,11 @@ pub enum Event { ItemAdded, ItemRemoved, ActiveItemChanged, + UserSavedItem { + pane: WeakView, + item: Box, + save_intent: SaveIntent, + }, ContactRequestedJoin(u64), WorkspaceCreated(WeakView), SpawnTask(Box), @@ -2934,6 +2939,11 @@ impl Workspace { self.update_active_view_for_followers(cx); } } + pane::Event::UserSavedItem { item, save_intent } => cx.emit(Event::UserSavedItem { + pane: pane.downgrade(), + item: item.boxed_clone(), + save_intent: *save_intent, + }), pane::Event::ChangeItemTitle => { if pane == self.active_pane { self.active_item_path_changed(cx);