@ -1,7 +1,7 @@
import type { CapacitorElectronConfig } from '@capacitor-community/electron' ;
import { getCapacitorElectronConfig , setupElectronDeepLinking } from '@capacitor-community/electron' ;
import type { MenuItemConstructorOptions } from 'electron' ;
import { app , MenuItem , ipcMain } from 'electron' ;
import { app , MenuItem , ipcMain , dialog } from 'electron' ;
import electronIsDev from 'electron-is-dev' ;
import unhandled from 'electron-unhandled' ;
import { autoUpdater } from 'electron-updater' ;
@ -10,6 +10,27 @@ import { join } from 'path';
import { ElectronCapacitorApp , setupContentSecurityPolicy , setupReloadWatcher } from './setup' ;
// Single instance enforcement
const gotTheLock = app . requestSingleInstanceLock ( ) ;
if ( ! gotTheLock ) {
console . log ( '[Electron] Another instance is already running. Exiting...' ) ;
// Show user-friendly dialog before quitting
dialog . showMessageBox ( {
type : 'info' ,
title : 'TimeSafari Already Running' ,
message : 'TimeSafari is already running in another window.' ,
detail : 'Please use the existing TimeSafari window instead of opening a new one.' ,
buttons : [ 'OK' ]
} ) . then ( ( ) = > {
app . quit ( ) ;
} ) ;
// Exit immediately
process . exit ( 0 ) ;
}
// Graceful handling of unhandled errors.
unhandled ( {
logger : ( error ) = > {
@ -79,6 +100,20 @@ autoUpdater.on('error', (error) => {
// Initialize our app, build windows, and load content.
await myCapacitorApp . init ( ) ;
// Handle second instance launch (focus existing window)
app . on ( 'second-instance' , ( event , commandLine , workingDirectory ) = > {
console . log ( '[Electron] Second instance attempted to launch' ) ;
// Someone tried to run a second instance, we should focus our window instead
const mainWindow = myCapacitorApp . getMainWindow ( ) ;
if ( mainWindow ) {
if ( mainWindow . isMinimized ( ) ) {
mainWindow . restore ( ) ;
}
mainWindow . focus ( ) ;
}
} ) ;
// Only check for updates in production builds, not in development or AppImage
if ( ! electronIsDev && ! process . env . APPIMAGE ) {
try {