From 0f9e1a3526064c74cc9d130d0e5cba266d32a498 Mon Sep 17 00:00:00 2001 From: Emil Ernerfeldt Date: Tue, 18 Apr 2023 20:26:02 +0200 Subject: [PATCH] eframe web: Store app state to local storage when leaving site (#2927) --- crates/eframe/src/web/backend.rs | 24 +++++++++++++----------- crates/eframe/src/web/events.rs | 21 +++++++++++++++++---- 2 files changed, 30 insertions(+), 15 deletions(-) diff --git a/crates/eframe/src/web/backend.rs b/crates/eframe/src/web/backend.rs index 3835dfb0..2baf1d1b 100644 --- a/crates/eframe/src/web/backend.rs +++ b/crates/eframe/src/web/backend.rs @@ -299,21 +299,23 @@ impl AppRunner { .unwrap() } - pub fn auto_save(&mut self) { - let now = now_sec(); - let time_since_last_save = now - self.last_save_time; - + pub fn auto_save_if_needed(&mut self) { + let time_since_last_save = now_sec() - self.last_save_time; if time_since_last_save > self.app.auto_save_interval().as_secs_f64() { - if self.app.persist_egui_memory() { - save_memory(&self.egui_ctx); - } - if let Some(storage) = self.frame.storage_mut() { - self.app.save(storage); - } - self.last_save_time = now; + self.save(); } } + pub fn save(&mut self) { + if self.app.persist_egui_memory() { + save_memory(&self.egui_ctx); + } + if let Some(storage) = self.frame.storage_mut() { + self.app.save(storage); + } + self.last_save_time = now_sec(); + } + pub fn canvas_id(&self) -> &str { self.painter.canvas_id() } diff --git a/crates/eframe/src/web/events.rs b/crates/eframe/src/web/events.rs index 3208ffe4..bf710ea8 100644 --- a/crates/eframe/src/web/events.rs +++ b/crates/eframe/src/web/events.rs @@ -21,7 +21,7 @@ pub fn paint_and_schedule( runner_lock .needs_repaint .repaint_after(repaint_after.as_secs_f64()); - runner_lock.auto_save(); + runner_lock.auto_save_if_needed(); } Ok(IsDestroyed(is_destroyed)) @@ -54,13 +54,17 @@ pub fn install_document_events(runner_container: &mut AppRunnerContainer) -> Res { // Avoid sticky modifier keys on alt-tab: - let clear_modifiers = ["blur", "focus"]; - - for event_name in clear_modifiers { + for event_name in ["blur", "focus"] { let closure = move |_event: web_sys::MouseEvent, mut runner_lock: egui::mutex::MutexGuard<'_, AppRunner>| { let has_focus = event_name == "focus"; + + if !has_focus { + // We lost focus - good idea to save + runner_lock.save(); + } + runner_lock.input.on_web_page_focus_change(has_focus); runner_lock.egui_ctx().request_repaint(); // tracing::debug!("{event_name:?}"); @@ -208,6 +212,15 @@ pub fn install_document_events(runner_container: &mut AppRunnerContainer) -> Res pub fn install_window_events(runner_container: &mut AppRunnerContainer) -> Result<(), JsValue> { let window = web_sys::window().unwrap(); + // Save-on-close + runner_container.add_event_listener( + &window, + "onbeforeunload", + |_: web_sys::Event, mut runner_lock| { + runner_lock.save(); + }, + )?; + for event_name in &["load", "pagehide", "pageshow", "resize"] { runner_container.add_event_listener( &window,