diff --git a/electron.js b/electron.js index 0d6cd06..d6761cb 100644 --- a/electron.js +++ b/electron.js @@ -155,6 +155,19 @@ const standardIPCReply = (event, channel, data, error) => { }); }; +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, { + Exists: exists, + }); + } catch (e) { + standardIPCReply(event, Constants.IPC_Check_Dependency_Installed_Reply, { + Exists: false, + }, e); + } +}); + ipcMain.on(Constants.IPC_Check_Installed, (event, data) => { const dataDirectory = helpers.resolvePath(data.Directory); const destination = path.join(dataDirectory, data.Version); @@ -406,18 +419,37 @@ ipcMain.on(Constants.IPC_Grab_UI_Releases, (event) => { }); ipcMain.on(Constants.IPC_Install_Dependency, (event, data) => { - helpers + if (data.Source.toLowerCase().endsWith('.dmg')) { + helpers + .executeAsync('hdiutil', ['attach', 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(()=> { + .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) => { diff --git a/helpers.js b/helpers.js index 95abc90..1e97d5f 100644 --- a/helpers.js +++ b/helpers.js @@ -125,7 +125,7 @@ module.exports.executeAndWait = command => { }); }; -module.exports.executeAsync = (command) => { +module.exports.executeAsync = (command, args=[]) => { return new Promise((resolve, reject) => { const launchProcess = (count, timeout) => { const processOptions = { @@ -133,7 +133,7 @@ module.exports.executeAsync = (command) => { shell: true, }; - const process = new spawn(command, [], processOptions); + const process = new spawn(command, args, processOptions); const pid = process.pid; process.on('error', (err) => { @@ -146,10 +146,13 @@ module.exports.executeAsync = (command) => { }); process.on('exit', (code) => { - if (++count === 5) { - reject(code, pid); - } else { - setTimeout(()=>launchProcess(count, setTimeout(() => resolve(), 3000)), 1000); + if (code !== 0) { + if (++count === 5) { + reject(code, pid); + } else { + clearTimeout(timeout); + setTimeout(() => launchProcess(count, setTimeout(() => resolve(), 3000)), 1000); + } } }); diff --git a/package.json b/package.json index 5466217..e51ffe7 100644 --- a/package.json +++ b/package.json @@ -36,18 +36,18 @@ "html-webpack-plugin": "2.29.0", "jest": "20.0.4", "node-schedule": "^1.3.0", - "npm": "^6.2.0", + "npm": "^6.4.1", "object-assign": "4.1.1", "postcss-flexbugs-fixes": "3.2.0", "postcss-loader": "2.0.8", "promise": "8.0.1", "raf": "3.4.0", - "react": "^16.4.1", + "react": "^16.6.1", "react-css-modules": "^4.7.4", "react-dev-utils": "^5.0.1", - "react-dom": "^16.4.1", - "react-loader-spinner": "^2.0.6", - "react-tooltip": "^3.8.4", + "react-dom": "^16.6.1", + "react-loader-spinner": "^2.2.0", + "react-tooltip": "^3.9.0", "resolve": "1.6.0", "style-loader": "0.19.0", "sw-precache-webpack-plugin": "0.11.4", diff --git a/src/App.js b/src/App.js index 134aa02..47aef27 100644 --- a/src/App.js +++ b/src/App.js @@ -171,78 +171,27 @@ class App extends Component { }; handleAutoMountChanged = (storageType, e) => { - let sia = { - ...this.state.Sia + const state = { + ...this.state[storageType], + AutoMount: e.target.checked, }; - - let siaPrime = { - ...this.state.SiaPrime - }; - - let hyperspace = { - ...this.state.Hyperspace - }; - - if (storageType === 'Hyperspace') { - hyperspace.AutoMount = e.target.checked; - this.setState({ - Hyperspace: hyperspace, - }, ()=> { - this.saveState(this.state.Release, this.state.Version, this.state.Sia, this.state.Hyperspace, this.state.SiaPrime); - }); - } else if (storageType === 'Sia') { - sia.AutoMount = e.target.checked; - this.setState({ - Sia: sia, - }, ()=> { - this.saveState(this.state.Release, this.state.Version, this.state.Sia, this.state.Hyperspace, this.state.SiaPrime); - }); - } else if (storageType === 'SiaPrime') { - siaPrime.AutoMount = e.target.checked; - this.setState({ - SiaPrime: siaPrime, - }, ()=> { - this.saveState(this.state.Release, this.state.Version, this.state.Sia, this.state.Hyperspace, this.state.SiaPrime); - }); - } - + this.setState({ + [storageType]: state, + }, ()=> { + this.saveState(this.state.Release, this.state.Version, this.state.Sia, this.state.Hyperspace, this.state.SiaPrime); + }); }; handleAutoRestartChanged = (storageType, e) => { - let sia = { - ...this.state.Sia + const state = { + ...this.state[storageType], + AutoRestart: e.target.checked, }; - - let siaPrime = { - ...this.state.SiaPrime - }; - - let hyperspace = { - ...this.state.Hyperspace - }; - - if (storageType === 'Hyperspace') { - hyperspace.AutoRestart = e.target.checked; - this.setState({ - Hyperspace: hyperspace, - }, ()=> { - this.saveState(this.state.Release, this.state.Version, this.state.Sia, this.state.Hyperspace, this.state.SiaPrime); - }); - } else if (storageType === 'Sia') { - sia.AutoRestart = e.target.checked; - this.setState({ - Sia: sia, - }, ()=> { - this.saveState(this.state.Release, this.state.Version, this.state.Sia, this.state.Hyperspace, this.state.SiaPrime); - }); - } else if (storageType === 'SiaPrime') { - siaPrime.AutoRestart = e.target.checked; - this.setState({ - SiaPrime: siaPrime, - }, ()=> { - this.saveState(this.state.Release, this.state.Version, this.state.Sia, this.state.Hyperspace, this.state.SiaPrime); - }); - } + this.setState({ + [storageType]: state, + }, ()=> { + this.saveState(this.state.Release, this.state.Version, this.state.Sia, this.state.Hyperspace, this.state.SiaPrime); + }); }; handleConfigClicked = (storageType) => { @@ -281,30 +230,21 @@ class App extends Component { ...this.state[storageType], MountLocation: location, }; - const hyperspace = (storageType === 'Hyperspace') ? state : { - ...this.state.Hyperspace, - }; - const sia = storageType === 'Sia' ? state : { - ...this.state.Sia, - }; - const siaPrime = storageType === 'SiaPrime' ? state : { - ...this.state.SiaPrime, - }; - - this.saveState(this.state.Release, this.state.Version, sia, hyperspace, siaPrime); this.setState({ [storageType]: state, + }, ()=> { + this.saveState(this.state.Release, this.state.Version, this.state.Sia, this.state.Hyperspace, this.state.SiaPrime); }); }; handleReleaseChanged = (e) => { const val = parseInt(e.target.value, 10); const versionIndex = this.state.VersionLookup[this.state.ReleaseTypes[val]].length - 1; - this.saveState(val, versionIndex, this.state.Sia, this.state.Hyperspace, this.state.SiaPrime); this.setState({ Release: val, Version: versionIndex }, ()=> { + this.saveState(this.state.Release, this.state.Version, this.state.Sia, this.state.Hyperspace, this.state.SiaPrime); this.checkVersionInstalled( ); }); }; @@ -346,11 +286,10 @@ class App extends Component { }; handleVersionChanged = (e) => { - const val = parseInt(e.target.value, 10); - this.saveState(this.state.Release, val, this.state.Sia, this.state.Hyperspace, this.state.SiaPrime); this.setState({ - Version: val + Version: parseInt(e.target.value, 10), }, ()=> { + this.saveState(this.state.Release, this.state.Version, this.state.Sia, this.state.Hyperspace, this.state.SiaPrime); this.checkVersionInstalled( ); }); }; @@ -415,6 +354,7 @@ class App extends Component { if (arg.data.Success) { ipcRenderer.send(Constants.IPC_Install_Dependency, { Source: arg.data.Destination, + URL: arg.data.URL, }); } @@ -579,10 +519,14 @@ class App extends Component { }; onInstallDependencyReply = (event, arg) => { - ipcRenderer.send(Constants.IPC_Delete_File, { - FilePath: arg.data.Source, - }); - this.checkVersionInstalled( ); + if (arg.data.Success && arg.data.Source.toLowerCase().endsWith('.dmg')) { + this.waitForDependencyInstall(arg.data.URL); + } else { + ipcRenderer.send(Constants.IPC_Delete_File, { + FilePath: arg.data.Source, + }); + this.checkVersionInstalled(); + } }; onInstallUpgradeReply = (event, arg) => { @@ -627,6 +571,22 @@ class App extends Component { } }; + waitForDependencyInstall = (url) => { + const dep = this.state.MissingDependencies.find(d => { + return d.download === url; + }); + + const i = setInterval(()=> { + const ret = ipcRenderer.sendSync(Constants.IPC_Check_Dependency_Installed, { + File: dep.file, + }); + if (ret.data.Exists || !ret.data.Success) { + clearInterval(i); + this.checkVersionInstalled(); + } + }, 3000); + }; + render() { const selectedVersion = (this.state.Version === -1) ? 'unavailable' : diff --git a/src/constants.js b/src/constants.js index 06b1a92..407c7a5 100644 --- a/src/constants.js +++ b/src/constants.js @@ -9,6 +9,9 @@ exports.DATA_LOCATIONS = { }; exports.UI_RELEASES_URL = 'https://bitbucket.org/blockstorage/repertory-ui/raw/master/releases.json'; +exports.IPC_Check_Dependency_Installed = 'check_dependency_installed'; +exports.IPC_Check_Dependency_Installed_Reply = 'check_dependency_installed'; + exports.IPC_Check_Installed = 'check_installed'; exports.IPC_Check_Installed_Reply = 'check_installed_reply';