diff options
| author | _ov4 <ov4@ov4.org> | 2026-10-27 12:36:06 +0000 |
|---|---|---|
| committer | _ov4 <ov4@ov4.org> | 2026-10-27 12:36:06 +0000 |
| commit | 30178981f487c225901f404040c027d4d1f49fea (patch) | |
| tree | 34c9d0e85cc3b35965d039f2acbf31b339d48915 | |
| parent | c63584c388ea6acb7ad2f244376ae005536b6838 (diff) | |
fix(bundle): allow windows to close and route quit through document cleanup
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
| -rw-r--r-- | bundle/src-tauri/capabilities/default.json | 2 | ||||
| -rw-r--r-- | bundle/src-tauri/src/main.rs | 11 | ||||
| -rw-r--r-- | bundle/src/main.js | 34 |
3 files changed, 31 insertions, 16 deletions
diff --git a/bundle/src-tauri/capabilities/default.json b/bundle/src-tauri/capabilities/default.json index a9c7253..4efbe87 100644 --- a/bundle/src-tauri/capabilities/default.json +++ b/bundle/src-tauri/capabilities/default.json @@ -2,5 +2,5 @@ "$schema": "../gen/schemas/desktop-schema.json", "identifier": "main", "windows": ["*"], - "permissions": ["core:default", "core:window:allow-set-title", "core:window:allow-close", "dialog:default"] + "permissions": ["core:default", "core:window:allow-set-title", "core:window:allow-close", "core:window:allow-destroy", "dialog:default"] } diff --git a/bundle/src-tauri/src/main.rs b/bundle/src-tauri/src/main.rs index c361260..7dbccd9 100644 --- a/bundle/src-tauri/src/main.rs +++ b/bundle/src-tauri/src/main.rs @@ -117,7 +117,16 @@ fn main() { .build(tauri::generate_context!()) .expect("Could not start CPSC Bundle") .run(|app, event| match event { - // Also reached when macOS terminates without closing windows, such as Dock Quit. + // Dock Quit must run the same document-close flow as the menu and title bar. + tauri::RunEvent::ExitRequested { api, code: None, .. } => { + let windows = app.webview_windows(); + if !windows.is_empty() { + api.prevent_exit(); + for window in windows.into_values() { + let _ = window.close(); + } + } + } tauri::RunEvent::Exit => { let runners: Vec<Runner> = app .state::<Runners>() diff --git a/bundle/src/main.js b/bundle/src/main.js index e36b743..6734bc4 100644 --- a/bundle/src/main.js +++ b/bundle/src/main.js @@ -17,6 +17,7 @@ const filters = [{ name: 'Pseudocode', extensions: ['cps'] }]; let path = null; let savedText = ''; let busy = false; +let actionDone = Promise.resolve(); let closing = false; let editor; let running = false; @@ -26,11 +27,12 @@ function setRunning(value) { runButton.textContent = value ? 'Stop' : 'Run'; for (const id of ['new', 'open', 'save']) document.getElementById(id).disabled = value; input.disabled = value; - editor.updateOptions({ readOnly: value }); + editor.updateOptions({ readOnly: value || closing }); } async function runFile() { if (!await saveFile()) return; + if (closing) return; setRunning(true); output.textContent = ''; status.textContent = 'Running'; @@ -132,9 +134,12 @@ async function openFile() { status.textContent = 'Ready'; } async function action(callback) { - if (busy || running) return; + if (busy || running || closing) return; busy = true; - try { await callback(); } catch (error) { report(error); } finally { busy = false; } + actionDone = (async () => { + try { await callback(); } catch (error) { report(error); } finally { busy = false; } + })(); + await actionDone; } function editorAction(id) { editor.focus(); editor.getAction(id).run(); } // Keyed by the menu item ids in src-tauri/src/menu.rs. @@ -177,19 +182,20 @@ try { }); await window.listen('menu', event => commands[event.payload]()); await window.onCloseRequested(async event => { - if (closing) return; event.preventDefault(); - if (running) { - try { await invoke('stop_run'); } catch (error) { report(error); return; } - // The command drains pipes before completing; let runFile release its UI lock. - busy = false; - setRunning(false); - } - await action(async () => { + if (closing) return; + closing = true; + editor.updateOptions({ readOnly: true }); + try { + if (running) await invoke('stop_run'); + // Finish any pending save/open or stopped run before closing the document. + await actionDone; if (!await canReplace()) return; - closing = true; - await window.close(); - }); + await window.destroy(); + } catch (error) { report(error); } finally { + closing = false; + editor.updateOptions({ readOnly: running }); + } }); editor.focus(); } catch (error) { report(error); } |
