fix(web): warn before losing unsaved changes

Closes #556
This commit is contained in:
Hakan Seven committed 2026-07-29 22:42:04 +03:00
1 parent 7b708372a8
commit 5f0e1732c1
4 files changed
+46

No files matched your search

+1
View File
@@ -163,6 +163,7 @@ web-sys = { version = "0.3", features = [
"KeyboardEventInit",
"EventInit",
"EventTarget",
"BeforeUnloadEvent",
# Error banner (web_diag): forward wgpu/naga errors to the browser console
# and inject a copyable DOM overlay (document.body → append_child).
"console",
+2
View File
@@ -3178,6 +3178,8 @@ pub fn run() -> iced::Result {
impl Drop for OpenCADStudio {
fn drop(&mut self) {
#[cfg(target_arch = "wasm32")]
crate::sys::set_unsaved_changes_warning(false);
// Kill plugin runner processes as soon as the application state is
// dropped, instead of waiting for the thread-local manager destructor.
// This makes host shutdown deterministic and fast on every exit path.
+2
View File
@@ -217,6 +217,8 @@ impl OpenCADStudio {
);
}
}
#[cfg(target_arch = "wasm32")]
crate::sys::set_unsaved_changes_warning(self.tabs.iter().any(|tab| tab.dirty));
task
}
+41
View File
@@ -17,6 +17,47 @@ pub fn open_url(url: &str) {
}
}
#[cfg(target_arch = "wasm32")]
thread_local! {
static BEFORE_UNLOAD_WARNING: std::cell::RefCell<
Option<wasm_bindgen::closure::Closure<dyn FnMut(web_sys::BeforeUnloadEvent)>>
> = const { std::cell::RefCell::new(None) };
}
/// Enable the browser's standard leave-page confirmation while drawings have
/// unsaved changes. Browsers control the dialog text; preventing the event and
/// setting `returnValue` are the portable signal that a warning is required.
///
/// The callback is installed only while needed so clean sessions remain
/// eligible for the browser back/forward cache.
#[cfg(target_arch = "wasm32")]
pub fn set_unsaved_changes_warning(active: bool) {
use wasm_bindgen::JsCast;
let Some(window) = web_sys::window() else {
return;
};
BEFORE_UNLOAD_WARNING.with(|warning| {
let mut warning = warning.borrow_mut();
if active == warning.is_some() {
return;
}
if active {
let callback = wasm_bindgen::closure::Closure::new(
move |event: web_sys::BeforeUnloadEvent| {
event.prevent_default();
event.set_return_value("");
},
);
window.set_onbeforeunload(Some(callback.as_ref().unchecked_ref()));
*warning = Some(callback);
} else {
window.set_onbeforeunload(None);
warning.take();
}
});
}
/// Reveal a saved drawing in the native platform's file manager.
#[cfg(not(target_arch = "wasm32"))]
pub fn reveal_in_file_manager(path: &std::path::Path) -> Result<(), String> {