const { app, BrowserWindow, dialog, ipcMain, Menu, nativeImage, Tray } = require('electron'); const AutoLaunch = require('auto-launch'); const Constants = require('../src/constants'); const fs = require('fs'); const helpers = require('../src/helpers'); const os = require('os'); const path = require('path'); const url = require('url'); const debug = require('electron-debug'); debug({ devToolsMode: 'undocked', isEnabled: true, showDevTools: !!process.env.ELECTRON_START_URL, }); require.extensions['.sh'] = function (module, filename) { module.exports = fs.readFileSync(filename, 'utf8'); }; const detectScript = require('./detect_linux.sh'); const AppIPC = require('../src/renderer/ipc/AppIPC'); const ConfigIPC = require('../src/renderer/ipc/ConfigIPC'); const DaemonIPC = require('../src/renderer/ipc/DaemonIPC'); const DependencyIPC = require('../src/renderer/ipc/DependencyIPC'); const DownloadIPC = require('../src/renderer/ipc/DownloadIPC'); const FilesystemIPC = require('../src/renderer/ipc/FilesystemIPC'); const MountsIPC = require('../src/renderer/ipc/MountsIPC'); const PlatformIPC = require('../src/renderer/ipc/PlatformIPC'); const ReleaseIPC = require('../src/renderer/ipc/ReleaseIPC'); const StateIPC = require('../src/renderer/ipc/StateIPC'); const SystemIPC = require('../src/renderer/ipc/SystemIPC'); const UpgradeIPC = require('../src/renderer/ipc/UpgradeIPC'); const platform = os.platform(); const dimensions = { height: (platform === 'win32') ? 326 : (platform === 'darwin') ? 322 : 300, width: (platform === 'win32') ? 468 : 628, }; let isShutdown = false; let isQuiting = false; let isInstalling = false; let launchHidden = false; let mainWindow; let mainWindowTray; let trayContextMenu; const closeApplication = () => { if (!isShutdown) { isShutdown = true; if (mainWindowTray) { mainWindowTray.destroy(); } app.quit(); } }; const configurePrimaryApp = () => { app.on('second-instance', () => { if (!isInstalling && mainWindow) { setWindowVisibility(true); } }); app.on('ready', createWindow); app.on('window-all-closed', () => { closeApplication(); }); }; const createWindow = () => { loadUiSettings(); let extra = {}; if (platform === 'linux') { extra = { icon: path.join(__dirname, '../build/', 'logo.png'), } } // Create the browser window. mainWindow = new BrowserWindow({ height: dimensions.height, width: dimensions.width, fullscreen: false, resizable: false, show: !launchHidden, title: 'Repertory UI', ...extra, webPreferences: { nodeIntegration: true, webSecurity: !process.env.ELECTRON_START_URL } }); if (platform === 'linux') { mainWindow.setMenuBarVisibility(false); } else { mainWindow.removeMenu(); } if ((platform === 'darwin') && launchHidden) { app.dock.hide(); } // and load the index.html of the app. const startUrl = process.env.ELECTRON_START_URL || url.format({ pathname: path.join(__dirname, '../build/index.html'), protocol: 'file:', slashes: true }); mainWindow.on('close', function (event) { if (!isQuiting) { event.preventDefault(); if (mainWindow.isVisible()) { setWindowVisibility(false); } event.returnValue = false; } }); mainWindow.on('closed', function () { // Dereference the window object, usually you would store windows // in an array if your app supports multi windows, this is the time // when you should delete the corresponding element. mainWindow = null; MountsIPC.unmountAllDrives(); }); const appPath = (platform === 'win32') ? path.resolve(path.join(app.getAppPath(), '..\\..\\repertory-ui.exe')) : (platform === 'darwin') ? path.resolve(path.join(path.dirname(app.getAppPath()), '../MacOS/repertory-ui')) : process.env.APPIMAGE; const autoLauncher = new AutoLaunch({ name: 'Repertory UI', path: appPath, }); trayContextMenu = Menu.buildFromTemplate([ { label: 'Visible', type: 'checkbox', click(item) { setWindowVisibility(item.checked); }, checked: !launchHidden, }, { label: 'Auto-start', type: 'checkbox', click(item) { if (item.checked) { autoLauncher.enable(); } else { autoLauncher.disable(); } } }, { type: 'separator' }, { label: 'Launch Hidden', type: 'checkbox', click(item) { launchHidden = !!item.checked; saveUiSettings(); }, checked: launchHidden, }, { type: 'separator' }, { label: 'Exit and Unmount', click() { closeApplication(); } } ]); const image = nativeImage.createFromPath(path.join(__dirname, (platform === 'darwin') ? '../build/logo_mac.png' : '../build/logo.png')); mainWindowTray = new Tray(image); autoLauncher .isEnabled() .then((enabled) => { trayContextMenu.items[1].checked = enabled; mainWindowTray.setToolTip('Repertory UI'); mainWindowTray.setContextMenu(trayContextMenu) }) .catch(() => { closeApplication(); }); mainWindow.loadURL(startUrl); }; const getMainWindow = () => { return mainWindow; }; const loadUiSettings = () => { const settingFile = path.join(helpers.resolvePath(Constants.DATA_LOCATIONS[platform]), 'ui.json'); try { if (fs.statSync(settingFile).isFile()) { const settings = JSON.parse(fs.readFileSync(settingFile, 'utf8')); launchHidden = settings.launch_hidden; PlatformIPC.setPlatformOverride(settings.platform_override); } } catch (e) { } }; const saveUiSettings = () => { const settingFile = path.join(helpers.getDataDirectory(), 'ui.json'); try { fs.writeFileSync(settingFile, JSON.stringify({ launch_hidden: launchHidden, platform_override: PlatformIPC.getPlatformOverride(), }), 'utf-8'); } catch (e) { } }; const setIsInstalling = installing => { isInstalling = installing; }; const setTrayImage = driveInUse => { let image; if (driveInUse) { image = nativeImage.createFromPath(path.join(__dirname, platform === 'darwin' ? '../build/logo_both_mac.png' : '../build/logo_both.png')); } else { image = nativeImage.createFromPath(path.join(__dirname, platform === 'darwin' ? '../build/logo_mac.png' : '../build/logo.png')); } mainWindowTray.setImage(image); }; const setWindowVisibility = show => { if (show) { mainWindow.show(); if (platform === 'darwin') { app.dock.show(); } else if (platform === 'linux') { mainWindow.setSize(dimensions.width, dimensions.height); } if (mainWindow.isMinimized()) { mainWindow.restore(); } mainWindow.focus(); } else { mainWindow.hide(); if (platform === 'darwin') { app.dock.hide(); } } if (trayContextMenu && mainWindowTray) { trayContextMenu.items[0].checked = show; mainWindowTray.setContextMenu(trayContextMenu) } }; const standardIPCReply = (event, channel, data, error) => { if (mainWindow) { event.sender.send(channel, { data: { ...data, Error: error instanceof Error ? error.toString() : error, Success: !error, } }); } }; app.on('before-quit', function () { isQuiting = true; }); let instanceLock = app.requestSingleInstanceLock(); if (!instanceLock) { setTimeout(() => { if ((instanceLock = app.requestSingleInstanceLock())) { configurePrimaryApp(); } else { closeApplication(); } }, 3000); } else { configurePrimaryApp(); } AppIPC.addListeners(ipcMain, closeApplication, setWindowVisibility); ConfigIPC.addListeners(ipcMain, standardIPCReply); DaemonIPC.addListeners(ipcMain, standardIPCReply); DependencyIPC.addListeners(ipcMain, standardIPCReply); DownloadIPC.addListeners(ipcMain, standardIPCReply); FilesystemIPC.addListeners(ipcMain, getMainWindow, dialog); MountsIPC.addListeners(ipcMain, setTrayImage, standardIPCReply); PlatformIPC.addListeners(ipcMain, detectScript, saveUiSettings); ReleaseIPC.addListeners(ipcMain, standardIPCReply); StateIPC.addListeners(ipcMain); SystemIPC.addListeners(ipcMain, closeApplication); UpgradeIPC.addListeners(ipcMain, setIsInstalling, MountsIPC.unmountAllDrives, standardIPCReply);