reconnect ssh (#12147)

Release Notes:

- N/A

---------

Co-authored-by: Bennet <bennet@zed.dev>
This commit is contained in:
Conrad Irwin 2024-05-22 21:25:38 -06:00 committed by GitHub
parent ea166f0b27
commit af8641ce5b
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 230 additions and 125 deletions

View file

@ -1,5 +1,7 @@
mod dev_servers;
use client::ProjectId;
use dev_servers::reconnect_to_dev_server;
pub use dev_servers::DevServerProjects;
use feature_flags::FeatureFlagAppExt;
use fuzzy::{StringMatch, StringMatchCandidate};
@ -17,6 +19,7 @@ use serde::Deserialize;
use std::{
path::{Path, PathBuf},
sync::Arc,
time::Duration,
};
use ui::{
prelude::*, tooltip_container, ButtonLike, IconWithIndicator, Indicator, KeyBinding, ListItem,
@ -313,73 +316,59 @@ impl PickerDelegate for RecentProjectsDelegate {
}
}
SerializedWorkspaceLocation::DevServer(dev_server_project) => {
let store = dev_server_projects::Store::global(cx).read(cx);
let Some(project_id) = store
let store = dev_server_projects::Store::global(cx);
let Some(project_id) = store.read(cx)
.dev_server_project(dev_server_project.id)
.and_then(|p| p.project_id)
else {
let dev_server_name = dev_server_project.dev_server_name.clone();
return cx.spawn(|workspace, mut cx| async move {
let response =
cx.prompt(gpui::PromptLevel::Warning,
"Dev Server is offline",
Some(format!("Cannot connect to {}. To debug open the remote project settings.", dev_server_name).as_str()),
&["Ok", "Open Settings"]
).await?;
if response == 1 {
workspace.update(&mut cx, |workspace, cx| {
let handle = cx.view().downgrade();
workspace.toggle_modal(cx, |cx| DevServerProjects::new(cx, handle))
})?;
} else {
workspace.update(&mut cx, |workspace, cx| {
RecentProjects::open(workspace, true, cx);
})?;
}
Ok(())
})
};
if let Some(app_state) = AppState::global(cx).upgrade() {
let handle = if replace_current_window {
cx.window_handle().downcast::<Workspace>()
} else {
None
};
let server = store.read(cx).dev_server_for_project(dev_server_project.id);
if server.is_some_and(|server| server.ssh_connection_string.is_some()) {
let reconnect = reconnect_to_dev_server(cx.view().clone(), server.unwrap().clone(), cx);
let id = dev_server_project.id;
return cx.spawn(|workspace, mut cx| async move {
reconnect.await?;
if let Some(handle) = handle {
cx.spawn(move |workspace, mut cx| async move {
let continue_replacing = workspace
.update(&mut cx, |workspace, cx| {
workspace.
prepare_to_close(true, cx)
})?
.await?;
if continue_replacing {
workspace
.update(&mut cx, |_workspace, cx| {
workspace::join_dev_server_project(project_id, app_state, Some(handle), cx)
})?
.await?;
cx.background_executor().timer(Duration::from_millis(1000)).await;
if let Some(project_id) = store.update(&mut cx, |store, _| {
store.dev_server_project(id)
.and_then(|p| p.project_id)
})? {
workspace.update(&mut cx, move |_, cx| {
open_dev_server_project(replace_current_window, project_id, cx)
})?.await?;
}
Ok(())
})
}
else {
let task =
workspace::join_dev_server_project(project_id, app_state, None, cx);
cx.spawn(|_, _| async move {
task.await?;
Ok(())
})
} else {
let dev_server_name = dev_server_project.dev_server_name.clone();
return cx.spawn(|workspace, mut cx| async move {
let response =
cx.prompt(gpui::PromptLevel::Warning,
"Dev Server is offline",
Some(format!("Cannot connect to {}. To debug open the remote project settings.", dev_server_name).as_str()),
&["Ok", "Open Settings"]
).await?;
if response == 1 {
workspace.update(&mut cx, |workspace, cx| {
let handle = cx.view().downgrade();
workspace.toggle_modal(cx, |cx| DevServerProjects::new(cx, handle))
})?;
} else {
workspace.update(&mut cx, |workspace, cx| {
RecentProjects::open(workspace, true, cx);
})?;
}
Ok(())
})
}
} else {
Task::ready(Err(anyhow::anyhow!("App state not found")))
}
}
};
open_dev_server_project(replace_current_window, project_id, cx)
}
}
}
})
.detach_and_log_err(cx);
.detach_and_log_err(cx);
cx.emit(DismissEvent);
}
}
@ -563,6 +552,51 @@ impl PickerDelegate for RecentProjectsDelegate {
}
}
fn open_dev_server_project(
replace_current_window: bool,
project_id: ProjectId,
cx: &mut ViewContext<Workspace>,
) -> Task<anyhow::Result<()>> {
if let Some(app_state) = AppState::global(cx).upgrade() {
let handle = if replace_current_window {
cx.window_handle().downcast::<Workspace>()
} else {
None
};
if let Some(handle) = handle {
cx.spawn(move |workspace, mut cx| async move {
let continue_replacing = workspace
.update(&mut cx, |workspace, cx| {
workspace.prepare_to_close(true, cx)
})?
.await?;
if continue_replacing {
workspace
.update(&mut cx, |_workspace, cx| {
workspace::join_dev_server_project(
project_id,
app_state,
Some(handle),
cx,
)
})?
.await?;
}
Ok(())
})
} else {
let task = workspace::join_dev_server_project(project_id, app_state, None, cx);
cx.spawn(|_, _| async move {
task.await?;
Ok(())
})
}
} else {
Task::ready(Err(anyhow::anyhow!("App state not found")))
}
}
// Compute the highlighted text for the name and path
fn highlights_for_path(
path: &Path,