mirror of
https://github.com/zed-industries/zed.git
synced 2025-02-03 17:44:30 +00:00
parent
67c9fc575f
commit
18b6ded8f0
2 changed files with 154 additions and 126 deletions
|
@ -4,6 +4,7 @@ use dev_server_projects::{DevServer, DevServerId, DevServerProject, DevServerPro
|
||||||
use editor::Editor;
|
use editor::Editor;
|
||||||
use feature_flags::FeatureFlagAppExt;
|
use feature_flags::FeatureFlagAppExt;
|
||||||
use feature_flags::FeatureFlagViewExt;
|
use feature_flags::FeatureFlagViewExt;
|
||||||
|
use gpui::Subscription;
|
||||||
use gpui::{
|
use gpui::{
|
||||||
percentage, Action, Animation, AnimationExt, AnyElement, AppContext, ClipboardItem,
|
percentage, Action, Animation, AnimationExt, AnyElement, AppContext, ClipboardItem,
|
||||||
DismissEvent, EventEmitter, FocusHandle, FocusableView, Model, ScrollHandle, Transformation,
|
DismissEvent, EventEmitter, FocusHandle, FocusableView, Model, ScrollHandle, Transformation,
|
||||||
|
@ -53,10 +54,10 @@ enum EditDevServerState {
|
||||||
RegeneratedToken(RegenerateDevServerTokenResponse),
|
RegeneratedToken(RegenerateDevServerTokenResponse),
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone)]
|
|
||||||
struct CreateDevServerProject {
|
struct CreateDevServerProject {
|
||||||
dev_server_id: DevServerId,
|
dev_server_id: DevServerId,
|
||||||
creating: bool,
|
creating: bool,
|
||||||
|
_opening: Option<Subscription>,
|
||||||
}
|
}
|
||||||
|
|
||||||
enum Mode {
|
enum Mode {
|
||||||
|
@ -94,7 +95,7 @@ impl DevServerProjects {
|
||||||
pub fn new(cx: &mut ViewContext<Self>) -> Self {
|
pub fn new(cx: &mut ViewContext<Self>) -> Self {
|
||||||
let project_path_input = cx.new_view(|cx| {
|
let project_path_input = cx.new_view(|cx| {
|
||||||
let mut editor = Editor::single_line(cx);
|
let mut editor = Editor::single_line(cx);
|
||||||
editor.set_placeholder_text("Project path", cx);
|
editor.set_placeholder_text("Project path (~/work/zed, /workspace/zed, …)", cx);
|
||||||
editor
|
editor
|
||||||
});
|
});
|
||||||
let dev_server_name_input =
|
let dev_server_name_input =
|
||||||
|
@ -165,15 +166,45 @@ impl DevServerProjects {
|
||||||
cx.spawn(|this, mut cx| async move {
|
cx.spawn(|this, mut cx| async move {
|
||||||
let result = create.await;
|
let result = create.await;
|
||||||
this.update(&mut cx, |this, cx| {
|
this.update(&mut cx, |this, cx| {
|
||||||
if result.is_ok() {
|
if let Ok(result) = &result {
|
||||||
this.project_path_input.update(cx, |editor, cx| {
|
if let Some(dev_server_project_id) =
|
||||||
editor.set_text("", cx);
|
result.dev_server_project.as_ref().map(|p| p.id)
|
||||||
});
|
{
|
||||||
this.mode = Mode::Default(None);
|
let subscription =
|
||||||
|
cx.observe(&this.dev_server_store, move |this, store, cx| {
|
||||||
|
if let Some(project_id) = store
|
||||||
|
.read(cx)
|
||||||
|
.dev_server_project(DevServerProjectId(dev_server_project_id))
|
||||||
|
.and_then(|p| p.project_id)
|
||||||
|
{
|
||||||
|
this.project_path_input.update(cx, |editor, cx| {
|
||||||
|
editor.set_text("", cx);
|
||||||
|
});
|
||||||
|
this.mode = Mode::Default(None);
|
||||||
|
if let Some(app_state) = AppState::global(cx).upgrade() {
|
||||||
|
workspace::join_dev_server_project(
|
||||||
|
project_id, app_state, None, cx,
|
||||||
|
)
|
||||||
|
.detach_and_prompt_err(
|
||||||
|
"Could not join project",
|
||||||
|
cx,
|
||||||
|
|_, _| None,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
this.mode = Mode::Default(Some(CreateDevServerProject {
|
||||||
|
dev_server_id,
|
||||||
|
creating: true,
|
||||||
|
_opening: Some(subscription),
|
||||||
|
}));
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
this.mode = Mode::Default(Some(CreateDevServerProject {
|
this.mode = Mode::Default(Some(CreateDevServerProject {
|
||||||
dev_server_id,
|
dev_server_id,
|
||||||
creating: false,
|
creating: false,
|
||||||
|
_opening: None,
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
@ -196,6 +227,7 @@ impl DevServerProjects {
|
||||||
self.mode = Mode::Default(Some(CreateDevServerProject {
|
self.mode = Mode::Default(Some(CreateDevServerProject {
|
||||||
dev_server_id,
|
dev_server_id,
|
||||||
creating: true,
|
creating: true,
|
||||||
|
_opening: None,
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -443,109 +475,74 @@ impl DevServerProjects {
|
||||||
fn render_dev_server(
|
fn render_dev_server(
|
||||||
&mut self,
|
&mut self,
|
||||||
dev_server: &DevServer,
|
dev_server: &DevServer,
|
||||||
mut create_project: Option<CreateDevServerProject>,
|
create_project: Option<bool>,
|
||||||
cx: &mut ViewContext<Self>,
|
cx: &mut ViewContext<Self>,
|
||||||
) -> impl IntoElement {
|
) -> impl IntoElement {
|
||||||
let dev_server_id = dev_server.id;
|
let dev_server_id = dev_server.id;
|
||||||
let status = dev_server.status;
|
let status = dev_server.status;
|
||||||
let dev_server_name = dev_server.name.clone();
|
let dev_server_name = dev_server.name.clone();
|
||||||
if create_project
|
|
||||||
.as_ref()
|
|
||||||
.is_some_and(|cp| cp.dev_server_id != dev_server.id)
|
|
||||||
{
|
|
||||||
create_project = None;
|
|
||||||
}
|
|
||||||
|
|
||||||
v_flex()
|
v_flex()
|
||||||
.w_full()
|
.w_full()
|
||||||
.child(
|
.child(
|
||||||
h_flex()
|
h_flex().group("dev-server").justify_between().child(
|
||||||
.group("dev-server")
|
h_flex()
|
||||||
.justify_between()
|
.gap_2()
|
||||||
.child(
|
.child(
|
||||||
h_flex()
|
div()
|
||||||
.gap_2()
|
.id(("status", dev_server.id.0))
|
||||||
.child(
|
.relative()
|
||||||
div()
|
.child(Icon::new(IconName::Server).size(IconSize::Small))
|
||||||
.id(("status", dev_server.id.0))
|
.child(div().absolute().bottom_0().left(rems_from_px(8.0)).child(
|
||||||
.relative()
|
Indicator::dot().color(match status {
|
||||||
.child(Icon::new(IconName::Server).size(IconSize::Small))
|
DevServerStatus::Online => Color::Created,
|
||||||
.child(
|
DevServerStatus::Offline => Color::Hidden,
|
||||||
div().absolute().bottom_0().left(rems_from_px(8.0)).child(
|
|
||||||
Indicator::dot().color(match status {
|
|
||||||
DevServerStatus::Online => Color::Created,
|
|
||||||
DevServerStatus::Offline => Color::Hidden,
|
|
||||||
}),
|
|
||||||
),
|
|
||||||
)
|
|
||||||
.tooltip(move |cx| {
|
|
||||||
Tooltip::text(
|
|
||||||
match status {
|
|
||||||
DevServerStatus::Online => "Online",
|
|
||||||
DevServerStatus::Offline => "Offline",
|
|
||||||
},
|
|
||||||
cx,
|
|
||||||
)
|
|
||||||
}),
|
}),
|
||||||
)
|
))
|
||||||
.child(dev_server_name.clone())
|
.tooltip(move |cx| {
|
||||||
.child(
|
Tooltip::text(
|
||||||
h_flex()
|
match status {
|
||||||
.visible_on_hover("dev-server")
|
DevServerStatus::Online => "Online",
|
||||||
.gap_1()
|
DevServerStatus::Offline => "Offline",
|
||||||
.child(
|
},
|
||||||
IconButton::new("edit-dev-server", IconName::Pencil)
|
cx,
|
||||||
.on_click(cx.listener(move |this, _, cx| {
|
|
||||||
this.mode = Mode::EditDevServer(EditDevServer {
|
|
||||||
dev_server_id,
|
|
||||||
state: EditDevServerState::Default,
|
|
||||||
});
|
|
||||||
let dev_server_name = dev_server_name.clone();
|
|
||||||
this.rename_dev_server_input.update(
|
|
||||||
cx,
|
|
||||||
move |input, cx| {
|
|
||||||
input.editor().update(
|
|
||||||
cx,
|
|
||||||
move |editor, cx| {
|
|
||||||
editor.set_text(dev_server_name, cx)
|
|
||||||
},
|
|
||||||
)
|
|
||||||
},
|
|
||||||
)
|
|
||||||
}))
|
|
||||||
.tooltip(|cx| Tooltip::text("Edit dev server", cx)),
|
|
||||||
)
|
)
|
||||||
.child({
|
}),
|
||||||
let dev_server_id = dev_server.id;
|
)
|
||||||
IconButton::new("remove-dev-server", IconName::Trash)
|
.child(dev_server_name.clone())
|
||||||
.on_click(cx.listener(move |this, _, cx| {
|
.child(
|
||||||
this.delete_dev_server(dev_server_id, cx)
|
h_flex()
|
||||||
}))
|
.visible_on_hover("dev-server")
|
||||||
.tooltip(|cx| Tooltip::text("Remove dev server", cx))
|
.gap_1()
|
||||||
}),
|
.child(
|
||||||
),
|
IconButton::new("edit-dev-server", IconName::Pencil)
|
||||||
)
|
.on_click(cx.listener(move |this, _, cx| {
|
||||||
.child(
|
this.mode = Mode::EditDevServer(EditDevServer {
|
||||||
h_flex().gap_1().child(
|
dev_server_id,
|
||||||
IconButton::new(
|
state: EditDevServerState::Default,
|
||||||
("add-remote-project", dev_server_id.0),
|
});
|
||||||
IconName::Plus,
|
let dev_server_name = dev_server_name.clone();
|
||||||
)
|
this.rename_dev_server_input.update(
|
||||||
.tooltip(|cx| Tooltip::text("Add a remote project", cx))
|
cx,
|
||||||
.on_click(cx.listener(
|
move |input, cx| {
|
||||||
move |this, _, cx| {
|
input.editor().update(cx, move |editor, cx| {
|
||||||
if let Mode::Default(project) = &mut this.mode {
|
editor.set_text(dev_server_name, cx)
|
||||||
*project = Some(CreateDevServerProject {
|
})
|
||||||
dev_server_id,
|
},
|
||||||
creating: false,
|
)
|
||||||
});
|
}))
|
||||||
}
|
.tooltip(|cx| Tooltip::text("Edit dev server", cx)),
|
||||||
this.project_path_input.read(cx).focus_handle(cx).focus(cx);
|
)
|
||||||
cx.notify();
|
.child({
|
||||||
},
|
let dev_server_id = dev_server.id;
|
||||||
)),
|
IconButton::new("remove-dev-server", IconName::Trash)
|
||||||
|
.on_click(cx.listener(move |this, _, cx| {
|
||||||
|
this.delete_dev_server(dev_server_id, cx)
|
||||||
|
}))
|
||||||
|
.tooltip(|cx| Tooltip::text("Remove dev server", cx))
|
||||||
|
}),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
.child(
|
.child(
|
||||||
v_flex()
|
v_flex()
|
||||||
|
@ -567,8 +564,32 @@ impl DevServerProjects {
|
||||||
.iter()
|
.iter()
|
||||||
.map(|p| self.render_dev_server_project(p, cx)),
|
.map(|p| self.render_dev_server_project(p, cx)),
|
||||||
)
|
)
|
||||||
.when_some(create_project, |el, create_project| {
|
.when(
|
||||||
el.child(self.render_create_new_project(&create_project, cx))
|
create_project.is_none()
|
||||||
|
&& dev_server.status == DevServerStatus::Online,
|
||||||
|
|el| {
|
||||||
|
el.child(
|
||||||
|
ListItem::new("new-remote_project")
|
||||||
|
.start_slot(Icon::new(IconName::Plus))
|
||||||
|
.child(Label::new("Open folder…"))
|
||||||
|
.on_click(cx.listener(move |this, _, cx| {
|
||||||
|
this.mode =
|
||||||
|
Mode::Default(Some(CreateDevServerProject {
|
||||||
|
dev_server_id,
|
||||||
|
creating: false,
|
||||||
|
_opening: None,
|
||||||
|
}));
|
||||||
|
this.project_path_input
|
||||||
|
.read(cx)
|
||||||
|
.focus_handle(cx)
|
||||||
|
.focus(cx);
|
||||||
|
cx.notify();
|
||||||
|
})),
|
||||||
|
)
|
||||||
|
},
|
||||||
|
)
|
||||||
|
.when_some(create_project, |el, creating| {
|
||||||
|
el.child(self.render_create_new_project(creating, cx))
|
||||||
}),
|
}),
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
|
@ -576,29 +597,24 @@ impl DevServerProjects {
|
||||||
|
|
||||||
fn render_create_new_project(
|
fn render_create_new_project(
|
||||||
&mut self,
|
&mut self,
|
||||||
create_project: &CreateDevServerProject,
|
creating: bool,
|
||||||
_: &mut ViewContext<Self>,
|
_: &mut ViewContext<Self>,
|
||||||
) -> impl IntoElement {
|
) -> impl IntoElement {
|
||||||
ListItem::new("create-remote-project")
|
ListItem::new("create-remote-project")
|
||||||
|
.disabled(true)
|
||||||
.start_slot(Icon::new(IconName::FileTree).color(Color::Muted))
|
.start_slot(Icon::new(IconName::FileTree).color(Color::Muted))
|
||||||
.child(self.project_path_input.clone())
|
.child(self.project_path_input.clone())
|
||||||
.child(
|
.child(div().w(IconSize::Medium.rems()).when(creating, |el| {
|
||||||
div()
|
el.child(
|
||||||
.w(IconSize::Medium.rems())
|
Icon::new(IconName::ArrowCircle)
|
||||||
.when(create_project.creating, |el| {
|
.size(IconSize::Medium)
|
||||||
el.child(
|
.with_animation(
|
||||||
Icon::new(IconName::ArrowCircle)
|
"arrow-circle",
|
||||||
.size(IconSize::Medium)
|
Animation::new(Duration::from_secs(2)).repeat(),
|
||||||
.with_animation(
|
|icon, delta| icon.transform(Transformation::rotate(percentage(delta))),
|
||||||
"arrow-circle",
|
),
|
||||||
Animation::new(Duration::from_secs(2)).repeat(),
|
)
|
||||||
|icon, delta| {
|
}))
|
||||||
icon.transform(Transformation::rotate(percentage(delta)))
|
|
||||||
},
|
|
||||||
),
|
|
||||||
)
|
|
||||||
}),
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn render_dev_server_project(
|
fn render_dev_server_project(
|
||||||
|
@ -920,7 +936,18 @@ impl DevServerProjects {
|
||||||
let Mode::Default(create_dev_server_project) = &self.mode else {
|
let Mode::Default(create_dev_server_project) = &self.mode else {
|
||||||
unreachable!()
|
unreachable!()
|
||||||
};
|
};
|
||||||
let create_dev_server_project = create_dev_server_project.clone();
|
|
||||||
|
let mut is_creating = None;
|
||||||
|
let mut creating_dev_server = None;
|
||||||
|
if let Some(CreateDevServerProject {
|
||||||
|
creating,
|
||||||
|
dev_server_id,
|
||||||
|
..
|
||||||
|
}) = create_dev_server_project
|
||||||
|
{
|
||||||
|
is_creating = Some(*creating);
|
||||||
|
creating_dev_server = Some(*dev_server_id);
|
||||||
|
};
|
||||||
|
|
||||||
v_flex()
|
v_flex()
|
||||||
.id("scroll-container")
|
.id("scroll-container")
|
||||||
|
@ -960,12 +987,13 @@ impl DevServerProjects {
|
||||||
),
|
),
|
||||||
))
|
))
|
||||||
.children(dev_servers.iter().map(|dev_server| {
|
.children(dev_servers.iter().map(|dev_server| {
|
||||||
self.render_dev_server(
|
let creating = if creating_dev_server == Some(dev_server.id) {
|
||||||
dev_server,
|
is_creating
|
||||||
create_dev_server_project.clone(),
|
} else {
|
||||||
cx,
|
None
|
||||||
)
|
};
|
||||||
.into_any_element()
|
self.render_dev_server(dev_server, creating, cx)
|
||||||
|
.into_any_element()
|
||||||
})),
|
})),
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
|
|
|
@ -157,7 +157,7 @@ impl RenderOnce for ListItem {
|
||||||
this.ml(self.indent_level as f32 * self.indent_step_size)
|
this.ml(self.indent_level as f32 * self.indent_step_size)
|
||||||
.px_2()
|
.px_2()
|
||||||
})
|
})
|
||||||
.when(!self.inset, |this| {
|
.when(!self.inset && !self.disabled, |this| {
|
||||||
this
|
this
|
||||||
// TODO: Add focus state
|
// TODO: Add focus state
|
||||||
// .when(self.state == InteractionState::Focused, |this| {
|
// .when(self.state == InteractionState::Focused, |this| {
|
||||||
|
|
Loading…
Reference in a new issue