// Modules to control application life and create native browser window const {app, BrowserWindow, Tray, nativeImage, Menu, dialog} = require('electron'); const {ipcMain} = require('electron'); const Constants = require('../src/constants'); const path = require('path'); const url = require('url'); require('electron-debug/index')(); const os = require('os'); const helpers = require('../src/helpers'); const fs = require('fs'); const unzip = require('unzipper'); const AutoLaunch = require('auto-launch'); require.extensions['.sh'] = function (module, filename) { module.exports = fs.readFileSync(filename, 'utf8'); }; const detectScript = require('./detect_linux.sh'); const installScript = require('./update_linux.sh'); const publicKey = '-----BEGIN PUBLIC KEY-----\n' + 'MIIEIjANBgkqhkiG9w0BAQEFAAOCBA8AMIIECgKCBAEKfZmq5mMAtD4kSt2Gc/5J\n' + 'H+HHTYtUZE6YYvsvz8TNG/bNL67ZtNRyaoMyhLTfIN4rPBNLUfD+owNS+u5Yk+lS\n' + 'ZLYyOuhoCZIFefayYqKLr42G8EeuRbx0IMzXmJtN0a4rqxlWhkYufJubpdQ+V4DF\n' + 'oeupcPdIATaadCKVeZC7A0G0uaSwoiAVMG5dZqjQW7F2LoQm3PhNkPvAybIJ6vBy\n' + 'LqdBegS1JrDn43x/pvQHzLO+l+FIG23D1F7iF+yZm3DkzBdcmi/mOMYs/rXZpBym\n' + '2/kTuSGh5buuJCeyOwR8N3WdvXw6+KHMU/wWU8qTCTT87mYbzH4YR8HgkjkLHxAO\n' + '5waHK6vMu0TxugCdJmVV6BSbiarJsh66VRosn7+6hlq6AdgksxqCeNELZBS+LBki\n' + 'tb5hKyL+jNZnaHiR0U7USWtmnqZG6FVVRzlCnxP7tZo5O5Ex9AAFGz5JzOzsFNbv\n' + 'xwQ0zqaTQOze+MJbkda7JfRoC6TncD0+3hoXsiaF4mCn8PqUCn0DwhglcRucZlST\n' + 'ZvDNDo1WAtxPJebb3aS6uymNhBIquQbVAWxVO4eTrOYEgutxwkHE3yO3is+ogp8d\n' + 'xot7f/+vzlbsbIDyuZBDe0fFkbTIMTU48QuUUVZpRKmKZTHQloz4EHqminbfX1sh\n' + 'M7wvDkpJEtqbc0VnG/BukUzP6e7Skvgc7eF1sI3+8jH8du2rivZeZAl7Q2f+L9JA\n' + 'BY9pjaxttxsud7V5jeFi4tKuDHi21/XhSjlJK2c2C4AiUEK5/WhtGbQ5JjmcOjRq\n' + 'yXFRqLlerzOcop2kbtU3Ar230wOx3Dj23Wg8++lV3LU4U9vMR/t0qnSbCSGJys7m\n' + 'ax2JpFlTwj/0wYuTlVFoNQHZJ1cdfyRiRBY4Ou7XO0W5hcBBKiYsC+neEeMMHdCe\n' + 'iTDIW/ojcVTdFovl+sq3n1u4SBknE90JC/3H+TPE1s2iB+fwORVg0KPosQSNDS0A\n' + '7iK6AZCDC3YooFo+OzHkYMt9uLkXiXMSLx70az+qlIwOzVHKxCo7W/QpeKCXUCRZ\n' + 'MMdlYEUs1PC8x2qIRUEVHuJ0XMTKNyOHmzVLuLK93wUWbToh+rdDxnbhX+emuESn\n' + 'XH6aKiUwX4olEVKSylRUQw8nVckZGVWXzLDlgpzDrLHC8J8qHzFt7eCqOdiqsxhZ\n' + 'x1U5LtugxwSWncTZ7vlKl0DuC/AWB7SuDi7bGRMSVp2n+MnD1VLKlsCclHXjIciE\n' + 'W29n3G3lJ/sOta2sxqLd0j1XBQddrFXl5b609sIY81ocHqu8P2hRu5CpqJ/sGZC5\n' + 'mMH3segHBkRj0xJcfOxceRLj1a+ULIIR3xL/3f8s5Id25TDo/nqBoCvu5PeCpo6L\n' + '9wIDAQAB\n' + '-----END PUBLIC KEY-----'; // 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 trayContextMenu; let mainWindow; let mainWindowTray; let mountedData = {}; let mountedLocations = []; let expectedUnmount = {}; let launchHidden = false; let firstMountCheck = true; let manualMountDetection = {}; let isQuiting = false; app.on('before-quit', function () { isQuiting = true; }); function closeApplication() { app.quit(); } function setWindowVisibility(show) { if (show) { mainWindow.show(); if (os.platform() === 'darwin') { app.dock.show(); } if (mainWindow.isMinimized()) { mainWindow.restore(); } mainWindow.focus(); } else { mainWindow.hide(); if (os.platform() === 'darwin') { app.dock.hide(); } } if (trayContextMenu && mainWindowTray) { trayContextMenu.items[0].checked = show; mainWindowTray.setContextMenu(trayContextMenu) } } function createWindow() { loadUiSettings(); // Create the browser window. const height = (process.env.ELECTRON_START_URL || (os.platform() === 'darwin') ? 364 : 344) - ((os.platform() === 'win32') ? 0 : 20); mainWindow = new BrowserWindow({ width: 428 + ((os.platform() === 'win32') ? 0 : (os.platform() === 'darwin') ? 150 : 160), height: height, fullscreen: false, resizable: false, show: !launchHidden, title: 'Repertory UI', webPreferences: { webSecurity: !process.env.ELECTRON_START_URL } }); if ((os.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; // Unmount all items for (const i in mountedLocations) { const data = mountedData[mountedLocations[i]]; helpers.stopMountProcessSync(data.DataDirectory, data.Version, data.StorageType); } mountedLocations = []; mountedData = {}; }); const appPath = (os.platform() === 'win32') ? path.resolve(path.join(app.getAppPath(), '..\\..\\repertory-ui.exe')) : (os.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, (os.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 instanceLock = app.requestSingleInstanceLock(); if (!instanceLock) { closeApplication(); } else { app.on('second-instance', () => { if (mainWindow) { setWindowVisibility(true); } }); app.on('ready', createWindow); app.on('window-all-closed', () => { closeApplication(); }); } const clearManualMountDetection = (storageType) => { if (manualMountDetection[storageType]) { clearInterval(manualMountDetection[storageType]); delete manualMountDetection[storageType]; } }; const loadUiSettings = () => { const settingFile = path.join(helpers.resolvePath(Constants.DATA_LOCATIONS[os.platform()]), 'ui.json'); try { if (fs.statSync(settingFile).isFile()) { const settings = JSON.parse(fs.readFileSync(settingFile, 'utf8')); launchHidden = settings.launch_hidden; } } catch (e) { } }; const monitorMount = (sender, storageType, dataDirectory, version, pid, location) => { manualMountDetection[storageType] = setInterval(() => { helpers .detectRepertoryMounts(dataDirectory, version) .then(result => { if (result[storageType].PID !== pid) { if (result[storageType].PID === -1) { clearManualMountDetection(storageType); sender.send(Constants.IPC_Unmount_Drive_Reply, { data: { Expected: expectedUnmount[storageType], Location: location, StorageType: storageType, Error: Error(storageType + ' Unmounted').toString(), Success: false, } }); } else { pid = result[storageType].PID; } } }) .catch(e => { console.log(e); }); },6000); }; const saveUiSettings = () => { const settingFile = path.join(helpers.resolvePath(Constants.DATA_LOCATIONS[os.platform()]), 'ui.json'); try { fs.writeFileSync(settingFile, JSON.stringify({ launch_hidden: launchHidden, }), 'utf-8'); } catch (e) { } }; const standardIPCReply = (event, channel, data, error) => { if (mainWindow) { event.sender.send(channel, { data: { ...data, Error: error instanceof Error ? error.toString() : error, Success: !error, } }); } }; ipcMain.on(Constants.IPC_Browse_Directory + '_sync', (event, data) => { dialog.showOpenDialog(mainWindow, { defaultPath: data.Location, properties: ['openDirectory'], title: data.Title, }, (filePaths) => { if (filePaths && (filePaths.length > 0)) { event.returnValue = filePaths[0]; } else { event.returnValue = ''; } }); }); ipcMain.on(Constants.IPC_Check_Dependency_Installed, (event, data) => { try { const exists = fs.lstatSync(data.File).isFile(); standardIPCReply(event, Constants.IPC_Check_Dependency_Installed_Reply, { data: { Exists: exists, }, }); } catch (e) { standardIPCReply(event, Constants.IPC_Check_Dependency_Installed_Reply, { data : { Exists: false, }, }); } }); ipcMain.on(Constants.IPC_Check_Dependency_Installed + '_sync', (event, data) => { try { const ls = fs.lstatSync(data.File); event.returnValue = { data: { Exists: ls.isFile() || ls.isSymbolicLink(), }, }; } catch (e) { event.returnValue = { data: { Exists: false }, }; } }); ipcMain.on(Constants.IPC_Check_Installed, (event, data) => { const dataDirectory = helpers.resolvePath(data.Directory); const destination = path.join(dataDirectory, data.Version); helpers .getMissingDependencies(data.Dependencies) .then((dependencies) => { let exists = false; try { exists = fs.existsSync(destination) && fs.lstatSync(destination).isDirectory(); } catch (e) { } standardIPCReply(event, Constants.IPC_Check_Installed_Reply, { Dependencies: dependencies, Exists: exists, Version: data.Version, }); }).catch(error => { standardIPCReply(event, Constants.IPC_Check_Installed_Reply, { Dependencies: [], Version: data.Version, }, error); }); }); ipcMain.on(Constants.IPC_Check_Mount_Location + '_sync', (event, data) => { let response = { Success: true, Error: '' }; try { if (fs.existsSync(data.Location) && fs.statSync(data.Location).isDirectory()) { if (fs.readdirSync(data.Location).length !== 0) { response.Success = false; response.Error = 'Directory not empty: ' + data.Location; } } else { response.Success = false; response.Error = 'Directory not found: ' + data.Location; } } catch (e) { response.Success = false; response.Error = e.toString(); } event.returnValue = response; }); ipcMain.on(Constants.IPC_Delete_File, (event, data) => { try { if (fs.existsSync(data.FilePath)) { fs.unlinkSync(data.FilePath); } } catch (e) { } }); ipcMain.on(Constants.IPC_Delete_File + '_sync', (event, data) => { try { if (fs.existsSync(data.FilePath)) { fs.unlinkSync(data.FilePath); } event.returnValue = { data: true, }; } catch (e) { event.returnValue = { data: false, }; } }); ipcMain.on(Constants.IPC_Detect_Mounts, (event, data) => { let driveLetters = {}; for (const provider of Constants.PROVIDER_LIST) { driveLetters[provider] = []; } const grabDriveLetters = (locations) => { for (let i = 'c'.charCodeAt(0); i <= 'z'.charCodeAt(0); i++) { const drive = (String.fromCharCode(i) + ':').toUpperCase(); let driveInUse; if (Object.keys(locations).length > 0) { for (const provider of Constants.PROVIDER_LIST) { driveInUse = locations[provider].startsWith(drive); if (driveInUse) break; } } if (!driveInUse) { try { if (!fs.existsSync(drive)) { for (const provider of Constants.PROVIDER_LIST) { driveLetters[provider].push(drive); } } } catch (e) { } } } if (Object.keys(locations).length > 0) { for (const provider of Constants.PROVIDER_LIST) { if (locations[provider].length > 0) { if (!driveLetters[provider].find((driveLetter) => { return driveLetter === locations[provider]; })) { driveLetters[provider].push(locations[provider]); } } } } }; const setImage = (locations) => { let driveInUse; if (Object.keys(locations).length > 0) { for (const provider of Constants.PROVIDER_LIST) { driveInUse = locations[provider].length > 0; if (driveInUse) break; } } let image; if (driveInUse) { image = nativeImage.createFromPath(path.join(__dirname, os.platform() === 'darwin' ? '../build/logo_both_mac.png' : '../build/logo_both.png')); } else { image = nativeImage.createFromPath(path.join(__dirname, os.platform() === 'darwin' ? '../build/logo_mac.png' : '../build/logo.png')); } mainWindowTray.setImage(image); }; const dataDirectory = helpers.resolvePath(data.Directory); helpers .detectRepertoryMounts(dataDirectory, data.Version) .then((results) => { let storageData = {}; let locations = {}; for (const provider of Constants.PROVIDER_LIST) { storageData[provider] = results[provider] ? results[provider] : { Active: false, Location: '', PID: -1, }; locations[provider] = storageData[provider].Location; if (storageData[provider].PID !== -1) { expectedUnmount[provider] = false; if (firstMountCheck) { monitorMount(event.sender, provider, dataDirectory, data.Version, storageData[provider].PID, storageData[provider].Location); } } } if (os.platform() === 'win32') { grabDriveLetters(locations); } setImage(locations); if (firstMountCheck) { firstMountCheck = false; } standardIPCReply(event, Constants.IPC_Detect_Mounts_Reply, { DriveLetters: driveLetters, Locations: locations, }); }) .catch(error => { if (os.platform() === 'win32') { grabDriveLetters({}); } setImage({}); standardIPCReply(event, Constants.IPC_Detect_Mounts_Reply, { DriveLetters: driveLetters, }, error); }); }); ipcMain.on(Constants.IPC_Download_File, (event, data) => { const dataDirectory = helpers.resolvePath(data.Directory); const destination = path.join(dataDirectory, data.Filename); helpers.downloadFile(data.URL, destination, (progress) => { standardIPCReply(event, Constants.IPC_Download_File_Progress, { Destination: destination, Progress: progress, URL: data.URL, }); }, error => { standardIPCReply(event, Constants.IPC_Download_File_Complete, { Destination: destination, URL: data.URL, }, error); }); }); ipcMain.on(Constants.IPC_Extract_Release, (event, data) => { const dataDirectory = helpers.resolvePath(data.Directory); const destination = path.join(dataDirectory, data.Version); helpers.mkDirByPathSync(destination); const stream = fs.createReadStream(data.Source); stream .pipe(unzip.Extract({ path: destination })) .on('error', error => { try { helpers.removeDirectoryRecursively(destination); } catch (e) { } stream.close(); standardIPCReply(event, Constants.IPC_Extract_Release_Complete, { Source: data.Source, }, error); }) .on('finish', () => { stream.close(); if (os.platform() !== 'win32') { helpers .executeAndWait("chmod +x \"" + path.join(destination, 'repertory') + "\"") .then(() => { standardIPCReply(event, Constants.IPC_Extract_Release_Complete, { Source: data.Source, }); }) .catch(error => { standardIPCReply(event, Constants.IPC_Extract_Release_Complete, { Source: data.Source, }, error); }) } else { standardIPCReply(event, Constants.IPC_Extract_Release_Complete, { Source: data.Source, }); } }); }); ipcMain.on(Constants.IPC_Get_Config, (event, data) => { const dataDirectory = helpers.resolvePath(data.Directory); helpers .getConfig(dataDirectory, data.Version, data.StorageType) .then((data) => { if (data.Code === 0) { standardIPCReply(event, Constants.IPC_Get_Config_Reply, { Config: data.Data, }); } else { standardIPCReply(event, Constants.IPC_Get_Config_Reply, {}, data.Code); } }) .catch(error => { standardIPCReply(event, Constants.IPC_Get_Config_Reply, {}, error); }); }); ipcMain.on(Constants.IPC_Get_Config_Template, (event, data) => { const dataDirectory = helpers.resolvePath(data.Directory); helpers .getConfigTemplate(dataDirectory, data.Version, data.StorageType) .then((data) => { standardIPCReply(event, Constants.IPC_Get_Config_Template_Reply, { Template: data, }); }) .catch(error => { standardIPCReply(event, Constants.IPC_Get_Config_Template_Reply, {}, error); }); }); ipcMain.on(Constants.IPC_Get_Platform, (event) => { let platform = os.platform(); if (platform === 'linux') { const scriptFile = path.join(os.tmpdir(), 'repertory_detect_linux.sh'); fs.writeFileSync(scriptFile, detectScript); helpers .executeScript(scriptFile) .then(data => { platform = data.replace(/(\r\n|\n|\r)/gm,""); event.sender.send(Constants.IPC_Get_Platform_Reply, { data: platform, }); }) .catch(() => { event.sender.send(Constants.IPC_Get_Platform_Reply, { data: platform, }); }); } else { event.sender.send(Constants.IPC_Get_Platform_Reply, { data: platform, }); } }); ipcMain.on(Constants.IPC_Get_State, (event, data) => { const dataDirectory = helpers.resolvePath(data); helpers.mkDirByPathSync(dataDirectory); const configFile = path.join(dataDirectory, 'settings.json'); if (fs.existsSync(configFile)) { event.sender.send(Constants.IPC_Get_State_Reply, { data: JSON.parse(fs.readFileSync(configFile, 'utf8')), }); } else { event.sender.send(Constants.IPC_Get_State_Reply, { data: null, }); } }); ipcMain.on(Constants.IPC_Grab_Releases, (event) => { standardIPCReply(event, Constants.IPC_Grab_Releases_Reply); }); ipcMain.on(Constants.IPC_Grab_UI_Releases, (event) => { standardIPCReply(event, Constants.IPC_Grab_UI_Releases_Reply); }); ipcMain.on(Constants.IPC_Install_Dependency, (event, data) => { if (data.Source.toLowerCase().endsWith('.dmg')) { helpers .executeAsync('open', ['-a', 'Finder', '-W', data.Source]) .then(() => { standardIPCReply(event, Constants.IPC_Install_Dependency_Reply, { Source: data.Source, URL: data.URL, }); }) .catch(error=> { standardIPCReply(event, Constants.IPC_Install_Dependency_Reply, { Source: data.Source, URL: data.URL, }, error); }); } else { helpers .executeAndWait(data.Source) .then(() => { standardIPCReply(event, Constants.IPC_Install_Dependency_Reply, { Source: data.Source, URL: data.URL, }); }) .catch(error => { standardIPCReply(event, Constants.IPC_Install_Dependency_Reply, { Source: data.Source, URL: data.URL, }, error); }); } }); ipcMain.on(Constants.IPC_Install_Upgrade, (event, data) => { let tempSig; let tempPub; const hasSignature = data.Signature && (data.Signature.length > 0); const hasHash = data.Sha256 && (data.Sha256.length > 0); if (hasSignature) { try { const files = helpers.createSignatureFiles(data.Signature, publicKey); tempPub = files.PublicKeyFile; tempSig = files.SignatureFile; } catch (e) { standardIPCReply(event, Constants.IPC_Install_Upgrade_Reply, { Source: data.Source, }, e); return; } } const cleanupFiles = () => { try { if (tempSig) { fs.unlinkSync(tempSig); } if (tempPub) { fs.unlinkSync(tempPub); } } catch (e) { } }; let command; let args; const platform = os.platform(); if (platform === 'win32') { command = data.Source; } else if (platform === 'darwin') { command = 'open'; args = ['-a', 'Finder', data.Source]; } else if (platform === 'linux') { try { const execPath = path.join(os.tmpdir(), 'install_linux.sh'); fs.writeFileSync(execPath, installScript); fs.chmodSync(execPath, '750'); command = execPath; args = [data.Source]; } catch (e) { cleanupFiles(); standardIPCReply(event, Constants.IPC_Install_Upgrade_Reply, { Source: data.Source, }, e); } } else { cleanupFiles(); standardIPCReply(event, Constants.IPC_Install_Upgrade_Reply, { Source: data.Source, }, Error('Platform not supported: ' + os.platform())); } if (command) { const executeInstall = () => { helpers .executeAsync(command, args) .then(() => { cleanupFiles(); closeApplication(); }) .catch(error => { cleanupFiles(); standardIPCReply(event, Constants.IPC_Install_Upgrade_Reply, { Source: data.Source, }, error); }); }; if (hasSignature) { helpers .verifySignature(data.Source, tempSig, tempPub) .then(() => { executeInstall(); }) .catch(() => { cleanupFiles(); standardIPCReply(event, Constants.IPC_Install_Upgrade_Reply, { Source: data.Source, }, 'Failed to verify installation package signature'); }); } else if (hasHash) { helpers .verifyHash(data.Source, data.Sha256) .then(()=> { executeInstall(); }) .catch(() => { cleanupFiles(); standardIPCReply(event, Constants.IPC_Install_Upgrade_Reply, { Source: data.Source, }, 'Failed to verify installation package hash'); }); } else { executeInstall(); } } else { cleanupFiles(); standardIPCReply(event, Constants.IPC_Install_Upgrade_Reply, { Source: data.Source, }, Error('Unsupported upgrade: ' + data.Source)); } }); ipcMain.on(Constants.IPC_Mount_Drive, (event, data) => { expectedUnmount[data.StorageType] = false; const dataDirectory = helpers.resolvePath(data.Directory); if (mountedLocations.indexOf(data.Location) !== -1) { console.log(data.StorageType + ' already mounted: ' + data.Location); } else { mountedLocations.push(data.Location); mountedData[data.Location] = { DataDirectory: dataDirectory, Version: data.Version, StorageType: data.StorageType, }; const errorHandler = (pid, error) => { if (mountedLocations.indexOf(data.Location) !== -1) { mountedLocations.splice(mountedLocations.indexOf(data.Location), 1); delete mountedData[data.Location]; } standardIPCReply(event, Constants.IPC_Unmount_Drive_Reply, { Expected: expectedUnmount[data.StorageType], Location: data.Location, StorageType: data.StorageType, }, error || Error(data.StorageType + ' Unmounted')); }; helpers .executeMount(dataDirectory, data.Version, data.StorageType, data.Location, data.NoConsoleSupported, (error, pid) => { errorHandler(pid, error); }) .then(() => { standardIPCReply(event, Constants.IPC_Mount_Drive_Reply, { StorageType: data.StorageType, }); }) .catch(error => { errorHandler(-1, error); }); } }); ipcMain.on(Constants.IPC_Save_State, (event, data) => { const dataDirectory = helpers.resolvePath(data.Directory); helpers.mkDirByPathSync(dataDirectory); const configFile = path.join(dataDirectory, 'settings.json'); fs.writeFileSync(configFile, JSON.stringify(data.State), 'utf8'); }); ipcMain.on(Constants.IPC_Set_Config_Values, (event, data) => { const dataDirectory = helpers.resolvePath(data.Directory); const setConfigValue = (i) => { if (i < data.Items.length) { helpers .setConfigValue(data.Items[i].Name, data.Items[i].Value, dataDirectory, data.StorageType, data.Version) .then(() => { setConfigValue(++i); }) .catch(() => { setConfigValue(++i); }); } else { standardIPCReply(event, Constants.IPC_Set_Config_Values_Reply, {}); } }; setConfigValue(0); }); ipcMain.on(Constants.IPC_Shutdown, () => { closeApplication(); }); ipcMain.on(Constants.IPC_Unmount_Drive, (event, data) => { clearManualMountDetection(data.StorageType); const dataDirectory = helpers.resolvePath(data.Directory); expectedUnmount[data.StorageType] = true; helpers .stopMountProcess(dataDirectory, data.Version, data.StorageType) .then((result)=> { console.log(result); }) .catch((e) => { console.log(e); }); });