@@ -2003,7 +2003,7 @@ mod tests {
use std::path::PathBuf;
use editor::Editor;
- use gpui::{TestAppContext, UpdateGlobal, WindowHandle};
+ use gpui::{TestAppContext, UpdateGlobal, VisualTestContext, WindowHandle};
use serde_json::json;
use settings::SettingsStore;
@@ -2242,6 +2242,71 @@ mod tests {
.unwrap();
}
+ #[gpui::test]
+ async fn test_dev_container_modal_not_dismissed_on_backdrop_click(cx: &mut TestAppContext) {
+ let app_state = init_test(cx);
+
+ app_state
+ .fs
+ .as_fake()
+ .insert_tree(
+ path!("/project"),
+ json!({
+ ".devcontainer": {
+ "devcontainer.json": "{}"
+ },
+ "src": {
+ "main.rs": "fn main() {}"
+ }
+ }),
+ )
+ .await;
+
+ cx.update(|cx| {
+ open_paths(
+ &[PathBuf::from(path!("/project"))],
+ app_state,
+ workspace::OpenOptions::default(),
+ cx,
+ )
+ })
+ .await
+ .unwrap();
+
+ assert_eq!(cx.update(|cx| cx.windows().len()), 1);
+ let multi_workspace = cx.update(|cx| cx.windows()[0].downcast::<MultiWorkspace>().unwrap());
+
+ cx.run_until_parked();
+
+ cx.dispatch_action(*multi_workspace, OpenDevContainer);
+
+ multi_workspace
+ .update(cx, |multi_workspace, _, cx| {
+ assert!(
+ multi_workspace
+ .active_modal::<RemoteServerProjects>(cx)
+ .is_some(),
+ "Dev container modal should be open"
+ );
+ })
+ .unwrap();
+
+ // Click outside the modal (on the backdrop) to try to dismiss it
+ let mut vcx = VisualTestContext::from_window(*multi_workspace, cx);
+ vcx.simulate_click(gpui::point(px(1.0), px(1.0)), gpui::Modifiers::default());
+
+ multi_workspace
+ .update(cx, |multi_workspace, _, cx| {
+ assert!(
+ multi_workspace
+ .active_modal::<RemoteServerProjects>(cx)
+ .is_some(),
+ "Dev container modal should remain open during creation"
+ );
+ })
+ .unwrap();
+ }
+
#[gpui::test]
async fn test_open_dev_container_action_with_multiple_configs(cx: &mut TestAppContext) {
let app_state = init_test(cx);
@@ -54,7 +54,7 @@ use util::{
rel_path::RelPath,
};
use workspace::{
- AppState, ModalView, MultiWorkspace, OpenLog, OpenOptions, Toast, Workspace,
+ AppState, DismissDecision, ModalView, MultiWorkspace, OpenLog, OpenOptions, Toast, Workspace,
notifications::{DetachAndPromptErr, NotificationId},
open_remote_project_with_existing_connection,
};
@@ -69,6 +69,7 @@ pub struct RemoteServerProjects {
create_new_window: bool,
dev_container_picker: Option<Entity<Picker<DevContainerPickerDelegate>>>,
_subscription: Subscription,
+ allow_dismissal: bool,
}
struct CreateRemoteServer {
@@ -920,6 +921,7 @@ impl RemoteServerProjects {
create_new_window,
dev_container_picker: None,
_subscription,
+ allow_dismissal: true,
}
}
@@ -1140,6 +1142,7 @@ impl RemoteServerProjects {
}
fn view_in_progress_dev_container(&mut self, window: &mut Window, cx: &mut Context<Self>) {
+ self.allow_dismissal = false;
self.mode = Mode::CreateRemoteDevContainer(CreateRemoteDevContainer::new(
DevContainerCreationProgress::Creating,
cx,
@@ -1309,6 +1312,7 @@ impl RemoteServerProjects {
cx.emit(DismissEvent);
}
_ => {
+ self.allow_dismissal = true;
self.mode = Mode::default_mode(&self.ssh_config_servers, cx);
self.focus_handle(cx).focus(window, cx);
cx.notify();
@@ -1875,6 +1879,7 @@ impl RemoteServerProjects {
.ok();
entity
.update_in(cx, |remote_server_projects, window, cx| {
+ remote_server_projects.allow_dismissal = true;
remote_server_projects.mode =
Mode::CreateRemoteDevContainer(CreateRemoteDevContainer::new(
DevContainerCreationProgress::Error(format!("{e}")),
@@ -1897,7 +1902,8 @@ impl RemoteServerProjects {
.log_err();
entity
- .update(cx, |_, cx| {
+ .update(cx, |this, cx| {
+ this.allow_dismissal = true;
cx.emit(DismissEvent);
})
.log_err();
@@ -2948,7 +2954,15 @@ fn get_text(element: &Entity<Editor>, cx: &mut App) -> String {
element.read(cx).text(cx).trim().to_string()
}
-impl ModalView for RemoteServerProjects {}
+impl ModalView for RemoteServerProjects {
+ fn on_before_dismiss(
+ &mut self,
+ _window: &mut Window,
+ _cx: &mut Context<Self>,
+ ) -> DismissDecision {
+ DismissDecision::Dismiss(self.allow_dismissal)
+ }
+}
impl Focusable for RemoteServerProjects {
fn focus_handle(&self, cx: &App) -> FocusHandle {