import './DataMigration' ; import './HyperfileMigration' ; import { app , protocol , BrowserWindow , Menu , shell , MenuItemConstructorOptions } from 'electron' ; import installExtension , { REACT_DEVELOPER_TOOLS } from 'electron-devtools-installer' ; import Debug from 'debug' ; import * as Hyperfile from '../renderer/hyperfile' ; import { FromSystemMsg } from '../renderer/System' ; const log = Debug ( 'pushpin:electron' ) ; let mainWindow = null ; let backgroundWindow = null ; const isDevelopment = process . env . NODE_ENV !== 'production' ; app . on ( 'ready' , ( ) => { installExtension ( REACT_DEVELOPER_TOOLS ) ; registerProtocolHandlers ( ) ; createMenu ( ) ; createWindow ( ) ; } ) ; protocol . registerSchemesAsPrivileged ( [ { scheme : 'pushpin' , privileges : { standard : true , bypassCSP : true } } , ] ) ; async function createWindow ( ) { mainWindow = new BrowserWindow ( { width : 1400 , height : 1000 , webPreferences : { nodeIntegration : true , webSecurity : false } } ) ; createBackgroundWindow ( ) ; if ( isDevelopment ) { mainWindow . webContents . openDevTools ( ) ; mainWindow . loadURL ( `http://localhost:8080` ) ; } else { mainWindow . loadFile ( 'dist/index.html' ) ; } mainWindow . once ( 'closed' , ( ) => { mainWindow = null ; } ) ; mainWindow . webContents . on ( 'devtools-opened' , ( ) => { mainWindow && mainWindow . focus ( ) ; setImmediate ( ( ) => { mainWindow && mainWindow . focus ( ) ; } ) ; } ) ; mainWindow . webContents . on ( 'devtools-reload-page' , ( ) => { backgroundWindow && backgroundWindow . reload ( ) ; } ) ; mainWindow . webContents . on ( 'will-navigate' , ( event , url ) => { if ( isDevelopment && url . startsWith ( `http://localhost:8080` ) ) { return ; } if ( ! url . startsWith ( 'pushpin://' ) ) { event . preventDefault ( ) ; } if ( isSafeishURL ( url ) ) { shell . openExternal ( url ) ; } } ) ; mainWindow . webContents . on ( 'new-window' , ( event , url ) => { if ( ! url . startsWith ( 'pushpin://' ) ) { event . preventDefault ( ) ; } if ( isSafeishURL ( url ) ) { shell . openExternal ( url ) ; } } ) ; } app . on ( 'window-all-closed' , ( ) => { if ( process . platform !== 'darwin' ) { app . quit ( ) ; } } ) ; app . on ( 'activate' , ( ) => { if ( mainWindow === null ) { createWindow ( ) ; } } ) ; function createBackgroundWindow ( ) { if ( backgroundWindow ) { backgroundWindow . once ( 'closed' , ( ) => { createBackgroundWindow ( ) ; } ) ; backgroundWindow . close ( ) ; return ; } backgroundWindow = new BrowserWindow ( { width : 1400 , height : 1000 , show : false , webPreferences : { nodeIntegration : true } } ) ; const isDevelopment = process . env . NODE_ENV !== 'production' ; if ( isDevelopment ) { backgroundWindow . loadURL ( `http://localhost:8080/background.html` ) ; } else { backgroundWindow . loadFile ( 'dist/background.html' ) ; } backgroundWindow . once ( 'closed' , ( ) => { backgroundWindow = null ; } ) ; } function createMenu ( ) { const template = [ { label : 'File' , submenu : [ { label : 'New' , accelerator : 'CmdOrCtrl+N' , click : ( _item , _focusedWindow ) => { sendSystemMsg ( { type : 'NewDocument' } ) ; } } , ] } , { label : 'Edit' , submenu : [ { role : 'cut' } , { role : 'copy' } , { role : 'paste' } , { role : 'selectAll' } ] } , { label : 'Develop' , submenu : [ { label : 'Refresh' , accelerator : 'CmdOrCtrl+R' , click : ( _item , _focusedWindow ) => { mainWindow && mainWindow . reload ( ) ; backgroundWindow && backgroundWindow . reload ( ) ; } } , { label : 'Toggle Background Window' , accelerator : 'CmdOrCtrl+Option+B' , click : ( _item , _focusedWindow ) => { backgroundWindow && toggleWindow ( backgroundWindow ) ; } } , { label : 'Open Inspector' , accelerator : 'CmdOrCtrl+Option+I' , click : ( _item , focusedWindow ) => { focusedWindow . webContents . toggleDevTools ( ) ; } } , ] } , ] ; if ( process . platform === 'darwin' ) { template . unshift ( { label : app . getName ( ) , submenu : [ { role : 'about' } , { role : 'quit' } ] } ) ; } const menu = Menu . buildFromTemplate ( template ) ; Menu . setApplicationMenu ( menu ) ; } function registerProtocolHandlers ( ) { protocol . registerHttpProtocol ( 'pushpin' , ( req , _cb ) => { sendSystemMsg ( { type : 'IncomingUrl' , url : req . url } ) ; } ) ; protocol . registerBufferProtocol ( 'hyperfile' , async ( request , callback ) => { try { if ( Hyperfile . isHyperfileUrl ( request . url ) ) { const [ stream ] = await Hyperfile . fetch ( request . url ) ; const buffer = await Hyperfile . streamToBuffer ( stream ) ; callback ( buffer ) ; } } catch ( e ) { log ( e ) ; } } , ( error ) => { if ( error ) { log ( 'Failed to register protocol' ) ; } } ) ; } function sendSystemMsg ( msg ) { mainWindow && mainWindow . webContents . send ( 'system.msg' , msg ) ; } function toggleWindow ( win ) { if ( win . isVisible ( ) ) { win . hide ( ) ; return false ; } win . show ( ) ; return true ; } function isSafeishURL ( url ) { return url . startsWith ( 'http:' ) || url . startsWith ( 'https:' ) ; }