Dismiss stale remote connection modal when switching back to local workspace (#53575)
When the sidebar opens a remote SSH project, it shows a `RemoteConnectionModal` on the currently active (local) workspace. After the connection succeeds and a new remote workspace is created and activated, the modal on the local workspace was never dismissed. Switching back to the local workspace (e.g. by activating a thread) would re-render the local workspace's modal layer, revealing the stale "Starting proxy..." modal. Other code paths that show this modal (`recent_projects`, `git_ui`) already call `modal.finished(cx)` after the connection completes. The sidebar and agent panel paths were missing this cleanup. ## Changes - **`remote_connection`**: Added `dismiss_connection_modal()`, a public utility that finds and dismisses any active `RemoteConnectionModal` on a given workspace. - **`sidebar`**: Fixed two call sites (`open_workspace_for_group` and `open_workspace_and_activate_thread`) to dismiss the modal after the connection task completes, regardless of success or failure. - **`agent_ui`**: Fixed `open_worktree_workspace_and_start_thread` to dismiss the modal after workspace creation completes. Release Notes: - (Preview only) Fixed a spurious "Starting proxy..." modal appearing and hanging when switching back to a local project after opening a remote SSH project in a multi-project workspace.
This commit is contained in:
1 parent
5d9ee5fe78
commit
d634055a19
3 files changed
+65
-32
No files matched your search
@@ -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();
|
||||
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();
|
||||
|
||||
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 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());
|
||||
|
||||
|
||||
@@ -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<Workspace>, cx: &mut gpui::AsyncWindowContext) {
|
||||
workspace
|
||||
.update_in(cx, |workspace, _window, cx| {
|
||||
if let Some(modal) = workspace.active_modal::<RemoteConnectionModal>(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`.
|
||||
|
||||
@@ -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| {
|
||||
|
||||
Reference in new issue
Block a user