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