mirror of
https://github.com/DayuanJiang/next-ai-draw-io.git
synced 2026-10-13 04:59:51 +08:00
- delete electron/settings, the settings preload and window, the config-presets IPC channels, the Configuration menu and the preset watcher in scripts/electron-dev.mjs; config-manager.ts keeps only the user locale (still read from config-presets.json so the saved language survives) - electron/main/env-loader.ts parses .env with dotenv instead of a hand-written parser; electron:compile bundles dependencies - drop the unreachable development branches in port-manager.ts and next-server.ts, the duplicated locale normalisation in menu-i18n.ts, the unused electronAPI members, resources/entitlements.mac.plist - scripts/copy-dereferenced.cjs shared by afterPack and prepare-electron-build - CI: delete ci.yml, move type check and concurrency into test.yml, Node 24 everywhere, docker-build only on main - remove unused dependencies (@xmldom/xmldom, remark-gfm, @anthropic-ai/tokenizer, @testing-library/user-event, concurrently, wait-on, eslint, eslint-config-next, @vitest/coverage-v8, shx), .eslintrc.json and the vitest coverage block
133 lines
3.9 KiB
TypeScript
133 lines
3.9 KiB
TypeScript
import { app, BrowserWindow, dialog, shell } from "electron"
|
|
import { buildAppMenu } from "./app-menu"
|
|
import { loadEnvFile } from "./env-loader"
|
|
import { registerIpcHandlers } from "./ipc-handlers"
|
|
import { startNextServer, stopNextServer } from "./next-server"
|
|
import { applyProxyToEnv } from "./proxy-manager"
|
|
import {
|
|
createWindow,
|
|
getAppUrl,
|
|
getMainWindow,
|
|
isAppUrl,
|
|
} from "./window-manager"
|
|
|
|
// Single instance lock
|
|
const gotTheLock = app.requestSingleInstanceLock()
|
|
|
|
if (!gotTheLock) {
|
|
app.quit()
|
|
} else {
|
|
app.on("second-instance", () => {
|
|
const mainWindow = getMainWindow()
|
|
if (mainWindow) {
|
|
if (mainWindow.isMinimized()) mainWindow.restore()
|
|
mainWindow.focus()
|
|
}
|
|
})
|
|
|
|
// Load environment variables from .env files
|
|
loadEnvFile()
|
|
|
|
// Apply proxy settings from saved config
|
|
applyProxyToEnv()
|
|
|
|
const isDev = !app.isPackaged
|
|
|
|
app.whenReady().then(async () => {
|
|
// Register IPC handlers
|
|
registerIpcHandlers()
|
|
|
|
// Build application menu
|
|
buildAppMenu()
|
|
|
|
try {
|
|
let serverUrl: string
|
|
if (isDev) {
|
|
// Development: use the dev server URL
|
|
serverUrl =
|
|
process.env.ELECTRON_DEV_URL || "http://localhost:6002"
|
|
console.log(`Development mode: connecting to ${serverUrl}`)
|
|
} else {
|
|
// Production: start Next.js standalone server
|
|
serverUrl = await startNextServer()
|
|
}
|
|
|
|
// Create main window
|
|
createWindow(serverUrl)
|
|
} catch (error) {
|
|
console.error("Failed to start application:", error)
|
|
dialog.showErrorBox(
|
|
"Startup Error",
|
|
`Failed to start the application: ${error instanceof Error ? error.message : "Unknown error"}`,
|
|
)
|
|
app.quit()
|
|
}
|
|
|
|
app.on("activate", () => {
|
|
if (BrowserWindow.getAllWindows().length === 0) {
|
|
const appUrl = getAppUrl()
|
|
if (appUrl) {
|
|
createWindow(appUrl)
|
|
}
|
|
}
|
|
})
|
|
})
|
|
|
|
app.on("window-all-closed", () => {
|
|
if (process.platform !== "darwin") {
|
|
stopNextServer()
|
|
app.quit()
|
|
}
|
|
})
|
|
|
|
app.on("before-quit", () => {
|
|
stopNextServer()
|
|
})
|
|
|
|
// Pages allowed inside app windows: the app server and draw.io
|
|
const isInAppUrl = (url: string): boolean => {
|
|
if (isAppUrl(url)) return true
|
|
try {
|
|
const { hostname } = new URL(url)
|
|
return ["diagrams.net", "draw.io"].some(
|
|
(domain) =>
|
|
hostname === domain || hostname.endsWith(`.${domain}`),
|
|
)
|
|
} catch {
|
|
return false
|
|
}
|
|
}
|
|
|
|
const isWebUrl = (url: string): boolean =>
|
|
url.startsWith("http://") || url.startsWith("https://")
|
|
|
|
// Open external links in default browser
|
|
app.on("web-contents-created", (_, contents) => {
|
|
contents.setWindowOpenHandler(({ url }) => {
|
|
if (isInAppUrl(url)) {
|
|
return { action: "allow" }
|
|
}
|
|
// Open other links in external browser
|
|
if (isWebUrl(url)) {
|
|
shell.openExternal(url)
|
|
return { action: "deny" }
|
|
}
|
|
return { action: "allow" }
|
|
})
|
|
|
|
// Clicking a plain link would otherwise replace the app page with
|
|
// an external site that keeps the preload API. Only the page
|
|
// itself may navigate there; draw.io stays in its frame (this event
|
|
// is for the main frame only)
|
|
contents.on("will-navigate", (event) => {
|
|
if (isAppUrl(event.url)) {
|
|
return
|
|
}
|
|
event.preventDefault()
|
|
if (isWebUrl(event.url)) {
|
|
shell.openExternal(event.url)
|
|
}
|
|
})
|
|
})
|
|
}
|