First pass at the modal for setting up devcontainer from scratch.
This commit is contained in:
@@ -1,12 +1,19 @@
|
||||
use std::path::{Path, PathBuf};
|
||||
use std::sync::Arc;
|
||||
|
||||
use gpui::AsyncWindowContext;
|
||||
use gpui::{
|
||||
Action, AsyncWindowContext, DismissEvent, EventEmitter, FocusHandle, Focusable, RenderOnce,
|
||||
};
|
||||
use node_runtime::NodeRuntime;
|
||||
use serde::Deserialize;
|
||||
use settings::DevContainerConnection;
|
||||
use smol::fs;
|
||||
use workspace::Workspace;
|
||||
use ui::{
|
||||
App, Color, Context, Headline, HeadlineSize, Icon, IconName, InteractiveElement, IntoElement,
|
||||
Label, ListItem, ListSeparator, ModalHeader, Navigable, NavigableEntry, ParentElement, Render,
|
||||
Styled, StyledExt, Toggleable, Window, div, rems,
|
||||
};
|
||||
use workspace::{ModalView, Workspace, with_active_or_new_workspace};
|
||||
|
||||
use crate::remote_connections::Connection;
|
||||
|
||||
@@ -275,6 +282,122 @@ pub(crate) enum DevContainerError {
|
||||
DevContainerParseFailed,
|
||||
}
|
||||
|
||||
#[derive(PartialEq, Clone, Deserialize, Default, Action)]
|
||||
#[action(namespace = containers)]
|
||||
#[serde(deny_unknown_fields)]
|
||||
pub struct InitDevContainer;
|
||||
|
||||
pub fn init(cx: &mut App) {
|
||||
cx.on_action(|_: &InitDevContainer, cx| {
|
||||
with_active_or_new_workspace(cx, move |workspace, window, cx| {
|
||||
workspace.toggle_modal(window, cx, |window, cx| DevContainerModal::new(window, cx));
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
struct DevContainerModal {
|
||||
focus_handle: FocusHandle,
|
||||
search_navigable_entry: NavigableEntry,
|
||||
other_navigable_entry: NavigableEntry,
|
||||
}
|
||||
|
||||
impl DevContainerModal {
|
||||
fn new(window: &mut Window, cx: &mut App) -> Self {
|
||||
let search_navigable_entry = NavigableEntry::focusable(cx);
|
||||
let other_navigable_entry = NavigableEntry::focusable(cx);
|
||||
let focus_handle = cx.focus_handle();
|
||||
DevContainerModal {
|
||||
focus_handle,
|
||||
search_navigable_entry,
|
||||
other_navigable_entry,
|
||||
}
|
||||
}
|
||||
|
||||
fn dismiss(&mut self, _: &menu::Cancel, _: &mut Window, cx: &mut Context<Self>) {
|
||||
cx.emit(DismissEvent);
|
||||
}
|
||||
}
|
||||
|
||||
impl ModalView for DevContainerModal {}
|
||||
impl EventEmitter<DismissEvent> for DevContainerModal {}
|
||||
impl Focusable for DevContainerModal {
|
||||
fn focus_handle(&self, _cx: &App) -> FocusHandle {
|
||||
self.focus_handle.clone()
|
||||
}
|
||||
}
|
||||
|
||||
impl Render for DevContainerModal {
|
||||
fn render(
|
||||
&mut self,
|
||||
window: &mut ui::Window,
|
||||
cx: &mut ui::Context<Self>,
|
||||
) -> impl ui::IntoElement {
|
||||
let mut view =
|
||||
Navigable::new(
|
||||
div()
|
||||
.child(div().track_focus(&self.focus_handle).child(
|
||||
ModalHeader::new().child(
|
||||
Headline::new("Create Dev Container").size(HeadlineSize::XSmall),
|
||||
),
|
||||
))
|
||||
.child(ListSeparator)
|
||||
.child(
|
||||
div()
|
||||
.track_focus(&self.search_navigable_entry.focus_handle)
|
||||
.on_action(cx.listener(|this, _: &menu::Confirm, window, cx| {
|
||||
println!("action on search containers");
|
||||
}))
|
||||
.child(
|
||||
ListItem::new("li-search-containers")
|
||||
.inset(true)
|
||||
.spacing(ui::ListItemSpacing::Sparse)
|
||||
.start_slot(Icon::new(IconName::Pencil).color(Color::Muted))
|
||||
.toggle_state(
|
||||
self.search_navigable_entry
|
||||
.focus_handle
|
||||
.contains_focused(window, cx),
|
||||
)
|
||||
.child(Label::new("Search for dev containers in registry")),
|
||||
),
|
||||
)
|
||||
.child(
|
||||
div()
|
||||
.track_focus(&self.other_navigable_entry.focus_handle)
|
||||
.on_action(cx.listener(|this, _: &menu::Confirm, window, cx| {
|
||||
println!("action on other containers");
|
||||
}))
|
||||
.child(
|
||||
ListItem::new("li-search-containers")
|
||||
.inset(true)
|
||||
.spacing(ui::ListItemSpacing::Sparse)
|
||||
.start_slot(Icon::new(IconName::Pencil).color(Color::Muted))
|
||||
.toggle_state(
|
||||
self.other_navigable_entry
|
||||
.focus_handle
|
||||
.contains_focused(window, cx),
|
||||
)
|
||||
.child(Label::new("Do another thing")),
|
||||
),
|
||||
)
|
||||
.into_any_element(),
|
||||
);
|
||||
view = view.entry(self.search_navigable_entry.clone());
|
||||
view = view.entry(self.other_navigable_entry.clone());
|
||||
|
||||
// // This is an interesting edge. Can't focus in render, or you'll just override whatever was focused before.
|
||||
// // self.search_navigable_entry.focus_handle.focus(window, cx);
|
||||
|
||||
// view.render(window, cx).into_any_element()
|
||||
div()
|
||||
.elevation_3(cx)
|
||||
.w(rems(34.))
|
||||
// WHY IS THIS NEEDED FOR ACTION DISPATCH OMG
|
||||
.key_context("ContainerModal")
|
||||
.on_action(cx.listener(Self::dismiss))
|
||||
.child(view.render(window, cx).into_any_element())
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
mod dev_container;
|
||||
pub mod dev_container;
|
||||
mod dev_container_suggest;
|
||||
pub mod disconnected_overlay;
|
||||
mod remote_connections;
|
||||
|
||||
@@ -33,7 +33,7 @@ use assets::Assets;
|
||||
use node_runtime::{NodeBinaryOptions, NodeRuntime};
|
||||
use parking_lot::Mutex;
|
||||
use project::{project_settings::ProjectSettings, trusted_worktrees};
|
||||
use recent_projects::{SshSettings, open_remote_project};
|
||||
use recent_projects::{SshSettings, dev_container, open_remote_project};
|
||||
use release_channel::{AppCommitSha, AppVersion, ReleaseChannel};
|
||||
use session::{AppSession, Session};
|
||||
use settings::{BaseKeymap, Settings, SettingsStore, watch_config_file};
|
||||
@@ -616,6 +616,7 @@ fn main() {
|
||||
agent_ui_v2::agents_panel::init(cx);
|
||||
repl::init(app_state.fs.clone(), cx);
|
||||
recent_projects::init(cx);
|
||||
dev_container::init(cx);
|
||||
|
||||
load_embedded_fonts(cx);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user