diff --git a/crates/dev_container/src/devcontainer_api.rs b/crates/dev_container/src/devcontainer_api.rs index 3c822aa139001e3ccb2d6350a2380b36e8925d1b..0407bbf7c710924c2b33f31b8df24780e103d4b2 100644 --- a/crates/dev_container/src/devcontainer_api.rs +++ b/crates/dev_container/src/devcontainer_api.rs @@ -78,14 +78,14 @@ impl Display for DevContainerError { "{}", match self { DevContainerError::DockerNotAvailable => - "Docker CLI not found on $PATH".to_string(), + "docker CLI not found on $PATH".to_string(), DevContainerError::DevContainerCliNotAvailable => - "Docker not found on path".to_string(), - DevContainerError::DevContainerUpFailed(message) => { - format!("DevContainer creation failed with error: {}", message) + "devcontainer CLI not found on path".to_string(), + DevContainerError::DevContainerUpFailed(_) => { + "DevContainer creation failed".to_string() } - DevContainerError::DevContainerTemplateApplyFailed(message) => { - format!("DevContainer template apply failed with error: {}", message) + DevContainerError::DevContainerTemplateApplyFailed(_) => { + "DevContainer template apply failed".to_string() } DevContainerError::DevContainerNotFound => "No valid dev container definition found in project".to_string(), @@ -257,13 +257,6 @@ pub fn find_devcontainer_configs(cx: &mut AsyncWindowContext) -> Vec Result<(DevContainerConnection, String), DevContainerError> { - start_dev_container_with_config(cx, node_runtime, None).await -} - pub async fn start_dev_container_with_config( cx: &mut AsyncWindowContext, node_runtime: NodeRuntime, @@ -479,7 +472,7 @@ async fn devcontainer_up( parse_json_from_cli(&raw) } else { let message = format!( - "Non-success status running devcontainer up for workspace: out: {:?}, err: {:?}", + "Non-success status running devcontainer up for workspace: out: {}, err: {}", String::from_utf8_lossy(&output.stdout), String::from_utf8_lossy(&output.stderr) ); diff --git a/crates/dev_container/src/lib.rs b/crates/dev_container/src/lib.rs index 1168bdc6cfb56463697d2bd5b26e4ce95387003b..699285e074f325bea78a240c1a2a696cfc578929 100644 --- a/crates/dev_container/src/lib.rs +++ b/crates/dev_container/src/lib.rs @@ -47,8 +47,7 @@ use crate::devcontainer_api::DevContainerError; use crate::devcontainer_api::apply_dev_container_template; pub use devcontainer_api::{ - DevContainerConfig, find_devcontainer_configs, start_dev_container, - start_dev_container_with_config, + DevContainerConfig, find_devcontainer_configs, start_dev_container_with_config, }; #[derive(RegisterSetting)] diff --git a/crates/recent_projects/src/recent_projects.rs b/crates/recent_projects/src/recent_projects.rs index f3660a6e3fe5404296c24fbd7daa5e04aa8db92a..7f67627ad4d6841419292e58b5b41a5fd5ef7d5b 100644 --- a/crates/recent_projects/src/recent_projects.rs +++ b/crates/recent_projects/src/recent_projects.rs @@ -238,7 +238,7 @@ pub fn init(cx: &mut App) { if !is_local { cx.prompt( gpui::PromptLevel::Critical, - "Cannot open Dev Container from remote project", + "Cannot open Dev Container from remote project", None, &["Ok"], ) diff --git a/crates/recent_projects/src/remote_servers.rs b/crates/recent_projects/src/remote_servers.rs index 3fd9603ad4793635da0fabd3f52d3868ee90521b..5b719940f958ac0e4ecb6e186052e3e09987f80e 100644 --- a/crates/recent_projects/src/remote_servers.rs +++ b/crates/recent_projects/src/remote_servers.rs @@ -51,7 +51,7 @@ use util::{ rel_path::RelPath, }; use workspace::{ - ModalView, OpenOptions, Toast, Workspace, + ModalView, OpenLog, OpenOptions, Toast, Workspace, notifications::{DetachAndPromptErr, NotificationId}, open_remote_project_with_existing_connection, }; @@ -99,14 +99,17 @@ enum DevContainerCreationProgress { #[derive(Clone)] struct CreateRemoteDevContainer { + view_logs_entry: NavigableEntry, back_entry: NavigableEntry, progress: DevContainerCreationProgress, } impl CreateRemoteDevContainer { fn new(progress: DevContainerCreationProgress, cx: &mut Context) -> Self { + let view_logs_entry = NavigableEntry::focusable(cx); let back_entry = NavigableEntry::focusable(cx); Self { + view_logs_entry, back_entry, progress, } @@ -1293,6 +1296,12 @@ impl RemoteServerProjects { self.mode = Mode::CreateRemoteServer(new_state); cx.notify(); } + Mode::CreateRemoteDevContainer(CreateRemoteDevContainer { + progress: DevContainerCreationProgress::Error(_), + .. + }) => { + cx.emit(DismissEvent); + } _ => { self.mode = Mode::default_mode(&self.ssh_config_servers, cx); self.focus_handle(cx).focus(window, cx); @@ -1839,23 +1848,24 @@ impl RemoteServerProjects { Ok((c, s)) => (Connection::DevContainer(c), s), Err(e) => { log::error!("Failed to start dev container: {:?}", e); - entity - .update_in(cx, |remote_server_projects, _window, cx| { - remote_server_projects.mode = - Mode::CreateRemoteDevContainer(CreateRemoteDevContainer::new( - DevContainerCreationProgress::Error(format!("{:?}", e)), - cx, - )); - }) - .log_err(); cx.prompt( gpui::PromptLevel::Critical, - "Failed to start Dev Container", - Some(&format!("{:?}", e)), + "Failed to start Dev Container. See logs for details", + Some(&format!("{e}")), &["Ok"], ) .await .ok(); + entity + .update_in(cx, |remote_server_projects, window, cx| { + remote_server_projects.mode = + Mode::CreateRemoteDevContainer(CreateRemoteDevContainer::new( + DevContainerCreationProgress::Error(format!("{e}")), + cx, + )); + remote_server_projects.focus_handle(cx).focus(window, cx); + }) + .ok(); return; } }; @@ -1899,69 +1909,83 @@ impl RemoteServerProjects { ) -> impl IntoElement { match &state.progress { DevContainerCreationProgress::Error(message) => { - self.focus_handle(cx).focus(window, cx); - div() - .track_focus(&self.focus_handle(cx)) - .size_full() - .child( - v_flex() - .py_1() - .child( - ListItem::new("Error") - .inset(true) - .selectable(false) - .spacing(ui::ListItemSpacing::Sparse) - .start_slot(Icon::new(IconName::XCircle).color(Color::Error)) - .child(Label::new("Error Creating Dev Container:")) - .child(Label::new(message).buffer_font(cx)), - ) - .child(ListSeparator) - .child( - div() - .id("devcontainer-go-back") - .track_focus(&state.back_entry.focus_handle) - .on_action(cx.listener( - |this, _: &menu::Confirm, window, cx| { - this.mode = - Mode::default_mode(&this.ssh_config_servers, cx); - cx.focus_self(window); - cx.notify(); - }, - )) - .child( - ListItem::new("li-devcontainer-go-back") - .toggle_state( - state - .back_entry - .focus_handle - .contains_focused(window, cx), - ) - .inset(true) - .spacing(ui::ListItemSpacing::Sparse) - .start_slot( - Icon::new(IconName::ArrowLeft).color(Color::Muted), - ) - .child(Label::new("Go Back")) - .end_slot( - KeyBinding::for_action_in( - &menu::Cancel, - &self.focus_handle, - cx, - ) - .size(rems_from_px(12.)), - ) - .on_click(cx.listener(|this, _, window, cx| { - this.mode = Mode::default_mode( - &this.ssh_config_servers, - cx, - ); - cx.focus_self(window); - cx.notify(); - })), - ), + let view = Navigable::new( + div() + .child( + div().track_focus(&self.focus_handle(cx)).size_full().child( + v_flex().py_1().child( + ListItem::new("Error") + .inset(true) + .selectable(false) + .spacing(ui::ListItemSpacing::Sparse) + .start_slot( + Icon::new(IconName::XCircle).color(Color::Error), + ) + .child(Label::new("Error Creating Dev Container:")) + .child(Label::new(message).buffer_font(cx)), + ), ), - ) - .into_any_element() + ) + .child(ListSeparator) + .child( + div() + .id("devcontainer-see-log") + .track_focus(&state.view_logs_entry.focus_handle) + .on_action(cx.listener(|_, _: &menu::Confirm, window, cx| { + window.dispatch_action(Box::new(OpenLog), cx); + cx.emit(DismissEvent); + cx.notify(); + })) + .child( + ListItem::new("li-devcontainer-see-log") + .toggle_state( + state + .view_logs_entry + .focus_handle + .contains_focused(window, cx), + ) + .inset(true) + .spacing(ui::ListItemSpacing::Sparse) + .start_slot(Icon::new(IconName::File).color(Color::Muted)) + .child(Label::new("Open Zed Log")) + .on_click(cx.listener(|_, _, window, cx| { + window.dispatch_action(Box::new(OpenLog), cx); + cx.emit(DismissEvent); + cx.notify(); + })), + ), + ) + .child( + div() + .id("devcontainer-go-back") + .track_focus(&state.back_entry.focus_handle) + .on_action(cx.listener(|this, _: &menu::Confirm, window, cx| { + this.cancel(&menu::Cancel, window, cx); + cx.notify(); + })) + .child( + ListItem::new("li-devcontainer-go-back") + .toggle_state( + state + .back_entry + .focus_handle + .contains_focused(window, cx), + ) + .inset(true) + .spacing(ui::ListItemSpacing::Sparse) + .start_slot(Icon::new(IconName::Exit).color(Color::Muted)) + .child(Label::new("Exit")) + .on_click(cx.listener(|this, _, window, cx| { + this.cancel(&menu::Cancel, window, cx); + cx.notify(); + })), + ), + ) + .into_any_element(), + ) + .entry(state.view_logs_entry.clone()) + .entry(state.back_entry.clone()); + view.render(window, cx).into_any_element() } DevContainerCreationProgress::SelectingConfig => { self.render_config_selection(window, cx).into_any_element()