Keep Open and Save asynchronous to prevent macOS resize crashes (#1127)

Open and Save use parented AsyncFileDialog sheets; their answers run on the UI thread in a later frame, so resizing the window while a picker is open no longer re-enters winit and aborts. Editors, tab changes, Close/Quit and model-changing control requests wait for the answer; the local library Open and Export in the Appearance dialog use the same flow. Fixes #1088.
This commit is contained in:
Karl Von Richter authored and GitHub committed 2026-10-14 13:41:29 -04:00
1 parent f425089983
commit 37547f8eba
18 files changed
+564 -137

No files matched your search

+10 -6
View File
@@ -116,10 +116,12 @@ fn flat_exports_use_the_save_picker() {
let captured = picks.clone();
app.services.pick_save = Some(Box::new(move |name, extensions| {
captured.lock().unwrap().push((name.to_string(), extensions.iter().map(|x| x.to_string()).collect::<Vec<_>>()));
None
Box::pin(std::future::ready(None))
}));
assert_eq!(export_flat(&mut app, "Base", "csv"), "Export cancelled");
assert_eq!(export_flat(&mut app, "Base", "dxf"), "Export cancelled");
assert_eq!(export_flat(&mut app, "Base", "csv"), "Choose an export file…");
crate::file_picker::tick(&mut app, &egui::Context::default());
assert_eq!(export_flat(&mut app, "Base", "dxf"), "Choose an export file…");
crate::file_picker::tick(&mut app, &egui::Context::default());
let picks = picks.lock().unwrap();
assert!(picks[0].0.ends_with("-Base.csv"));
assert_eq!(picks[0].1, vec!["csv"]);
@@ -275,7 +277,7 @@ fn pocket_export_button_uses_the_picker_and_preserves_depth_layers() {
h.app.services.pick_save = Some(Box::new(move |name, extensions| {
assert!(name.ends_with("-Body1.dxf"));
assert_eq!(extensions, &["dxf"]);
Some(chosen.clone())
Box::pin(std::future::ready(Some(chosen.clone())))
}));
h.app.start("sheet.flat_pattern");
h.settle();
@@ -300,10 +302,12 @@ fn bend_table_picker_writes_the_current_body() {
let chosen = output.clone();
app.services.pick_save = Some(Box::new(move |_, extensions| {
assert_eq!(extensions, &["csv"]);
Some(chosen.clone())
Box::pin(std::future::ready(Some(chosen.clone())))
}));
let undo = app.session.undo.len();
assert_eq!(export_flat(&mut app, &body, "csv"), format!("Saved {output}"));
assert_eq!(export_flat(&mut app, &body, "csv"), "Choose an export file…");
crate::file_picker::tick(&mut app, &egui::Context::default());
assert_eq!(app.status.as_ref().map(|s| &s.0), Some(&format!("Exported {output}")));
let contents = std::fs::read_to_string(&path).unwrap();
std::fs::remove_file(&path).unwrap();
assert_eq!(contents.lines().count(), 2);