const path = require("path"); const { app, BrowserWindow, Tray, Menu, ipcMain, dialog, shell, globalShortcut, } = require("electron"); const isDev = require("electron-is-dev"); const { default: ipcTypes } = require("../src/ipc.types"); const { store } = require("./electron-store"); const { autoUpdater } = require("electron-updater"); const log = require("electron-log"); const { default: logger } = require("redux-logger"); require("./ipc-main-handler"); autoUpdater.logger = log; autoUpdater.logger.transports.file.level = "info"; log.info("App starting..."); // Conditionally include the dev tools installer to load React Dev Tools let installExtension, REACT_DEVELOPER_TOOLS; // if (isDev) { // const devTools = require("electron-devtools-installer"); // installExtension = devTools.default; // REACT_DEVELOPER_TOOLS = devTools.REACT_DEVELOPER_TOOLS; // } var menu = Menu.buildFromTemplate([ { label: "File", submenu: [ { label: "Relaunch", click() { app.exit(); app.relaunch(); }, }, { label: "Clear Settings", click() { store.reset("filePaths"); mainWindow.webContents.session.clearStorageData(); }, }, { label: "Exit", click() { app.quit(); }, }, ], // Other code removed for brevity }, { label: "Help", submenu: [ { label: "Rescue", click() { shell.openExternal("http://imexrescue.com"); }, }, { label: "Check for Updates", click() { autoUpdater.checkForUpdatesAndNotify(); }, }, { label: "Open Log File", click() { shell.openPath(store.path); }, }, ], }, ]); let mainWindow; let tray = null; function createWindow() { makeSingleInstance(); // Create the browser window. Menu.setApplicationMenu(menu); mainWindow = new BrowserWindow({ width: 800, height: 600, title: "ImEX RPS", icon: path.join(__dirname, "../src/assets/logo192.png"), webPreferences: { nodeIntegration: false, enableRemoteModule: false, webSecurity: true, worldSafeExecuteJavaScript: true, contextIsolation: true, preload: path.join(__dirname, "preload.js"), // use a preload script }, }); // and load the index.html of the app. // win.loadFile("index.html"); mainWindow.loadURL( isDev ? "http://localhost:3000" : `file://${path.join(__dirname, "/../build/index.html")}` ); // mainWindow.on("close", function (event) { // event.preventDefault(); // mainWindow.hide(); // tray = createTray(); // }); mainWindow.on("minimize", function (event) { event.preventDefault(); mainWindow.hide(); tray = createTray(); }); ipcMain.on(ipcTypes.quit, (event, arg) => { app.isQuiting = true; app.quit(); }); // Open the DevTools. if (isDev) { mainWindow.webContents.openDevTools({ // mode: "detach" }); } mainWindow.maximize(); autoUpdater.checkForUpdatesAndNotify(); globalShortcut.register("CommandOrControl+Shift+I", () => { mainWindow.webContents.toggleDevTools(); }); } exports.mainWindow = mainWindow; // This method will be called when Electron has finished // initialization and is ready to create browser windows. // Some APIs can only be used after this event occurs. app.whenReady().then(() => { createWindow(); if (isDev) { console.log(`Path to Settings File: ${store.path}`); console.log(`Path to Log File: ${log.log}`); installExtension(REACT_DEVELOPER_TOOLS) .then((name) => console.log(`Added Extension: ${name}`)) .catch((error) => console.log(`An error occurred: , ${error}`)); } // ipcMain.on(ipcTypes.default.webcontent, (event, ...obj) => { // console.log("event", event); // mainWindow.webContents.send(event, obj); // }); }); if (isDev) app.setAppUserModelId(process.execPath); else app.setAppUserModelId("com.imex.rps"); // Quit when all windows are closed, except on macOS. There, it's common // for applications and their menu bar to stay active until the user quits // explicitly with Cmd + Q. app.on("window-all-closed", () => { 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 (BrowserWindow.getAllWindows().length === 0) { createWindow(); } }); // In this file you can include the rest of your app's specific main process // code. You can also put them in separate files and require them here. function makeSingleInstance() { if (process.mas) return; app.requestSingleInstanceLock(); app.on("second-instance", () => { if (mainWindow) { if (mainWindow.isMinimized()) mainWindow.restore(); mainWindow.focus(); } }); } function createTray() { let appIcon = new Tray(path.join(__dirname, "../src/assets/logo192.png")); const contextMenu = Menu.buildFromTemplate([ { label: "Show", click: function () { mainWindow.show(); }, }, { label: "Exit", click: function () { app.isQuiting = true; app.quit(); }, }, ]); appIcon.on("double-click", function (event) { mainWindow.show(); }); appIcon.setToolTip("ImEX RPS"); appIcon.setContextMenu(contextMenu); return appIcon; } autoUpdater.on("checking-for-update", () => { console.log("Checking for update..."); }); autoUpdater.on("update-available", (ev, info) => { console.log("Update available."); }); autoUpdater.on("update-not-available", (ev, info) => { console.log("Update not available."); }); autoUpdater.on("error", (ev, err) => { console.log("Error in auto-updater."); }); autoUpdater.on("download-progress", (ev, progressObj) => { console.log("Download progress..."); }); autoUpdater.on("update-downloaded", (ev, info) => { console.log("Update downloaded; will install in 5 seconds"); }); autoUpdater.on("update-downloaded", (ev, info) => { if (process.env.NODE_ENV === "production") { dialog.showMessageBox( { type: "info", title: "Found Updates", message: "Found updates, do you want update now?", buttons: ["Sure", "No"], }, (buttonIndex) => { if (buttonIndex === 0) { const isSilent = true; const isForceRunAfter = true; autoUpdater.quitAndInstall(isSilent, isForceRunAfter); } else { logger.warn("Error"); } } ); } });