desktop: add electron version (#15663)

This commit is contained in:
Brendan Allan
2026-03-04 15:12:34 +08:00
committed by GitHub
parent e4f0825c56
commit 5cf235fa6c
223 changed files with 4293 additions and 47 deletions

View File

@@ -0,0 +1,135 @@
import windowState from "electron-window-state"
import { app, BrowserWindow, nativeImage } from "electron"
import { dirname, join } from "node:path"
import { fileURLToPath } from "node:url"
type Globals = {
updaterEnabled: boolean
wsl: boolean
deepLinks?: string[]
}
const root = dirname(fileURLToPath(import.meta.url))
function iconsDir() {
return app.isPackaged ? join(process.resourcesPath, "icons") : join(root, "../../resources/icons")
}
function iconPath() {
const ext = process.platform === "win32" ? "ico" : "png"
return join(iconsDir(), `icon.${ext}`)
}
export function setDockIcon() {
if (process.platform !== "darwin") return
app.dock?.setIcon(nativeImage.createFromPath(join(iconsDir(), "128x128@2x.png")))
}
export function createMainWindow(globals: Globals) {
const state = windowState({
defaultWidth: 1280,
defaultHeight: 800,
})
const win = new BrowserWindow({
x: state.x,
y: state.y,
width: state.width,
height: state.height,
show: true,
title: "OpenCode",
icon: iconPath(),
...(process.platform === "darwin"
? {
titleBarStyle: "hidden" as const,
trafficLightPosition: { x: 12, y: 14 },
}
: {}),
...(process.platform === "win32"
? {
frame: false,
titleBarStyle: "hidden" as const,
titleBarOverlay: {
color: "transparent",
symbolColor: "#999",
height: 40,
},
}
: {}),
webPreferences: {
preload: join(root, "../preload/index.mjs"),
sandbox: false,
},
})
state.manage(win)
loadWindow(win, "index.html")
wireZoom(win)
injectGlobals(win, globals)
return win
}
export function createLoadingWindow(globals: Globals) {
const win = new BrowserWindow({
width: 640,
height: 480,
resizable: false,
center: true,
show: true,
icon: iconPath(),
...(process.platform === "darwin" ? { titleBarStyle: "hidden" as const } : {}),
...(process.platform === "win32"
? {
frame: false,
titleBarStyle: "hidden" as const,
titleBarOverlay: {
color: "transparent",
symbolColor: "#999",
height: 40,
},
}
: {}),
webPreferences: {
preload: join(root, "../preload/index.mjs"),
sandbox: false,
},
})
loadWindow(win, "loading.html")
injectGlobals(win, globals)
return win
}
function loadWindow(win: BrowserWindow, html: string) {
const devUrl = process.env.ELECTRON_RENDERER_URL
if (devUrl) {
const url = new URL(html, devUrl)
void win.loadURL(url.toString())
return
}
void win.loadFile(join(root, `../renderer/${html}`))
}
function injectGlobals(win: BrowserWindow, globals: Globals) {
win.webContents.on("dom-ready", () => {
const deepLinks = globals.deepLinks ?? []
const data = {
updaterEnabled: globals.updaterEnabled,
wsl: globals.wsl,
deepLinks: Array.isArray(deepLinks) ? deepLinks.splice(0) : deepLinks,
}
void win.webContents.executeJavaScript(
`window.__OPENCODE__ = Object.assign(window.__OPENCODE__ ?? {}, ${JSON.stringify(data)})`,
)
})
}
function wireZoom(win: BrowserWindow) {
win.webContents.setZoomFactor(1)
win.webContents.on("zoom-changed", () => {
win.webContents.setZoomFactor(1)
})
}