diff --git a/src/main/main.ts b/src/main/main.ts index 1a45778..37c775f 100644 --- a/src/main/main.ts +++ b/src/main/main.ts @@ -20,6 +20,12 @@ const mainDashboardUrl = `http://localhost:${appConfig.nodecgPort}/bundles/${app const loadingDashboardUrl = `http://localhost:${appConfig.nodecgPort}/bundles/${appConfig.bundleName}/${appConfig.loadingDashboardRoute}`; const nodecgBaseUrl = `http://127.0.0.1:${appConfig.nodecgPort}`; +const hasSingleInstanceLock = app.requestSingleInstanceLock(); + +if (!hasSingleInstanceLock) { + app.quit(); +} + const nodecgManager = createNodecgProcessManager({ isDev, nodecgRootPath, @@ -34,6 +40,21 @@ let mainWindow: BrowserWindow | null = null; let loadingWindow: BrowserWindow | null = null; let shutdownState: AppShutdownState = "running"; +function focusExistingWindow(): void { + const targetWindow = mainWindow && !mainWindow.isDestroyed() ? mainWindow : loadingWindow; + + if (!targetWindow || targetWindow.isDestroyed()) { + return; + } + + if (targetWindow.isMinimized()) { + targetWindow.restore(); + } + + targetWindow.show(); + targetWindow.focus(); +} + async function launchApplication(): Promise { // We create both windows early so startup feels instant while NodeCG is booting in the background. mainWindow = createMainWindow({ appConfig, rootPath, mainDashboardUrl }); @@ -100,6 +121,10 @@ function stopNodecgGracefully(): Promise { } app.on("ready", () => { + if (!hasSingleInstanceLock) { + return; + } + if (process.platform === "win32") { app.setAppUserModelId(appConfig.userModelId); } @@ -111,6 +136,10 @@ app.on("ready", () => { }); }); +app.on("second-instance", () => { + focusExistingWindow(); +}); + app.on("activate", async () => { if (BrowserWindow.getAllWindows().length === 0) { mainWindow = createMainWindow({ appConfig, rootPath, mainDashboardUrl });