import { app , BrowserWindow , ipcMain , Menu , MenuItem , nativeImage , screen , Tray } from "electron" ; import log from "electron-log" ; import settings from "electron-settings" ; import os from "os" ; import path from "path" ; import { IPCMessageNames } from "../ipc/IPCMessageNames" ; import { CompositeWindow } from "./CompositeWindow" ; const windowSettingsKey = 'overlayed.window' ; export class Bootstrap { public compositor : CompositeWindow ; public settings ? : BrowserWindow ; public tray : Tray ; constructor ( ) { ipcMain . on ( IPCMessageNames . ShowTooltip , ( e , tooltipOpts ) => { log . info ( `showing tooltip ${ tooltipOpts . title }` ) ; this . tray . displayBalloon ( tooltipOpts ) ; } ) ; ipcMain . on ( IPCMessageNames . RequestCompositorReload , ( ) => { if ( this . compositor && ! this . compositor . isDestroyed ( ) ) { this . compositor . reload ( ) ; } } ) ; this . tray = new Tray ( this . getTrayIcon ( ) ) ; this . tray . setContextMenu ( this . buildTrayMenu ( ) ) ; this . tray . setToolTip ( 'Overlayed' ) ; this . tray . on ( 'click' , ( ) => { this . tray . popUpContextMenu ( ) ; } ) ; this . compositor = new CompositeWindow ( this . getCompositorSettings ( ) ) ; this . compositor . loadFile ( `${ __dirname }/../app/main/main.html` ) ; let isShuttingDown = false ; this . compositor . on ( 'close' , ( e ) => { if ( ! isShuttingDown ) { e . preventDefault ( ) ; isShuttingDown = true ; setTimeout ( ( ) => { this . compositor . close ( ) ; } , 5000 ) ; ipcMain . on ( IPCMessageNames . AllowShutdown , ( ) => { this . compositor . close ( ) ; } ) ; this . compositor . webContents . send ( IPCMessageNames . RequestShutdown ) ; } } ) ; this . compositor . on ( 'close' , ( ) => { settings . set ( windowSettingsKey , this . compositor . getBounds ( ) as any , { prettify : true } ) ; } ) ; log . info ( 'completed electron bootstrapping' ) ; } private getCompositorSettings ( ) { return settings . get ( windowSettingsKey , screen . getPrimaryDisplay ( ) . workArea ) as { x : number ; y : number ; width : number ; height : number ; } ; } private buildTrayMenu ( ) { const mainTrayMenu = new Menu ( ) ; const devTrayMenu = new Menu ( ) ; mainTrayMenu . append ( new MenuItem ( { click : ( ) => { this . compositor . toggleWindowInteractivity ( ) ; } , label : 'Toggle Edit' , } ) ) ; mainTrayMenu . append ( new MenuItem ( { click : ( ) => { if ( this . settings && ! this . settings . isDestroyed ( ) ) { this . settings . show ( ) ; } else { this . settings = new BrowserWindow ( ) ; this . settings . loadFile ( `${ __dirname }/../app/settings/settings.html` ) ; } } , label : 'Settings' , } ) ) ; mainTrayMenu . append ( new MenuItem ( { label : 'Developer' , submenu : devTrayMenu , } ) ) ; mainTrayMenu . append ( new MenuItem ( { click : ( ) => { app . quit ( ) ; } , label : 'Close' , } ) ) ; devTrayMenu . append ( new MenuItem ( { click : ( ) => { this . compositor . toggleDevTools ( ) ; } , label : 'Toggle Tools' , } ) ) ; devTrayMenu . append ( new MenuItem ( { click : ( ) => { this . compositor . reload ( ) ; } , label : 'Force Reload' , } ) ) ; return mainTrayMenu ; } private getTrayIcon ( ) { const getNativeImage = ( filename ) => nativeImage . createFromPath ( path . join ( __dirname , '../../build' , filename ) ) ; switch ( os . platform ( ) ) { case 'darwin' : const image = getNativeImage ( 'icon.png' ) ; image . setTemplateImage ( true ) ; return image ; case 'win32' : return getNativeImage ( 'icon.ico' ) ; default : return getNativeImage ( 'iconFull.png' ) ; } } }