mirror of
https://github.com/zed-industries/zed.git
synced 2025-01-04 07:29:32 +00:00
ssh: Expose server address in the title bar (#19549)
This PR exposes the server address (or the nickname, if there is one) on the title bar and in all modals that have the SSH header. The title bar tooltip meta description still shows the original server address (regardless of a nickname existing in this case), though. <img width="600" alt="Screenshot 2024-10-22 at 10 58 36" src="https://github.com/user-attachments/assets/64a94d9f-798b-44a4-9dee-6056886535bb"> Release Notes: - N/A --------- Co-authored-by: Piotr Osiewicz <24362066+osiewicz@users.noreply.github.com>
This commit is contained in:
parent
d8d8c908ed
commit
3ba2af289b
8 changed files with 119 additions and 15 deletions
|
@ -3,6 +3,7 @@ use std::path::PathBuf;
|
||||||
use dev_server_projects::DevServer;
|
use dev_server_projects::DevServer;
|
||||||
use gpui::{ClickEvent, DismissEvent, EventEmitter, FocusHandle, FocusableView, Render, WeakView};
|
use gpui::{ClickEvent, DismissEvent, EventEmitter, FocusHandle, FocusableView, Render, WeakView};
|
||||||
use remote::SshConnectionOptions;
|
use remote::SshConnectionOptions;
|
||||||
|
use settings::Settings;
|
||||||
use ui::{
|
use ui::{
|
||||||
div, h_flex, rems, Button, ButtonCommon, ButtonStyle, Clickable, ElevationIndex, FluentBuilder,
|
div, h_flex, rems, Button, ButtonCommon, ButtonStyle, Clickable, ElevationIndex, FluentBuilder,
|
||||||
Headline, HeadlineSize, IconName, IconPosition, InteractiveElement, IntoElement, Label, Modal,
|
Headline, HeadlineSize, IconName, IconPosition, InteractiveElement, IntoElement, Label, Modal,
|
||||||
|
@ -12,7 +13,7 @@ use workspace::{notifications::DetachAndPromptErr, ModalView, OpenOptions, Works
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
open_dev_server_project, open_ssh_project, remote_servers::reconnect_to_dev_server_project,
|
open_dev_server_project, open_ssh_project, remote_servers::reconnect_to_dev_server_project,
|
||||||
RemoteServerProjects,
|
RemoteServerProjects, SshSettings,
|
||||||
};
|
};
|
||||||
|
|
||||||
enum Host {
|
enum Host {
|
||||||
|
@ -157,6 +158,16 @@ impl DisconnectedOverlay {
|
||||||
let paths = ssh_project.paths.iter().map(PathBuf::from).collect();
|
let paths = ssh_project.paths.iter().map(PathBuf::from).collect();
|
||||||
|
|
||||||
cx.spawn(move |_, mut cx| async move {
|
cx.spawn(move |_, mut cx| async move {
|
||||||
|
let nickname = cx
|
||||||
|
.update(|cx| {
|
||||||
|
SshSettings::get_global(cx).nickname_for(
|
||||||
|
&connection_options.host,
|
||||||
|
connection_options.port,
|
||||||
|
&connection_options.username,
|
||||||
|
)
|
||||||
|
})
|
||||||
|
.ok()
|
||||||
|
.flatten();
|
||||||
open_ssh_project(
|
open_ssh_project(
|
||||||
connection_options,
|
connection_options,
|
||||||
paths,
|
paths,
|
||||||
|
@ -165,6 +176,7 @@ impl DisconnectedOverlay {
|
||||||
replace_window: Some(window),
|
replace_window: Some(window),
|
||||||
..Default::default()
|
..Default::default()
|
||||||
},
|
},
|
||||||
|
nickname,
|
||||||
&mut cx,
|
&mut cx,
|
||||||
)
|
)
|
||||||
.await?;
|
.await?;
|
||||||
|
|
|
@ -388,6 +388,7 @@ impl PickerDelegate for RecentProjectsDelegate {
|
||||||
};
|
};
|
||||||
|
|
||||||
let args = SshSettings::get_global(cx).args_for(&ssh_project.host, ssh_project.port, &ssh_project.user);
|
let args = SshSettings::get_global(cx).args_for(&ssh_project.host, ssh_project.port, &ssh_project.user);
|
||||||
|
let nickname = SshSettings::get_global(cx).nickname_for(&ssh_project.host, ssh_project.port, &ssh_project.user);
|
||||||
let connection_options = SshConnectionOptions {
|
let connection_options = SshConnectionOptions {
|
||||||
host: ssh_project.host.clone(),
|
host: ssh_project.host.clone(),
|
||||||
username: ssh_project.user.clone(),
|
username: ssh_project.user.clone(),
|
||||||
|
@ -399,7 +400,7 @@ impl PickerDelegate for RecentProjectsDelegate {
|
||||||
let paths = ssh_project.paths.iter().map(PathBuf::from).collect();
|
let paths = ssh_project.paths.iter().map(PathBuf::from).collect();
|
||||||
|
|
||||||
cx.spawn(|_, mut cx| async move {
|
cx.spawn(|_, mut cx| async move {
|
||||||
open_ssh_project(connection_options, paths, app_state, open_options, &mut cx).await
|
open_ssh_project(connection_options, paths, app_state, open_options, nickname, &mut cx).await
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -87,6 +87,7 @@ impl CreateRemoteServer {
|
||||||
|
|
||||||
struct ProjectPicker {
|
struct ProjectPicker {
|
||||||
connection_string: SharedString,
|
connection_string: SharedString,
|
||||||
|
nickname: Option<SharedString>,
|
||||||
picker: View<Picker<OpenPathDelegate>>,
|
picker: View<Picker<OpenPathDelegate>>,
|
||||||
_path_task: Shared<Task<Option<()>>>,
|
_path_task: Shared<Task<Option<()>>>,
|
||||||
}
|
}
|
||||||
|
@ -191,7 +192,7 @@ impl FocusableView for ProjectPicker {
|
||||||
impl ProjectPicker {
|
impl ProjectPicker {
|
||||||
fn new(
|
fn new(
|
||||||
ix: usize,
|
ix: usize,
|
||||||
connection_string: SharedString,
|
connection: SshConnectionOptions,
|
||||||
project: Model<Project>,
|
project: Model<Project>,
|
||||||
workspace: WeakView<Workspace>,
|
workspace: WeakView<Workspace>,
|
||||||
cx: &mut ViewContext<RemoteServerProjects>,
|
cx: &mut ViewContext<RemoteServerProjects>,
|
||||||
|
@ -208,6 +209,12 @@ impl ProjectPicker {
|
||||||
picker.set_query(query, cx);
|
picker.set_query(query, cx);
|
||||||
picker
|
picker
|
||||||
});
|
});
|
||||||
|
let connection_string = connection.connection_string().into();
|
||||||
|
let nickname = SshSettings::get_global(cx).nickname_for(
|
||||||
|
&connection.host,
|
||||||
|
connection.port,
|
||||||
|
&connection.username,
|
||||||
|
);
|
||||||
cx.new_view(|cx| {
|
cx.new_view(|cx| {
|
||||||
let _path_task = cx
|
let _path_task = cx
|
||||||
.spawn({
|
.spawn({
|
||||||
|
@ -293,6 +300,7 @@ impl ProjectPicker {
|
||||||
_path_task,
|
_path_task,
|
||||||
picker,
|
picker,
|
||||||
connection_string,
|
connection_string,
|
||||||
|
nickname,
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -304,7 +312,7 @@ impl gpui::Render for ProjectPicker {
|
||||||
.child(
|
.child(
|
||||||
SshConnectionHeader {
|
SshConnectionHeader {
|
||||||
connection_string: self.connection_string.clone(),
|
connection_string: self.connection_string.clone(),
|
||||||
nickname: None,
|
nickname: self.nickname.clone(),
|
||||||
}
|
}
|
||||||
.render(cx),
|
.render(cx),
|
||||||
)
|
)
|
||||||
|
@ -380,7 +388,7 @@ impl RemoteServerProjects {
|
||||||
let mut this = Self::new(cx, workspace.clone());
|
let mut this = Self::new(cx, workspace.clone());
|
||||||
this.mode = Mode::ProjectPicker(ProjectPicker::new(
|
this.mode = Mode::ProjectPicker(ProjectPicker::new(
|
||||||
ix,
|
ix,
|
||||||
connection_options.connection_string().into(),
|
connection_options,
|
||||||
project,
|
project,
|
||||||
workspace,
|
workspace,
|
||||||
cx,
|
cx,
|
||||||
|
@ -408,7 +416,7 @@ impl RemoteServerProjects {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
let ssh_prompt = cx.new_view(|cx| SshPrompt::new(&connection_options, cx));
|
let ssh_prompt = cx.new_view(|cx| SshPrompt::new(&connection_options, None, cx));
|
||||||
|
|
||||||
let connection = connect_over_ssh(
|
let connection = connect_over_ssh(
|
||||||
connection_options.remote_server_identifier(),
|
connection_options.remote_server_identifier(),
|
||||||
|
@ -485,10 +493,13 @@ impl RemoteServerProjects {
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
let nickname = ssh_connection.nickname.clone();
|
||||||
let connection_options = ssh_connection.into();
|
let connection_options = ssh_connection.into();
|
||||||
workspace.update(cx, |_, cx| {
|
workspace.update(cx, |_, cx| {
|
||||||
cx.defer(move |workspace, cx| {
|
cx.defer(move |workspace, cx| {
|
||||||
workspace.toggle_modal(cx, |cx| SshConnectionModal::new(&connection_options, cx));
|
workspace.toggle_modal(cx, |cx| {
|
||||||
|
SshConnectionModal::new(&connection_options, nickname, cx)
|
||||||
|
});
|
||||||
let prompt = workspace
|
let prompt = workspace
|
||||||
.active_modal::<SshConnectionModal>(cx)
|
.active_modal::<SshConnectionModal>(cx)
|
||||||
.unwrap()
|
.unwrap()
|
||||||
|
@ -737,11 +748,13 @@ impl RemoteServerProjects {
|
||||||
let project = project.clone();
|
let project = project.clone();
|
||||||
let server = server.clone();
|
let server = server.clone();
|
||||||
cx.spawn(|_, mut cx| async move {
|
cx.spawn(|_, mut cx| async move {
|
||||||
|
let nickname = server.nickname.clone();
|
||||||
let result = open_ssh_project(
|
let result = open_ssh_project(
|
||||||
server.into(),
|
server.into(),
|
||||||
project.paths.into_iter().map(PathBuf::from).collect(),
|
project.paths.into_iter().map(PathBuf::from).collect(),
|
||||||
app_state,
|
app_state,
|
||||||
OpenOptions::default(),
|
OpenOptions::default(),
|
||||||
|
nickname,
|
||||||
&mut cx,
|
&mut cx,
|
||||||
)
|
)
|
||||||
.await;
|
.await;
|
||||||
|
|
|
@ -52,6 +52,23 @@ impl SshSettings {
|
||||||
})
|
})
|
||||||
.next()
|
.next()
|
||||||
}
|
}
|
||||||
|
pub fn nickname_for(
|
||||||
|
&self,
|
||||||
|
host: &str,
|
||||||
|
port: Option<u16>,
|
||||||
|
user: &Option<String>,
|
||||||
|
) -> Option<SharedString> {
|
||||||
|
self.ssh_connections()
|
||||||
|
.filter_map(|conn| {
|
||||||
|
if conn.host == host && &conn.username == user && conn.port == port {
|
||||||
|
Some(conn.nickname)
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.next()
|
||||||
|
.flatten()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Default, Serialize, Deserialize, JsonSchema)]
|
#[derive(Clone, Default, Serialize, Deserialize, JsonSchema)]
|
||||||
|
@ -103,6 +120,7 @@ impl Settings for SshSettings {
|
||||||
|
|
||||||
pub struct SshPrompt {
|
pub struct SshPrompt {
|
||||||
connection_string: SharedString,
|
connection_string: SharedString,
|
||||||
|
nickname: Option<SharedString>,
|
||||||
status_message: Option<SharedString>,
|
status_message: Option<SharedString>,
|
||||||
prompt: Option<(View<Markdown>, oneshot::Sender<Result<String>>)>,
|
prompt: Option<(View<Markdown>, oneshot::Sender<Result<String>>)>,
|
||||||
editor: View<Editor>,
|
editor: View<Editor>,
|
||||||
|
@ -116,11 +134,13 @@ pub struct SshConnectionModal {
|
||||||
impl SshPrompt {
|
impl SshPrompt {
|
||||||
pub(crate) fn new(
|
pub(crate) fn new(
|
||||||
connection_options: &SshConnectionOptions,
|
connection_options: &SshConnectionOptions,
|
||||||
|
nickname: Option<SharedString>,
|
||||||
cx: &mut ViewContext<Self>,
|
cx: &mut ViewContext<Self>,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
let connection_string = connection_options.connection_string().into();
|
let connection_string = connection_options.connection_string().into();
|
||||||
Self {
|
Self {
|
||||||
connection_string,
|
connection_string,
|
||||||
|
nickname,
|
||||||
status_message: None,
|
status_message: None,
|
||||||
prompt: None,
|
prompt: None,
|
||||||
editor: cx.new_view(Editor::single_line),
|
editor: cx.new_view(Editor::single_line),
|
||||||
|
@ -228,9 +248,13 @@ impl Render for SshPrompt {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl SshConnectionModal {
|
impl SshConnectionModal {
|
||||||
pub fn new(connection_options: &SshConnectionOptions, cx: &mut ViewContext<Self>) -> Self {
|
pub(crate) fn new(
|
||||||
|
connection_options: &SshConnectionOptions,
|
||||||
|
nickname: Option<SharedString>,
|
||||||
|
cx: &mut ViewContext<Self>,
|
||||||
|
) -> Self {
|
||||||
Self {
|
Self {
|
||||||
prompt: cx.new_view(|cx| SshPrompt::new(connection_options, cx)),
|
prompt: cx.new_view(|cx| SshPrompt::new(connection_options, nickname, cx)),
|
||||||
finished: false,
|
finished: false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -297,6 +321,7 @@ impl RenderOnce for SshConnectionHeader {
|
||||||
|
|
||||||
impl Render for SshConnectionModal {
|
impl Render for SshConnectionModal {
|
||||||
fn render(&mut self, cx: &mut ui::ViewContext<Self>) -> impl ui::IntoElement {
|
fn render(&mut self, cx: &mut ui::ViewContext<Self>) -> impl ui::IntoElement {
|
||||||
|
let nickname = self.prompt.read(cx).nickname.clone();
|
||||||
let connection_string = self.prompt.read(cx).connection_string.clone();
|
let connection_string = self.prompt.read(cx).connection_string.clone();
|
||||||
let theme = cx.theme();
|
let theme = cx.theme();
|
||||||
|
|
||||||
|
@ -313,7 +338,7 @@ impl Render for SshConnectionModal {
|
||||||
.child(
|
.child(
|
||||||
SshConnectionHeader {
|
SshConnectionHeader {
|
||||||
connection_string,
|
connection_string,
|
||||||
nickname: None,
|
nickname,
|
||||||
}
|
}
|
||||||
.render(cx),
|
.render(cx),
|
||||||
)
|
)
|
||||||
|
@ -589,6 +614,7 @@ pub async fn open_ssh_project(
|
||||||
paths: Vec<PathBuf>,
|
paths: Vec<PathBuf>,
|
||||||
app_state: Arc<AppState>,
|
app_state: Arc<AppState>,
|
||||||
open_options: workspace::OpenOptions,
|
open_options: workspace::OpenOptions,
|
||||||
|
nickname: Option<SharedString>,
|
||||||
cx: &mut AsyncAppContext,
|
cx: &mut AsyncAppContext,
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
let window = if let Some(window) = open_options.replace_window {
|
let window = if let Some(window) = open_options.replace_window {
|
||||||
|
@ -612,9 +638,12 @@ pub async fn open_ssh_project(
|
||||||
loop {
|
loop {
|
||||||
let delegate = window.update(cx, {
|
let delegate = window.update(cx, {
|
||||||
let connection_options = connection_options.clone();
|
let connection_options = connection_options.clone();
|
||||||
|
let nickname = nickname.clone();
|
||||||
move |workspace, cx| {
|
move |workspace, cx| {
|
||||||
cx.activate_window();
|
cx.activate_window();
|
||||||
workspace.toggle_modal(cx, |cx| SshConnectionModal::new(&connection_options, cx));
|
workspace.toggle_modal(cx, |cx| {
|
||||||
|
SshConnectionModal::new(&connection_options, nickname.clone(), cx)
|
||||||
|
});
|
||||||
let ui = workspace
|
let ui = workspace
|
||||||
.active_modal::<SshConnectionModal>(cx)
|
.active_modal::<SshConnectionModal>(cx)
|
||||||
.unwrap()
|
.unwrap()
|
||||||
|
|
|
@ -44,6 +44,7 @@ recent_projects.workspace = true
|
||||||
remote.workspace = true
|
remote.workspace = true
|
||||||
rpc.workspace = true
|
rpc.workspace = true
|
||||||
serde.workspace = true
|
serde.workspace = true
|
||||||
|
settings.workspace = true
|
||||||
smallvec.workspace = true
|
smallvec.workspace = true
|
||||||
story = { workspace = true, optional = true }
|
story = { workspace = true, optional = true }
|
||||||
theme.workspace = true
|
theme.workspace = true
|
||||||
|
|
|
@ -18,8 +18,10 @@ 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::{OpenRemote, RecentProjects};
|
use recent_projects::{OpenRemote, RecentProjects, SshSettings};
|
||||||
|
use remote::SshConnectionOptions;
|
||||||
use rpc::proto::{self, DevServerStatus};
|
use rpc::proto::{self, DevServerStatus};
|
||||||
|
use settings::Settings;
|
||||||
use smallvec::SmallVec;
|
use smallvec::SmallVec;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use theme::ActiveTheme;
|
use theme::ActiveTheme;
|
||||||
|
@ -27,7 +29,7 @@ use ui::{
|
||||||
h_flex, prelude::*, Avatar, Button, ButtonLike, ButtonStyle, ContextMenu, Icon, IconName,
|
h_flex, prelude::*, Avatar, Button, ButtonLike, ButtonStyle, ContextMenu, Icon, IconName,
|
||||||
IconSize, IconWithIndicator, Indicator, PopoverMenu, Tooltip,
|
IconSize, IconWithIndicator, Indicator, PopoverMenu, Tooltip,
|
||||||
};
|
};
|
||||||
use util::ResultExt;
|
use util::{maybe, ResultExt};
|
||||||
use vcs_menu::{BranchList, OpenRecent as ToggleVcsMenu};
|
use vcs_menu::{BranchList, OpenRecent as ToggleVcsMenu};
|
||||||
use workspace::{notifications::NotifyResultExt, Workspace};
|
use workspace::{notifications::NotifyResultExt, Workspace};
|
||||||
|
|
||||||
|
@ -263,7 +265,18 @@ impl TitleBar {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn render_ssh_project_host(&self, cx: &mut ViewContext<Self>) -> Option<AnyElement> {
|
fn render_ssh_project_host(&self, cx: &mut ViewContext<Self>) -> Option<AnyElement> {
|
||||||
let host = self.project.read(cx).ssh_connection_string(cx)?;
|
let options = self.project.read(cx).ssh_connection_options(cx)?;
|
||||||
|
let host: SharedString = options.connection_string().into();
|
||||||
|
|
||||||
|
let nickname = maybe!({
|
||||||
|
SshSettings::get_global(cx)
|
||||||
|
.ssh_connections
|
||||||
|
.as_ref()?
|
||||||
|
.into_iter()
|
||||||
|
.find(|connection| SshConnectionOptions::from((*connection).clone()) == options)
|
||||||
|
.and_then(|connection| connection.nickname.clone())
|
||||||
|
})
|
||||||
|
.unwrap_or_else(|| host.clone());
|
||||||
|
|
||||||
let (indicator_color, meta) = match self.project.read(cx).ssh_connection_state(cx)? {
|
let (indicator_color, meta) = match self.project.read(cx).ssh_connection_state(cx)? {
|
||||||
remote::ConnectionState::Connecting => (Color::Info, format!("Connecting to: {host}")),
|
remote::ConnectionState::Connecting => (Color::Info, format!("Connecting to: {host}")),
|
||||||
|
@ -295,12 +308,22 @@ impl TitleBar {
|
||||||
ButtonLike::new("ssh-server-icon")
|
ButtonLike::new("ssh-server-icon")
|
||||||
.child(
|
.child(
|
||||||
IconWithIndicator::new(
|
IconWithIndicator::new(
|
||||||
Icon::new(IconName::Server).color(icon_color),
|
Icon::new(IconName::Server)
|
||||||
|
.size(IconSize::XSmall)
|
||||||
|
.color(icon_color),
|
||||||
Some(Indicator::dot().color(indicator_color)),
|
Some(Indicator::dot().color(indicator_color)),
|
||||||
)
|
)
|
||||||
.indicator_border_color(Some(cx.theme().colors().title_bar_background))
|
.indicator_border_color(Some(cx.theme().colors().title_bar_background))
|
||||||
.into_any_element(),
|
.into_any_element(),
|
||||||
)
|
)
|
||||||
|
.child(
|
||||||
|
div()
|
||||||
|
.max_w_32()
|
||||||
|
.overflow_hidden()
|
||||||
|
.truncate()
|
||||||
|
.text_ellipsis()
|
||||||
|
.child(Label::new(nickname.clone()).size(LabelSize::Small)),
|
||||||
|
)
|
||||||
.tooltip(move |cx| {
|
.tooltip(move |cx| {
|
||||||
Tooltip::with_meta("Remote Project", Some(&OpenRemote), meta.clone(), cx)
|
Tooltip::with_meta("Remote Project", Some(&OpenRemote), meta.clone(), cx)
|
||||||
})
|
})
|
||||||
|
|
|
@ -713,6 +713,16 @@ fn handle_open_request(
|
||||||
|
|
||||||
if let Some(connection_info) = request.ssh_connection {
|
if let Some(connection_info) = request.ssh_connection {
|
||||||
cx.spawn(|mut cx| async move {
|
cx.spawn(|mut cx| async move {
|
||||||
|
let nickname = cx
|
||||||
|
.update(|cx| {
|
||||||
|
SshSettings::get_global(cx).nickname_for(
|
||||||
|
&connection_info.host,
|
||||||
|
connection_info.port,
|
||||||
|
&connection_info.username,
|
||||||
|
)
|
||||||
|
})
|
||||||
|
.ok()
|
||||||
|
.flatten();
|
||||||
let paths_with_position =
|
let paths_with_position =
|
||||||
derive_paths_with_position(app_state.fs.as_ref(), request.open_paths).await;
|
derive_paths_with_position(app_state.fs.as_ref(), request.open_paths).await;
|
||||||
open_ssh_project(
|
open_ssh_project(
|
||||||
|
@ -720,6 +730,7 @@ fn handle_open_request(
|
||||||
paths_with_position.into_iter().map(|p| p.path).collect(),
|
paths_with_position.into_iter().map(|p| p.path).collect(),
|
||||||
app_state,
|
app_state,
|
||||||
workspace::OpenOptions::default(),
|
workspace::OpenOptions::default(),
|
||||||
|
nickname,
|
||||||
&mut cx,
|
&mut cx,
|
||||||
)
|
)
|
||||||
.await
|
.await
|
||||||
|
@ -888,6 +899,12 @@ async fn restore_or_create_workspace(
|
||||||
})
|
})
|
||||||
.ok()
|
.ok()
|
||||||
.flatten();
|
.flatten();
|
||||||
|
let nickname = cx
|
||||||
|
.update(|cx| {
|
||||||
|
SshSettings::get_global(cx).nickname_for(&ssh.host, ssh.port, &ssh.user)
|
||||||
|
})
|
||||||
|
.ok()
|
||||||
|
.flatten();
|
||||||
let connection_options = SshConnectionOptions {
|
let connection_options = SshConnectionOptions {
|
||||||
args,
|
args,
|
||||||
host: ssh.host.clone(),
|
host: ssh.host.clone(),
|
||||||
|
@ -902,6 +919,7 @@ async fn restore_or_create_workspace(
|
||||||
ssh.paths.into_iter().map(PathBuf::from).collect(),
|
ssh.paths.into_iter().map(PathBuf::from).collect(),
|
||||||
app_state,
|
app_state,
|
||||||
workspace::OpenOptions::default(),
|
workspace::OpenOptions::default(),
|
||||||
|
nickname,
|
||||||
&mut cx,
|
&mut cx,
|
||||||
)
|
)
|
||||||
.await
|
.await
|
||||||
|
|
|
@ -437,12 +437,19 @@ async fn open_workspaces(
|
||||||
port: ssh.port,
|
port: ssh.port,
|
||||||
password: None,
|
password: None,
|
||||||
};
|
};
|
||||||
|
let nickname = cx
|
||||||
|
.update(|cx| {
|
||||||
|
SshSettings::get_global(cx).nickname_for(&ssh.host, ssh.port, &ssh.user)
|
||||||
|
})
|
||||||
|
.ok()
|
||||||
|
.flatten();
|
||||||
cx.spawn(|mut cx| async move {
|
cx.spawn(|mut cx| async move {
|
||||||
open_ssh_project(
|
open_ssh_project(
|
||||||
connection_options,
|
connection_options,
|
||||||
ssh.paths.into_iter().map(PathBuf::from).collect(),
|
ssh.paths.into_iter().map(PathBuf::from).collect(),
|
||||||
app_state,
|
app_state,
|
||||||
OpenOptions::default(),
|
OpenOptions::default(),
|
||||||
|
nickname,
|
||||||
&mut cx,
|
&mut cx,
|
||||||
)
|
)
|
||||||
.await
|
.await
|
||||||
|
|
Loading…
Reference in a new issue