mirror of
https://github.com/storytold/figcraft.git
synced 2026-10-24 10:27:00 -06:00
- **Quit (macOS):** `on_exit` now calls `services::shutdown` and then, on macOS only, `std::process::exit(0)`. This happens before eframe tears the windows down, which is where the crash in #781 is thrown (same approach as the sibling apps, tracked in craft-libs#3). - **`services::shutdown(app, dir, recovery)`** replaces `save_state`. It runs on every platform and everything in it is finished before it returns: 1. the preferences (`state.json`) are written atomically, as before; 2. this run's recovery copies are settled by the new `Recovery::quit(session, asked)`: - if the unsaved-changes question was asked (`ui.quit`: last window closed through the question, or `app.quit`), or nothing is unsaved, it works as before: `finish()` removes them; - otherwise the unsaved documents are copied (waiting for any copy still being written) and the copies stay for the next start, as after a crash. This is the macOS Quit menu (Cmd+Q): winit's menu calls `terminate:`, which reaches `on_exit` without asking. Until now that path removed the recovery copies of files that had unsaved changes; 3. live sessions end explicitly: a session this app hosts tells everyone and stops; a joined session is left. Before, this only happened in the app's thread-local destructor at process exit, if at all. - If the app can't be reached in `on_exit` (it's busy), the recovery copies are left on disk for the next start rather than removed. Quit paths checked: - **Cmd+Q / the menu bar's Quit (macOS):** `terminate:` → winit `applicationWillTerminate` → eframe `exiting` → `on_exit`. Covered. - **Last window closed** (close button, title bar Close, Dock/Finder quit Apple event → `Close`): `on_close_request` → `begin` sets `ui.quit` → root `Close` → `on_exit`. Covered. - **`app.quit` (control channel / MCP):** sets `ui.quit` and closes the root window → `on_exit`. Covered. Its reply goes to the connection thread before the window closes. The process now ends sooner after that, so a client that reads very slowly could in theory see EOF instead of the reply (not seen). - **The frame guard (panic):** isn't a quit. It writes recovery copies and the app keeps running, so it doesn't need this. A panic outside the guard aborts as before. - **eframe error mid-run:** eframe also calls `on_exit` before `run_native` returns `Err`. On macOS that error now only reaches the log (eframe logs it), not the "window couldn't open" box. Startup failures still show the box: `on_exit` only runs once the app exists. Part of #781.