menu.ts
1 import { app, BrowserWindow, Menu, MenuItemConstructorOptions, shell } from 'electron' 2 import { RuntimePaths } from './paths' 3 4 export function buildAppMenu(paths: RuntimePaths, getWindow: () => BrowserWindow | null): void { 5 const isMac = process.platform === 'darwin' 6 7 const macAppMenu: MenuItemConstructorOptions = { 8 label: app.name, 9 submenu: [ 10 { role: 'about' }, 11 { type: 'separator' }, 12 { role: 'services' }, 13 { type: 'separator' }, 14 { role: 'hide' }, 15 { role: 'hideOthers' }, 16 { role: 'unhide' }, 17 { type: 'separator' }, 18 { role: 'quit' }, 19 ], 20 } 21 22 const fileMenu: MenuItemConstructorOptions = { 23 label: 'File', 24 submenu: [ 25 { 26 label: 'Open Data Folder', 27 click: () => void shell.openPath(paths.swarmclawHome), 28 }, 29 { type: 'separator' }, 30 isMac ? { role: 'close' } : { role: 'quit' }, 31 ], 32 } 33 34 const editMenu: MenuItemConstructorOptions = { 35 label: 'Edit', 36 submenu: [ 37 { role: 'undo' }, 38 { role: 'redo' }, 39 { type: 'separator' }, 40 { role: 'cut' }, 41 { role: 'copy' }, 42 { role: 'paste' }, 43 { role: 'selectAll' }, 44 ], 45 } 46 47 const viewMenu: MenuItemConstructorOptions = { 48 label: 'View', 49 submenu: [ 50 { 51 label: 'Reload', 52 accelerator: isMac ? 'Cmd+R' : 'Ctrl+R', 53 click: () => getWindow()?.webContents.reload(), 54 }, 55 { 56 label: 'Force Reload', 57 accelerator: isMac ? 'Shift+Cmd+R' : 'Ctrl+Shift+R', 58 click: () => getWindow()?.webContents.reloadIgnoringCache(), 59 }, 60 { type: 'separator' }, 61 { role: 'resetZoom' }, 62 { role: 'zoomIn' }, 63 { role: 'zoomOut' }, 64 { type: 'separator' }, 65 { role: 'togglefullscreen' }, 66 { role: 'toggleDevTools' }, 67 ], 68 } 69 70 const windowMenu: MenuItemConstructorOptions = { 71 label: 'Window', 72 submenu: isMac 73 ? [ 74 { role: 'minimize' }, 75 { role: 'zoom' }, 76 { type: 'separator' }, 77 { role: 'front' }, 78 ] 79 : [{ role: 'minimize' }, { role: 'close' }], 80 } 81 82 const helpMenu: MenuItemConstructorOptions = { 83 role: 'help', 84 submenu: [ 85 { 86 label: 'SwarmClaw Website', 87 click: () => void shell.openExternal('https://swarmclaw.ai'), 88 }, 89 { 90 label: 'Documentation', 91 click: () => void shell.openExternal('https://swarmclaw.ai/docs'), 92 }, 93 { 94 label: 'Report an Issue', 95 click: () => void shell.openExternal('https://github.com/swarmclawai/swarmclaw/issues'), 96 }, 97 ], 98 } 99 100 const template: MenuItemConstructorOptions[] = [ 101 ...(isMac ? [macAppMenu] : []), 102 fileMenu, 103 editMenu, 104 viewMenu, 105 windowMenu, 106 helpMenu, 107 ] 108 109 Menu.setApplicationMenu(Menu.buildFromTemplate(template)) 110 }