Disallow multiple quit confirmations (#24180)

Kirill Bulatov created

Closes https://github.com/zed-industries/zed/issues/10192 , again.

Release Notes:

- Fixed multiple save modals appearing when app is being closed multiple
times

Change summary

crates/zed/src/zed.rs | 42 ++++++++++++++++++++++++++----------------
1 file changed, 26 insertions(+), 16 deletions(-)

Detailed changes

crates/zed/src/zed.rs 🔗

@@ -45,6 +45,7 @@ use settings::{
 };
 use std::any::TypeId;
 use std::path::PathBuf;
+use std::sync::atomic::{self, AtomicBool};
 use std::{borrow::Cow, ops::Deref, path::Path, sync::Arc};
 use terminal_view::terminal_panel::{self, TerminalPanel};
 use theme::{ActiveTheme, ThemeSettings};
@@ -965,7 +966,12 @@ fn install_cli(
     .detach_and_prompt_err("Error installing zed cli", window, cx, |_, _, _| None);
 }
 
+static WAITING_QUIT_CONFIRMATION: AtomicBool = AtomicBool::new(false);
 fn quit(_: &Quit, cx: &mut App) {
+    if WAITING_QUIT_CONFIRMATION.load(atomic::Ordering::Acquire) {
+        return;
+    }
+
     let should_confirm = WorkspaceSettings::get_global(cx).confirm_quit;
     cx.spawn(|mut cx| async move {
         let mut workspace_windows = cx.update(|cx| {
@@ -982,23 +988,27 @@ fn quit(_: &Quit, cx: &mut App) {
         })
         .log_err();
 
-        if let (true, Some(workspace)) = (should_confirm, workspace_windows.first().copied()) {
-            let answer = workspace
-                .update(&mut cx, |_, window, cx| {
-                    window.prompt(
-                        PromptLevel::Info,
-                        "Are you sure you want to quit?",
-                        None,
-                        &["Quit", "Cancel"],
-                        cx,
-                    )
-                })
-                .log_err();
+        if should_confirm {
+            if let Some(workspace) = workspace_windows.first() {
+                let answer = workspace
+                    .update(&mut cx, |_, window, cx| {
+                        window.prompt(
+                            PromptLevel::Info,
+                            "Are you sure you want to quit?",
+                            None,
+                            &["Quit", "Cancel"],
+                            cx,
+                        )
+                    })
+                    .log_err();
 
-            if let Some(answer) = answer {
-                let answer = answer.await.ok();
-                if answer != Some(0) {
-                    return Ok(());
+                if let Some(answer) = answer {
+                    WAITING_QUIT_CONFIRMATION.store(true, atomic::Ordering::Release);
+                    let answer = answer.await.ok();
+                    WAITING_QUIT_CONFIRMATION.store(false, atomic::Ordering::Release);
+                    if answer != Some(0) {
+                        return Ok(());
+                    }
                 }
             }
         }