Add WSL opening UI (#38260)

This PR adds an option to open WSL machines from the UI.

- [x] Open wsl from open remote
- [ ] Open local folder in wsl action
- [ ] Open wsl shortcut (shortcuts to open remote)

Release Notes:

- N/A
This commit is contained in:
localcc
2025-09-17 09:44:16 +00:00
committed by GitHub
parent c5ac1e6218
commit 83d9f07547
4 changed files with 1219 additions and 430 deletions
@@ -17,7 +17,7 @@ use markdown::{Markdown, MarkdownElement, MarkdownStyle};
use release_channel::ReleaseChannel;
use remote::{
ConnectionIdentifier, RemoteClient, RemoteConnectionOptions, RemotePlatform,
SshConnectionOptions, SshPortForwardOption,
SshConnectionOptions, SshPortForwardOption, WslConnectionOptions,
};
use schemars::JsonSchema;
use serde::{Deserialize, Serialize};
@@ -33,6 +33,7 @@ use workspace::{AppState, ModalView, Workspace};
#[derive(Deserialize)]
pub struct SshSettings {
pub ssh_connections: Option<Vec<SshConnection>>,
pub wsl_connections: Option<Vec<WslConnection>>,
/// Whether to read ~/.ssh/config for ssh connection sources.
#[serde(default = "default_true")]
pub read_ssh_config: bool,
@@ -43,6 +44,10 @@ impl SshSettings {
self.ssh_connections.clone().into_iter().flatten()
}
pub fn wsl_connections(&self) -> impl Iterator<Item = WslConnection> + use<> {
self.wsl_connections.clone().into_iter().flatten()
}
pub fn fill_connection_options_from_settings(&self, options: &mut SshConnectionOptions) {
for conn in self.ssh_connections() {
if conn.host == options.host
@@ -116,6 +121,51 @@ impl From<SshConnection> for SshConnectionOptions {
}
}
#[derive(Clone, Default, Serialize, Deserialize, PartialEq, JsonSchema)]
pub struct WslConnection {
pub distro_name: SharedString,
#[serde(default)]
pub user: Option<String>,
#[serde(default)]
pub projects: BTreeSet<SshProject>,
}
impl From<WslConnection> for WslConnectionOptions {
fn from(val: WslConnection) -> Self {
WslConnectionOptions {
distro_name: val.distro_name.into(),
user: val.user,
}
}
}
#[derive(Clone, Serialize, Deserialize, PartialEq, JsonSchema)]
pub enum Connection {
Ssh(SshConnection),
Wsl(WslConnection),
}
impl From<Connection> for RemoteConnectionOptions {
fn from(val: Connection) -> Self {
match val {
Connection::Ssh(conn) => RemoteConnectionOptions::Ssh(conn.into()),
Connection::Wsl(conn) => RemoteConnectionOptions::Wsl(conn.into()),
}
}
}
impl From<SshConnection> for Connection {
fn from(val: SshConnection) -> Self {
Connection::Ssh(val)
}
}
impl From<WslConnection> for Connection {
fn from(val: WslConnection) -> Self {
Connection::Wsl(val)
}
}
#[derive(Clone, Default, Serialize, PartialEq, Eq, PartialOrd, Ord, Deserialize, JsonSchema)]
pub struct SshProject {
pub paths: Vec<String>,
@@ -125,6 +175,7 @@ pub struct SshProject {
#[settings_key(None)]
pub struct RemoteSettingsContent {
pub ssh_connections: Option<Vec<SshConnection>>,
pub wsl_connections: Option<Vec<WslConnection>>,
pub read_ssh_config: Option<bool>,
}
@@ -561,6 +612,36 @@ pub fn connect_over_ssh(
)
}
pub fn connect(
unique_identifier: ConnectionIdentifier,
connection_options: RemoteConnectionOptions,
ui: Entity<RemoteConnectionPrompt>,
window: &mut Window,
cx: &mut App,
) -> Task<Result<Option<Entity<RemoteClient>>>> {
let window = window.window_handle();
let known_password = match &connection_options {
RemoteConnectionOptions::Ssh(ssh_connection_options) => {
ssh_connection_options.password.clone()
}
_ => None,
};
let (tx, rx) = oneshot::channel();
ui.update(cx, |ui, _cx| ui.set_cancellation_tx(tx));
remote::RemoteClient::new(
unique_identifier,
connection_options,
rx,
Arc::new(RemoteClientDelegate {
window,
ui: ui.downgrade(),
known_password,
}),
cx,
)
}
pub async fn open_remote_project(
connection_options: RemoteConnectionOptions,
paths: Vec<PathBuf>,
File diff suppressed because it is too large Load Diff