import { ApplicationWindow } from '@main/application-window' ; import { File } from '@main/file' ; import { Menu as Base } from 'electron' ; export class Menu { protected window : ApplicationWindow ; protected built = false ; protected menu : Electron . Menu | null = null ; protected options : object = { } ; protected template : Array < Electron . MenuItemConstructorOptions > = [ ] ; protected beforeCallbacks : Array < Function > = [ ] ; protected afterCallbacks : Array < Function > = [ ] ; constructor ( webContents ) { this . window = ApplicationWindow . getFromWebContents ( webContents ) ! ; } add ( item ) { this . template . push ( item ) ; return this ; } addIf ( condition , item ) { if ( condition ) { this . add ( item ) ; } return this ; } addMultiple ( items ) { items . forEach ( ( item ) => { this . add ( item ) ; } ) ; return this ; } separator ( ) { this . add ( { type : 'separator' } ) ; return this ; } before ( callback ) { this . beforeCallbacks . push ( callback ) ; return this ; } after ( callback ) { this . afterCallbacks . push ( callback ) ; return this ; } attachTo ( rect , padding = true ) { if ( rect ) { const { x , y , height } = rect ; this . options = { ... this . options , ... { x : Math . ceil ( x ) , y : Math . ceil ( y + height + ( padding ? 7 : 0 ) ) } } ; } return this ; } build ( ) { this . menu = Base . buildFromTemplate ( this . template ) ; if ( this . beforeCallbacks . length ) { this . beforeCallbacks . forEach ( callback => { this . menu ! . on ( 'menu-will-show' , ( ) => { callback ( ) ; } ) ; } ) ; } if ( this . afterCallbacks . length ) { this . afterCallbacks . forEach ( callback => { this . menu ! . on ( 'menu-will-close' , ( ) => { callback ( ) ; } ) ; } ) ; } this . built = true ; return this ; } open ( options ? ) { if ( ! this . built ) { this . build ( ) ; } this . menu ! . popup ( { ... this . options , ... { window : this . window . getChild ( ) } , ... ( options || { } ) } ) ; return this ; } public getTemplate ( ) { return this . template ; } public emit ( name , properties ? ) { this . window . sendMenuEvent ( { name , properties } ) ; } public async openFile ( path ) { try { await File . open ( path ) ; } catch ( error ) { log . error ( `Error while trying to open file in path: '${ path }'` , error ) ; this . window . send ( 'error' , [ 'Unable to open file in an external program. Please check you have a program associated with this file extension.' , 'The following path was attempted: `' + path + '`' ] ) ; } } }