diff --git a/crates/assistant/src/assistant_panel.rs b/crates/assistant/src/assistant_panel.rs index 0375dede06..2f83e6bc21 100644 --- a/crates/assistant/src/assistant_panel.rs +++ b/crates/assistant/src/assistant_panel.rs @@ -2692,14 +2692,25 @@ impl ContextEditor { fn update_active_workflow_step(&mut self, cx: &mut ViewContext) { let new_step = self.active_workflow_step_for_cursor(cx); if new_step.as_ref() != self.active_workflow_step.as_ref() { + let mut old_editor = None; + let mut old_editor_was_open = None; if let Some(old_step) = self.active_workflow_step.take() { - self.hide_workflow_step(old_step.range, cx); + (old_editor, old_editor_was_open) = + self.hide_workflow_step(old_step.range, cx).unzip(); } + let mut new_editor = None; if let Some(new_step) = new_step { - self.show_workflow_step(new_step.range.clone(), cx); + new_editor = self.show_workflow_step(new_step.range.clone(), cx); self.active_workflow_step = Some(new_step); } + + if new_editor != old_editor { + if let Some((old_editor, old_editor_was_open)) = old_editor.zip(old_editor_was_open) + { + self.close_workflow_editor(cx, old_editor, old_editor_was_open) + } + } } } @@ -2707,15 +2718,15 @@ impl ContextEditor { &mut self, step_range: Range, cx: &mut ViewContext, - ) { + ) -> Option<(View, bool)> { let Some(step) = self.workflow_steps.get_mut(&step_range) else { - return; + return None; }; let Some(assist) = step.assist.as_ref() else { - return; + return None; }; let Some(editor) = assist.editor.upgrade() else { - return; + return None; }; if matches!(step.status(cx), WorkflowStepStatus::Idle) { @@ -2725,32 +2736,42 @@ impl ContextEditor { assistant.finish_assist(assist_id, true, cx) } }); - - self.workspace - .update(cx, |workspace, cx| { - if let Some(pane) = workspace.pane_for(&editor) { - pane.update(cx, |pane, cx| { - let item_id = editor.entity_id(); - if !assist.editor_was_open && pane.is_active_preview_item(item_id) { - pane.close_item_by_id(item_id, SaveIntent::Skip, cx) - .detach_and_log_err(cx); - } - }); - } - }) - .ok(); + return Some((editor, assist.editor_was_open)); } + + return None; + } + + fn close_workflow_editor( + &mut self, + cx: &mut ViewContext, + editor: View, + editor_was_open: bool, + ) { + self.workspace + .update(cx, |workspace, cx| { + if let Some(pane) = workspace.pane_for(&editor) { + pane.update(cx, |pane, cx| { + let item_id = editor.entity_id(); + if !editor_was_open && pane.is_active_preview_item(item_id) { + pane.close_item_by_id(item_id, SaveIntent::Skip, cx) + .detach_and_log_err(cx); + } + }); + } + }) + .ok(); } fn show_workflow_step( &mut self, step_range: Range, cx: &mut ViewContext, - ) { + ) -> Option> { let Some(step) = self.workflow_steps.get_mut(&step_range) else { - return; + return None; }; - + let mut editor_to_return = None; let mut scroll_to_assist_id = None; match step.status(cx) { WorkflowStepStatus::Idle => { @@ -2764,6 +2785,10 @@ impl ContextEditor { &self.workspace, cx, ); + editor_to_return = step + .assist + .as_ref() + .and_then(|assist| assist.editor.upgrade()); } } WorkflowStepStatus::Pending => { @@ -2785,14 +2810,15 @@ impl ContextEditor { } if let Some(assist_id) = scroll_to_assist_id { - if let Some(editor) = step + if let Some(assist_editor) = step .assist .as_ref() .and_then(|assists| assists.editor.upgrade()) { + editor_to_return = Some(assist_editor.clone()); self.workspace .update(cx, |workspace, cx| { - workspace.activate_item(&editor, false, false, cx); + workspace.activate_item(&assist_editor, false, false, cx); }) .ok(); InlineAssistant::update_global(cx, |assistant, cx| { @@ -2800,6 +2826,8 @@ impl ContextEditor { }); } } + + return editor_to_return; } fn open_assists_for_step( @@ -2843,7 +2871,6 @@ impl ContextEditor { ) }) .log_err()?; - let (&excerpt_id, _, _) = editor .read(cx) .buffer() diff --git a/crates/workspace/src/item.rs b/crates/workspace/src/item.rs index 6ea8be830d..14535a72fb 100644 --- a/crates/workspace/src/item.rs +++ b/crates/workspace/src/item.rs @@ -373,6 +373,7 @@ pub trait ItemHandle: 'static + Send { fn dragged_tab_content(&self, params: TabContentParams, cx: &WindowContext) -> AnyElement; fn project_path(&self, cx: &AppContext) -> Option; fn project_entry_ids(&self, cx: &AppContext) -> SmallVec<[ProjectEntryId; 3]>; + fn project_paths(&self, cx: &AppContext) -> SmallVec<[ProjectPath; 3]>; fn project_item_model_ids(&self, cx: &AppContext) -> SmallVec<[EntityId; 3]>; fn for_each_project_item( &self, @@ -531,6 +532,16 @@ impl ItemHandle for View { result } + fn project_paths(&self, cx: &AppContext) -> SmallVec<[ProjectPath; 3]> { + let mut result = SmallVec::new(); + self.read(cx).for_each_project_item(cx, &mut |_, item| { + if let Some(id) = item.project_path(cx) { + result.push(id); + } + }); + result + } + fn project_item_model_ids(&self, cx: &AppContext) -> SmallVec<[EntityId; 3]> { let mut result = SmallVec::new(); self.read(cx).for_each_project_item(cx, &mut |id, _| { diff --git a/crates/workspace/src/pane.rs b/crates/workspace/src/pane.rs index a2956a01a9..393a47d134 100644 --- a/crates/workspace/src/pane.rs +++ b/crates/workspace/src/pane.rs @@ -920,7 +920,22 @@ impl Pane { cx: &AppContext, ) -> Option> { self.items.iter().find_map(|item| { - if item.is_singleton(cx) && item.project_entry_ids(cx).as_slice() == [entry_id] { + if item.is_singleton(cx) && (item.project_entry_ids(cx).as_slice() == [entry_id]) { + Some(item.boxed_clone()) + } else { + None + } + }) + } + + pub fn item_for_path( + &self, + project_path: ProjectPath, + cx: &AppContext, + ) -> Option> { + self.items.iter().find_map(move |item| { + if item.is_singleton(cx) && (item.project_path(cx).as_slice() == [project_path.clone()]) + { Some(item.boxed_clone()) } else { None diff --git a/crates/workspace/src/workspace.rs b/crates/workspace/src/workspace.rs index 07e60754a8..2dffd8667f 100644 --- a/crates/workspace/src/workspace.rs +++ b/crates/workspace/src/workspace.rs @@ -2618,6 +2618,33 @@ impl Workspace { open_project_item } + pub fn find_project_item( + &self, + pane: &View, + project_item: &Model, + cx: &AppContext, + ) -> Option> + where + T: ProjectItem, + { + use project::Item as _; + let project_item = project_item.read(cx); + let entry_id = project_item.entry_id(cx); + let project_path = project_item.project_path(cx); + + let mut item = None; + if let Some(entry_id) = entry_id { + item = pane.read(cx).item_for_entry(entry_id, cx); + } + if item.is_none() { + if let Some(project_path) = project_path { + item = pane.read(cx).item_for_path(project_path, cx); + } + } + + item.and_then(|item| item.downcast::()) + } + pub fn is_project_item_open( &self, pane: &View, @@ -2627,13 +2654,7 @@ impl Workspace { where T: ProjectItem, { - use project::Item as _; - - project_item - .read(cx) - .entry_id(cx) - .and_then(|entry_id| pane.read(cx).item_for_entry(entry_id, cx)) - .and_then(|item| item.downcast::()) + self.find_project_item::(pane, project_item, cx) .is_some() } @@ -2648,19 +2669,12 @@ impl Workspace { where T: ProjectItem, { - use project::Item as _; - - let entry_id = project_item.read(cx).entry_id(cx); - if let Some(item) = entry_id - .and_then(|entry_id| pane.read(cx).item_for_entry(entry_id, cx)) - .and_then(|item| item.downcast()) - { + if let Some(item) = self.find_project_item(&pane, &project_item, cx) { self.activate_item(&item, activate_pane, focus_item, cx); return item; } let item = cx.new_view(|cx| T::for_project_item(self.project().clone(), project_item, cx)); - let item_id = item.item_id(); let mut destination_index = None; pane.update(cx, |pane, cx| {