2026-03-13 00:27:36 +08:00
|
|
|
|
const { app, Tray, Menu, nativeImage } = require('electron');
|
2026-03-12 21:33:50 +08:00
|
|
|
|
const path = require('path');
|
2026-03-13 00:27:36 +08:00
|
|
|
|
const fs = require('fs');
|
2026-03-12 21:33:50 +08:00
|
|
|
|
const { spawn } = require('child_process');
|
|
|
|
|
|
|
2026-03-13 00:27:36 +08:00
|
|
|
|
let tray = null;
|
2026-03-13 00:52:19 +08:00
|
|
|
|
let serverPort = '3000';
|
2026-03-12 21:33:50 +08:00
|
|
|
|
|
|
|
|
|
|
function startServer() {
|
|
|
|
|
|
console.log('Starting OpenChamber server...');
|
|
|
|
|
|
|
2026-03-13 00:27:36 +08:00
|
|
|
|
let serverPath;
|
|
|
|
|
|
let cwdPath;
|
|
|
|
|
|
let execPath;
|
|
|
|
|
|
|
|
|
|
|
|
if (app.isPackaged) {
|
|
|
|
|
|
serverPath = path.join(process.resourcesPath, 'server', 'index.js');
|
|
|
|
|
|
cwdPath = path.join(process.resourcesPath);
|
|
|
|
|
|
execPath = path.join(process.resourcesPath, 'nodejs', 'node.exe');
|
|
|
|
|
|
} else {
|
|
|
|
|
|
serverPath = path.join(__dirname, '..', 'server', 'index.js');
|
|
|
|
|
|
cwdPath = path.join(__dirname, '..');
|
|
|
|
|
|
execPath = 'node';
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
console.log('Server path:', serverPath);
|
|
|
|
|
|
console.log('CWD:', cwdPath);
|
|
|
|
|
|
console.log('Exec:', execPath);
|
|
|
|
|
|
|
2026-03-13 00:52:19 +08:00
|
|
|
|
// 支持命令行参数或环境变量指定端口
|
|
|
|
|
|
const port = process.argv.find(arg => arg.startsWith('--port='))?.split('=')[1]
|
|
|
|
|
|
|| process.env.OPENCHAMBER_PORT
|
|
|
|
|
|
|| '3000';
|
2026-03-13 00:27:36 +08:00
|
|
|
|
|
2026-03-13 00:52:19 +08:00
|
|
|
|
serverPort = port;
|
|
|
|
|
|
console.log('Port:', port);
|
2026-03-13 00:27:36 +08:00
|
|
|
|
|
|
|
|
|
|
try {
|
2026-03-13 00:52:19 +08:00
|
|
|
|
// 设置环境变量
|
|
|
|
|
|
const env = { ...process.env };
|
|
|
|
|
|
env.OPENCHAMBER_PORT = port;
|
|
|
|
|
|
env.OPENCODE_SKIP_START = 'true';
|
|
|
|
|
|
|
|
|
|
|
|
// 直接 spawn,用命令行参数指定端口
|
|
|
|
|
|
const child = spawn(execPath, [serverPath, '--port=' + port], {
|
2026-03-13 00:27:36 +08:00
|
|
|
|
cwd: cwdPath,
|
|
|
|
|
|
stdio: 'inherit',
|
|
|
|
|
|
env: env,
|
2026-03-13 00:52:19 +08:00
|
|
|
|
windowsHide: true
|
2026-03-13 00:27:36 +08:00
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
child.on('error', (err) => {
|
|
|
|
|
|
console.error('Server error:', err);
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
child.on('exit', (code) => {
|
|
|
|
|
|
console.log('Server exited:', code);
|
|
|
|
|
|
});
|
|
|
|
|
|
} catch (e) {
|
|
|
|
|
|
console.error('Failed to start:', e);
|
|
|
|
|
|
}
|
2026-03-12 21:33:50 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2026-03-13 00:52:19 +08:00
|
|
|
|
function createTray(port) {
|
2026-03-13 00:27:36 +08:00
|
|
|
|
try {
|
|
|
|
|
|
let iconPath;
|
|
|
|
|
|
if (app.isPackaged) {
|
|
|
|
|
|
iconPath = path.join(process.resourcesPath, 'public', 'favicon.png');
|
|
|
|
|
|
} else {
|
|
|
|
|
|
iconPath = path.join(__dirname, '..', 'public', 'favicon.png');
|
2026-03-12 21:33:50 +08:00
|
|
|
|
}
|
2026-03-13 00:27:36 +08:00
|
|
|
|
|
|
|
|
|
|
let icon;
|
|
|
|
|
|
try {
|
|
|
|
|
|
icon = nativeImage.createFromPath(iconPath);
|
|
|
|
|
|
if (icon.isEmpty()) {
|
|
|
|
|
|
icon = nativeImage.createEmpty();
|
|
|
|
|
|
}
|
|
|
|
|
|
} catch (e) {
|
|
|
|
|
|
icon = nativeImage.createEmpty();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
tray = new Tray(icon);
|
|
|
|
|
|
|
|
|
|
|
|
const contextMenu = Menu.buildFromTemplate([
|
2026-03-13 00:52:19 +08:00
|
|
|
|
{ label: `OpenChamber Server (:${port})`, enabled: false },
|
2026-03-13 00:27:36 +08:00
|
|
|
|
{ type: 'separator' },
|
2026-03-13 00:52:19 +08:00
|
|
|
|
{ label: `Open http://localhost:${port}`, click: () => {
|
|
|
|
|
|
require('electron').shell.openExternal(`http://localhost:${port}`);
|
2026-03-13 00:27:36 +08:00
|
|
|
|
}},
|
|
|
|
|
|
{ type: 'separator' },
|
|
|
|
|
|
{ label: 'Quit', click: () => {
|
|
|
|
|
|
app.quit();
|
|
|
|
|
|
}}
|
|
|
|
|
|
]);
|
|
|
|
|
|
|
2026-03-13 00:52:19 +08:00
|
|
|
|
tray.setToolTip(`OpenChamber Server (:${port})`);
|
2026-03-13 00:27:36 +08:00
|
|
|
|
tray.setContextMenu(contextMenu);
|
|
|
|
|
|
} catch (e) {
|
|
|
|
|
|
console.error('Failed to create tray:', e);
|
|
|
|
|
|
}
|
2026-03-12 21:33:50 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
app.whenReady().then(() => {
|
|
|
|
|
|
startServer();
|
2026-03-13 00:52:19 +08:00
|
|
|
|
createTray(serverPort);
|
2026-03-12 21:33:50 +08:00
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
app.on('window-all-closed', () => {
|
|
|
|
|
|
app.quit();
|
|
|
|
|
|
});
|