mirror of
https://gitee.com/zhangsken/opencode.git
synced 2026-10-16 10:30:01 +08:00
90 lines
2.9 KiB
TypeScript
90 lines
2.9 KiB
TypeScript
import { BrowserWindow, Menu } from "electron"
|
|
import type { MenuItemConstructorOptions } from "electron"
|
|
import {
|
|
DESKTOP_MENU,
|
|
desktopMenuVisible,
|
|
type DesktopMenuEntry,
|
|
type DesktopMenuRole,
|
|
} from "@opencode/app/desktop-menu"
|
|
import { MenuCommandTriggered } from "../../shared/ipc-rpc/events"
|
|
import { emitIpcEvent } from "../ipc-events"
|
|
|
|
import { CHANNEL, UPDATER_ENABLED } from "../constants"
|
|
import { runDesktopMenuAction } from "./menu-actions"
|
|
import { nativeT } from "./translations"
|
|
import { createMenuQueue } from "./menu-queue"
|
|
import type { MenuCommand } from "../../shared/menu-command"
|
|
|
|
export const menuCommands = createMenuQueue<BrowserWindow, MenuCommand>((win, command) => {
|
|
emitIpcEvent(win.webContents, new MenuCommandTriggered({ command }))
|
|
})
|
|
|
|
type Deps = {
|
|
trigger: (id: string) => void
|
|
checkForUpdates: () => void
|
|
installCli: () => void
|
|
createWindow: () => void
|
|
openExternal: (url: string) => void
|
|
relaunch: () => void
|
|
}
|
|
|
|
export function createMenu(deps: Deps) {
|
|
if (process.platform !== "darwin") return
|
|
|
|
const template = DESKTOP_MENU.filter((menu) => desktopMenuVisible(menu, "macos")).map((menu) => {
|
|
if (menu.role) return { role: nativeRole(menu.role), label: nativeT(menu.labelKey) }
|
|
return {
|
|
label: nativeT(menu.labelKey),
|
|
submenu: menu.items
|
|
?.filter((entry) => desktopMenuVisible(entry, "macos"))
|
|
.map((entry) => nativeItem(entry, deps)),
|
|
}
|
|
})
|
|
|
|
Menu.setApplicationMenu(Menu.buildFromTemplate(template))
|
|
}
|
|
|
|
export function sendMenuCommand(win: BrowserWindow, id: string) {
|
|
menuCommands.trigger(win, { type: "command", id })
|
|
}
|
|
|
|
function nativeItem(entry: DesktopMenuEntry, deps: Deps): MenuItemConstructorOptions {
|
|
if (entry.type === "separator") return { type: "separator" }
|
|
if (entry.role) return { role: nativeRole(entry.role), label: entry.labelKey ? nativeT(entry.labelKey) : undefined }
|
|
|
|
const item: MenuItemConstructorOptions = {
|
|
label: entry.labelKey ? nativeT(entry.labelKey) : undefined,
|
|
accelerator: entry.accelerator?.macos,
|
|
enabled: entry.enabled === "updater" ? UPDATER_ENABLED : undefined,
|
|
}
|
|
|
|
if (entry.command) {
|
|
const command = entry.command
|
|
item.click = () => deps.trigger(command)
|
|
}
|
|
if (entry.action) {
|
|
const action = entry.action
|
|
if (action === "app.checkForUpdates" && CHANNEL === "beta") {
|
|
item.click = () => deps.trigger(action)
|
|
return item
|
|
}
|
|
item.click = () =>
|
|
runDesktopMenuAction(BrowserWindow.getFocusedWindow(), action, {
|
|
checkForUpdates: deps.checkForUpdates,
|
|
installCli: deps.installCli,
|
|
createWindow: deps.createWindow,
|
|
relaunch: deps.relaunch,
|
|
})
|
|
}
|
|
if (entry.href) {
|
|
const href = entry.href
|
|
item.click = () => deps.openExternal(href)
|
|
}
|
|
|
|
return item
|
|
}
|
|
|
|
function nativeRole(role: DesktopMenuRole) {
|
|
return role as NonNullable<MenuItemConstructorOptions["role"]>
|
|
}
|