feat: add Electron desktop app wrapper
This commit is contained in:
127
electron/main.cjs
Normal file
127
electron/main.cjs
Normal file
@@ -0,0 +1,127 @@
|
||||
const { app, BrowserWindow, dialog, shell } = require("electron");
|
||||
const { spawn } = require("node:child_process");
|
||||
const fs = require("node:fs");
|
||||
const path = require("node:path");
|
||||
const readline = require("node:readline");
|
||||
|
||||
let mainWindow = null;
|
||||
let backendProcess = null;
|
||||
|
||||
app.disableHardwareAcceleration();
|
||||
app.commandLine.appendSwitch("ozone-platform-hint", "auto");
|
||||
|
||||
function backendBinary() {
|
||||
const candidates = [
|
||||
path.join(process.resourcesPath || "", "bin", "lazy-update-manager"),
|
||||
path.join(app.getAppPath(), "bin", "lazy-update-manager"),
|
||||
path.join(app.getAppPath(), "..", "bin", "lazy-update-manager"),
|
||||
];
|
||||
|
||||
for (const candidate of candidates) {
|
||||
if (candidate && fs.existsSync(candidate)) {
|
||||
return candidate;
|
||||
}
|
||||
}
|
||||
|
||||
return "lazy-update-manager";
|
||||
}
|
||||
|
||||
function startBackend() {
|
||||
return new Promise((resolve, reject) => {
|
||||
const binary = backendBinary();
|
||||
backendProcess = spawn(binary, ["gui", "-no-open"], {
|
||||
stdio: ["ignore", "pipe", "pipe"],
|
||||
env: process.env,
|
||||
});
|
||||
|
||||
let stderr = "";
|
||||
const rl = readline.createInterface({ input: backendProcess.stdout });
|
||||
|
||||
const timeout = setTimeout(() => {
|
||||
reject(new Error("Backend did not report a GUI URL."));
|
||||
}, 8000);
|
||||
|
||||
rl.on("line", (line) => {
|
||||
const match = line.match(/LazyUpdateManager GUI:\s+(http:\/\/127\.0\.0\.1:\d+)/);
|
||||
if (!match) {
|
||||
return;
|
||||
}
|
||||
|
||||
clearTimeout(timeout);
|
||||
resolve(match[1]);
|
||||
});
|
||||
|
||||
backendProcess.stderr.on("data", (chunk) => {
|
||||
stderr += chunk.toString();
|
||||
});
|
||||
|
||||
backendProcess.on("error", (error) => {
|
||||
clearTimeout(timeout);
|
||||
reject(error);
|
||||
});
|
||||
|
||||
backendProcess.on("exit", (code) => {
|
||||
if (mainWindow) {
|
||||
return;
|
||||
}
|
||||
clearTimeout(timeout);
|
||||
reject(new Error(stderr || `Backend exited with code ${code}`));
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
async function createWindow() {
|
||||
const url = await startBackend();
|
||||
|
||||
mainWindow = new BrowserWindow({
|
||||
width: 1180,
|
||||
height: 760,
|
||||
minWidth: 860,
|
||||
minHeight: 560,
|
||||
title: "LazyUpdateManager",
|
||||
backgroundColor: "#101114",
|
||||
autoHideMenuBar: true,
|
||||
webPreferences: {
|
||||
contextIsolation: true,
|
||||
nodeIntegration: false,
|
||||
sandbox: true,
|
||||
},
|
||||
});
|
||||
|
||||
mainWindow.webContents.setWindowOpenHandler(({ url: targetURL }) => {
|
||||
shell.openExternal(targetURL);
|
||||
return { action: "deny" };
|
||||
});
|
||||
|
||||
await mainWindow.loadURL(url);
|
||||
}
|
||||
|
||||
function stopBackend() {
|
||||
if (!backendProcess || backendProcess.killed) {
|
||||
return;
|
||||
}
|
||||
|
||||
backendProcess.kill("SIGTERM");
|
||||
backendProcess = null;
|
||||
}
|
||||
|
||||
app.whenReady().then(async () => {
|
||||
try {
|
||||
await createWindow();
|
||||
} catch (error) {
|
||||
await dialog.showMessageBox({
|
||||
type: "error",
|
||||
title: "LazyUpdateManager",
|
||||
message: "Die Desktop-App konnte nicht gestartet werden.",
|
||||
detail: error.message,
|
||||
});
|
||||
app.quit();
|
||||
}
|
||||
});
|
||||
|
||||
app.on("window-all-closed", () => {
|
||||
stopBackend();
|
||||
app.quit();
|
||||
});
|
||||
|
||||
app.on("before-quit", stopBackend);
|
||||
Reference in New Issue
Block a user