From 87efd274593c1e104f839e5e103d39dcd39f341e Mon Sep 17 00:00:00 2001 From: Brendan Allan Date: Tue, 16 Dec 2025 18:33:04 +0800 Subject: [PATCH] tauri: macos-only app menu --- packages/tauri/scripts/predev.ts | 1 - packages/tauri/src/index.tsx | 8 ++- packages/tauri/src/menu.ts | 94 ++++++++++++++++++++++++++++++++ packages/tauri/src/updater.ts | 2 + 4 files changed, 102 insertions(+), 3 deletions(-) create mode 100644 packages/tauri/src/menu.ts diff --git a/packages/tauri/scripts/predev.ts b/packages/tauri/scripts/predev.ts index 6b69a3ae5..218215197 100644 --- a/packages/tauri/scripts/predev.ts +++ b/packages/tauri/scripts/predev.ts @@ -1,4 +1,3 @@ -import * as fs from "node:fs/promises" import { $ } from "bun" import { copyBinaryToSidecarFolder, getCurrentSidecar } from "./utils" diff --git a/packages/tauri/src/index.tsx b/packages/tauri/src/index.tsx index 84ba73c07..f3c329b34 100644 --- a/packages/tauri/src/index.tsx +++ b/packages/tauri/src/index.tsx @@ -1,12 +1,14 @@ // @refresh reload import { render } from "solid-js/web" import { App, PlatformProvider, Platform } from "@opencode-ai/desktop" -import { runUpdater } from "./updater" import { onMount } from "solid-js" import { open, save } from "@tauri-apps/plugin-dialog" import { open as shellOpen } from "@tauri-apps/plugin-shell" import { type as ostype } from "@tauri-apps/plugin-os" +import { runUpdater, UPDATER_ENABLED } from "./updater" +import { createMenu } from "./menu" + const root = document.getElementById("root") if (import.meta.env.DEV && !(root instanceof HTMLElement)) { throw new Error( @@ -48,9 +50,11 @@ const platform: Platform = { }, } +createMenu() + render(() => { onMount(() => { - if (window.__OPENCODE__?.updaterEnabled) runUpdater() + if (UPDATER_ENABLED) runUpdater() }) return ( diff --git a/packages/tauri/src/menu.ts b/packages/tauri/src/menu.ts new file mode 100644 index 000000000..72ba9b754 --- /dev/null +++ b/packages/tauri/src/menu.ts @@ -0,0 +1,94 @@ +import { Menu, MenuItem, PredefinedMenuItem, Submenu } from "@tauri-apps/api/menu" +import { type as ostype } from "@tauri-apps/plugin-os" + +import { runUpdater, UPDATER_ENABLED } from "./updater" + +export async function createMenu() { + if (ostype() !== "macos") return; + + const menu = await Menu.new({ + items: [ + await Submenu.new({ + text: "OpenCode", + items: [ + await PredefinedMenuItem.new({ + item: { About: null }, + }), + await MenuItem.new({ + enabled: UPDATER_ENABLED, + action: () => runUpdater(), + text: "Check For Updates...", + }), + await PredefinedMenuItem.new({ + item: "Separator", + }), + await PredefinedMenuItem.new({ + item: "Hide", + }), + await PredefinedMenuItem.new({ + item: "HideOthers", + }), + await PredefinedMenuItem.new({ + item: "ShowAll", + }), + await PredefinedMenuItem.new({ + item: "Separator", + }), + await PredefinedMenuItem.new({ + item: "Quit", + }), + ].filter(Boolean), + }), + // await Submenu.new({ + // text: "File", + // items: [ + // await MenuItem.new({ + // enabled: false, + // text: "Open Project...", + // }), + // await PredefinedMenuItem.new({ + // item: "Separator" + // }), + // await MenuItem.new({ + // enabled: false, + // text: "New Session", + // }), + // await PredefinedMenuItem.new({ + // item: "Separator" + // }), + // await MenuItem.new({ + // enabled: false, + // text: "Close Project", + // }) + // ] + // }), + await Submenu.new({ + text: "Edit", + items: [ + await PredefinedMenuItem.new({ + item: "Undo", + }), + await PredefinedMenuItem.new({ + item: "Redo", + }), + await PredefinedMenuItem.new({ + item: "Separator", + }), + await PredefinedMenuItem.new({ + item: "Cut", + }), + await PredefinedMenuItem.new({ + item: "Copy", + }), + await PredefinedMenuItem.new({ + item: "Paste", + }), + await PredefinedMenuItem.new({ + item: "SelectAll", + }), + ], + }), + ], + }) + menu.setAsAppMenu() +} diff --git a/packages/tauri/src/updater.ts b/packages/tauri/src/updater.ts index 0d3737d1e..d62aae424 100644 --- a/packages/tauri/src/updater.ts +++ b/packages/tauri/src/updater.ts @@ -2,6 +2,8 @@ import { check, DownloadEvent } from "@tauri-apps/plugin-updater" import { relaunch } from "@tauri-apps/plugin-process" import { ask, message } from "@tauri-apps/plugin-dialog" +export const UPDATER_ENABLED = window.__OPENCODE__?.updaterEnabled ?? false + export async function runUpdater(onDownloadEvent?: (progress: DownloadEvent) => void) { let update try {