diff --git a/public/electron.js b/public/electron.js index 982c2dd..f98786c 100644 --- a/public/electron.js +++ b/public/electron.js @@ -662,10 +662,6 @@ ipcMain.on(Constants.IPC_Get_State, event => { } }); -ipcMain.on(Constants.IPC_Grab_Releases, (event) => { - standardIPCReply(event, Constants.IPC_Grab_Releases_Reply); -}); - ipcMain.on(Constants.IPC_Install_Dependency, (event, data) => { if (data.Source.toLowerCase().endsWith('.dmg')) { helpers diff --git a/src/App.js b/src/App.js index b7ba90d..565bf0b 100644 --- a/src/App.js +++ b/src/App.js @@ -1,5 +1,4 @@ import React from 'react'; -import axios from 'axios'; import './App.css'; import Box from './components/UI/Box/Box'; import Configuration from './containers/Configuration/Configuration'; @@ -8,6 +7,7 @@ import DependencyList from './components/DependencyList/DependencyList'; import DownloadProgress from './components/DownloadProgress/DownloadProgress'; import ErrorDetails from './components/ErrorDetails/ErrorDetails'; import Grid from './components/UI/Grid/Grid'; +import IPCContainer from './containers/IPCContainer/IPCContainer'; import Loading from './components/UI/Loading/Loading'; import Modal from './components/UI/Modal/Modal'; import MountItems from './containers/MountItems/MountItems'; @@ -15,8 +15,7 @@ import ReleaseVersionDisplay from './components/ReleaseVersionDisplay/ReleaseVer import Text from './components/UI/Text/Text'; import UpgradeIcon from './components/UpgradeIcon/UpgradeIcon'; import UpgradeUI from './components/UpgradeUI/UpgradeUI'; -import IPCContainer from './containers/IPCContainer/IPCContainer'; -import {detectUIUpgrade, setDismissUIUpgrade} from './redux/actions/release_version_actions'; +import {detectUIUpgrade, loadReleases, setActiveRelease, setDismissUIUpgrade, setReleaseUpgradeAvailable} from './redux/actions/release_version_actions'; const Constants = require('./constants'); const Scheduler = require('node-schedule'); @@ -38,18 +37,15 @@ class App extends IPCContainer { 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_Grab_Releases_Reply, this.onGrabReleasesReply); this.setRequestHandler(Constants.IPC_Install_Dependency_Reply, this.onInstallDependencyReply); this.setRequestHandler(Constants.IPC_Install_Upgrade_Reply, this.onInstallUpgradeReply); - this.sendRequest(Constants.IPC_Get_State); Scheduler.scheduleJob('23 11 * * *', this.updateCheckScheduledJob); } state = { AllowDownload: false, DisplayError: false, - DisplayMainContent: false, Error: null, ErrorAction: null, ErrorCritical: false, @@ -60,26 +56,8 @@ class App extends IPCContainer { DownloadingRelease: false, DownloadingUpgrade: false, ExtractActive: false, - LocationsLookup: {}, MissingDependencies: [], - Release: 2, InstalledVersion: 'none', - Version: -1, - VersionAvailable: false, - VersionLookup: { - Alpha: [ - 'unavailable' - ], - Beta: [ - 'unavailable' - ], - RC: [ - 'unavailable' - ], - Release: [ - 'unavailable' - ], - } }; checkVersionInstalled = () => { @@ -89,8 +67,8 @@ class App extends IPCContainer { const selectedVersion = this.getSelectedVersion(); if (selectedVersion !== 'unavailable') { let dependencies = []; - if (this.state.LocationsLookup[selectedVersion] && this.state.LocationsLookup[selectedVersion].dependencies) { - dependencies = this.state.LocationsLookup[selectedVersion].dependencies; + if (this.props.LocationsLookup[selectedVersion] && this.props.LocationsLookup[selectedVersion].dependencies) { + dependencies = this.props.LocationsLookup[selectedVersion].dependencies; } this.sendRequest(Constants.IPC_Check_Installed, { @@ -116,6 +94,19 @@ class App extends IPCContainer { } }; + componentDidMount() { + this.sendRequest(Constants.IPC_Get_State); + } + + componentDidUpdate(prevProps) { + if ((prevProps.Release !== this.props.Release) || + (prevProps.ReleaseVersion !== this.props.ReleaseVersion) || + (prevProps.VersionLookup !== this.props.VersionLookup)) { + this.saveState(); + this.checkVersionInstalled(); + } + } + extractFileNameFromURL = url => { const parts = url.split('/'); return parts[parts.length - 1]; @@ -140,12 +131,12 @@ class App extends IPCContainer { }; getSelectedVersion = () => { - return this.state.VersionLookup[Constants.RELEASE_TYPES[this.state.Release]][this.state.Version]; + return this.props.VersionLookup[Constants.RELEASE_TYPES[this.props.Release]][this.props.ReleaseVersion]; }; - grabReleases = () => { + detectUpgrades = () => { if (this.props.AppPlatform !== 'unknown') { - this.sendRequest(Constants.IPC_Grab_Releases); + this.props.loadReleases(); this.props.detectUIUpgrade(); } }; @@ -200,15 +191,9 @@ class App extends IPCContainer { }; handleReleaseChanged = (e) => { - const val = parseInt(e.target.value, 10); - const versionIndex = this.state.VersionLookup[Constants.RELEASE_TYPES[val]].length - 1; - this.setState({ - Release: val, - Version: versionIndex - }, ()=> { - this.saveState(); - this.checkVersionInstalled( ); - }); + const release = parseInt(e.target.value, 10); + const releaseVersion = this.props.VersionLookup[Constants.RELEASE_TYPES[release]].length - 1; + this.props.setActiveRelease(release, releaseVersion); }; handleReleaseDownload = () => { @@ -221,7 +206,7 @@ class App extends IPCContainer { }, () => { this.sendRequest(Constants.IPC_Download_File, { Filename: this.state.DownloadName, - URL: this.state.LocationsLookup[selectedVersion].urls[0], + URL: this.props.LocationsLookup[selectedVersion].urls[0], }); }); }; @@ -241,12 +226,7 @@ class App extends IPCContainer { }; handleVersionChanged = (e) => { - this.setState({ - Version: parseInt(e.target.value, 10), - }, ()=> { - this.saveState(); - this.checkVersionInstalled( ); - }); + this.props.setActiveRelease(this.props.Release, parseInt(e.target.value, 10)); }; installDependency = data => { @@ -267,8 +247,8 @@ class App extends IPCContainer { installUpgrade = data => { if (data.Success) { - const sha256 = this.state.LocationsLookup[this.props.AppPlatform][this.state.VersionLookup[this.props.AppPlatform][0]].sha256; - const signature = this.state.LocationsLookup[this.props.AppPlatform][this.state.VersionLookup[this.props.AppPlatform][0]].sig; + 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, @@ -288,23 +268,25 @@ class App extends IPCContainer { onCheckInstalledReply = (event, arg) => { const action = () => { const installedVersion = arg.data.Success && arg.data.Exists ? arg.data.Version : 'none'; - let versionAvailable = false; + let upgradeAvailable = false; if (installedVersion !== 'none') { - const latestVersion = this.state.VersionLookup[Constants.RELEASE_TYPES[this.state.Release]].length - 1; - let version = this.state.Version; + const latestVersion = this.props.VersionLookup[Constants.RELEASE_TYPES[this.props.Release]].length - 1; + let version = this.props.ReleaseVersion; if (version === -1) { version = latestVersion; + this.props.setActiveRelease(this.props.Release, version); + } else { + upgradeAvailable = version !== latestVersion; } - versionAvailable = version !== latestVersion; } + this.props.setReleaseUpgradeAvailable(upgradeAvailable); this.setState({ AllowDownload: true, DownloadingDependency: false, MissingDependencies: arg.data.Dependencies, InstalledVersion: installedVersion, - VersionAvailable: versionAvailable, }); }; @@ -351,11 +333,9 @@ class App extends IPCContainer { onGetStateReply = (event, arg) => { if (arg.data) { - let state = { - Release: arg.data.Release, - Version: arg.data.Version, - }; + this.props.setActiveRelease(arg.data.Release, arg.data.Version); + let state = {}; for (const provider of Constants.PROVIDER_LIST) { let data = arg.data[provider] || this.state[provider]; if (data.AutoMount === undefined) { @@ -368,66 +348,13 @@ class App extends IPCContainer { } this.setState(state, ()=> { - this.grabReleases(); + this.detectUpgrades(); }); } else { - this.grabReleases(); + this.detectUpgrades(); } }; - onGrabReleasesReply = ()=> { - const doUpdate = (locationsLookup, versionLookup) => { - const latestVersion = versionLookup[Constants.RELEASE_TYPES[this.state.Release]].length - 1; - let version = this.state.Version; - if ((version === -1) || !versionLookup[Constants.RELEASE_TYPES[this.state.Release]][version]) { - version = latestVersion; - this.saveState(version); - } - - this.setState({ - DisplayMainContent: true, - LocationsLookup: locationsLookup, - Version: version, - VersionAvailable: version !== latestVersion, - VersionLookup: versionLookup, - }, () => { - this.checkVersionInstalled( ); - }); - }; - - axios - .get(Constants.RELEASES_URL) - .then(response => { - const versionLookup = { - Alpha: response.data.Versions.Alpha[this.props.AppPlatform], - Beta: response.data.Versions.Beta[this.props.AppPlatform], - RC: response.data.Versions.RC[this.props.AppPlatform], - Release: response.data.Versions.Release[this.props.AppPlatform], - }; - const locationsLookup = { - ...response.data.Locations[this.props.AppPlatform], - }; - - window.localStorage.setItem('releases', JSON.stringify({ - LocationsLookup: locationsLookup, - VersionLookup: versionLookup - })); - - doUpdate(locationsLookup, versionLookup); - }).catch(error => { - const releases = window.localStorage.getItem('releases'); - if (releases && (releases.length > 0)) { - const obj = JSON.parse(releases); - const locationsLookup = obj.LocationsLookup; - const versionLookup = obj.VersionLookup; - - doUpdate(locationsLookup, versionLookup); - } else { - this.setErrorState(error, null, true); - } - }); - }; - onInstallDependencyReply = (event, arg) => { if (arg.data.Success && arg.data.Source.toLowerCase().endsWith('.dmg')) { this.waitForDependencyInstall(arg.data.URL); @@ -464,18 +391,21 @@ class App extends IPCContainer { }); }; - saveState = version => { - let state = { - Release: this.state.Release, - Version: version || this.state.Version, - }; - for (const provider of Constants.PROVIDER_LIST) { - state[provider] = this.state[provider]; - } + saveState = () => { + if (this.props.AppReady) { + let state = { + Release: this.props.Release, + Version: this.props.ReleaseVersion, + }; - this.sendRequest(Constants.IPC_Save_State, { - State: state - }); + for (const provider of Constants.PROVIDER_LIST) { + state[provider] = this.state[provider]; + } + + this.sendRequest(Constants.IPC_Save_State, { + State: state + }); + } }; setErrorState = (error, action, critical) => { @@ -491,7 +421,7 @@ class App extends IPCContainer { updateCheckScheduledJob = () => { if (this.props.AppPlatform !== 'unknown') { - this.grabReleases(); + this.detectUpgrades(); } }; @@ -514,7 +444,7 @@ class App extends IPCContainer { }; render() { - const selectedVersion = (this.state.Version === -1) ? + const selectedVersion = (this.props.ReleaseVersion === -1) ? 'unavailable' : this.getSelectedVersion(); @@ -527,14 +457,14 @@ class App extends IPCContainer { const missingDependencies = (this.state.MissingDependencies.length > 0); const allowMount = this.state.InstalledVersion !== 'none' && !missingDependencies; - const allowConfig = this.state.LocationsLookup[selectedVersion] && - this.state.LocationsLookup[selectedVersion].config_support; + const allowConfig = this.props.LocationsLookup[selectedVersion] && + this.props.LocationsLookup[selectedVersion].config_support; - const allowSiaPrime = this.state.LocationsLookup[selectedVersion] && - this.state.LocationsLookup[selectedVersion].siaprime_support; + const allowSiaPrime = this.props.LocationsLookup[selectedVersion] && + this.props.LocationsLookup[selectedVersion].siaprime_support; - const noConsoleSupported = this.state.LocationsLookup[selectedVersion] && - this.state.LocationsLookup[selectedVersion].no_console_supported; + const noConsoleSupported = this.props.LocationsLookup[selectedVersion] && + this.props.LocationsLookup[selectedVersion].no_console_supported; const showConfig = !missingDependencies && this.props.DisplayConfiguration && @@ -602,7 +532,7 @@ class App extends IPCContainer { } let mainContent = []; - if (this.state.DisplayMainContent) { + if (this.props.AppReady) { let key = 0; mainContent.push((
+ text={this.state.InstalledVersion + ' [' + this.props.AppPlatform + ']'} + versionChanged={this.handleVersionChanged}/>
)); @@ -687,20 +613,28 @@ class App extends IPCContainer { const mapStateToProps = state => { return { AppPlatform: state.common.AppPlatform, + AppReady: state.common.AppReady, DisplayConfiguration: state.mounts.DisplayConfiguration, + LocationsLookup: state.relver.LocationsLookup, MountsBusy: state.mounts.MountsBusy, Platform: state.common.Platform, + Release: state.relver.Release, + ReleaseVersion: state.relver.Version, UpgradeAvailable: state.relver.UpgradeAvailable, UpgradeData: state.relver.UpgradeData, UpgradeDismissed: state.relver.UpgradeDismissed, Version: state.common.Version, + VersionLookup: state.relver.VersionLookup, }; }; const mapDispatchToProps = dispatch => { return { detectUIUpgrade: () => dispatch(detectUIUpgrade()), + loadReleases: ()=> dispatch(loadReleases()), + setActiveRelease: (release, version) => dispatch(setActiveRelease(release, version)), setDismissUIUpgrade: dismiss => dispatch(setDismissUIUpgrade(dismiss)), + setReleaseUpgradeAvailable: available => dispatch(setReleaseUpgradeAvailable(available)), }; }; diff --git a/src/components/ReleaseVersionDisplay/ReleaseVersionDisplay.js b/src/components/ReleaseVersionDisplay/ReleaseVersionDisplay.js index 0992e4a..1e111a6 100644 --- a/src/components/ReleaseVersionDisplay/ReleaseVersionDisplay.js +++ b/src/components/ReleaseVersionDisplay/ReleaseVersionDisplay.js @@ -1,13 +1,23 @@ import React from 'react'; import './ReleaseVersionDisplay.css'; import * as Constants from '../../constants'; +import {connect} from 'react-redux'; import DropDown from '../UI/DropDown/DropDown'; import Grid from '../UI/Grid/Grid'; import Text from '../UI/Text/Text'; import Button from '../UI/Button/Button'; import UpgradeIcon from '../UpgradeIcon/UpgradeIcon'; -export default props => { +const mapStateToProps = state => { + return { + Release: state.relver.Release, + ReleaseUpgradeAvailable: state.relver.ReleaseUpgradeAvailable, + ReleaseVersion: state.relver.Version, + VersionLookup: state.relver.VersionLookup, + }; +}; + +export default connect(mapStateToProps)(props => { let optionsDisplay = []; let key = 0; if (props.releaseExtracting) { @@ -26,7 +36,7 @@ export default props => { key={key++} row={5} rowSpan={7} - text={props.installedVersion} + text={props.text} textAlign={'left'}/> )); } else if (props.downloadDisabled) { @@ -46,7 +56,7 @@ export default props => { key={key++} row={5} rowSpan={7} - text={props.installedVersion} + text={props.text} textAlign={'left'}/> )); } else { @@ -74,14 +84,14 @@ export default props => { items={Constants.RELEASE_TYPES} row={5} rowSpan={7} - selected={props.release}/> + selected={props.Release}/> dimensions.columns / 3} colSpan={remain=>remain / 2} rowSpan={4} text={'Version'} textAlign={'left'} type={'Heading2'}/> - ((dimensions.columns / 3) * 2) - 6} colSpan={4} release @@ -90,11 +100,11 @@ export default props => { col={dimensions => dimensions.columns / 3} colSpan={remain=>remain / 2 - 1} disabled={props.disabled} - items={props.versions} + items={props.VersionLookup[Constants.RELEASE_TYPES[props.Release]]} row={5} rowSpan={7} - selected={props.version}/> + selected={props.ReleaseVersion}/> {optionsDisplay} ); -}; \ No newline at end of file +}); \ No newline at end of file diff --git a/src/constants.js b/src/constants.js index dabe650..11246f3 100644 --- a/src/constants.js +++ b/src/constants.js @@ -102,9 +102,6 @@ exports.IPC_Get_Platform_Reply = 'get_platform_reply'; exports.IPC_Get_State = 'get_state'; exports.IPC_Get_State_Reply = 'get_state_reply'; -exports.IPC_Grab_Releases = 'grab_releases'; -exports.IPC_Grab_Releases_Reply = 'grab_releases_reply'; - exports.IPC_Install_Dependency = 'install_dependency'; exports.IPC_Install_Dependency_Reply = 'install_dependency_reply'; diff --git a/src/redux/actions/common_actions.js b/src/redux/actions/common_actions.js new file mode 100644 index 0000000..04e57ea --- /dev/null +++ b/src/redux/actions/common_actions.js @@ -0,0 +1,3 @@ +import {createAction} from 'redux-starter-kit'; + +export const setApplicationReady = createAction('common/setApplicationReady'); \ No newline at end of file diff --git a/src/redux/actions/release_version_actions.js b/src/redux/actions/release_version_actions.js index cac2990..cb53568 100644 --- a/src/redux/actions/release_version_actions.js +++ b/src/redux/actions/release_version_actions.js @@ -1,6 +1,7 @@ import axios from 'axios'; import * as Constants from '../../constants'; import {createAction} from 'redux-starter-kit'; +import {setApplicationReady} from '../actions/common_actions'; export const CLEAR_UI_UPGRADE = 'relver/clearUIUpgrade'; export const clearUIUpgrade = () => { @@ -35,6 +36,59 @@ export const detectUIUpgrade = () => { }; }; +export const loadReleases = () => { + return (dispatch, getState) => { + const dispatchActions = (locationsLookup, versionLookup)=> { + const state = getState().relver; + const latestVersion = versionLookup[Constants.RELEASE_TYPES[state.Release]].length - 1; + let version = state.Version; + if ((version === -1) || !versionLookup[Constants.RELEASE_TYPES[state.Release]][version]) { + version = latestVersion; + } + + dispatch(setReleaseData(locationsLookup, versionLookup)); + if (version !== state.Version) { + dispatch(setActiveRelease(state.Release, version)); + } + dispatch(setReleaseUpgradeAvailable((version !== latestVersion))); + dispatch(setApplicationReady(true)); + }; + + axios + .get(Constants.RELEASES_URL) + .then(response => { + const appPlatform = getState().common.AppPlatform; + const versionLookup = { + Release: response.data.Versions.Release[appPlatform], + RC: response.data.Versions.RC[appPlatform], + Beta: response.data.Versions.Beta[appPlatform], + Alpha: response.data.Versions.Alpha[appPlatform], + }; + const locationsLookup = { + ...response.data.Locations[appPlatform], + }; + + localStorage.setItem('releases', JSON.stringify({ + LocationsLookup: locationsLookup, + VersionLookup: versionLookup + })); + dispatchActions(locationsLookup, versionLookup); + }).catch(error => { + const releases = window.localStorage.getItem('releases'); + if (releases && (releases.length > 0)) { + const obj = JSON.parse(releases); + const locationsLookup = obj.LocationsLookup; + const versionLookup = obj.VersionLookup; + + dispatchActions(locationsLookup, versionLookup); + } else { + //this.setErrorState(error, null, true); + //TODO Display error + } + }); + }; +}; + export const SET_ACTIVE_RELEASE = 'relver/setActiveRelease'; export const setActiveRelease = (release, version) => { return { @@ -47,4 +101,17 @@ export const setActiveRelease = (release, version) => { }; export const setDismissUIUpgrade = createAction('relver/setDismissUIUpgrade'); + +export const SET_RELEASE_DATA = 'relver/setReleaseData'; +export const setReleaseData = (locationsLookup, versionLookup)=> { + return { + type: SET_RELEASE_DATA, + payload: { + locations: locationsLookup, + versions: versionLookup, + } + } +}; + +export const setReleaseUpgradeAvailable = createAction('relver/setReleaseUpgradeAvailable'); export const setUIUpgradeData = createAction('relver/setUIUpgradeData'); \ No newline at end of file diff --git a/src/redux/reducers/common_reducer.js b/src/redux/reducers/common_reducer.js new file mode 100644 index 0000000..91f4294 --- /dev/null +++ b/src/redux/reducers/common_reducer.js @@ -0,0 +1,18 @@ +import {createReducer} from "redux-starter-kit"; +import {setApplicationReady} from "../actions/common_actions"; + +export const createCommonReducer = (platform, appPlatform, version) => { + return createReducer({ + AppReady: false, + AppPlatform: appPlatform, + Platform: platform, + Version: version, + }, { + [setApplicationReady]: (state, action) => { + return { + ...state, + AppReady: action.payload, + }; + } + }); +}; \ No newline at end of file diff --git a/src/redux/reducers/release_version_reducer.js b/src/redux/reducers/release_version_reducer.js index b6e715c..a84e258 100644 --- a/src/redux/reducers/release_version_reducer.js +++ b/src/redux/reducers/release_version_reducer.js @@ -16,6 +16,7 @@ const versionLookup = Constants.RELEASE_TYPES.map(k=> { export const releaseVersionReducer = createReducer({ LocationsLookup: {}, Release: 2, + ReleaseUpgradeAvailable: false, UpgradeAvailable: false, UpgradeDismissed: false, Version: -1, @@ -42,6 +43,19 @@ export const releaseVersionReducer = createReducer({ UpgradeDismissed: action.payload, }; }, + [Actions.SET_RELEASE_DATA]: (state, action) => { + return { + ...state, + LocationsLookup: action.payload.locations, + VersionLookup: action.payload.versions, + }; + }, + [Actions.setReleaseUpgradeAvailable]: (state, action) => { + return { + ...state, + ReleaseUpgradeAvailable: action.payload, + }; + }, [Actions.setUIUpgradeData]: (state, action) => { return { ...state, diff --git a/src/redux/store/createAppStore.js b/src/redux/store/createAppStore.js index 6793173..180a910 100644 --- a/src/redux/store/createAppStore.js +++ b/src/redux/store/createAppStore.js @@ -1,16 +1,9 @@ -import {configureStore, createReducer, getDefaultMiddleware} from 'redux-starter-kit'; +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'; export default function createAppStore(platform, appPlatform, version) { - const createCommonReducer = () => { - return createReducer({ - AppPlatform: appPlatform, - Platform: platform, - Version: version, - }, {}); - }; - const reducer = { common: createCommonReducer(platform, appPlatform, version), mounts: mountReducer,