()
| 1110 | }; |
| 1111 | |
| 1112 | const installApplicationMenu = () => { |
| 1113 | const isMac = process.platform === "darwin"; |
| 1114 | const appMenu: MenuItemConstructorOptions = { |
| 1115 | label: app.name, |
| 1116 | submenu: [ |
| 1117 | { role: "about" }, |
| 1118 | { |
| 1119 | label: "Check for Updates…", |
| 1120 | click: () => void runUpdateCheck({ alertOnFail: true, trigger: "manual" }), |
| 1121 | }, |
| 1122 | { |
| 1123 | label: "Export Diagnostics…", |
| 1124 | click: () => void exportDiagnosticsInteractive(), |
| 1125 | }, |
| 1126 | { |
| 1127 | label: "Report a Problem…", |
| 1128 | click: () => void reportAProblem(), |
| 1129 | }, |
| 1130 | { |
| 1131 | label: "Documentation", |
| 1132 | click: () => void shell.openExternal("https://executor.sh/docs"), |
| 1133 | }, |
| 1134 | { type: "separator" }, |
| 1135 | ...(isMac |
| 1136 | ? ([ |
| 1137 | { role: "services" }, |
| 1138 | { type: "separator" }, |
| 1139 | { role: "hide" }, |
| 1140 | { role: "hideOthers" }, |
| 1141 | { role: "unhide" }, |
| 1142 | { type: "separator" }, |
| 1143 | ] as MenuItemConstructorOptions[]) |
| 1144 | : []), |
| 1145 | { role: "quit" }, |
| 1146 | ], |
| 1147 | }; |
| 1148 | // The close-window accelerator (Cmd+W on macOS, Ctrl+W elsewhere) lives on |
| 1149 | // the `close` role, which the File menu carries. The Window menu's role only |
| 1150 | // provides Minimize/Zoom/Front, so without an explicit File menu nothing |
| 1151 | // binds Cmd+W and the window can't be closed from the keyboard. |
| 1152 | const fileMenu: MenuItemConstructorOptions = { |
| 1153 | label: "File", |
| 1154 | submenu: [{ role: "close" }], |
| 1155 | }; |
| 1156 | // The web shell navigates with browser history (TanStack Router pushState), |
| 1157 | // but Electron binds none of the history shortcuts by default and the menu is |
| 1158 | // built from roles, none of which carry Back/Forward. So the standard macOS |
| 1159 | // Cmd+[ / Cmd+] (Ctrl+[ / Ctrl+] elsewhere) are dead keys inside the desktop |
| 1160 | // window, with no browser chrome to fall back on. Bind them here, driving the |
| 1161 | // focused window's navigation history. canGo* guards keep the keys no-ops at |
| 1162 | // the ends of the stack, matching how they behave in a browser. |
| 1163 | const navigateHistory = (direction: "back" | "forward") => { |
| 1164 | const nav = BrowserWindow.getFocusedWindow()?.webContents.navigationHistory; |
| 1165 | if (!nav) return; |
| 1166 | if (direction === "back") { |
| 1167 | if (nav.canGoBack()) nav.goBack(); |
| 1168 | } else if (nav.canGoForward()) { |
| 1169 | nav.goForward(); |
no test coverage detected