multiple instances
Some checks failed
CI / check (push) Has been cancelled

This commit is contained in:
2026-06-16 13:35:28 +02:00
parent 4b4676a673
commit 16296a27da

View File

@@ -1,5 +1,6 @@
import { join, resolve, sep } from 'node:path'
import { readFileSync, statSync } from 'node:fs'
import { spawn } from 'node:child_process'
import { app, dialog, shell, BrowserWindow, ipcMain, Menu } from 'electron'
import { watch, type FSWatcher } from 'chokidar'
import { addRecentProject, getName, getRecentProjects, getRoot, openDialog, setRoot } from './project'
@@ -27,6 +28,32 @@ function broadcast(channel: string): void {
for (const w of BrowserWindow.getAllWindows()) w.webContents.send(channel)
}
/**
* Each Helder window is one project, and one project owns global main-process
* state (root + FS/git/config watchers + PTYs). To run several projects beside
* each other we therefore spawn a *separate, detached* Helder process per window
* rather than opening a second BrowserWindow in this process.
*
* Spawning `process.execPath` directly also sidesteps macOS LaunchServices, which
* otherwise just re-activates the running instance when the bundle is launched
* again from Finder/Dock. `HELDER_PROJECT` points the child at a project (the
* child's `resolveInitialRoot` reads it); with no path it lands on the launcher.
*/
function spawnInstance(projectPath?: string): void {
const env = { ...process.env }
if (projectPath && safeIsDir(projectPath)) env.HELDER_PROJECT = resolve(projectPath)
else delete env.HELDER_PROJECT
// Packaged: execPath IS the app, no app path needed. Dev: replay our own argv
// (the electron-vite main entry) so the child loads the same app.
const args = app.isPackaged ? [] : process.argv.slice(1)
const child = spawn(process.execPath, args, { detached: true, stdio: 'ignore', env })
child.unref()
}
function safeIsDir(p: string): boolean {
try { return statSync(p).isDirectory() } catch { return false }
}
function startConfigWatcher(): void {
if (configWatcher) { configWatcher.close(); configWatcher = null }
const root = getRoot()
@@ -96,6 +123,11 @@ function buildAppMenu(): Menu {
{
label: 'File',
submenu: [
{
label: 'New Window',
accelerator: 'CmdOrCtrl+Shift+N',
click: () => spawnInstance(),
},
{
label: 'Open Folder…',
accelerator: 'CmdOrCtrl+O',