diff --git a/apps/desktop/package.json b/apps/desktop/package.json index 64f5eac..712aee2 100644 --- a/apps/desktop/package.json +++ b/apps/desktop/package.json @@ -68,6 +68,7 @@ "tailwindcss": "^4.1.18", "typescript": "^5.9.3", "vite": "^6.3.5", + "vite-plugin-top-level-await": "^1.6.0", "vitest": "^3.1.1" } } diff --git a/apps/desktop/src-tauri/src/lib.rs b/apps/desktop/src-tauri/src/lib.rs index 2274495..9f8e1e2 100644 --- a/apps/desktop/src-tauri/src/lib.rs +++ b/apps/desktop/src-tauri/src/lib.rs @@ -326,7 +326,27 @@ pub fn run() { .manage(claude::ClaudeProcessState::default()) .manage(latex::LatexCompilerState::default()) .manage(zotero::ZoteroOAuthState::default()) - .setup(|_app| Ok(())) + .setup(|app| { + // Safety net: force-show the main window after a timeout if the + // frontend JS never calls `getCurrentWindow().show()`. + // This prevents the window from staying permanently hidden when + // WKWebView fails to execute JS (e.g. WebKit top-level-await bug + // on macOS 12). See https://bugs.webkit.org/show_bug.cgi?id=242740 + let handle = app.handle().clone(); + tauri::async_runtime::spawn(async move { + tokio::time::sleep(std::time::Duration::from_secs(8)).await; + if let Some(window) = handle.get_webview_window("main") { + if !window.is_visible().unwrap_or(true) { + eprintln!( + "[safety] Main window still hidden after 8s, force-showing" + ); + let _ = window.show(); + let _ = window.set_focus(); + } + } + }); + Ok(()) + }) .invoke_handler(tauri::generate_handler![ create_new_window, detect_editors, diff --git a/apps/desktop/src/main.tsx b/apps/desktop/src/main.tsx index 56d3c4f..4b278e0 100644 --- a/apps/desktop/src/main.tsx +++ b/apps/desktop/src/main.tsx @@ -73,10 +73,11 @@ if (isDebugWindow) { }); } else { // Main app window - const { App } = await import("./App"); - ReactDOM.createRoot(rootEl).render( - - - , - ); + import("./App").then(({ App }) => { + ReactDOM.createRoot(rootEl).render( + + + , + ); + }); } diff --git a/apps/desktop/vite.config.ts b/apps/desktop/vite.config.ts index d0236b3..57e85b3 100644 --- a/apps/desktop/vite.config.ts +++ b/apps/desktop/vite.config.ts @@ -1,11 +1,12 @@ import { defineConfig } from "vite"; import react from "@vitejs/plugin-react"; +import topLevelAwait from "vite-plugin-top-level-await"; import path from "node:path"; const host = process.env.TAURI_DEV_HOST; export default defineConfig({ - plugins: [react()], + plugins: [react(), topLevelAwait()], resolve: { alias: { "@": path.resolve(__dirname, "src"), @@ -35,7 +36,8 @@ export default defineConfig({ }, envPrefix: ["VITE_", "TAURI_"], build: { - target: "esnext", + target: + process.env.TAURI_ENV_PLATFORM === "windows" ? "chrome105" : "safari14", minify: !process.env.TAURI_ENV_DEBUG ? "esbuild" : false, sourcemap: !!process.env.TAURI_ENV_DEBUG, }, diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 3ed126a..f7a3245 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -184,6 +184,9 @@ importers: vite: specifier: ^6.3.5 version: 6.4.1(@types/node@25.0.10)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.16.9)(tsx@4.21.0)(yaml@2.8.2) + vite-plugin-top-level-await: + specifier: ^1.6.0 + version: 1.6.0(rollup@4.59.0)(vite@6.4.1(@types/node@25.0.10)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.16.9)(tsx@4.21.0)(yaml@2.8.2)) vitest: specifier: ^3.1.1 version: 3.2.4(@types/debug@4.1.12)(@types/node@25.0.10)(jiti@2.6.1)(jsdom@26.1.0)(lightningcss@1.30.2)(msw@2.12.10(@types/node@25.0.10)(typescript@5.9.3))(terser@5.16.9)(tsx@4.21.0)(yaml@2.8.2) @@ -2555,6 +2558,15 @@ packages: '@rolldown/pluginutils@1.0.0-beta.27': resolution: {integrity: sha512-+d0F4MKMCbeVUJwG96uQ4SgAznZNSq93I3V+9NHA4OpvqG8mRCpGdKmK8l/dl02h2CCDHwW2FqilnTyDcAnqjA==} + '@rollup/plugin-virtual@3.0.2': + resolution: {integrity: sha512-10monEYsBp3scM4/ND4LNH5Rxvh3e/cVeL3jWTgZ2SrQ+BmUoQcopVQvnaMcOnykb1VkxUFuDAN+0FnpTFRy2A==} + engines: {node: '>=14.0.0'} + peerDependencies: + rollup: '>=4.58.0' + peerDependenciesMeta: + rollup: + optional: true + '@rollup/rollup-android-arm-eabi@4.59.0': resolution: {integrity: sha512-upnNBkA6ZH2VKGcBj9Fyl9IGNPULcjXRlg0LLeaioQWueH30p6IXtJEbKAgvyv+mJaMxSm1l6xwDXYjpEMiLMg==} cpu: [arm] @@ -2926,9 +2938,105 @@ packages: '@speed-highlight/core@1.2.14': resolution: {integrity: sha512-G4ewlBNhUtlLvrJTb88d2mdy2KRijzs4UhnlrOSRT4bmjh/IqNElZa3zkrZ+TC47TwtlDWzVLFADljF1Ijp5hA==} + '@swc/core-darwin-arm64@1.15.21': + resolution: {integrity: sha512-SA8SFg9dp0qKRH8goWsax6bptFE2EdmPf2YRAQW9WoHGf3XKM1bX0nd5UdwxmC5hXsBUZAYf7xSciCler6/oyA==} + engines: {node: '>=10'} + cpu: [arm64] + os: [darwin] + + '@swc/core-darwin-x64@1.15.21': + resolution: {integrity: sha512-//fOVntgowz9+V90lVsNCtyyrtbHp3jWH6Rch7MXHXbcvbLmbCTmssl5DeedUWLLGiAAW1wksBdqdGYOTjaNLw==} + engines: {node: '>=10'} + cpu: [x64] + os: [darwin] + + '@swc/core-linux-arm-gnueabihf@1.15.21': + resolution: {integrity: sha512-meNI4Sh6h9h8DvIfEc0l5URabYMSuNvyisLmG6vnoYAS43s8ON3NJR8sDHvdP7NJTrLe0q/x2XCn6yL/BeHcZg==} + engines: {node: '>=10'} + cpu: [arm] + os: [linux] + + '@swc/core-linux-arm64-gnu@1.15.21': + resolution: {integrity: sha512-QrXlNQnHeXqU2EzLlnsPoWEh8/GtNJLvfMiPsDhk+ht6Xv8+vhvZ5YZ/BokNWSIZiWPKLAqR0M7T92YF5tmD3g==} + engines: {node: '>=10'} + cpu: [arm64] + os: [linux] + libc: [glibc] + + '@swc/core-linux-arm64-musl@1.15.21': + resolution: {integrity: sha512-8/yGCMO333ultDaMQivE5CjO6oXDPeeg1IV4sphojPkb0Pv0i6zvcRIkgp60xDB+UxLr6VgHgt+BBgqS959E9g==} + engines: {node: '>=10'} + cpu: [arm64] + os: [linux] + libc: [musl] + + '@swc/core-linux-ppc64-gnu@1.15.21': + resolution: {integrity: sha512-ucW0HzPx0s1dgRvcvuLSPSA/2Kk/VYTv9st8qe1Kc22Gu0Q0rH9+6TcBTmMuNIp0Xs4BPr1uBttmbO1wEGI49Q==} + engines: {node: '>=10'} + cpu: [ppc64] + os: [linux] + libc: [glibc] + + '@swc/core-linux-s390x-gnu@1.15.21': + resolution: {integrity: sha512-ulTnOGc5I7YRObE/9NreAhQg94QkiR5qNhhcUZ1iFAYjzg/JGAi1ch+s/Ixe61pMIr8bfVrF0NOaB0f8wjaAfA==} + engines: {node: '>=10'} + cpu: [s390x] + os: [linux] + libc: [glibc] + + '@swc/core-linux-x64-gnu@1.15.21': + resolution: {integrity: sha512-D0RokxtM+cPvSqJIKR6uja4hbD+scI9ezo95mBhfSyLUs9wnPPl26sLp1ZPR/EXRdYm3F3S6RUtVi+8QXhT24Q==} + engines: {node: '>=10'} + cpu: [x64] + os: [linux] + libc: [glibc] + + '@swc/core-linux-x64-musl@1.15.21': + resolution: {integrity: sha512-nER8u7VeRfmU6fMDzl1NQAbbB/G7O2avmvCOwIul1uGkZ2/acbPH+DCL9h5+0yd/coNcxMBTL6NGepIew+7C2w==} + engines: {node: '>=10'} + cpu: [x64] + os: [linux] + libc: [musl] + + '@swc/core-win32-arm64-msvc@1.15.21': + resolution: {integrity: sha512-+/AgNBnjYugUA8C0Do4YzymgvnGbztv7j8HKSQLvR/DQgZPoXQ2B3PqB2mTtGh/X5DhlJWiqnunN35JUgWcAeQ==} + engines: {node: '>=10'} + cpu: [arm64] + os: [win32] + + '@swc/core-win32-ia32-msvc@1.15.21': + resolution: {integrity: sha512-IkSZj8PX/N4HcaFhMQtzmkV8YSnuNoJ0E6OvMwFiOfejPhiKXvl7CdDsn1f4/emYEIDO3fpgZW9DTaCRMDxaDA==} + engines: {node: '>=10'} + cpu: [ia32] + os: [win32] + + '@swc/core-win32-x64-msvc@1.15.21': + resolution: {integrity: sha512-zUyWso7OOENB6e1N1hNuNn8vbvLsTdKQ5WKLgt/JcBNfJhKy/6jmBmqI3GXk/MyvQKd5SLvP7A0F36p7TeDqvw==} + engines: {node: '>=10'} + cpu: [x64] + os: [win32] + + '@swc/core@1.15.21': + resolution: {integrity: sha512-fkk7NJcBscrR3/F8jiqlMptRHP650NxqDnspBMrRe5d8xOoCy9MLL5kOBLFXjFLfMo3KQQHhk+/jUULOMlR1uQ==} + engines: {node: '>=10'} + peerDependencies: + '@swc/helpers': '>=0.5.17' + peerDependenciesMeta: + '@swc/helpers': + optional: true + + '@swc/counter@0.1.3': + resolution: {integrity: sha512-e2BR4lsJkkRlKZ/qCHPw9ZaSxc0MVUd7gtbtaB7aMvHeJVYe8sOB8DBZkP2DtISHGSku9sCK6T6cnY0CtXrOCQ==} + '@swc/helpers@0.5.15': resolution: {integrity: sha512-JQ5TuMi45Owi4/BIMAJBoSQoOJu12oOk/gADqlcUL9JEdHB8vyjUSsxqeNXnmXHjYKMi2WcYtezGEEhqUI/E2g==} + '@swc/types@0.1.26': + resolution: {integrity: sha512-lyMwd7WGgG79RS7EERZV3T8wMdmPq3xwyg+1nmAM64kIhx5yl+juO2PYIHb7vTiPgPCj8LYjsNV2T5wiQHUEaw==} + + '@swc/wasm@1.15.21': + resolution: {integrity: sha512-AVomFdpE9LiB8Q0dNo1UqpqGut//Q7HJNyyCzyHsywHSUM/1pKfzywIjdha4WipgjyOPebYb93pTDBUn2iWvVA==} + '@tailwindcss/node@4.1.18': resolution: {integrity: sha512-DoR7U1P7iYhw16qJ49fgXUlry1t4CpXeErJHnQ44JgTSKMaZUdf17cfn5mHchfJ4KRBZRFA/Coo+MUF5+gOaCQ==} @@ -6253,6 +6361,10 @@ packages: util-deprecate@1.0.2: resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==} + uuid@10.0.0: + resolution: {integrity: sha512-8XkAphELsDnEGrDxUOHB3RGvXz6TeuYSGEZBOjtTtPm2lwhGBjLgOzLHB63IUWfBpNucQjND6d3AOudO+H3RWQ==} + hasBin: true + validate-npm-package-name@7.0.2: resolution: {integrity: sha512-hVDIBwsRruT73PbK7uP5ebUt+ezEtCmzZz3F59BSr2F6OVFnJ/6h8liuvdLrQ88Xmnk6/+xGGuq+pG9WwTuy3A==} engines: {node: ^20.17.0 || >=22.9.0} @@ -6281,6 +6393,11 @@ packages: engines: {node: ^18.0.0 || ^20.0.0 || >=22.0.0} hasBin: true + vite-plugin-top-level-await@1.6.0: + resolution: {integrity: sha512-bNhUreLamTIkoulCR9aDXbTbhLk6n1YE8NJUTTxl5RYskNRtzOR0ASzSjBVRtNdjIfngDXo11qOsybGLNsrdww==} + peerDependencies: + vite: '>=2.8' + vite@6.4.1: resolution: {integrity: sha512-+Oxm7q9hDoLMyJOYfUYBuHQo+dkAloi33apOPP56pzj+vsdJDzr+j1NISE5pyaAuKL4A3UD34qd0lx5+kfKp2g==} engines: {node: ^18.0.0 || ^20.0.0 || >=22.0.0} @@ -9245,6 +9362,10 @@ snapshots: '@rolldown/pluginutils@1.0.0-beta.27': {} + '@rollup/plugin-virtual@3.0.2(rollup@4.59.0)': + optionalDependencies: + rollup: 4.59.0 + '@rollup/rollup-android-arm-eabi@4.59.0': optional: true @@ -9669,10 +9790,72 @@ snapshots: '@speed-highlight/core@1.2.14': {} + '@swc/core-darwin-arm64@1.15.21': + optional: true + + '@swc/core-darwin-x64@1.15.21': + optional: true + + '@swc/core-linux-arm-gnueabihf@1.15.21': + optional: true + + '@swc/core-linux-arm64-gnu@1.15.21': + optional: true + + '@swc/core-linux-arm64-musl@1.15.21': + optional: true + + '@swc/core-linux-ppc64-gnu@1.15.21': + optional: true + + '@swc/core-linux-s390x-gnu@1.15.21': + optional: true + + '@swc/core-linux-x64-gnu@1.15.21': + optional: true + + '@swc/core-linux-x64-musl@1.15.21': + optional: true + + '@swc/core-win32-arm64-msvc@1.15.21': + optional: true + + '@swc/core-win32-ia32-msvc@1.15.21': + optional: true + + '@swc/core-win32-x64-msvc@1.15.21': + optional: true + + '@swc/core@1.15.21': + dependencies: + '@swc/counter': 0.1.3 + '@swc/types': 0.1.26 + optionalDependencies: + '@swc/core-darwin-arm64': 1.15.21 + '@swc/core-darwin-x64': 1.15.21 + '@swc/core-linux-arm-gnueabihf': 1.15.21 + '@swc/core-linux-arm64-gnu': 1.15.21 + '@swc/core-linux-arm64-musl': 1.15.21 + '@swc/core-linux-ppc64-gnu': 1.15.21 + '@swc/core-linux-s390x-gnu': 1.15.21 + '@swc/core-linux-x64-gnu': 1.15.21 + '@swc/core-linux-x64-musl': 1.15.21 + '@swc/core-win32-arm64-msvc': 1.15.21 + '@swc/core-win32-ia32-msvc': 1.15.21 + '@swc/core-win32-x64-msvc': 1.15.21 + + '@swc/counter@0.1.3': {} + '@swc/helpers@0.5.15': dependencies: tslib: 2.8.1 + '@swc/types@0.1.26': + dependencies: + '@swc/counter': 0.1.3 + + '@swc/wasm@1.15.21': {} + '@tailwindcss/node@4.1.18': dependencies: '@jridgewell/remapping': 2.3.5 @@ -13697,6 +13880,8 @@ snapshots: util-deprecate@1.0.2: {} + uuid@10.0.0: {} + validate-npm-package-name@7.0.2: {} vary@1.1.2: {} @@ -13746,6 +13931,17 @@ snapshots: - tsx - yaml + vite-plugin-top-level-await@1.6.0(rollup@4.59.0)(vite@6.4.1(@types/node@25.0.10)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.16.9)(tsx@4.21.0)(yaml@2.8.2)): + dependencies: + '@rollup/plugin-virtual': 3.0.2(rollup@4.59.0) + '@swc/core': 1.15.21 + '@swc/wasm': 1.15.21 + uuid: 10.0.0 + vite: 6.4.1(@types/node@25.0.10)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.16.9)(tsx@4.21.0)(yaml@2.8.2) + transitivePeerDependencies: + - '@swc/helpers' + - rollup + vite@6.4.1(@types/node@25.0.10)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.16.9)(tsx@4.21.0)(yaml@2.8.2): dependencies: esbuild: 0.25.12