()
| 1062 | }; |
| 1063 | |
| 1064 | const installApplicationMenu = () => { |
| 1065 | const isMac = process.platform === "darwin"; |
| 1066 | const appMenu: MenuItemConstructorOptions = { |
| 1067 | label: app.name, |
| 1068 | submenu: [ |
| 1069 | { role: "about" }, |
| 1070 | { |
| 1071 | label: "Check for Updates…", |
| 1072 | click: () => void runUpdateCheck({ alertOnFail: true, trigger: "manual" }), |
| 1073 | }, |
| 1074 | { |
| 1075 | label: "Export Diagnostics…", |
| 1076 | click: () => void exportDiagnosticsInteractive(), |
| 1077 | }, |
| 1078 | { |
| 1079 | label: "Report a Problem…", |
| 1080 | click: () => void reportAProblem(), |
| 1081 | }, |
| 1082 | { |
| 1083 | label: "Documentation", |
| 1084 | click: () => void shell.openExternal("https://executor.sh/docs"), |
| 1085 | }, |
| 1086 | { type: "separator" }, |
| 1087 | ...(isMac |
| 1088 | ? ([ |
| 1089 | { role: "services" }, |
| 1090 | { type: "separator" }, |
| 1091 | { role: "hide" }, |
| 1092 | { role: "hideOthers" }, |
| 1093 | { role: "unhide" }, |
| 1094 | { type: "separator" }, |
| 1095 | ] as MenuItemConstructorOptions[]) |
| 1096 | : []), |
| 1097 | { role: "quit" }, |
| 1098 | ], |
| 1099 | }; |
| 1100 | // The close-window accelerator (Cmd+W on macOS, Ctrl+W elsewhere) lives on |
| 1101 | // the `close` role, which the File menu carries. The Window menu's role only |
| 1102 | // provides Minimize/Zoom/Front, so without an explicit File menu nothing |
| 1103 | // binds Cmd+W and the window can't be closed from the keyboard. |
| 1104 | const fileMenu: MenuItemConstructorOptions = { |
| 1105 | label: "File", |
| 1106 | submenu: [{ role: "close" }], |
| 1107 | }; |
| 1108 | // The web shell navigates with browser history (TanStack Router pushState), |
| 1109 | // but Electron binds none of the history shortcuts by default and the menu is |
| 1110 | // built from roles, none of which carry Back/Forward. So the standard macOS |
| 1111 | // Cmd+[ / Cmd+] (Ctrl+[ / Ctrl+] elsewhere) are dead keys inside the desktop |
| 1112 | // window, with no browser chrome to fall back on. Bind them here, driving the |
| 1113 | // focused window's navigation history. canGo* guards keep the keys no-ops at |
| 1114 | // the ends of the stack, matching how they behave in a browser. |
| 1115 | const navigateHistory = (direction: "back" | "forward") => { |
| 1116 | const nav = BrowserWindow.getFocusedWindow()?.webContents.navigationHistory; |
| 1117 | if (!nav) return; |
| 1118 | if (direction === "back") { |
| 1119 | if (nav.canGoBack()) nav.goBack(); |
| 1120 | } else if (nav.canGoForward()) { |
| 1121 | nav.goForward(); |
no test coverage detected