ssh: Add session state indicator to title bar (#18645)
 The indicator turns yellow when ssh client is trying to reconnect. Note that the state tracking is probably not ideal (we'll see how it pans out once we start dog-fooding), but at the very least "green=good" should be a decent mental model for now. Release Notes: - N/A
This commit is contained in:
parent
e2d613a803
commit
19b186671b
4 changed files with 66 additions and 5 deletions
|
@ -1217,7 +1217,10 @@ impl Project {
|
||||||
server.ssh_connection_string.is_some()
|
server.ssh_connection_string.is_some()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn ssh_connection_string(&self, cx: &ModelContext<Self>) -> Option<SharedString> {
|
pub fn ssh_connection_string(&self, cx: &AppContext) -> Option<SharedString> {
|
||||||
|
if let Some(ssh_state) = &self.ssh_client {
|
||||||
|
return Some(ssh_state.connection_string().into());
|
||||||
|
}
|
||||||
let dev_server_id = self.dev_server_project_id()?;
|
let dev_server_id = self.dev_server_project_id()?;
|
||||||
dev_server_projects::Store::global(cx)
|
dev_server_projects::Store::global(cx)
|
||||||
.read(cx)
|
.read(cx)
|
||||||
|
@ -1226,6 +1229,10 @@ impl Project {
|
||||||
.clone()
|
.clone()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn ssh_is_connected(&self) -> Option<bool> {
|
||||||
|
Some(!self.ssh_client.as_ref()?.is_reconnect_underway())
|
||||||
|
}
|
||||||
|
|
||||||
pub fn replica_id(&self) -> ReplicaId {
|
pub fn replica_id(&self) -> ReplicaId {
|
||||||
match self.client_state {
|
match self.client_state {
|
||||||
ProjectClientState::Remote { replica_id, .. } => replica_id,
|
ProjectClientState::Remote { replica_id, .. } => replica_id,
|
||||||
|
|
|
@ -317,6 +317,7 @@ impl SshClientDelegate {
|
||||||
if release_channel == ReleaseChannel::Dev
|
if release_channel == ReleaseChannel::Dev
|
||||||
&& platform.arch == std::env::consts::ARCH
|
&& platform.arch == std::env::consts::ARCH
|
||||||
&& platform.os == std::env::consts::OS
|
&& platform.os == std::env::consts::OS
|
||||||
|
&& false
|
||||||
{
|
{
|
||||||
use smol::process::{Command, Stdio};
|
use smol::process::{Command, Stdio};
|
||||||
|
|
||||||
|
|
|
@ -36,6 +36,7 @@ use std::{
|
||||||
time::Instant,
|
time::Instant,
|
||||||
};
|
};
|
||||||
use tempfile::TempDir;
|
use tempfile::TempDir;
|
||||||
|
use util::maybe;
|
||||||
|
|
||||||
#[derive(
|
#[derive(
|
||||||
Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Clone, Copy, serde::Serialize, serde::Deserialize,
|
Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Clone, Copy, serde::Serialize, serde::Deserialize,
|
||||||
|
@ -48,7 +49,7 @@ pub struct SshSocket {
|
||||||
socket_path: PathBuf,
|
socket_path: PathBuf,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
#[derive(Debug, Default, Clone, PartialEq, Eq)]
|
||||||
pub struct SshConnectionOptions {
|
pub struct SshConnectionOptions {
|
||||||
pub host: String,
|
pub host: String,
|
||||||
pub username: Option<String>,
|
pub username: Option<String>,
|
||||||
|
@ -250,6 +251,7 @@ struct SshRemoteClientState {
|
||||||
pub struct SshRemoteClient {
|
pub struct SshRemoteClient {
|
||||||
client: Arc<ChannelClient>,
|
client: Arc<ChannelClient>,
|
||||||
inner_state: Mutex<Option<SshRemoteClientState>>,
|
inner_state: Mutex<Option<SshRemoteClientState>>,
|
||||||
|
connection_options: SshConnectionOptions,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl SshRemoteClient {
|
impl SshRemoteClient {
|
||||||
|
@ -265,6 +267,7 @@ impl SshRemoteClient {
|
||||||
let this = Arc::new(Self {
|
let this = Arc::new(Self {
|
||||||
client,
|
client,
|
||||||
inner_state: Mutex::new(None),
|
inner_state: Mutex::new(None),
|
||||||
|
connection_options: connection_options.clone(),
|
||||||
});
|
});
|
||||||
|
|
||||||
let inner_state = {
|
let inner_state = {
|
||||||
|
@ -272,8 +275,7 @@ impl SshRemoteClient {
|
||||||
ChannelForwarder::new(incoming_tx, outgoing_rx, cx);
|
ChannelForwarder::new(incoming_tx, outgoing_rx, cx);
|
||||||
|
|
||||||
let (ssh_connection, ssh_process) =
|
let (ssh_connection, ssh_process) =
|
||||||
Self::establish_connection(connection_options.clone(), delegate.clone(), cx)
|
Self::establish_connection(connection_options, delegate.clone(), cx).await?;
|
||||||
.await?;
|
|
||||||
|
|
||||||
let multiplex_task = Self::multiplex(
|
let multiplex_task = Self::multiplex(
|
||||||
Arc::downgrade(&this),
|
Arc::downgrade(&this),
|
||||||
|
@ -505,6 +507,13 @@ impl SshRemoteClient {
|
||||||
self.client.clone().into()
|
self.client.clone().into()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn connection_string(&self) -> String {
|
||||||
|
self.connection_options.connection_string()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn is_reconnect_underway(&self) -> bool {
|
||||||
|
maybe!({ Some(self.inner_state.try_lock()?.is_none()) }).unwrap_or_default()
|
||||||
|
}
|
||||||
#[cfg(any(test, feature = "test-support"))]
|
#[cfg(any(test, feature = "test-support"))]
|
||||||
pub fn fake(
|
pub fn fake(
|
||||||
client_cx: &mut gpui::TestAppContext,
|
client_cx: &mut gpui::TestAppContext,
|
||||||
|
@ -519,6 +528,7 @@ impl SshRemoteClient {
|
||||||
Arc::new(Self {
|
Arc::new(Self {
|
||||||
client,
|
client,
|
||||||
inner_state: Mutex::new(None),
|
inner_state: Mutex::new(None),
|
||||||
|
connection_options: SshConnectionOptions::default(),
|
||||||
})
|
})
|
||||||
}),
|
}),
|
||||||
server_cx.update(|cx| ChannelClient::new(client_to_server_rx, server_to_client_tx, cx)),
|
server_cx.update(|cx| ChannelClient::new(client_to_server_rx, server_to_client_tx, cx)),
|
||||||
|
|
|
@ -18,7 +18,7 @@ use gpui::{
|
||||||
StatefulInteractiveElement, Styled, Subscription, View, ViewContext, VisualContext, WeakView,
|
StatefulInteractiveElement, Styled, Subscription, View, ViewContext, VisualContext, WeakView,
|
||||||
};
|
};
|
||||||
use project::{Project, RepositoryEntry};
|
use project::{Project, RepositoryEntry};
|
||||||
use recent_projects::RecentProjects;
|
use recent_projects::{OpenRemote, RecentProjects};
|
||||||
use rpc::proto::{self, DevServerStatus};
|
use rpc::proto::{self, DevServerStatus};
|
||||||
use smallvec::SmallVec;
|
use smallvec::SmallVec;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
@ -262,6 +262,46 @@ impl TitleBar {
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn render_ssh_project_host(&self, cx: &mut ViewContext<Self>) -> Option<AnyElement> {
|
||||||
|
let host = self.project.read(cx).ssh_connection_string(cx)?;
|
||||||
|
let meta = SharedString::from(format!("Connected to: {host}"));
|
||||||
|
let indicator_color = if self.project.read(cx).ssh_is_connected()? {
|
||||||
|
Color::Success
|
||||||
|
} else {
|
||||||
|
Color::Warning
|
||||||
|
};
|
||||||
|
let indicator = div()
|
||||||
|
.absolute()
|
||||||
|
.w_1_4()
|
||||||
|
.h_1_4()
|
||||||
|
.right_0p5()
|
||||||
|
.bottom_0p5()
|
||||||
|
.p_1()
|
||||||
|
.rounded_2xl()
|
||||||
|
.bg(indicator_color.color(cx));
|
||||||
|
|
||||||
|
Some(
|
||||||
|
div()
|
||||||
|
.child(
|
||||||
|
IconButton::new("ssh-server-icon", IconName::Server)
|
||||||
|
.tooltip(move |cx| {
|
||||||
|
Tooltip::with_meta(
|
||||||
|
"Remote Project",
|
||||||
|
Some(&OpenRemote),
|
||||||
|
meta.clone(),
|
||||||
|
cx,
|
||||||
|
)
|
||||||
|
})
|
||||||
|
.shape(ui::IconButtonShape::Square)
|
||||||
|
.on_click(|_, cx| {
|
||||||
|
cx.dispatch_action(OpenRemote.boxed_clone());
|
||||||
|
}),
|
||||||
|
)
|
||||||
|
.child(indicator)
|
||||||
|
.into_any_element(),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
pub fn render_project_host(&self, cx: &mut ViewContext<Self>) -> Option<AnyElement> {
|
pub fn render_project_host(&self, cx: &mut ViewContext<Self>) -> Option<AnyElement> {
|
||||||
if let Some(dev_server) =
|
if let Some(dev_server) =
|
||||||
self.project
|
self.project
|
||||||
|
@ -296,6 +336,9 @@ impl TitleBar {
|
||||||
.into_any_element(),
|
.into_any_element(),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
if self.project.read(cx).is_via_ssh() {
|
||||||
|
return self.render_ssh_project_host(cx);
|
||||||
|
}
|
||||||
|
|
||||||
if self.project.read(cx).is_disconnected() {
|
if self.project.read(cx).is_disconnected() {
|
||||||
return Some(
|
return Some(
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue