From 13f5f00bcac81e758aed85f3669fe7268107bc6f Mon Sep 17 00:00:00 2001 From: ".CooCoo" Date: Mon, 9 Nov 2026 02:05:17 -0800 Subject: [PATCH] Updates: a ready update starts its helper when the app exits (#6688) --- crates/ui-egui/Cargo.toml | 3 ++- crates/ui-egui/src/app.rs | 5 +++++ crates/ui-egui/src/platform/updates.rs | 30 ++++++++++++++++++++++++++ 3 files changed, 37 insertions(+), 1 deletion(-) diff --git a/crates/ui-egui/Cargo.toml b/crates/ui-egui/Cargo.toml index c6c934171c..994dfc8a1b 100644 --- a/crates/ui-egui/Cargo.toml +++ b/crates/ui-egui/Cargo.toml @@ -29,7 +29,8 @@ pdfcraft-model = { workspace = true } pdfcraft-platform = { workspace = true } egui = { workspace = true, features = ["bytemuck", "default_fonts", "monochrome_emoji_fonts"] } egui_extras = { workspace = true } -eframe = { workspace = true, features = ["default_fonts", "wgpu", "accesskit", "persistence", "links", "clipboard"] } +# `glow` is always on: `eframe::App::on_exit` takes a GL context when that feature is enabled. +eframe = { workspace = true, features = ["default_fonts", "wgpu", "glow", "accesskit", "persistence", "links", "clipboard"] } serde = { workspace = true } serde_json = { workspace = true } log = { workspace = true } diff --git a/crates/ui-egui/src/app.rs b/crates/ui-egui/src/app.rs index a48de69111..f72a831744 100644 --- a/crates/ui-egui/src/app.rs +++ b/crates/ui-egui/src/app.rs @@ -468,6 +468,11 @@ impl eframe::App for PdfCraftApp { storage.set_string("pdfcraft", self.persist()); } + /// Starts an update that waits for the exit. On macOS the process ends before the app is dropped. + fn on_exit(&mut self, _gl: Option<&eframe::glow::Context>) { + self.updates.exiting(); + } + /// Each frame's work before drawing: opens, operating-system and control-channel requests, /// the quit guard, shortcuts, and the background jobs' results. /// diff --git a/crates/ui-egui/src/platform/updates.rs b/crates/ui-egui/src/platform/updates.rs index 4a5df450a8..2f6630afdb 100644 --- a/crates/ui-egui/src/platform/updates.rs +++ b/crates/ui-egui/src/platform/updates.rs @@ -27,6 +27,9 @@ pub(crate) struct Updates { startup_check: bool, #[cfg(not(target_arch = "wasm32"))] check_requested: bool, + /// How many times `on_exit` called [`Updates::exiting`]. + #[cfg(test)] + exits: u32, } impl Default for Updates { @@ -39,6 +42,20 @@ impl Default for Updates { startup_check: false, #[cfg(not(target_arch = "wasm32"))] check_requested: false, + #[cfg(test)] + exits: 0, + } + } +} + +impl Updates { + /// Starts the helper of an update that waits for the app to exit. Later calls do nothing. + pub(crate) fn exiting(&mut self) { + #[cfg(not(target_arch = "wasm32"))] + self.updater.start_pending_update(); + #[cfg(test)] + { + self.exits += 1; } } } @@ -122,3 +139,16 @@ pub(crate) fn dialog(app: &mut PdfCraftApp, ctx: &egui::Context) { #[cfg(target_arch = "wasm32")] let _ = (app, ctx); } + +#[cfg(test)] +mod tests { + use super::*; + use eframe::App as _; + + #[test] + fn on_exit_calls_the_update_exit_hook_once() { + let mut app = PdfCraftApp::new(); + app.on_exit(None); + assert_eq!(app.updates.exits, 1); + } +}