Merge pull request #2056 from zed-industries/confirm-quit

Max Brunsfeld created

Add confirm_quit setting

Change summary

assets/settings/default.json    |  2 ++
crates/collab/src/tests.rs      |  5 +----
crates/gpui/src/app.rs          |  2 +-
crates/settings/src/settings.rs | 13 ++++++-------
crates/zed/src/zed.rs           | 22 +++++++++++++++++++++-
5 files changed, 31 insertions(+), 13 deletions(-)

Detailed changes

assets/settings/default.json 🔗

@@ -13,6 +13,8 @@
     // Whether to show the informational hover box when moving the mouse
     // over symbols in the editor.
     "hover_popover_enabled": true,
+    // Whether to confirm before quitting Zed.
+    "confirm_quit": false,
     // Whether the cursor blinks in the editor.
     "cursor_blink": true,
     // Whether to pop the completions menu while typing in an editor without

crates/collab/src/tests.rs 🔗

@@ -101,10 +101,7 @@ impl TestServer {
     async fn create_client(&mut self, cx: &mut TestAppContext, name: &str) -> TestClient {
         cx.update(|cx| {
             cx.set_global(HomeDir(Path::new("/tmp/").to_path_buf()));
-
-            let mut settings = Settings::test(cx);
-            settings.projects_online_by_default = false;
-            cx.set_global(settings);
+            cx.set_global(Settings::test(cx));
         });
 
         let http = FakeHttpClient::with_404_response();

crates/gpui/src/app.rs 🔗

@@ -989,7 +989,7 @@ impl MutableAppContext {
         window.toggle_full_screen();
     }
 
-    fn prompt(
+    pub fn prompt(
         &self,
         window_id: usize,
         level: PromptLevel,

crates/settings/src/settings.rs 🔗

@@ -28,12 +28,12 @@ pub use keymap_file::{keymap_file_json_schema, KeymapFileContent};
 #[derive(Clone)]
 pub struct Settings {
     pub experiments: FeatureFlags,
-    pub projects_online_by_default: bool,
     pub buffer_font_family: FamilyId,
     pub default_buffer_font_size: f32,
     pub buffer_font_size: f32,
     pub active_pane_magnification: f32,
     pub cursor_blink: bool,
+    pub confirm_quit: bool,
     pub hover_popover_enabled: bool,
     pub show_completions_on_input: bool,
     pub vim_mode: bool,
@@ -294,6 +294,8 @@ pub struct SettingsFileContent {
     #[serde(default)]
     pub cursor_blink: Option<bool>,
     #[serde(default)]
+    pub confirm_quit: Option<bool>,
+    #[serde(default)]
     pub hover_popover_enabled: Option<bool>,
     #[serde(default)]
     pub show_completions_on_input: Option<bool>,
@@ -356,10 +358,10 @@ impl Settings {
             buffer_font_size: defaults.buffer_font_size.unwrap(),
             active_pane_magnification: defaults.active_pane_magnification.unwrap(),
             default_buffer_font_size: defaults.buffer_font_size.unwrap(),
+            confirm_quit: defaults.confirm_quit.unwrap(),
             cursor_blink: defaults.cursor_blink.unwrap(),
             hover_popover_enabled: defaults.hover_popover_enabled.unwrap(),
             show_completions_on_input: defaults.show_completions_on_input.unwrap(),
-            projects_online_by_default: defaults.projects_online_by_default.unwrap(),
             vim_mode: defaults.vim_mode.unwrap(),
             autosave: defaults.autosave.unwrap(),
             default_dock_anchor: defaults.default_dock_anchor.unwrap(),
@@ -407,10 +409,6 @@ impl Settings {
             }
         }
 
-        merge(
-            &mut self.projects_online_by_default,
-            data.projects_online_by_default,
-        );
         merge(&mut self.buffer_font_size, data.buffer_font_size);
         merge(
             &mut self.active_pane_magnification,
@@ -418,6 +416,7 @@ impl Settings {
         );
         merge(&mut self.default_buffer_font_size, data.buffer_font_size);
         merge(&mut self.cursor_blink, data.cursor_blink);
+        merge(&mut self.confirm_quit, data.confirm_quit);
         merge(&mut self.hover_popover_enabled, data.hover_popover_enabled);
         merge(
             &mut self.show_completions_on_input,
@@ -557,6 +556,7 @@ impl Settings {
             buffer_font_size: 14.,
             active_pane_magnification: 1.,
             default_buffer_font_size: 14.,
+            confirm_quit: false,
             cursor_blink: true,
             hover_popover_enabled: true,
             show_completions_on_input: true,
@@ -582,7 +582,6 @@ impl Settings {
             language_defaults: Default::default(),
             language_overrides: Default::default(),
             lsp: Default::default(),
-            projects_online_by_default: true,
             theme: gpui::fonts::with_font_cache(cx.font_cache().clone(), Default::default),
             telemetry_defaults: TelemetrySettings {
                 diagnostics: Some(true),

crates/zed/src/zed.rs 🔗

@@ -14,6 +14,7 @@ use collections::VecDeque;
 pub use editor;
 use editor::{Editor, MultiBuffer};
 
+use futures::StreamExt;
 use gpui::{
     actions,
     geometry::{
@@ -22,7 +23,8 @@ use gpui::{
     },
     impl_actions,
     platform::{WindowBounds, WindowOptions},
-    AssetSource, AsyncAppContext, ClipboardItem, TitlebarOptions, ViewContext, WindowKind,
+    AssetSource, AsyncAppContext, ClipboardItem, PromptLevel, TitlebarOptions, ViewContext,
+    WindowKind,
 };
 use language::Rope;
 use lazy_static::lazy_static;
@@ -421,7 +423,25 @@ fn quit(_: &Quit, cx: &mut gpui::MutableAppContext) {
     // prompt in the active window before switching to a different window.
     workspaces.sort_by_key(|workspace| !cx.window_is_active(workspace.window_id()));
 
+    let should_confirm = cx.global::<Settings>().confirm_quit;
     cx.spawn(|mut cx| async move {
+        dbg!(should_confirm, workspaces.first());
+
+        if let (true, Some(workspace)) = (should_confirm, workspaces.first()) {
+            let answer = cx
+                .prompt(
+                    workspace.window_id(),
+                    PromptLevel::Info,
+                    "Are you sure you want to quit?",
+                    &["Quit", "Cancel"],
+                )
+                .next()
+                .await;
+            if answer != Some(0) {
+                return Ok(());
+            }
+        }
+
         // If the user cancels any save prompt, then keep the app open.
         for workspace in workspaces {
             if !workspace