Skip to content

Commit 4dd5417

Browse files
Merge pull request #21 from FritzBlignaut/feature/versioning
feat: implement graceful exit handling and improve quit functionality
2 parents e212070 + 425fe6c commit 4dd5417

2 files changed

Lines changed: 23 additions & 6 deletions

File tree

electron/main.cjs

Lines changed: 22 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -74,14 +74,27 @@ function createTrayIconPng() {
7474
])
7575
}
7676

77+
// Central quit — destroys GUI elements immediately then calls app.exit(0).
78+
// app.exit bypasses the window-all-closed no-op handler that otherwise keeps
79+
// the process alive as a background tray app, guaranteeing the process exits.
80+
function doQuit() {
81+
if (isQuitting) return
82+
isQuitting = true
83+
if (reconnectTimer) { clearInterval(reconnectTimer); reconnectTimer = null }
84+
if (deck) { deck.clearPanel().catch(() => {}); deck.close().catch(() => {}) }
85+
if (tray) { tray.destroy(); tray = null } // remove icon immediately
86+
if (mainWindow && !mainWindow.isDestroyed()) mainWindow.destroy()
87+
app.exit(0)
88+
}
89+
7790
function createTray() {
7891
const icon = nativeImage.createFromBuffer(createTrayIconPng())
7992
tray = new Tray(icon)
8093
tray.setToolTip('Tech Stack Stream Deck')
8194
const menu = Menu.buildFromTemplate([
8295
{ label: 'Show Window', click: () => { mainWindow?.show(); mainWindow?.focus() } },
8396
{ type: 'separator' },
84-
{ label: 'Quit', click: () => { isQuitting = true; if (mainWindow && !mainWindow.isDestroyed()) mainWindow.destroy(); app.quit() } },
97+
{ label: 'Quit', click: doQuit },
8598
])
8699
tray.setContextMenu(menu)
87100
// Left-click shows window (works on Windows/KDE; GNOME AppIndicator ignores it)
@@ -565,12 +578,15 @@ app.whenReady().then(async () => {
565578
// Tray keeps the process alive when the window is hidden
566579
app.on('window-all-closed', () => {})
567580

568-
// Allow OS-level quit (shutdown, pkill) to bypass the hide intercept
569-
app.on('before-quit', () => { isQuitting = true })
581+
// Ensure the tray icon disappears for any quit path that goes through app.quit()
582+
app.on('before-quit', () => {
583+
isQuitting = true
584+
if (tray) { tray.destroy(); tray = null }
585+
})
570586

571-
// Graceful exit on OS signals (e.g. pkill, systemd stop, taskbar "Quit")
572-
process.on('SIGTERM', () => { isQuitting = true; app.quit() })
573-
process.on('SIGINT', () => { isQuitting = true; app.quit() })
587+
// OS signals (pkill, systemd stop) → use doQuit() for immediate, guaranteed exit
588+
process.on('SIGTERM', doQuit)
589+
process.on('SIGINT', doQuit)
574590

575591
// Single-instance: second launch focuses the existing window instead
576592
const gotSingleInstanceLock = app.requestSingleInstanceLock()

vite.config.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import react from '@vitejs/plugin-react'
33

44
// https://vite.dev/config/
55
export default defineConfig({
6+
base: './',
67
plugins: [react()],
78
test: {
89
globals: true,

0 commit comments

Comments
 (0)