From 7dc91d59351bb4c8d126c6cd6dd3972a34553c2a Mon Sep 17 00:00:00 2001 From: Michael Neale Date: Thu, 30 Oct 2025 16:02:30 +1100 Subject: [PATCH] first cut at autostart and also cleanup --- ui/desktop/src/main.ts | 14 +++++++++++++ ui/desktop/src/utils/settings.ts | 1 + ui/desktop/src/utils/tunnel.ts | 36 ++++++++++++++++++++++++++++++-- 3 files changed, 49 insertions(+), 2 deletions(-) diff --git a/ui/desktop/src/main.ts b/ui/desktop/src/main.ts index 66769de145..2048a9d69e 100644 --- a/ui/desktop/src/main.ts +++ b/ui/desktop/src/main.ts @@ -1769,6 +1769,10 @@ async function appMain() { app.dock?.hide(); } + // Setup tunnel cleanup on app quit + const { setupTunnelCleanup } = await import('./utils/tunnel'); + setupTunnelCleanup(app); + // Parse command line arguments const { dirPath } = parseArgs(); @@ -2193,6 +2197,16 @@ async function appMain() { app.whenReady().then(async () => { try { await appMain(); + + // Auto-start tunnel if it was running when app closed (with delay to ensure window is loaded) + setTimeout(async () => { + try { + const { autoStartTunnel } = await import('./utils/tunnel'); + await autoStartTunnel(); + } catch (error) { + log.error('Failed to auto-start tunnel:', error); + } + }, 10000); // 10 second delay } catch (error) { dialog.showErrorBox('Goose Error', `Failed to create main window: ${error}`); app.quit(); diff --git a/ui/desktop/src/utils/settings.ts b/ui/desktop/src/utils/settings.ts index 1c0b449ef3..4b06d143cb 100644 --- a/ui/desktop/src/utils/settings.ts +++ b/ui/desktop/src/utils/settings.ts @@ -20,6 +20,7 @@ export interface Settings { tunnelSecret?: string; tunnelAgentId?: string; tunnelMode?: TunnelMode; + tunnelAutoStart?: boolean; } // Constants diff --git a/ui/desktop/src/utils/tunnel.ts b/ui/desktop/src/utils/tunnel.ts index 849a54e722..fd73bcf3d1 100644 --- a/ui/desktop/src/utils/tunnel.ts +++ b/ui/desktop/src/utils/tunnel.ts @@ -225,6 +225,12 @@ export async function startTunnel(): Promise { currentTunnelInfo = startLapstoneTunnel(port, secret, goosedProcess.pid || 0); currentState = 'running'; log.info('Lapstone tunnel started successfully:', currentTunnelInfo); + + // Save auto-start setting when tunnel starts + const settings = loadSettings(); + settings.tunnelAutoStart = true; + saveSettings(settings); + return currentTunnelInfo; } @@ -280,6 +286,12 @@ export async function startTunnel(): Promise { currentState = 'running'; log.info('Tunnel started successfully:', currentTunnelInfo); + + // Save auto-start setting when tunnel starts + const settings = loadSettings(); + settings.tunnelAutoStart = true; + saveSettings(settings); + return currentTunnelInfo; } catch (error) { currentState = 'error'; @@ -293,7 +305,7 @@ export async function startTunnel(): Promise { } } -export function stopTunnel(): void { +export function stopTunnel(clearAutoStart: boolean = true): void { // Stop Lapstone tunnel if active stopLapstoneTunnel(); @@ -326,6 +338,13 @@ export function stopTunnel(): void { currentState = 'idle'; currentTunnelInfo = null; + // Only clear auto-start setting when manually stopping (not on app quit) + if (clearAutoStart) { + const settings = loadSettings(); + settings.tunnelAutoStart = false; + saveSettings(settings); + } + // Clean up output file if (outputFilePath && fs.existsSync(outputFilePath)) { try { @@ -348,6 +367,19 @@ export function getTunnelStatus(): { state: TunnelState; info: TunnelInfo | null export function setupTunnelCleanup(electronApp: App): void { electronApp.on('will-quit', () => { log.info('App quitting, stopping tunnel if running'); - stopTunnel(); + stopTunnel(false); // Don't clear auto-start flag on quit }); } + +// Auto-start tunnel if it was running when app closed +export async function autoStartTunnel(): Promise { + const settings = loadSettings(); + if (settings.tunnelAutoStart) { + log.info('Auto-starting tunnel from previous session'); + try { + await startTunnel(); + } catch (error) { + log.error('Failed to auto-start tunnel:', error); + } + } +}