import { ipcMain, app, BrowserWindow, Menu, MenuItem } from 'electron' import { prerelease } from 'semver' import { join } from 'path' import { readdirSync } from 'fs-extra' import { format } from 'url' import { autoUpdater } from 'electron-updater' import isdev from '../common/util/isdev' const installExtensions = async () => { const installer = require('electron-devtools-installer') const forceDownload = !!process.env.UPGRADE_EXTENSIONS const extensions = ['REACT_DEVELOPER_TOOLS', 'REDUX_DEVTOOLS'] return Promise.all( extensions.map(name => installer.default(installer[name], forceDownload)) ).catch(console.log) // eslint-disable-line no-console } // Setup auto updater. function initAutoUpdater(event: any, data: any) { if(data){ autoUpdater.allowPrerelease = true } else { // Defaults to true if application version contains prerelease components (e.g. 0.12.1-alpha.1) // autoUpdater.allowPrerelease = true } if(isdev){ autoUpdater.autoInstallOnAppQuit = false autoUpdater.updateConfigPath = join(__dirname, '..', 'dev-app-update.yml') } if(process.platform === 'darwin'){ autoUpdater.autoDownload = false } autoUpdater.on('update-available', (info) => { event.sender.send('autoUpdateNotification', 'update-available', info) }) autoUpdater.on('update-downloaded', (info) => { event.sender.send('autoUpdateNotification', 'update-downloaded', info) }) autoUpdater.on('update-not-available', (info) => { event.sender.send('autoUpdateNotification', 'update-not-available', info) }) autoUpdater.on('checking-for-update', () => { event.sender.send('autoUpdateNotification', 'checking-for-update') }) autoUpdater.on('error', (err) => { event.sender.send('autoUpdateNotification', 'realerror', err) }) } // Open channel to listen for update actions. ipcMain.on('autoUpdateAction', (event, arg, data) => { switch(arg){ case 'initAutoUpdater': console.log('Initializing auto updater.') initAutoUpdater(event, data) event.sender.send('autoUpdateNotification', 'ready') break case 'checkForUpdate': autoUpdater.checkForUpdates() .catch(err => { event.sender.send('autoUpdateNotification', 'realerror', err) }) break case 'allowPrereleaseChange': if(!data){ const preRelComp = prerelease(app.getVersion()) if(preRelComp != null && preRelComp.length > 0){ autoUpdater.allowPrerelease = true } else { autoUpdater.allowPrerelease = data } } else { autoUpdater.allowPrerelease = data } break case 'installUpdateNow': autoUpdater.quitAndInstall() break default: console.log('Unknown argument', arg) break } }) // Redirect distribution index event from preloader to renderer. ipcMain.on('distributionIndexDone', (event, res) => { event.sender.send('distributionIndexDone', res) }) // Disable hardware acceleration. // https://electronjs.org/docs/tutorial/offscreen-rendering app.disableHardwareAcceleration() // Keep a global reference of the window object, if you don't, the window will // be closed automatically when the JavaScript object is garbage collected. let win: BrowserWindow | null async function createWindow() { if (process.env.NODE_ENV !== 'production') { await installExtensions() } win = new BrowserWindow({ width: 980, height: 552, icon: getPlatformIcon('SealCircle'), frame: false, webPreferences: { preload: join(__dirname, '..', 'out', 'preloader.js'), nodeIntegration: true, contextIsolation: false }, backgroundColor: '#171614' }) // ejse.data('bkid', Math.floor((Math.random() * readdirSync(join(__dirname, '..', 'assets', 'images', 'backgrounds')).length))) if (isdev) { win.loadURL(`http://localhost:${process.env.ELECTRON_WEBPACK_WDS_PORT}`) } else { win.loadURL(format({ pathname: join(__dirname, 'index.html'), protocol: 'file', slashes: true })) } // console.log(__dirname) // win.loadURL(format({ // pathname: join(__dirname, 'index.html'), // protocol: 'file', // slashes: true // })) /*win.once('ready-to-show', () => { win.show() })*/ win.removeMenu() win.resizable = true if (process.env.NODE_ENV !== 'production') { // Open DevTools, see https://github.com/electron/electron/issues/12438 for why we wait for dom-ready win.webContents.once('dom-ready', () => { win!.webContents.openDevTools() }) } win.on('closed', () => { win = null }) } function createMenu() { if(process.platform === 'darwin') { // Extend default included application menu to continue support for quit keyboard shortcut const applicationSubMenu = new MenuItem({ label: 'Application', submenu: [{ label: 'About Application', role: 'about' }, { type: 'separator' }, { label: 'Quit', accelerator: 'Command+Q', role: 'quit', click: () => { app.quit() } }] }) // New edit menu adds support for text-editing keyboard shortcuts const editSubMenu = new MenuItem({ label: 'Edit', submenu: [ { label: 'Undo', accelerator: 'CmdOrCtrl+Z', role: 'undo' }, { label: 'Redo', accelerator: 'Shift+CmdOrCtrl+Z', role: 'redo' }, { type: 'separator' }, { label: 'Cut', accelerator: 'CmdOrCtrl+X', role: 'cut' }, { label: 'Copy', accelerator: 'CmdOrCtrl+C', role: 'copy' }, { label: 'Paste', accelerator: 'CmdOrCtrl+V', role: 'paste' }, { label: 'Select All', accelerator: 'CmdOrCtrl+A', role: 'selectAll' } ] }) // Bundle submenus into a single template and build a menu object with it const menuTemplate: MenuItem[] = [applicationSubMenu, editSubMenu] const menuObject = Menu.buildFromTemplate(menuTemplate) // Assign it to the application Menu.setApplicationMenu(menuObject) } } function getPlatformIcon(filename: string){ let ext switch(process.platform) { case 'win32': ext = 'ico' break case 'darwin': case 'linux': default: ext = 'png' break } return join(__dirname, '..', 'assets', 'images', `${filename}.${ext}`) } app.on('ready', createWindow) app.on('ready', createMenu) app.on('window-all-closed', () => { // On macOS it is common for applications and their menu bar // to stay active until the user quits explicitly with Cmd + Q if (process.platform !== 'darwin') { app.quit() } }) app.on('activate', () => { // On macOS it's common to re-create a window in the app when the // dock icon is clicked and there are no other windows open. if (win === null) { createWindow() } })