diff --git a/crates/agent_ui/src/agent_panel.rs b/crates/agent_ui/src/agent_panel.rs index adb255ea62454d4e3eb3dcaa3f0d6cf481f66472..6c555af7fa630f5f5cc5995f36ec8ee7007508b9 100644 --- a/crates/agent_ui/src/agent_panel.rs +++ b/crates/agent_ui/src/agent_panel.rs @@ -3190,28 +3190,33 @@ impl AgentPanel { let window_handle = window_handle .ok_or_else(|| anyhow!("No window handle available for workspace creation"))?; - let workspace_task = window_handle.update(cx, |multi_workspace, window, cx| { - let path_list = PathList::new(&all_paths); - let active_workspace = multi_workspace.workspace().clone(); - - multi_workspace.find_or_create_workspace( - path_list, - remote_connection_options, - None, - move |connection_options, window, cx| { - remote_connection::connect_with_modal( - &active_workspace, - connection_options, - window, - cx, - ) - }, - window, - cx, - ) - })?; + let (workspace_task, modal_workspace) = + window_handle.update(cx, |multi_workspace, window, cx| { + let path_list = PathList::new(&all_paths); + let active_workspace = multi_workspace.workspace().clone(); + let modal_workspace = active_workspace.clone(); + + let task = multi_workspace.find_or_create_workspace( + path_list, + remote_connection_options, + None, + move |connection_options, window, cx| { + remote_connection::connect_with_modal( + &active_workspace, + connection_options, + window, + cx, + ) + }, + window, + cx, + ); + (task, modal_workspace) + })?; - let new_workspace = workspace_task.await?; + let result = workspace_task.await; + remote_connection::dismiss_connection_modal(&modal_workspace, cx); + let new_workspace = result?; let panels_task = new_workspace.update(cx, |workspace, _cx| workspace.take_panels_task()); diff --git a/crates/remote_connection/src/remote_connection.rs b/crates/remote_connection/src/remote_connection.rs index 48024af741b2b850c6cc9ff7379183cda8385efd..8aa4622929d6086b99e840e6b52bd5f46c49c898 100644 --- a/crates/remote_connection/src/remote_connection.rs +++ b/crates/remote_connection/src/remote_connection.rs @@ -574,6 +574,23 @@ pub fn connect_with_modal( }) } +/// Dismisses any active [`RemoteConnectionModal`] on the given workspace. +/// +/// This should be called after a remote connection attempt completes +/// (success or failure) when the modal was shown on a workspace that may +/// outlive the connection flow — for example, when the modal is shown +/// on a local workspace before switching to a newly-created remote +/// workspace. +pub fn dismiss_connection_modal(workspace: &Entity, cx: &mut gpui::AsyncWindowContext) { + workspace + .update_in(cx, |workspace, _window, cx| { + if let Some(modal) = workspace.active_modal::(cx) { + modal.update(cx, |modal, cx| modal.finished(cx)); + } + }) + .ok(); +} + /// Creates a [`RemoteClient`] by reusing an existing connection from the /// global pool. No interactive UI is shown. This should only be called /// when [`remote::has_active_connection`] returns `true`. diff --git a/crates/sidebar/src/sidebar.rs b/crates/sidebar/src/sidebar.rs index 488127eb0bd04b064c2c6e3b1d8dc297ada9c477..3cd7e0059ac165bcd5e738591363cb600abcd60f 100644 --- a/crates/sidebar/src/sidebar.rs +++ b/crates/sidebar/src/sidebar.rs @@ -753,19 +753,26 @@ impl Sidebar { let host = project_group_key.host(); let provisional_key = Some(project_group_key.clone()); let active_workspace = multi_workspace.read(cx).workspace().clone(); + let modal_workspace = active_workspace.clone(); - multi_workspace - .update(cx, |this, cx| { - this.find_or_create_workspace( - path_list, - host, - provisional_key, - |options, window, cx| connect_remote(active_workspace, options, window, cx), - window, - cx, - ) - }) - .detach_and_log_err(cx); + let task = multi_workspace.update(cx, |this, cx| { + this.find_or_create_workspace( + path_list, + host, + provisional_key, + |options, window, cx| connect_remote(active_workspace, options, window, cx), + window, + cx, + ) + }); + + cx.spawn_in(window, async move |_this, cx| { + let result = task.await; + remote_connection::dismiss_connection_modal(&modal_workspace, cx); + result?; + anyhow::Ok(()) + }) + .detach_and_log_err(cx); } /// Rebuilds the sidebar contents from current workspace and thread state. @@ -2292,6 +2299,7 @@ impl Sidebar { let host = project_group_key.host(); let provisional_key = Some(project_group_key.clone()); let active_workspace = multi_workspace.read(cx).workspace().clone(); + let modal_workspace = active_workspace.clone(); let open_task = multi_workspace.update(cx, |this, cx| { this.find_or_create_workspace( @@ -2306,6 +2314,9 @@ impl Sidebar { cx.spawn_in(window, async move |this, cx| { let result = open_task.await; + // Dismiss the modal as soon as the open attempt completes so + // failures or cancellations do not leave a stale connection modal behind. + remote_connection::dismiss_connection_modal(&modal_workspace, cx); if result.is_err() || is_remote { this.update(cx, |this, _cx| {