History

Disallow multiple save modals for the same pane item (#11931)

Fixes https://github.com/zed-industries/zed/issues/10192 Release Notes: - Fixed multiple save modals appearing for the same file being closed ([10192](https://github.com/zed-industries/zed/issues/10192))

Kirill Bulatov committed 2 years ago

Commit decfbc61 parent 65138861 file · +33 −14Browse files

Unified · Split

crates/workspace/src/pane.rs+33−14
@@ -41,7 +41,7 @@ use ui::{ · 40 unmodified lines
4141 IconSize, Indicator, Label, Tab, TabBar, TabPosition, Tooltip,
4242 };
4343 use ui::{v_flex, ContextMenu};
44−use util::{maybe, truncate_and_remove_front, ResultExt};
44+use util::{debug_panic, maybe, truncate_and_remove_front, ResultExt};
4545
4646 #[derive(PartialEq, Clone, Copy, Deserialize, Debug)]
4747 #[serde(rename_all = "camelCase")]
@@ -218,6 +218,7 @@ pub struct Pane { · 170 unmodified lines
218218 /// Otherwise, when `display_nav_history_buttons` is Some, it determines whether nav buttons should be displayed.
219219 display_nav_history_buttons: Option<bool>,
220220 double_click_dispatch_action: Box<dyn Action>,
221+ save_modals_spawned: HashSet<EntityId>,
221222 }
222223
223224 pub struct ActivationHistoryEntry {
@@ -401,6 +402,7 @@ impl Pane { · 177 unmodified lines
401402 ),
402403 _subscriptions: subscriptions,
403404 double_click_dispatch_action,
405+ save_modals_spawned: HashSet::default(),
404406 }
405407 }
406408
@@ -1367,20 +1369,37 @@ impl Pane { · 960 unmodified lines
13671369 ) && Self::can_autosave_item(item, cx)
13681370 })?;
13691371 if !will_autosave {
1370− let answer = pane.update(cx, |pane, cx| {
1371− pane.activate_item(item_ix, true, true, cx);
1372− let prompt = dirty_message_for(item.project_path(cx));
1373− cx.prompt(
1374− PromptLevel::Warning,
1375− &prompt,
1376− None,
1377− &["Save", "Don't Save", "Cancel"],
1378− )
1372+ let item_id = item.item_id();
1373+ let answer_task = pane.update(cx, |pane, cx| {
1374+ if pane.save_modals_spawned.insert(item_id) {
1375+ pane.activate_item(item_ix, true, true, cx);
1376+ let prompt = dirty_message_for(item.project_path(cx));
1377+ Some(cx.prompt(
1378+ PromptLevel::Warning,
1379+ &prompt,
1380+ None,
1381+ &["Save", "Don't Save", "Cancel"],
1382+ ))
1383+ } else {
1384+ None
1385+ }
13791386 })?;
1380− match answer.await {
1381− Ok(0) => {}
1382− Ok(1) => return Ok(true), // Don't save this file
1383− _ => return Ok(false), // Cancel
1387+ if let Some(answer_task) = answer_task {
1388+ let answer = answer_task.await;
1389+ pane.update(cx, |pane, _| {
1390+ if !pane.save_modals_spawned.remove(&item_id) {
1391+ debug_panic!(
1392+ "save modal was not present in spawned modals after awaiting for its answer"
1393+ )
1394+ }
1395+ })?;
1396+ match answer {
1397+ Ok(0) => {}
1398+ Ok(1) => return Ok(true), // Don't save this file
1399+ _ => return Ok(false), // Cancel
1400+ }
1401+ } else {
1402+ return Ok(false);
13841403 }
13851404 }
13861405 }