Rename dev servers to remote projects in UI (#19527)

Release Notes:

- N/A

Co-authored-by: Mikayla <mikayla@zed.dev>
This commit is contained in:
Conrad Irwin 2024-10-21 16:50:25 -06:00 committed by GitHub
parent 9bae93cd39
commit 6e485453d0
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
6 changed files with 62 additions and 49 deletions

View file

@ -11,8 +11,8 @@ use ui::{
use workspace::{notifications::DetachAndPromptErr, ModalView, OpenOptions, Workspace}; use workspace::{notifications::DetachAndPromptErr, ModalView, OpenOptions, Workspace};
use crate::{ use crate::{
dev_servers::reconnect_to_dev_server_project, open_dev_server_project, open_ssh_project, open_dev_server_project, open_ssh_project, remote_servers::reconnect_to_dev_server_project,
DevServerProjects, RemoteServerProjects,
}; };
enum Host { enum Host {
@ -130,7 +130,7 @@ impl DisconnectedOverlay {
} else { } else {
return workspace.update(cx, |workspace, cx| { return workspace.update(cx, |workspace, cx| {
let handle = cx.view().downgrade(); let handle = cx.view().downgrade();
workspace.toggle_modal(cx, |cx| DevServerProjects::new(cx, handle)) workspace.toggle_modal(cx, |cx| RemoteServerProjects::new(cx, handle))
}); });
} }
} }

View file

@ -1,12 +1,10 @@
mod dev_servers;
pub mod disconnected_overlay; pub mod disconnected_overlay;
mod remote_servers;
mod ssh_connections; mod ssh_connections;
use remote::SshConnectionOptions; use remote::SshConnectionOptions;
pub use ssh_connections::open_ssh_project; pub use ssh_connections::open_ssh_project;
use client::{DevServerProjectId, ProjectId}; use client::{DevServerProjectId, ProjectId};
use dev_servers::reconnect_to_dev_server_project;
pub use dev_servers::DevServerProjects;
use disconnected_overlay::DisconnectedOverlay; use disconnected_overlay::DisconnectedOverlay;
use fuzzy::{StringMatch, StringMatchCandidate}; use fuzzy::{StringMatch, StringMatchCandidate};
use gpui::{ use gpui::{
@ -19,6 +17,8 @@ use picker::{
highlighted_match_with_paths::{HighlightedMatchWithPaths, HighlightedText}, highlighted_match_with_paths::{HighlightedMatchWithPaths, HighlightedText},
Picker, PickerDelegate, Picker, PickerDelegate,
}; };
use remote_servers::reconnect_to_dev_server_project;
pub use remote_servers::RemoteServerProjects;
use rpc::proto::DevServerStatus; use rpc::proto::DevServerStatus;
use serde::Deserialize; use serde::Deserialize;
use settings::Settings; use settings::Settings;
@ -53,7 +53,8 @@ gpui::actions!(projects, [OpenRemote]);
pub fn init(cx: &mut AppContext) { pub fn init(cx: &mut AppContext) {
SshSettings::register(cx); SshSettings::register(cx);
cx.observe_new_views(RecentProjects::register).detach(); cx.observe_new_views(RecentProjects::register).detach();
cx.observe_new_views(DevServerProjects::register).detach(); cx.observe_new_views(RemoteServerProjects::register)
.detach();
cx.observe_new_views(DisconnectedOverlay::register).detach(); cx.observe_new_views(DisconnectedOverlay::register).detach();
} }
@ -359,7 +360,7 @@ impl PickerDelegate for RecentProjectsDelegate {
if response == 1 { if response == 1 {
workspace.update(&mut cx, |workspace, cx| { workspace.update(&mut cx, |workspace, cx| {
let handle = cx.view().downgrade(); let handle = cx.view().downgrade();
workspace.toggle_modal(cx, |cx| DevServerProjects::new(cx, handle)) workspace.toggle_modal(cx, |cx| RemoteServerProjects::new(cx, handle))
})?; })?;
} else { } else {
workspace.update(&mut cx, |workspace, cx| { workspace.update(&mut cx, |workspace, cx| {

View file

@ -55,7 +55,7 @@ use crate::ssh_connections::SshPrompt;
use crate::ssh_connections::SshSettings; use crate::ssh_connections::SshSettings;
use crate::OpenRemote; use crate::OpenRemote;
pub struct DevServerProjects { pub struct RemoteServerProjects {
mode: Mode, mode: Mode,
focus_handle: FocusHandle, focus_handle: FocusHandle,
scroll_handle: ScrollHandle, scroll_handle: ScrollHandle,
@ -63,14 +63,14 @@ pub struct DevServerProjects {
selectable_items: SelectableItemList, selectable_items: SelectableItemList,
} }
struct CreateDevServer { struct CreateRemoteServer {
address_editor: View<Editor>, address_editor: View<Editor>,
address_error: Option<SharedString>, address_error: Option<SharedString>,
ssh_prompt: Option<View<SshPrompt>>, ssh_prompt: Option<View<SshPrompt>>,
_creating: Option<Task<Option<()>>>, _creating: Option<Task<Option<()>>>,
} }
impl CreateDevServer { impl CreateRemoteServer {
fn new(cx: &mut WindowContext<'_>) -> Self { fn new(cx: &mut WindowContext<'_>) -> Self {
let address_editor = cx.new_view(Editor::single_line); let address_editor = cx.new_view(Editor::single_line);
address_editor.update(cx, |this, cx| { address_editor.update(cx, |this, cx| {
@ -92,7 +92,7 @@ struct ProjectPicker {
} }
type SelectedItemCallback = type SelectedItemCallback =
Box<dyn Fn(&mut DevServerProjects, &mut ViewContext<DevServerProjects>) + 'static>; Box<dyn Fn(&mut RemoteServerProjects, &mut ViewContext<RemoteServerProjects>) + 'static>;
/// Used to implement keyboard navigation for SSH modal. /// Used to implement keyboard navigation for SSH modal.
#[derive(Default)] #[derive(Default)]
@ -171,9 +171,13 @@ impl SelectableItemList {
self.active_item == self.items.len().checked_sub(1) self.active_item == self.items.len().checked_sub(1)
} }
fn confirm(&self, dev_modal: &mut DevServerProjects, cx: &mut ViewContext<DevServerProjects>) { fn confirm(
&self,
remote_modal: &mut RemoteServerProjects,
cx: &mut ViewContext<RemoteServerProjects>,
) {
if let Some(active_item) = self.active_item.and_then(|ix| self.items.get(ix)) { if let Some(active_item) = self.active_item.and_then(|ix| self.items.get(ix)) {
active_item(dev_modal, cx); active_item(remote_modal, cx);
} }
} }
} }
@ -184,7 +188,7 @@ impl ProjectPicker {
connection_string: SharedString, connection_string: SharedString,
project: Model<Project>, project: Model<Project>,
workspace: WeakView<Workspace>, workspace: WeakView<Workspace>,
cx: &mut ViewContext<DevServerProjects>, cx: &mut ViewContext<RemoteServerProjects>,
) -> View<Self> { ) -> View<Self> {
let (tx, rx) = oneshot::channel(); let (tx, rx) = oneshot::channel();
let lister = project::DirectoryLister::Project(project.clone()); let lister = project::DirectoryLister::Project(project.clone());
@ -208,7 +212,7 @@ impl ProjectPicker {
.update(&mut cx, |workspace, cx| { .update(&mut cx, |workspace, cx| {
let weak = cx.view().downgrade(); let weak = cx.view().downgrade();
workspace workspace
.toggle_modal(cx, |cx| DevServerProjects::new(cx, weak)); .toggle_modal(cx, |cx| RemoteServerProjects::new(cx, weak));
}) })
.log_err()?; .log_err()?;
return None; return None;
@ -306,7 +310,7 @@ enum Mode {
ViewServerOptions(usize, SshConnection), ViewServerOptions(usize, SshConnection),
EditNickname(EditNicknameState), EditNickname(EditNicknameState),
ProjectPicker(View<ProjectPicker>), ProjectPicker(View<ProjectPicker>),
CreateDevServer(CreateDevServer), CreateRemoteServer(CreateRemoteServer),
} }
impl Mode { impl Mode {
@ -315,7 +319,7 @@ impl Mode {
Self::Default(ScrollbarState::new(handle)) Self::Default(ScrollbarState::new(handle))
} }
} }
impl DevServerProjects { impl RemoteServerProjects {
pub fn register(workspace: &mut Workspace, _: &mut ViewContext<Workspace>) { pub fn register(workspace: &mut Workspace, _: &mut ViewContext<Workspace>) {
workspace.register_action(|workspace, _: &OpenRemote, cx| { workspace.register_action(|workspace, _: &OpenRemote, cx| {
let handle = cx.view().downgrade(); let handle = cx.view().downgrade();
@ -388,7 +392,7 @@ impl DevServerProjects {
let connection_options = match SshConnectionOptions::parse_command_line(&input) { let connection_options = match SshConnectionOptions::parse_command_line(&input) {
Ok(c) => c, Ok(c) => c,
Err(e) => { Err(e) => {
self.mode = Mode::CreateDevServer(CreateDevServer { self.mode = Mode::CreateRemoteServer(CreateRemoteServer {
address_editor: editor, address_editor: editor,
address_error: Some(format!("could not parse: {:?}", e).into()), address_error: Some(format!("could not parse: {:?}", e).into()),
ssh_prompt: None, ssh_prompt: None,
@ -400,7 +404,7 @@ impl DevServerProjects {
let ssh_prompt = cx.new_view(|cx| SshPrompt::new(&connection_options, cx)); let ssh_prompt = cx.new_view(|cx| SshPrompt::new(&connection_options, cx));
let connection = connect_over_ssh( let connection = connect_over_ssh(
connection_options.dev_server_identifier(), connection_options.remote_server_identifier(),
connection_options.clone(), connection_options.clone(),
ssh_prompt.clone(), ssh_prompt.clone(),
cx, cx,
@ -430,7 +434,7 @@ impl DevServerProjects {
address_editor.update(cx, |this, _| { address_editor.update(cx, |this, _| {
this.set_read_only(false); this.set_read_only(false);
}); });
this.mode = Mode::CreateDevServer(CreateDevServer { this.mode = Mode::CreateRemoteServer(CreateRemoteServer {
address_editor, address_editor,
address_error: None, address_error: None,
ssh_prompt: None, ssh_prompt: None,
@ -446,7 +450,7 @@ impl DevServerProjects {
editor.update(cx, |this, _| { editor.update(cx, |this, _| {
this.set_read_only(true); this.set_read_only(true);
}); });
self.mode = Mode::CreateDevServer(CreateDevServer { self.mode = Mode::CreateRemoteServer(CreateRemoteServer {
address_editor: editor, address_editor: editor,
address_error: None, address_error: None,
ssh_prompt: Some(ssh_prompt.clone()), ssh_prompt: Some(ssh_prompt.clone()),
@ -488,7 +492,7 @@ impl DevServerProjects {
.clone(); .clone();
let connect = connect_over_ssh( let connect = connect_over_ssh(
connection_options.dev_server_identifier(), connection_options.remote_server_identifier(),
connection_options.clone(), connection_options.clone(),
prompt, prompt,
cx, cx,
@ -499,7 +503,8 @@ impl DevServerProjects {
workspace workspace
.update(&mut cx, |workspace, cx| { .update(&mut cx, |workspace, cx| {
let weak = cx.view().downgrade(); let weak = cx.view().downgrade();
workspace.toggle_modal(cx, |cx| DevServerProjects::new(cx, weak)); workspace
.toggle_modal(cx, |cx| RemoteServerProjects::new(cx, weak));
}) })
.log_err(); .log_err();
return; return;
@ -519,7 +524,7 @@ impl DevServerProjects {
cx, cx,
); );
workspace.toggle_modal(cx, |cx| { workspace.toggle_modal(cx, |cx| {
DevServerProjects::project_picker( RemoteServerProjects::project_picker(
ix, ix,
connection_options, connection_options,
project, project,
@ -543,7 +548,7 @@ impl DevServerProjects {
self.selectable_items = items; self.selectable_items = items;
} }
Mode::ProjectPicker(_) => {} Mode::ProjectPicker(_) => {}
Mode::CreateDevServer(state) => { Mode::CreateRemoteServer(state) => {
if let Some(prompt) = state.ssh_prompt.as_ref() { if let Some(prompt) = state.ssh_prompt.as_ref() {
prompt.update(cx, |prompt, cx| { prompt.update(cx, |prompt, cx| {
prompt.confirm(cx); prompt.confirm(cx);
@ -575,8 +580,8 @@ impl DevServerProjects {
fn cancel(&mut self, _: &menu::Cancel, cx: &mut ViewContext<Self>) { fn cancel(&mut self, _: &menu::Cancel, cx: &mut ViewContext<Self>) {
match &self.mode { match &self.mode {
Mode::Default(_) => cx.emit(DismissEvent), Mode::Default(_) => cx.emit(DismissEvent),
Mode::CreateDevServer(state) if state.ssh_prompt.is_some() => { Mode::CreateRemoteServer(state) if state.ssh_prompt.is_some() => {
self.mode = Mode::CreateDevServer(CreateDevServer::new(cx)); self.mode = Mode::CreateRemoteServer(CreateRemoteServer::new(cx));
self.selectable_items.reset_selection(); self.selectable_items.reset_selection();
cx.notify(); cx.notify();
} }
@ -818,9 +823,9 @@ impl DevServerProjects {
}); });
} }
fn render_create_dev_server( fn render_create_remote_server(
&self, &self,
state: &CreateDevServer, state: &CreateRemoteServer,
cx: &mut ViewContext<Self>, cx: &mut ViewContext<Self>,
) -> impl IntoElement { ) -> impl IntoElement {
let ssh_prompt = state.ssh_prompt.clone(); let ssh_prompt = state.ssh_prompt.clone();
@ -834,7 +839,7 @@ impl DevServerProjects {
let theme = cx.theme(); let theme = cx.theme();
v_flex() v_flex()
.id("create-dev-server") .id("create-remote-server")
.overflow_hidden() .overflow_hidden()
.size_full() .size_full()
.flex_1() .flex_1()
@ -995,7 +1000,7 @@ impl DevServerProjects {
}) })
.child({ .child({
fn remove_ssh_server( fn remove_ssh_server(
dev_servers: View<DevServerProjects>, remote_servers: View<RemoteServerProjects>,
index: usize, index: usize,
connection_string: SharedString, connection_string: SharedString,
cx: &mut WindowContext<'_>, cx: &mut WindowContext<'_>,
@ -1011,7 +1016,7 @@ impl DevServerProjects {
cx.spawn(|mut cx| async move { cx.spawn(|mut cx| async move {
if confirmation.await.ok() == Some(0) { if confirmation.await.ok() == Some(0) {
dev_servers remote_servers
.update(&mut cx, |this, cx| { .update(&mut cx, |this, cx| {
this.delete_ssh_server(index, cx); this.delete_ssh_server(index, cx);
this.mode = Mode::default_mode(); this.mode = Mode::default_mode();
@ -1108,21 +1113,21 @@ impl DevServerProjects {
.ssh_connections() .ssh_connections()
.collect::<Vec<_>>(); .collect::<Vec<_>>();
self.selectable_items.add_item(Box::new(|this, cx| { self.selectable_items.add_item(Box::new(|this, cx| {
this.mode = Mode::CreateDevServer(CreateDevServer::new(cx)); this.mode = Mode::CreateRemoteServer(CreateRemoteServer::new(cx));
cx.notify(); cx.notify();
})); }));
let is_selected = self.selectable_items.is_selected(); let is_selected = self.selectable_items.is_selected();
let connect_button = ListItem::new("register-dev-server-button") let connect_button = ListItem::new("register-remove-server-button")
.selected(is_selected) .selected(is_selected)
.inset(true) .inset(true)
.spacing(ui::ListItemSpacing::Sparse) .spacing(ui::ListItemSpacing::Sparse)
.start_slot(Icon::new(IconName::Plus).color(Color::Muted)) .start_slot(Icon::new(IconName::Plus).color(Color::Muted))
.child(Label::new("Connect New Server")) .child(Label::new("Connect New Server"))
.on_click(cx.listener(|this, _, cx| { .on_click(cx.listener(|this, _, cx| {
let state = CreateDevServer::new(cx); let state = CreateRemoteServer::new(cx);
this.mode = Mode::CreateDevServer(state); this.mode = Mode::CreateRemoteServer(state);
cx.notify(); cx.notify();
})); }));
@ -1145,7 +1150,7 @@ impl DevServerProjects {
.child(ListSeparator) .child(ListSeparator)
.child( .child(
div().px_3().child( div().px_3().child(
Label::new("No dev servers registered yet.") Label::new("No remote servers registered yet.")
.color(Color::Muted), .color(Color::Muted),
), ),
) )
@ -1209,23 +1214,23 @@ fn get_text(element: &View<Editor>, cx: &mut WindowContext) -> String {
element.read(cx).text(cx).trim().to_string() element.read(cx).text(cx).trim().to_string()
} }
impl ModalView for DevServerProjects {} impl ModalView for RemoteServerProjects {}
impl FocusableView for DevServerProjects { impl FocusableView for RemoteServerProjects {
fn focus_handle(&self, _cx: &AppContext) -> FocusHandle { fn focus_handle(&self, _cx: &AppContext) -> FocusHandle {
self.focus_handle.clone() self.focus_handle.clone()
} }
} }
impl EventEmitter<DismissEvent> for DevServerProjects {} impl EventEmitter<DismissEvent> for RemoteServerProjects {}
impl Render for DevServerProjects { impl Render for RemoteServerProjects {
fn render(&mut self, cx: &mut ViewContext<Self>) -> impl IntoElement { fn render(&mut self, cx: &mut ViewContext<Self>) -> impl IntoElement {
self.selectable_items.reset(); self.selectable_items.reset();
div() div()
.track_focus(&self.focus_handle) .track_focus(&self.focus_handle)
.elevation_3(cx) .elevation_3(cx)
.key_context("DevServerModal") .key_context("RemoteServerModal")
.on_action(cx.listener(Self::cancel)) .on_action(cx.listener(Self::cancel))
.on_action(cx.listener(Self::confirm)) .on_action(cx.listener(Self::confirm))
.on_action(cx.listener(Self::prev_item)) .on_action(cx.listener(Self::prev_item))
@ -1245,9 +1250,9 @@ impl Render for DevServerProjects {
.render_view_options(*index, connection.clone(), cx) .render_view_options(*index, connection.clone(), cx)
.into_any_element(), .into_any_element(),
Mode::ProjectPicker(element) => element.clone().into_any_element(), Mode::ProjectPicker(element) => element.clone().into_any_element(),
Mode::CreateDevServer(state) => { Mode::CreateRemoteServer(state) => self
self.render_create_dev_server(state, cx).into_any_element() .render_create_remote_server(state, cx)
} .into_any_element(),
Mode::EditNickname(state) => { Mode::EditNickname(state) => {
self.render_edit_nickname(state, cx).into_any_element() self.render_edit_nickname(state, cx).into_any_element()
} }

View file

@ -376,7 +376,14 @@ impl FocusableView for SshConnectionModal {
impl EventEmitter<DismissEvent> for SshConnectionModal {} impl EventEmitter<DismissEvent> for SshConnectionModal {}
impl ModalView for SshConnectionModal {} impl ModalView for SshConnectionModal {
fn on_before_dismiss(&mut self, _: &mut ViewContext<Self>) -> workspace::DismissDecision {
return workspace::DismissDecision::Dismiss(false);
}
fn fade_out_background(&self) -> bool {
true
}
}
#[derive(Clone)] #[derive(Clone)]
pub struct SshClientDelegate { pub struct SshClientDelegate {

View file

@ -186,7 +186,7 @@ impl SshConnectionOptions {
// Uniquely identifies dev server projects on a remote host. Needs to be // Uniquely identifies dev server projects on a remote host. Needs to be
// stable for the same dev server project. // stable for the same dev server project.
pub fn dev_server_identifier(&self) -> String { pub fn remote_server_identifier(&self) -> String {
let mut identifier = format!("dev-server-{:?}", self.host); let mut identifier = format!("dev-server-{:?}", self.host);
if let Some(username) = self.username.as_ref() { if let Some(username) = self.username.as_ref() {
identifier.push('-'); identifier.push('-');

View file

@ -339,7 +339,7 @@ impl TitleBar {
.tooltip(move |cx| Tooltip::text("Project is hosted on a dev server", cx)) .tooltip(move |cx| Tooltip::text("Project is hosted on a dev server", cx))
.on_click(cx.listener(|this, _, cx| { .on_click(cx.listener(|this, _, cx| {
if let Some(workspace) = this.workspace.upgrade() { if let Some(workspace) = this.workspace.upgrade() {
recent_projects::DevServerProjects::open(workspace, cx) recent_projects::RemoteServerProjects::open(workspace, cx)
} }
})) }))
.into_any_element(), .into_any_element(),