ssh remoting: Enable reconnecting after connection losses (#18586)

Release Notes:

- N/A

---------

Co-authored-by: Bennet <bennet@zed.dev>
This commit is contained in:
Thorsten Ball 2024-10-07 11:40:59 +02:00 committed by GitHub
parent 67fbdbbed6
commit c03b8d6c48
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
19 changed files with 727 additions and 240 deletions

View file

@ -305,13 +305,19 @@ impl DevServerProjects {
let connection_options = remote::SshConnectionOptions {
host: host.to_string(),
username,
username: username.clone(),
port,
password: None,
};
let ssh_prompt = cx.new_view(|cx| SshPrompt::new(&connection_options, cx));
let connection = connect_over_ssh(connection_options.clone(), ssh_prompt.clone(), cx)
.prompt_err("Failed to connect", cx, |_, _| None);
let connection = connect_over_ssh(
connection_options.dev_server_identifier(),
connection_options.clone(),
ssh_prompt.clone(),
cx,
)
.prompt_err("Failed to connect", cx, |_, _| None);
let creating = cx.spawn(move |this, mut cx| async move {
match connection.await {
@ -363,11 +369,13 @@ impl DevServerProjects {
.prompt
.clone();
let connect = connect_over_ssh(connection_options, prompt, cx).prompt_err(
"Failed to connect",
let connect = connect_over_ssh(
connection_options.dev_server_identifier(),
connection_options,
prompt,
cx,
|_, _| None,
);
)
.prompt_err("Failed to connect", cx, |_, _| None);
cx.spawn(|workspace, mut cx| async move {
let Some(session) = connect.await else {
workspace

View file

@ -4,12 +4,12 @@ use anyhow::Result;
use auto_update::AutoUpdater;
use editor::Editor;
use futures::channel::oneshot;
use gpui::AppContext;
use gpui::{
percentage, px, Animation, AnimationExt, AnyWindowHandle, AsyncAppContext, DismissEvent,
EventEmitter, FocusableView, ParentElement as _, Render, SemanticVersion, SharedString, Task,
Transformation, View,
};
use gpui::{AppContext, Model};
use release_channel::{AppVersion, ReleaseChannel};
use remote::{SshConnectionOptions, SshPlatform, SshRemoteClient};
use schemars::JsonSchema;
@ -373,25 +373,24 @@ impl SshClientDelegate {
}
pub fn connect_over_ssh(
unique_identifier: String,
connection_options: SshConnectionOptions,
ui: View<SshPrompt>,
cx: &mut WindowContext,
) -> Task<Result<Arc<SshRemoteClient>>> {
) -> Task<Result<Model<SshRemoteClient>>> {
let window = cx.window_handle();
let known_password = connection_options.password.clone();
cx.spawn(|mut cx| async move {
remote::SshRemoteClient::new(
connection_options,
Arc::new(SshClientDelegate {
window,
ui,
known_password,
}),
&mut cx,
)
.await
})
remote::SshRemoteClient::new(
unique_identifier,
connection_options,
Arc::new(SshClientDelegate {
window,
ui,
known_password,
}),
cx,
)
}
pub async fn open_ssh_project(
@ -420,22 +419,25 @@ pub async fn open_ssh_project(
})?
};
let session = window
.update(cx, |workspace, cx| {
cx.activate_window();
workspace.toggle_modal(cx, |cx| SshConnectionModal::new(&connection_options, cx));
let ui = workspace
.active_modal::<SshConnectionModal>(cx)
.unwrap()
.read(cx)
.prompt
.clone();
connect_over_ssh(connection_options.clone(), ui, cx)
})?
.await?;
let delegate = window.update(cx, |workspace, cx| {
cx.activate_window();
workspace.toggle_modal(cx, |cx| SshConnectionModal::new(&connection_options, cx));
let ui = workspace
.active_modal::<SshConnectionModal>(cx)
.unwrap()
.read(cx)
.prompt
.clone();
Arc::new(SshClientDelegate {
window: cx.window_handle(),
ui,
known_password: connection_options.password.clone(),
})
})?;
cx.update(|cx| {
workspace::open_ssh_project(window, connection_options, session, app_state, paths, cx)
workspace::open_ssh_project(window, connection_options, delegate, app_state, paths, cx)
})?
.await
}