fix: app not closing on MacOS

Closes #5327
This commit is contained in:
Johannes Millan 2025-10-23 15:12:12 +02:00
parent f3fd788310
commit 6350a7249f
5 changed files with 36 additions and 19 deletions

View file

@ -20,6 +20,7 @@ import { exec } from 'child_process';
import { getWin } from './main-window';
import { quitApp, showOrFocus } from './various-shared';
import { loadSimpleStoreAll, saveSimpleStore } from './simple-store';
import { getIsLocked } from './shared-state';
import { BACKUP_DIR, BACKUP_DIR_WINSTORE } from './backup';
import { pluginNodeExecutor } from './plugin-node-executor';
@ -86,7 +87,7 @@ export const initIpcInterfaces = (): void => {
});
ipcMain.on(IPC.LOCK_SCREEN, () => {
if ((app as any).isLocked) {
if (getIsLocked()) {
return;
}

View file

@ -23,6 +23,7 @@ import {
hideOverlayWindow,
showOverlayWindow,
} from './overlay-indicator/overlay-indicator';
import { getIsQuiting, setIsQuiting } from './shared-state';
let mainWin: BrowserWindow;
@ -291,7 +292,7 @@ const appCloseHandler = (app: App): void => {
let ids: string[] = [];
const _quitApp = (): void => {
(app as any).isQuiting = true;
setIsQuiting(true);
// Destroy overlay window before closing main window to ensure window-all-closed fires
destroyOverlayWindow();
mainWin.close();
@ -315,11 +316,11 @@ const appCloseHandler = (app: App): void => {
mainWin.on('close', (event) => {
// NOTE: this might not work if we run a second instance of the app
log('close, isQuiting:', (app as any).isQuiting);
if (!(app as any).isQuiting) {
log('close, isQuiting:', getIsQuiting());
if (!getIsQuiting()) {
event.preventDefault();
getSettings(mainWin, (appCfg: GlobalConfigState) => {
if (appCfg && appCfg.misc.isMinimizeToTray && !(app as any).isQuiting) {
if (appCfg && appCfg.misc.isMinimizeToTray && !getIsQuiting()) {
mainWin.hide();
showOverlayWindow();
return;
@ -353,7 +354,7 @@ const appCloseHandler = (app: App): void => {
};
const appMinimizeHandler = (app: App): void => {
if (!(app as any).isQuiting) {
if (!getIsQuiting()) {
// TODO find reason for the typing error
// @ts-ignore
mainWin.on('minimize', (event: Event) => {

19
electron/shared-state.ts Normal file
View file

@ -0,0 +1,19 @@
/**
* Shared state module for Electron main process
* Provides a single source of truth for application-wide flags
*/
let isQuiting = false;
let isLocked = false;
export const getIsQuiting = (): boolean => isQuiting;
export const setIsQuiting = (value: boolean): void => {
isQuiting = value;
};
export const getIsLocked = (): boolean => isLocked;
export const setIsLocked = (value: boolean): void => {
isLocked = value;
};

View file

@ -27,6 +27,7 @@ import {
initializeProtocolHandling,
processPendingProtocolUrls,
} from './protocol-handler';
import { getIsQuiting, setIsLocked } from './shared-state';
const ICONS_FOLDER = __dirname + '/assets/icons/';
const IS_MAC = process.platform === 'darwin';
@ -44,12 +45,7 @@ if (IS_DEV) {
log('Starting in DEV Mode!!!');
}
interface MyApp extends App {
isQuiting?: boolean;
isLocked?: boolean;
}
const appIN: MyApp = app;
const appIN: App = app;
let mainWin: BrowserWindow;
let idleTimeHandler: IdleTimeHandler;
@ -193,7 +189,7 @@ export const startApp = (): void => {
return { sent: false, reason: 'no-window' };
}
if (appIN.isQuiting) {
if (getIsQuiting()) {
return { sent: false, reason: 'quitting' };
}
@ -249,14 +245,14 @@ export const startApp = (): void => {
powerMonitor.on('suspend', () => {
log('powerMonitor: System suspend detected');
appIN.isLocked = true;
setIsLocked(true);
suspendStart = Date.now();
mainWin.webContents.send(IPC.SUSPEND);
});
powerMonitor.on('lock-screen', () => {
log('powerMonitor: Screen lock detected');
appIN.isLocked = true;
setIsLocked(true);
suspendStart = Date.now();
mainWin.webContents.send(IPC.SUSPEND);
});
@ -264,7 +260,7 @@ export const startApp = (): void => {
powerMonitor.on('resume', () => {
const idleTime = Date.now() - suspendStart;
log(`powerMonitor: System resume detected. Idle time: ${idleTime}ms`);
appIN.isLocked = false;
setIsLocked(false);
sendIdleMsgIfOverMin(idleTime);
mainWin.webContents.send(IPC.RESUME);
});
@ -272,7 +268,7 @@ export const startApp = (): void => {
powerMonitor.on('unlock-screen', () => {
const idleTime = Date.now() - suspendStart;
log(`powerMonitor: Screen unlock detected. Idle time: ${idleTime}ms`);
appIN.isLocked = false;
setIsLocked(false);
sendIdleMsgIfOverMin(idleTime);
mainWin.webContents.send(IPC.RESUME);
});

View file

@ -2,11 +2,11 @@ import { app, BrowserWindow } from 'electron';
import { info } from 'electron-log/main';
import { getWin } from './main-window';
import { hideOverlayWindow } from './overlay-indicator/overlay-indicator';
import { setIsQuiting } from './shared-state';
// eslint-disable-next-line prefer-arrow/prefer-arrow-functions
export function quitApp(): void {
// tslint:disable-next-line
(app as any).isQuiting = true;
setIsQuiting(true);
app.quit();
}