From 4008871b8a8f51a5320e0d74bde76adb3e8ed817 Mon Sep 17 00:00:00 2001 From: Eric Holk Date: Wed, 8 Apr 2026 13:31:44 -0700 Subject: [PATCH] wip: improving things Co-authored-by: Max Brunsfeld Co-authored-by: Anthony Eid --- .../src/remote_connection.rs | 2 +- crates/sidebar/src/sidebar.rs | 152 +++++++++++------- 2 files changed, 95 insertions(+), 59 deletions(-) diff --git a/crates/remote_connection/src/remote_connection.rs b/crates/remote_connection/src/remote_connection.rs index d622769d90047f4f97338421ba2d62f9c878a46d..2dbe7668730c963464c00aec1a3842253b27a592 100644 --- a/crates/remote_connection/src/remote_connection.rs +++ b/crates/remote_connection/src/remote_connection.rs @@ -19,7 +19,7 @@ use ui::{ prelude::*, }; use ui_input::{ERASED_EDITOR_FACTORY, ErasedEditor}; -use workspace::{DismissDecision, ModalView}; +use workspace::{DismissDecision, ModalView, Workspace}; pub struct RemoteConnectionPrompt { connection_string: SharedString, diff --git a/crates/sidebar/src/sidebar.rs b/crates/sidebar/src/sidebar.rs index 3ea4046124e7e04aa70a5d6a81142d08307030e2..4658fdfecf16b1b08039777dc4cfaa48749e65c0 100644 --- a/crates/sidebar/src/sidebar.rs +++ b/crates/sidebar/src/sidebar.rs @@ -46,7 +46,8 @@ use workspace::{ AddFolderToProject, CloseWindow, FocusWorkspaceSidebar, MultiWorkspace, MultiWorkspaceEvent, NextProject, NextThread, Open, PreviousProject, PreviousThread, SerializedProjectGroupKey, ShowFewerThreads, ShowMoreThreads, Sidebar as WorkspaceSidebar, SidebarSide, - ToggleWorkspaceSidebar, Workspace, sidebar_side_context_menu, + ToggleWorkspaceSidebar, Workspace, notifications::DetachAndPromptErr, + sidebar_side_context_menu, }; use zed_actions::OpenRecent; @@ -2212,6 +2213,17 @@ impl Sidebar { }; if let Some(connection_options) = project_group_key.host() { + // If there's already an open workspace for this remote host, + // reuse it instead of establishing a new SSH connection. + if let Some(workspace) = multi_workspace + .read(cx) + .workspace_for_paths(&folder_paths, cx) + { + multi_workspace.update(cx, |mw, cx| mw.activate(workspace.clone(), window, cx)); + self.activate_thread(metadata, &workspace, false, window, cx); + return; + } + let pending_session_id = metadata.session_id.clone(); self.pending_remote_thread_activation = Some(pending_session_id.clone()); @@ -2228,68 +2240,50 @@ impl Sidebar { .app_state() .clone(); let paths = folder_paths.paths().to_vec(); - let provisional_project_group_key = project_group_key.clone(); - cx.spawn_in(window, async move |this, cx| { - let result: anyhow::Result<()> = async { - let delegate: std::sync::Arc = - std::sync::Arc::new(remote_connection::HeadlessRemoteClientDelegate); - let remote_connection = - remote::connect(connection_options.clone(), delegate.clone(), cx).await?; - - let (_cancel_tx, cancel_rx) = futures::channel::oneshot::channel(); - let session = cx - .update(|_, cx| { - remote::RemoteClient::new( - remote::remote_client::ConnectionIdentifier::setup(), - remote_connection, - cancel_rx, - delegate, - cx, - ) - })? - .await? - .ok_or_else(|| anyhow::anyhow!("Remote connection was cancelled"))?; - - let new_project = cx.update(|_, cx| { - project::Project::remote( - session, - app_state.client.clone(), - app_state.node_runtime.clone(), - app_state.user_store.clone(), - app_state.languages.clone(), - app_state.fs.clone(), - true, - cx, - ) - })?; - - workspace::open_remote_project_with_existing_connection( - connection_options, - new_project, - paths, - app_state, - window_handle, - Some(provisional_project_group_key), + let active_workspace = multi_workspace.read(cx).workspace().clone(); + let connect_task = active_workspace.update(cx, |workspace, cx| { + workspace.toggle_modal(window, cx, |window, cx| { + remote_connection::RemoteConnectionModal::new( + &connection_options, + Vec::new(), + window, cx, ) - .await?; + }); - let workspace = window_handle.update(cx, |multi_workspace, window, cx| { - let workspace = multi_workspace.workspace().clone(); - multi_workspace.add(workspace.clone(), window, cx); - workspace - })?; + let prompt = workspace + .active_modal::(cx) + .expect("Modal just created") + .read(cx) + .prompt + .clone(); - this.update_in(cx, |this, window, cx| { - this.activate_thread(metadata, &workspace, false, window, cx); - })?; - anyhow::Ok(()) - } - .await; + remote_connection::connect( + remote::remote_client::ConnectionIdentifier::setup(), + connection_options.clone(), + prompt, + window, + cx, + ) + .prompt_err("Failed to connect", window, cx, |_, _, _| None) + }); + + cx.spawn_in(window, async move |this, cx| { + let session = connect_task.await; - if result.is_err() { + active_workspace + .update_in(cx, |workspace, _window, cx| { + if let Some(modal) = + workspace.active_modal::(cx) + { + modal.update(cx, |modal, cx| modal.finished(cx)); + } + }) + .ok(); + + let Some(Some(session)) = session else { this.update(cx, |this, _cx| { if this.pending_remote_thread_activation.as_ref() == Some(&pending_session_id) @@ -2298,9 +2292,51 @@ impl Sidebar { } }) .ok(); - } + return anyhow::Ok(()); + }; + + let new_project = cx.update(|_, cx| { + project::Project::remote( + session, + app_state.client.clone(), + app_state.node_runtime.clone(), + app_state.user_store.clone(), + app_state.languages.clone(), + app_state.fs.clone(), + true, + cx, + ) + })?; - result + workspace::open_remote_project_with_existing_connection( + connection_options, + new_project, + paths, + app_state, + window_handle, + Some(provisional_project_group_key), + cx, + ) + .await?; + + let workspace = window_handle.update(cx, |multi_workspace, window, cx| { + let workspace = multi_workspace.workspace().clone(); + multi_workspace.add(workspace.clone(), window, cx); + workspace + })?; + + this.update_in(cx, |this, window, cx| { + this.activate_thread(metadata, &workspace, false, window, cx); + })?; + + this.update(cx, |this, _cx| { + if this.pending_remote_thread_activation.as_ref() == Some(&pending_session_id) { + this.pending_remote_thread_activation = None; + } + }) + .ok(); + + anyhow::Ok(()) }) .detach_and_log_err(cx); } else {