From 704a357dd0f78ba7ed17d015a1736161371c2d5e Mon Sep 17 00:00:00 2001 From: "Scott E. Graves" Date: Fri, 7 Jun 2019 15:34:09 -0500 Subject: [PATCH] Redux changes and refactoring --- src/App.js | 136 ++++++++++++-------------- src/constants.js | 6 ++ src/redux/actions/install_actions.js | 81 +++++++++++++++ src/redux/reducers/install_reducer.js | 25 +++++ src/redux/store/createAppStore.js | 4 +- 5 files changed, 177 insertions(+), 75 deletions(-) create mode 100644 src/redux/actions/install_actions.js create mode 100644 src/redux/reducers/install_reducer.js diff --git a/src/App.js b/src/App.js index bb89560..d66a926 100644 --- a/src/App.js +++ b/src/App.js @@ -18,25 +18,17 @@ import UpgradeUI from './components/UpgradeUI/UpgradeUI'; import {setProviderState} from './redux/actions/mount_actions'; import {detectUIUpgrade, loadReleases, setActiveRelease, setDismissUIUpgrade, setReleaseUpgradeAvailable} from './redux/actions/release_version_actions'; import {downloadItem, setAllowDownload} from './redux/actions/download_actions'; +import {installDependency, installRelease, installUpgrade} from './redux/actions/install_actions'; const Constants = require('./constants'); const Scheduler = require('node-schedule'); -const DownloadTypes = { - Dependency: 'dependency', - Release: 'release', - Upgrade: 'upgrade', -}; - class App extends IPCContainer { constructor(props) { super(props); this.setRequestHandler(Constants.IPC_Check_Installed_Reply, this.onCheckInstalledReply); - this.setRequestHandler(Constants.IPC_Extract_Release_Complete, this.onExtractReleaseComplete); this.setRequestHandler(Constants.IPC_Get_State_Reply, this.onGetStateReply); - this.setRequestHandler(Constants.IPC_Install_Dependency_Reply, this.onInstallDependencyReply); - this.setRequestHandler(Constants.IPC_Install_Upgrade_Reply, this.onInstallUpgradeReply); } state = { @@ -44,7 +36,6 @@ class App extends IPCContainer { Error: null, ErrorAction: null, ErrorCritical: false, - ExtractActive: false, MissingDependencies: [], InstalledVersion: 'none', }; @@ -108,16 +99,6 @@ class App extends IPCContainer { return parts[parts.length - 1]; }; - extractRelease = (data) => { - if (data.Success) { - const selectedVersion = this.getSelectedVersion(); - this.sendRequest(Constants.IPC_Extract_Release, { - Source: data.Destination, - Version: selectedVersion, - }); - } - }; - detectUpgrades = () => { if (this.props.AppPlatform !== 'unknown') { this.props.loadReleases(); @@ -132,26 +113,34 @@ class App extends IPCContainer { }; handleDownloadDependency = url => { - this.props.downloadItem(this.extractFileNameFromURL(url), DownloadTypes.Dependency, url, this.onDownloadFileComplete); + this.props.downloadItem(this.extractFileNameFromURL(url), Constants.INSTALL_TYPES.Dependency, url, this.onDownloadFileComplete); }; handleDownloadRelease = () => { const selectedVersion = this.getSelectedVersion(); const fileName = selectedVersion + '.zip'; - this.props.downloadItem(fileName, DownloadTypes.Release, this.props.LocationsLookup[selectedVersion].urls[0], this.onDownloadFileComplete); + this.props.downloadItem(fileName, Constants.INSTALL_TYPES.Release, this.props.LocationsLookup[selectedVersion].urls[0], this.onDownloadFileComplete); }; handleDownloadUpgrade = () => { const url = this.props.UpgradeData.urls[0]; const name = this.props.Platform === 'win32' ? 'upgrade.exe' : this.extractFileNameFromURL(url); - this.props.downloadItem(name, DownloadTypes.Upgrade, url, this.onDownloadFileComplete); + this.props.downloadItem(name, Constants.INSTALL_TYPES.Upgrade, url, this.onDownloadFileComplete); }; installDependency = data => { if (data.Success) { - this.sendRequest(Constants.IPC_Install_Dependency, { - Source: data.Destination, - URL: data.URL, + this.props.installDependency(data.Destination, data.URL, this.onInstallDependencyComplete); + } + }; + + installRelease = data => { + if (data.Success) { + const selectedVersion = this.getSelectedVersion(); + this.props.installRelease(data.Destination, selectedVersion, () => { + if (this.isMounted()) { + this.checkVersionInstalled(); + } }); } }; @@ -160,12 +149,7 @@ class App extends IPCContainer { if (data.Success) { const sha256 = this.props.LocationsLookup[this.props.AppPlatform][this.props.VersionLookup[this.props.AppPlatform][0]].sha256; const signature = this.props.LocationsLookup[this.props.AppPlatform][this.props.VersionLookup[this.props.AppPlatform][0]].sig; - this.sendRequest(Constants.IPC_Install_Upgrade, { - Sha256: sha256, - Signature: signature, - SkipVerification: !!data.SkipVerification, - Source: data.Destination, - }); + this.props.installUpgrade(data.Destination, sha256, signature, !!data.SkipVerification, this.onInstallUpgradeComplete); } }; @@ -201,28 +185,24 @@ class App extends IPCContainer { }; onDownloadFileComplete = (name, type, url, result) => { - switch (type) { - case DownloadTypes.Dependency: this.installDependency(result); break; - case DownloadTypes.Release: this.extractRelease(result); break; - case DownloadTypes.Upgrade: this.installUpgrade(result); break; - default: - this.setErrorState('Unknown download type: ' + type, null, false); - break; + if (this.isMounted()) { + switch (type) { + case Constants.INSTALL_TYPES.Dependency: + this.installDependency(result); + break; + case Constants.INSTALL_TYPES.Release: + this.installRelease(result); + break; + case Constants.INSTALL_TYPES.Upgrade: + this.installUpgrade(result); + break; + default: + this.setErrorState('Unknown download type: ' + type, null, false); + break; + } } }; - onExtractReleaseComplete = (event, arg) => { - this.sendRequest(Constants.IPC_Delete_File, { - FilePath: arg.data.Source, - }); - - this.setState({ - ExtractActive: false, - }, ()=> { - this.checkVersionInstalled( ); - }); - }; - onGetStateReply = (event, arg) => { if (arg.data) { this.props.setActiveRelease(arg.data.Release, arg.data.Version); @@ -242,29 +222,27 @@ class App extends IPCContainer { this.detectUpgrades(); }; - onInstallDependencyReply = (event, arg) => { - if (arg.data.Success && arg.data.Source.toLowerCase().endsWith('.dmg')) { - this.waitForDependencyInstall(arg.data.URL); - } else { - this.sendRequest(Constants.IPC_Delete_File, { - FilePath: arg.data.Source, - }); - this.checkVersionInstalled(); + onInstallDependencyComplete = (source, url, result) => { + if (this.isMounted()) { + if (result.Success && source.toLowerCase().endsWith('.dmg')) { + this.waitForDependencyInstall(source, url); + } else { + this.sendRequest(Constants.IPC_Delete_File, { + FilePath: source, + }); + this.checkVersionInstalled(); + } } }; - onInstallUpgradeReply = (event, arg) => { - this.sendSyncRequest(Constants.IPC_Delete_File, { - FilePath: arg.data.Source, - }); - - if (!arg.data.Success) { - this.setErrorState(arg.data.Error, () => { + onInstallUpgradeComplete = (source, result) => { + if (this.isMounted() && !result.Success) { + this.setErrorState(result.Error, () => { // TODO Prompt to verify - if (arg.data.AllowSkipVerification) { + if (result.AllowSkipVerification) { this.installUpgrade( { SkipVerification: true, - Source: arg.data.Source, + Source: source, Success: true, }); } @@ -306,7 +284,7 @@ class App extends IPCContainer { } }; - waitForDependencyInstall = (url) => { + waitForDependencyInstall = (source, url) => { const dep = this.state.MissingDependencies.find(d => { return d.download === url; }); @@ -318,6 +296,9 @@ class App extends IPCContainer { if (ret.data.Exists) { clearInterval(i); setTimeout(() => { + this.sendRequest(Constants.IPC_Delete_File, { + FilePath: source, + }); this.checkVersionInstalled(); }, 10000); } @@ -334,7 +315,9 @@ class App extends IPCContainer { (selectedVersion !== this.state.InstalledVersion); const missingDependencies = (this.state.MissingDependencies.length > 0); - const allowMount = this.state.InstalledVersion !== 'none' && !missingDependencies; + const allowMount = this.state.InstalledVersion !== 'none' && + !missingDependencies && + !this.props.InstallActive; const allowConfig = this.props.LocationsLookup[selectedVersion] && this.props.LocationsLookup[selectedVersion].config_support; @@ -384,7 +367,7 @@ class App extends IPCContainer { if (showDependencies) { dependencyDisplay = ( - @@ -415,10 +398,10 @@ class App extends IPCContainer { mainContent.push((
-
)); @@ -485,6 +468,8 @@ const mapStateToProps = state => { DisplayConfiguration: state.mounts.DisplayConfiguration, DownloadActive: state.download.DownloadActive, DownloadType: state.download.DownloadType, + InstallActive: state.install.InstallActive, + InstallType: state.install.InstallType, LocationsLookup: state.relver.LocationsLookup, MountsBusy: state.mounts.MountsBusy, Platform: state.common.Platform, @@ -502,7 +487,10 @@ const mapStateToProps = state => { const mapDispatchToProps = dispatch => { return { detectUIUpgrade: () => dispatch(detectUIUpgrade()), - downloadItem: (name, type, url, callback) => dispatch(downloadItem(name, type, url, callback)), + downloadItem: (name, type, url, completedCallback) => dispatch(downloadItem(name, type, url, completedCallback)), + installDependency: (source, url, completedCallback) => dispatch(installDependency(source, url, completedCallback)), + installRelease: (source, version, completedCallback) => dispatch(installRelease(source, version, completedCallback)), + installUpgrade: (source, sha256, signature, skipVerification, completedCallback) => dispatch(installUpgrade(source, sha256, signature, skipVerification, completedCallback)), loadReleases: ()=> dispatch(loadReleases()), setActiveRelease: (release, version) => dispatch(setActiveRelease(release, version)), setAllowDownload: allow => dispatch(setAllowDownload(allow)), diff --git a/src/constants.js b/src/constants.js index 11246f3..396ec97 100644 --- a/src/constants.js +++ b/src/constants.js @@ -65,6 +65,12 @@ exports.RELEASE_TYPES = [ 'Alpha', ]; +exports.INSTALL_TYPES = { + Dependency: 'dependency', + Release: 'release', + Upgrade: 'upgrade', +}; + exports.IPC_Browse_Directory = 'browse_directory'; exports.IPC_Check_Daemon_Version = 'check_daemon_version'; diff --git a/src/redux/actions/install_actions.js b/src/redux/actions/install_actions.js new file mode 100644 index 0000000..75f9ee9 --- /dev/null +++ b/src/redux/actions/install_actions.js @@ -0,0 +1,81 @@ +import * as Constants from '../../constants'; +import {createAction} from 'redux-starter-kit'; + +let ipcRenderer; +if (!process.versions.hasOwnProperty('electron')) { + ipcRenderer = ((window && window.require) ? window.require('electron').ipcRenderer : null); +} + +export const installDependency = (source, url, completedCallback) => { + return (dispatch, getState) => { + if (ipcRenderer && !getState().install.InstallActive) { + dispatch(setInstallActive(Constants.INSTALL_TYPES.Dependency)); + + const installDependencyComplete = (event, arg) => { + ipcRenderer.removeListener(Constants.IPC_Install_Dependency_Reply, installDependencyComplete); + dispatch(setInstallComplete(arg.data)); + completedCallback(source, url, arg.data); + }; + + ipcRenderer.on(Constants.IPC_Install_Dependency_Reply, installDependencyComplete); + ipcRenderer.send(Constants.IPC_Install_Dependency, { + Source: source, + URL: url, + }); + } + }; +}; + +export const installRelease = (source, version, completedCallback) => { + return (dispatch, getState) => { + if (ipcRenderer && !getState().install.InstallActive) { + dispatch(setInstallActive(Constants.INSTALL_TYPES.Release)); + + const extractReleaseComplete = (event, arg) => { + ipcRenderer.removeListener(Constants.IPC_Extract_Release_Complete, extractReleaseComplete); + ipcRenderer.sendSync(Constants.IPC_Delete_File, { + FilePath: source, + }); + + dispatch(setInstallComplete(arg.data)); + completedCallback(source, version, arg.data); + }; + + ipcRenderer.on(Constants.IPC_Extract_Release_Complete, extractReleaseComplete); + ipcRenderer.send(Constants.IPC_Extract_Release, { + Source: source, + Version: version, + }); + } + }; +}; + +export const installUpgrade = (source, sha256, signature, skipVerification, completedCallback) => { + return (dispatch, getState) => { + if (ipcRenderer && !getState().install.InstallActive) { + dispatch(setInstallActive(Constants.INSTALL_TYPES.Dependency)); + + const installUpgradeComplete = (event, arg) => { + ipcRenderer.removeListener(Constants.IPC_Install_Upgrade_Reply, installUpgradeComplete); + ipcRenderer.sendSync(Constants.IPC_Delete_File, { + FilePath: source, + }); + + dispatch(setInstallComplete(arg.data)); + completedCallback(source, arg.data); + }; + + ipcRenderer.on(Constants.IPC_Install_Upgrade_Reply, installUpgradeComplete); + ipcRenderer.send(Constants.IPC_Install_Upgrade, { + Sha256: sha256, + Signature: signature, + SkipVerification: skipVerification, + Source: source, + }); + } + }; +}; + + +export const setInstallActive = createAction('install/setInstallActive'); +export const setInstallComplete = createAction('install/setInstallComplete'); diff --git a/src/redux/reducers/install_reducer.js b/src/redux/reducers/install_reducer.js new file mode 100644 index 0000000..459e9e7 --- /dev/null +++ b/src/redux/reducers/install_reducer.js @@ -0,0 +1,25 @@ +import {createReducer} from 'redux-starter-kit'; +import {setInstallActive, setInstallComplete} from '../actions/install_actions'; + +export const installReducer = createReducer({ + InstallActive: false, + InstallResult: null, + InstallType: null, +}, { + [setInstallActive]: (state, action) => { + return { + ...state, + InstallActive: true, + InstallResult: null, + InstallType: action.payload, + }; + }, + [setInstallComplete]: (state, action) => { + return { + ...state, + InstallActive: false, + InstallResult: action.payload, + InstallType: null, + } + } +}); \ No newline at end of file diff --git a/src/redux/store/createAppStore.js b/src/redux/store/createAppStore.js index 86880b3..9191959 100644 --- a/src/redux/store/createAppStore.js +++ b/src/redux/store/createAppStore.js @@ -1,13 +1,15 @@ import {configureStore, getDefaultMiddleware} from 'redux-starter-kit'; import {createCommonReducer} from '../reducers/common_reducer'; +import {downloadReducer} from '../reducers/download_reducer'; +import {installReducer} from '../reducers/install_reducer'; import {mountReducer} from '../reducers/mount_reducer'; import {releaseVersionReducer} from '../reducers/release_version_reducer'; -import {downloadReducer} from '../reducers/download_reducer'; export default function createAppStore(platform, appPlatform, version) { const reducer = { common: createCommonReducer(platform, appPlatform, version), download: downloadReducer, + install: installReducer, mounts: mountReducer, relver: releaseVersionReducer, };