diff --git a/src/App.js b/src/App.js index 5a99932..baf8e30 100644 --- a/src/App.js +++ b/src/App.js @@ -17,17 +17,22 @@ import UpgradeIcon from './components/UpgradeIcon/UpgradeIcon'; 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'; 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_Download_File_Complete, this.onDownloadFileComplete); - this.setRequestHandler(Constants.IPC_Download_File_Progress, this.onDownloadFileProgress); 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); @@ -35,39 +40,29 @@ class App extends IPCContainer { } state = { - AllowDownload: false, DisplayError: false, Error: null, ErrorAction: null, ErrorCritical: false, - DownloadActive: false, - DownloadProgress: 0.0, - DownloadingDependency: false, - DownloadName: '', - DownloadingRelease: false, - DownloadingUpgrade: false, ExtractActive: false, MissingDependencies: [], InstalledVersion: 'none', }; checkVersionInstalled = () => { - this.setState({ - AllowDownload: false, - }, ()=> { - const selectedVersion = this.getSelectedVersion(); - if (selectedVersion !== 'unavailable') { - let dependencies = []; - if (this.props.LocationsLookup[selectedVersion] && this.props.LocationsLookup[selectedVersion].dependencies) { - dependencies = this.props.LocationsLookup[selectedVersion].dependencies; - } - - this.sendRequest(Constants.IPC_Check_Installed, { - Dependencies: dependencies, - Version: selectedVersion, - }); + this.props.setAllowDownload(false); + const selectedVersion = this.getSelectedVersion(); + if (selectedVersion !== 'unavailable') { + let dependencies = []; + if (this.props.LocationsLookup[selectedVersion] && this.props.LocationsLookup[selectedVersion].dependencies) { + dependencies = this.props.LocationsLookup[selectedVersion].dependencies; } - }); + + this.sendRequest(Constants.IPC_Check_Installed, { + Dependencies: dependencies, + Version: selectedVersion, + }); + } }; closeErrorDisplay = () => { @@ -121,14 +116,6 @@ class App extends IPCContainer { Version: selectedVersion, }); } - - this.setState({ - DownloadActive: false, - DownloadProgress: 0.0, - DownloadingRelease: false, - ExtractActive: data.Success, - DownloadName: '', - }); }; detectUpgrades = () => { @@ -144,46 +131,20 @@ class App extends IPCContainer { this.props.VersionLookup[Constants.RELEASE_TYPES[this.props.Release]][this.props.ReleaseVersion]; }; - handleDependencyDownload = (url) => { - this.setState({ - DownloadActive: true, - DownloadingDependency: true, - DownloadName: this.extractFileNameFromURL(url), - }, ()=> { - this.sendRequest(Constants.IPC_Download_File, { - Filename: this.state.DownloadName, - URL: url, - }); - }); + handleDownloadDependency = url => { + this.props.downloadItem(this.extractFileNameFromURL(url), DownloadTypes.Dependency, url, this.onDownloadFileComplete); }; - handleReleaseDownload = () => { + handleDownloadRelease = () => { const selectedVersion = this.getSelectedVersion(); const fileName = selectedVersion + '.zip'; - this.setState({ - DownloadActive: true, - DownloadingRelease: true, - DownloadName: fileName, - }, () => { - this.sendRequest(Constants.IPC_Download_File, { - Filename: this.state.DownloadName, - URL: this.props.LocationsLookup[selectedVersion].urls[0], - }); - }); + this.props.downloadItem(fileName, DownloadTypes.Release, this.props.LocationsLookup[selectedVersion].urls[0], this.onDownloadFileComplete); }; - handleUIDownload = () => { - this.setState({ - DownloadActive: true, - DownloadingUpgrade: true, - DownloadName: 'UI Upgrade', - }, ()=> { - const url = this.props.UpgradeData.urls[0]; - this.sendRequest(Constants.IPC_Download_File, { - Filename: this.props.Platform === 'win32' ? 'upgrade.exe' : this.extractFileNameFromURL(url), - URL: url, - }); - }); + 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); }; installDependency = data => { @@ -193,13 +154,6 @@ class App extends IPCContainer { URL: data.URL, }); } - - this.setState({ - DownloadActive: false, - DownloadProgress: 0.0, - DownloadingDependency: data.Success, - DownloadName: '', - }); }; installUpgrade = data => { @@ -212,13 +166,6 @@ class App extends IPCContainer { SkipVerification: !!data.SkipVerification, Source: data.Destination, }); - } else { - this.setState({ - DownloadActive: false, - DownloadProgress: 0.0, - DownloadingUpgrade: false, - DownloadName: '', - }); } }; @@ -238,10 +185,8 @@ class App extends IPCContainer { } } this.props.setReleaseUpgradeAvailable(upgradeAvailable); - + this.props.setAllowDownload(true); this.setState({ - AllowDownload: true, - DownloadingDependency: false, MissingDependencies: arg.data.Dependencies, InstalledVersion: installedVersion, }); @@ -254,28 +199,17 @@ class App extends IPCContainer { } }; - onDownloadFileComplete = (event, arg) => { - if (this.state.DownloadingRelease) { - this.extractRelease(arg.data); - } else if (this.state.DownloadingDependency) { - this.installDependency(arg.data); - } else if (this.state.DownloadingUpgrade) { - this.installUpgrade(arg.data); - } else { - this.setState({ - DownloadActive: false, - DownloadProgress: 0.0, - DownloadName: '', - }); + 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; } }; - onDownloadFileProgress = (event, arg) => { - this.setState({ - DownloadProgress: arg.data.Progress, - }); - }; - onExtractReleaseComplete = (event, arg) => { this.sendRequest(Constants.IPC_Delete_File, { FilePath: arg.data.Source, @@ -323,24 +257,18 @@ class App extends IPCContainer { FilePath: arg.data.Source, }); - this.setState({ - DownloadActive: false, - DownloadProgress: 0.0, - DownloadName: '', - }, () => { - if (!arg.data.Success) { - this.setErrorState(arg.data.Error, () => { - // TODO Prompt to verify - if (arg.data.AllowSkipVerification) { - this.installUpgrade( { - SkipVerification: true, - Source: arg.data.Source, - Success: true, - }); - } - }, false); - } - }); + if (!arg.data.Success) { + this.setErrorState(arg.data.Error, () => { + // TODO Prompt to verify + if (arg.data.AllowSkipVerification) { + this.installUpgrade( { + SkipVerification: true, + Source: arg.data.Source, + Success: true, + }); + } + }, false); + } }; saveState = () => { @@ -398,9 +326,9 @@ class App extends IPCContainer { render() { const selectedVersion = this.getSelectedVersion(); - const downloadEnabled = this.state.AllowDownload && + const downloadEnabled = this.props.AllowDownload && !this.props.MountsBusy && - !this.state.DownloadActive && + !this.props.DownloadActive && (selectedVersion !== 'unavailable') && (selectedVersion !== this.state.InstalledVersion); @@ -423,12 +351,12 @@ class App extends IPCContainer { const showUpgrade = this.props.UpgradeAvailable && !this.state.DisplayError && !showConfig && - !this.state.DownloadActive && + !this.props.DownloadActive && !this.props.UpgradeDismissed; const showDependencies = !showUpgrade && missingDependencies && - !this.state.DownloadActive; + !this.props.DownloadActive; let errorDisplay = null; if (this.state.DisplayError) { @@ -455,19 +383,18 @@ class App extends IPCContainer { if (showDependencies) { dependencyDisplay = ( - + onDownload={this.handleDownloadDependency}/> ); } let downloadDisplay = null; - if (this.state.DownloadActive) { + if (this.props.DownloadActive) { downloadDisplay = ( - + ); } @@ -476,7 +403,7 @@ class App extends IPCContainer { if (showUpgrade) { upgradeDisplay = ( - + ); } @@ -487,11 +414,10 @@ class App extends IPCContainer { mainContent.push((
-
)); @@ -503,7 +429,6 @@ class App extends IPCContainer { allowSiaPrime={allowSiaPrime} noConsoleSupported={noConsoleSupported} errorHandler={this.setErrorState} - saveState={this.saveState} version={this.state.InstalledVersion}/> )); @@ -553,9 +478,12 @@ class App extends IPCContainer { const mapStateToProps = state => { return { + AllowDownload: state.download.AllowDownload, AppPlatform: state.common.AppPlatform, AppReady: state.common.AppReady, DisplayConfiguration: state.mounts.DisplayConfiguration, + DownloadActive: state.download.DownloadActive, + DownloadType: state.download.DownloadType, LocationsLookup: state.relver.LocationsLookup, MountsBusy: state.mounts.MountsBusy, Platform: state.common.Platform, @@ -573,8 +501,10 @@ const mapStateToProps = state => { const mapDispatchToProps = dispatch => { return { detectUIUpgrade: () => dispatch(detectUIUpgrade()), + downloadItem: (name, type, url, callback) => dispatch(downloadItem(name, type, url, callback)), loadReleases: ()=> dispatch(loadReleases()), setActiveRelease: (release, version) => dispatch(setActiveRelease(release, version)), + setAllowDownload: allow => dispatch(setAllowDownload(allow)), setDismissUIUpgrade: dismiss => dispatch(setDismissUIUpgrade(dismiss)), setProviderState: (provider, state) => dispatch(setProviderState(provider, state)), setReleaseUpgradeAvailable: available => dispatch(setReleaseUpgradeAvailable(available)), diff --git a/src/components/DownloadProgress/DownloadProgress.js b/src/components/DownloadProgress/DownloadProgress.js index 3ca532a..7efed3f 100644 --- a/src/components/DownloadProgress/DownloadProgress.js +++ b/src/components/DownloadProgress/DownloadProgress.js @@ -1,16 +1,23 @@ import Box from '../UI/Box/Box'; +import {connect} from 'react-redux'; import React from 'react'; import './DownloadProgress.css'; -export default props => { +const mapStateToProps = state => { + return { + DownloadName: state.download.DownloadName, + DownloadProgress: state.download.DownloadProgress, + }; +}; +export default connect(mapStateToProps)(props => { return (
-

{'Downloading ' + props.display}

+

{'Downloading ' + props.DownloadName}

+ value={props.DownloadProgress}/>
); -}; \ No newline at end of file +}); \ No newline at end of file diff --git a/src/containers/MountItems/MountItems.js b/src/containers/MountItems/MountItems.js index 8b18b31..749756e 100644 --- a/src/containers/MountItems/MountItems.js +++ b/src/containers/MountItems/MountItems.js @@ -10,8 +10,8 @@ import { setAllowMount, setAutoMountProcessed, setBusy, - setMountState, setMounted, + setMountState, setProviderState } from '../../redux/actions/mount_actions'; @@ -221,7 +221,6 @@ class MountItems extends IPCContainer { RetrySeconds: 10, }; const mountState = { - ...this.props.MountState[provider], AllowMount: false, Mounted: false, }; diff --git a/src/redux/actions/download_actions.js b/src/redux/actions/download_actions.js new file mode 100644 index 0000000..0e03e64 --- /dev/null +++ b/src/redux/actions/download_actions.js @@ -0,0 +1,52 @@ +import * as Constants from '../../constants'; +import {createAction} from 'redux-starter-kit'; + +export const setAllowDownload = createAction('download/setAllowDownload'); + +export const SET_DOWNLOAD_BEGIN = 'download/setDownloadBegin'; +export const setDownloadBegin = (name, type, url) => { + return { + type: SET_DOWNLOAD_BEGIN, + payload: { + name, + type, + url + } + }; +}; + +export const setDownloadEnd = createAction('download/setDownloadEnd'); +export const setDownloadProgress = createAction('download/setDownloadProgress'); + +export const downloadItem = (name, type, url, completedCallback) => { + return (dispatch, getState) => { + const state = getState(); + if (!state.download.DownloadActive && state.download.AllowDownload) { + if (!process.versions.hasOwnProperty('electron')) { + const ipcRenderer = ((window && window.require) ? window.require('electron').ipcRenderer : null); + if (ipcRenderer) { + dispatch(setDownloadBegin(name, type, url)); + + const downloadFileProgress = (_, arg) => { + dispatch(setDownloadProgress(arg.data.Progress)); + }; + + const downloadFileComplete = (_, arg) => { + this.ipcRenderer.removeListener(Constants.IPC_Download_File_Progress, downloadFileProgress); + this.ipcRenderer.removeListener(Constants.IPC_Download_File_Complete, downloadFileComplete); + completedCallback(name, type, url, arg.data); + dispatch(setDownloadEnd(arg.data)); + }; + + ipcRenderer.on(Constants.IPC_Download_File_Progress, downloadFileProgress); + ipcRenderer.on(Constants.IPC_Download_File_Complete, downloadFileComplete); + + ipcRenderer.send(Constants.IPC_Download_File, { + Filename: name, + URL: url, + }); + } + } + } + }; +}; \ No newline at end of file diff --git a/src/redux/reducers/download_reducer.js b/src/redux/reducers/download_reducer.js new file mode 100644 index 0000000..dfb98cf --- /dev/null +++ b/src/redux/reducers/download_reducer.js @@ -0,0 +1,49 @@ +import {createReducer} from 'redux-starter-kit'; +import {setAllowDownload, SET_DOWNLOAD_BEGIN, setDownloadEnd, setDownloadProgress} from '../actions/download_actions'; + +const defaultDownloadState = { + DownloadActive: false, + DownloadProgress: 0.0, + DownloadingDependency: false, + DownloadName: '', + DownloadType: null, + DownloadingRelease: false, + DownloadResult: null, + DownloadingUpgrade: false +}; + +export const downloadReducer = createReducer({ + ...defaultDownloadState, + AllowDownload: false, +}, { + [setAllowDownload]: (state, action) => { + return { + ...state, + AllowDownload: action.payload, + }; + }, + [SET_DOWNLOAD_BEGIN]: (state, action) => { + return { + ...state, + DownloadActive: true, + DownloadName: action.payload.name, + DownloadProgress: 0.0, + DownloadResult: null, + DownloadType: action.payload.type, + DownloadURL: action.payload.url, + } + }, + [setDownloadEnd]: (state, action) => { + return { + ...state, + ...defaultDownloadState, + DownloadResult: action.payload, + }; + }, + [setDownloadProgress]: (state, action) => { + return { + ...state, + DownloadProgress: action.payload, + } + } +}); \ No newline at end of file diff --git a/src/redux/store/createAppStore.js b/src/redux/store/createAppStore.js index 180a910..86880b3 100644 --- a/src/redux/store/createAppStore.js +++ b/src/redux/store/createAppStore.js @@ -2,10 +2,12 @@ import {configureStore, getDefaultMiddleware} from 'redux-starter-kit'; import {createCommonReducer} from '../reducers/common_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, mounts: mountReducer, relver: releaseVersionReducer, };