diff --git a/electron.js b/electron.js index 428e275..22708eb 100644 --- a/electron.js +++ b/electron.js @@ -434,6 +434,10 @@ ipcMain.on(Constants.IPC_Set_Config_Values, (event, data) => { setConfigValue(0); }); +ipcMain.on(Constants.IPC_Shutdown, () => { + app.quit(); +}); + ipcMain.on(Constants.IPC_Unmount_Drive, (event, data) => { helpers .stopProcessByPID(data.PID) diff --git a/src/App.js b/src/App.js index e776027..6e9c39e 100644 --- a/src/App.js +++ b/src/App.js @@ -8,6 +8,7 @@ import CSSModules from 'react-css-modules'; import DependencyList from './components/DependencyList/DependencyList'; import DownloadProgress from './components/DownloadProgress/DownloadProgress'; import DropDown from './components/UI/DropDown/DropDown'; +import ErrorDetails from './components/ErrorDetails/ErrorDetails'; import Loading from './components/UI/Loading/Loading'; import Modal from './components/UI/Modal/Modal'; import MountItems from './containers/MountItems/MountItems'; @@ -31,14 +32,13 @@ class App extends Component { ipcRenderer.on(Constants.IPC_Download_File_Complete, this.onDownloadFileComplete); ipcRenderer.on(Constants.IPC_Download_File_Progress, this.onDownloadFileProgress); ipcRenderer.on(Constants.IPC_Extract_Release_Complete, this.onExtractReleaseComplete); - ipcRenderer.on(Constants.IPC_Get_Platform_Reply, this.onGetPlatformReply); ipcRenderer.on(Constants.IPC_Get_State_Reply, this.onGetStateReply); ipcRenderer.on(Constants.IPC_Grab_Releases_Reply, this.onGrabReleasesReply); ipcRenderer.on(Constants.IPC_Grab_UI_Releases_Reply, this.onGrabUiReleasesReply); ipcRenderer.on(Constants.IPC_Install_Dependency_Reply, this.onInstallDependencyReply); ipcRenderer.on(Constants.IPC_Install_Upgrade_Reply, this.onInstallUpgradeReply); - ipcRenderer.send(Constants.IPC_Get_Platform); + ipcRenderer.send(Constants.IPC_Get_State, Constants.DATA_LOCATIONS[this.props.platform]); Scheduler.scheduleJob('23 11 * * *', this.updateCheckScheduledJob); } } @@ -46,11 +46,12 @@ class App extends Component { state = { AllowOptions: false, AllowDownload: false, - AutoMountChecked: false, + AutoMountProcessed: false, ConfigStorageType: null, DisplayError: false, Error: null, ErrorAction: null, + ErrorCritical: false, DownloadActive: false, DownloadProgress: 0.0, DownloadingDependency: false, @@ -109,16 +110,35 @@ class App extends Component { AllowDownload: false, }); - if (ipcRenderer) { - let dependencies = []; - if (this.state.LocationsLookup[selectedVersion] && this.state.LocationsLookup[selectedVersion].dependencies) { - dependencies = this.state.LocationsLookup[selectedVersion].dependencies; - } + if (selectedVersion !== 'unavailable') { + if (ipcRenderer) { + let dependencies = []; + if (this.state.LocationsLookup[selectedVersion] && this.state.LocationsLookup[selectedVersion].dependencies) { + dependencies = this.state.LocationsLookup[selectedVersion].dependencies; + } - ipcRenderer.send(Constants.IPC_Check_Installed, { - Dependencies: dependencies, - Directory: Constants.DATA_LOCATIONS[this.state.Platform], - Version: selectedVersion, + ipcRenderer.send(Constants.IPC_Check_Installed, { + Dependencies: dependencies, + Directory: Constants.DATA_LOCATIONS[this.props.platform], + Version: selectedVersion, + }); + } + } + }; + + closeErrorDisplay = () => { + if (this.state.ErrorAction) { + this.state.ErrorAction(); + } + + if (this.state.ErrorCritical) { + if (ipcRenderer) { + ipcRenderer.send(Constants.IPC_Shutdown); + } + } else { + this.setState({ + DisplayError: false, + Error: null, }); } }; @@ -129,7 +149,6 @@ class App extends Component { ipcRenderer.removeListener(Constants.IPC_Download_File_Complete, this.onDownloadFileComplete); ipcRenderer.removeListener(Constants.IPC_Download_File_Progress, this.onDownloadFileProgress); ipcRenderer.removeListener(Constants.IPC_Extract_Release_Complete, this.onExtractReleaseComplete); - ipcRenderer.removeListener(Constants.IPC_Get_Platform_Reply, this.onGetPlatformReply); ipcRenderer.removeListener(Constants.IPC_Get_State_Reply, this.onGetStateReply); ipcRenderer.removeListener(Constants.IPC_Grab_Releases_Reply, this.onGrabReleasesReply); ipcRenderer.removeListener(Constants.IPC_Grab_UI_Releases_Reply, this.onGrabUiReleasesReply); @@ -137,9 +156,9 @@ class App extends Component { ipcRenderer.removeListener(Constants.IPC_Install_Upgrade_Reply, this.onInstallUpgradeReply); } }; - + grabReleases = () => { - if (this.state.Platform !== 'unknown') { + if (this.props.platform !== 'unknown') { if (ipcRenderer) { ipcRenderer.send(Constants.IPC_Grab_Releases); ipcRenderer.send(Constants.IPC_Grab_UI_Releases); @@ -195,7 +214,7 @@ class App extends Component { }); ipcRenderer.send(Constants.IPC_Download_File, { - Directory: Constants.DATA_LOCATIONS[this.state.Platform], + Directory: Constants.DATA_LOCATIONS[this.props.platform], Filename: fileName, URL: url, }); @@ -242,7 +261,7 @@ class App extends Component { }); ipcRenderer.send(Constants.IPC_Download_File, { - Directory: Constants.DATA_LOCATIONS[this.state.Platform], + Directory: Constants.DATA_LOCATIONS[this.props.platform], Filename: fileName, URL: this.state.LocationsLookup[selectedVersion].urls[0], }); @@ -258,8 +277,8 @@ class App extends Component { }); ipcRenderer.send(Constants.IPC_Download_File, { - Directory: Constants.DATA_LOCATIONS[this.state.Platform], - Filename: this.state.Platform === 'win32' ? 'upgrade.exe' : 'upgrade', + Directory: Constants.DATA_LOCATIONS[this.props.platform], + Filename: this.props.platform === 'win32' ? 'upgrade.exe' : 'upgrade', URL: this.state.UpgradeData.urls[0], }); } else { @@ -277,7 +296,7 @@ class App extends Component { }; notifyAutoMountProcessed = () => { - this.setState({AutoMountChecked: true}); + this.setState({AutoMountProcessed: true}); }; notifyMountsBusy = (busy) => { @@ -319,7 +338,7 @@ class App extends Component { if (arg.data.Success) { const selectedVersion = this.state.VersionLookup[this.state.ReleaseTypes[this.state.Release]][this.state.Version]; ipcRenderer.send(Constants.IPC_Extract_Release, { - Directory: Constants.DATA_LOCATIONS[this.state.Platform], + Directory: Constants.DATA_LOCATIONS[this.props.platform], Source: arg.data.Destination, Version: selectedVersion, }); @@ -384,13 +403,6 @@ class App extends Component { this.checkVersionInstalled(this.state.Release, this.state.Version); }; - onGetPlatformReply = (event, arg) => { - this.setState({ - Platform: arg.data, - }); - ipcRenderer.send(Constants.IPC_Get_State, Constants.DATA_LOCATIONS[arg.data]); - }; - onGetStateReply = (event, arg) => { if (arg.data) { if (arg.data.Hyperspace.AutoMount === undefined) { @@ -431,13 +443,13 @@ class App extends Component { axios.get(Constants.RELEASES_URL) .then(response => { const versionLookup = { - Alpha: response.data.Versions.Alpha[this.state.Platform], - Beta: response.data.Versions.Beta[this.state.Platform], - RC: response.data.Versions.RC[this.state.Platform], - Release: response.data.Versions.Release[this.state.Platform], + Alpha: response.data.Versions.Alpha[this.props.platform], + Beta: response.data.Versions.Beta[this.props.platform], + RC: response.data.Versions.RC[this.props.platform], + Release: response.data.Versions.Release[this.props.platform], }; const locationsLookup = { - ...response.data.Locations[this.state.Platform], + ...response.data.Locations[this.props.platform], }; window.localStorage.setItem('releases', JSON.stringify({ @@ -447,7 +459,6 @@ class App extends Component { doUpdate(locationsLookup, versionLookup); }).catch(error => { - console.log(error); const releases = window.localStorage.getItem('releases'); if (releases && (releases.length > 0)) { const obj = JSON.parse(releases); @@ -456,7 +467,7 @@ class App extends Component { doUpdate(locationsLookup, versionLookup); } else { - // TODO Handle error + this.setErrorState(error, null, true); } }); }; @@ -466,17 +477,16 @@ class App extends Component { .then(response => { const data = response.data; if (data.Versions && - data.Versions[this.state.Platform] && - (data.Versions[this.state.Platform].length > 0) && - (data.Versions[this.state.Platform][0] !== this.props.version)) { + data.Versions[this.props.platform] && + (data.Versions[this.props.platform].length > 0) && + (data.Versions[this.props.platform][0] !== this.props.version)) { this.setState({ UpgradeAvailable: true, UpgradeDismissed: false, - UpgradeData: data.Locations[this.state.Platform][data.Versions[this.state.Platform][0]], + UpgradeData: data.Locations[this.props.platform][data.Versions[this.props.platform][0]], }); } - }).catch(error => { - console.log(error); + }).catch(() => { this.setState({ UpgradeAvailable: false, UpgradeData: {}, @@ -506,7 +516,7 @@ class App extends Component { saveState = (release, version, sia, hyperspace)=> { if (ipcRenderer) { ipcRenderer.send(Constants.IPC_Save_State, { - Directory: Constants.DATA_LOCATIONS[this.state.Platform], + Directory: Constants.DATA_LOCATIONS[this.props.platform], State: { Hyperspace: hyperspace, Release: release, @@ -517,19 +527,18 @@ class App extends Component { } }; - setErrorState = (error, action) => { + setErrorState = (error, action, critical) => { this.setState({ DisplayError: true, Error: error, ErrorAction: action, + ErrorCritical: critical, }); }; updateCheckScheduledJob = () => { - if (this.state.Platform !== 'unknown') { - if (ipcRenderer) { - ipcRenderer.send(Constants.IPC_Grab_UI_Releases); - } + if (this.props.platform !== 'unknown') { + this.grabReleases(); } }; @@ -556,16 +565,22 @@ class App extends Component { this.state.ConfigStorageType && allowConfig; - const showUpgrade = !this.state.DisplayError && + const showUpgrade = this.state.UpgradeAvailable && + !this.state.DisplayError && !showConfig && !missingDependencies && !this.state.DownloadActive && - this.state.UpgradeAvailable && !this.state.UpgradeDismissed; let errorDisplay = null; if (this.state.DisplayError) { - + errorDisplay = ( + + + + ); } let configDisplay = null; @@ -573,7 +588,8 @@ class App extends Component { configDisplay = ( @@ -587,12 +603,12 @@ class App extends Component { autoMountProcessed={this.notifyAutoMountProcessed} changed={this.handleMountLocationChanged} configClicked={this.handleConfigClicked} - directory={Constants.DATA_LOCATIONS[this.state.Platform]} - disabled={!allowMount} + directory={Constants.DATA_LOCATIONS[this.props.platform]} + errorHandler={this.setErrorState} hyperspace={this.state.Hyperspace} mountsBusy={this.notifyMountsBusy} - platform={this.state.Platform} - processAutoMount={!this.state.AutoMountChecked} + platform={this.props.platform} + processAutoMount={!this.state.AutoMountProcessed} sia={this.state.Sia} version={this.state.RepertoryVersion}/>; } diff --git a/src/components/ErrorDetails/ErrorDetails.css b/src/components/ErrorDetails/ErrorDetails.css new file mode 100644 index 0000000..62616a8 --- /dev/null +++ b/src/components/ErrorDetails/ErrorDetails.css @@ -0,0 +1,11 @@ +.Heading { + color: var(--text_color_error); + text-align: center; + margin-bottom: 4px; +} + +.Content { + max-height: 60vh; + overflow-y: auto; + margin-bottom: 8px; +} \ No newline at end of file diff --git a/src/components/ErrorDetails/ErrorDetails.js b/src/components/ErrorDetails/ErrorDetails.js new file mode 100644 index 0000000..6bff639 --- /dev/null +++ b/src/components/ErrorDetails/ErrorDetails.js @@ -0,0 +1,18 @@ +import React from 'react'; +import Box from '../UI/Box/Box'; +import Button from '../UI/Button/Button'; +import CSSModules from 'react-css-modules'; +import styles from './ErrorDetails.css'; + +export default CSSModules((props) => { + return ( + +

Application Error

+
+

{props.error.toString()}

+
+ +
+ ); + +}, styles, {allowMultiple: true}); \ No newline at end of file diff --git a/src/components/UI/Modal/Modal.css b/src/components/UI/Modal/Modal.css index c5090ac..19e5f32 100644 --- a/src/components/UI/Modal/Modal.css +++ b/src/components/UI/Modal/Modal.css @@ -17,3 +17,11 @@ transform: translate(-50%, -50%); z-index: 2001; } + +.Modal.Critical { + z-index: 2100; +} + +.Content.Critical { + z-index: 2101; +} diff --git a/src/components/UI/Modal/Modal.js b/src/components/UI/Modal/Modal.js index 057f05b..6dc7223 100644 --- a/src/components/UI/Modal/Modal.js +++ b/src/components/UI/Modal/Modal.js @@ -3,11 +3,20 @@ import CSSModules from 'react-css-modules'; import styles from './Modal.css' export default CSSModules((props) => { + let modalStyles = []; + let contentStyles = []; + modalStyles.push('Modal'); + contentStyles.push('Content'); + if (props.critical) { + modalStyles.push('Critical'); + contentStyles.push('Critical'); + } + return (
-
+
{props.children}
); diff --git a/src/constants.js b/src/constants.js index 4b370d9..0726858 100644 --- a/src/constants.js +++ b/src/constants.js @@ -56,5 +56,7 @@ exports.IPC_Save_State = 'save_state'; exports.IPC_Set_Config_Values = 'set_config_values'; exports.IPC_Set_Config_Values_Reply = 'set_config_values_reply'; +exports.IPC_Shutdown = 'shutdown'; + exports.IPC_Unmount_Drive = 'unmount_drive'; exports.IPC_Unmount_Drive_Reply = 'unmount_drive_reply'; \ No newline at end of file diff --git a/src/containers/Configuration/Configuration.js b/src/containers/Configuration/Configuration.js index 9baeaaf..5e3e393 100644 --- a/src/containers/Configuration/Configuration.js +++ b/src/containers/Configuration/Configuration.js @@ -155,6 +155,8 @@ class Configuration extends Component { OriginalItemList: itemListCopy, OriginalObjectLookup: objectLookupCopy, }); + } else { + this.props.errorHandler(arg.data.Error); } }; @@ -168,6 +170,10 @@ class Configuration extends Component { StorageType: this.props.storageType, Version: this.props.version, }); + } else { + this.props.errorHandler(arg.data.Error, () => { + this.props.closed(); + }); } }; @@ -218,7 +224,7 @@ class Configuration extends Component {

Save Changes?

- +
@@ -227,7 +233,7 @@ class Configuration extends Component { ); } - let configurationItems = this.state.ItemList + const configurationItems = this.state.ItemList .map((k, i) => { return ( ((this.state.ShowAdvanced && k.advanced) || !k.advanced) ? diff --git a/src/containers/MountItems/MountItems.js b/src/containers/MountItems/MountItems.js index 363b1dd..ba40100 100644 --- a/src/containers/MountItems/MountItems.js +++ b/src/containers/MountItems/MountItems.js @@ -135,6 +135,8 @@ class MountItems extends Component { } this.performAutoMount(); + } else { + this.props.errorHandler(arg.data.Error); } }; diff --git a/src/index.css b/src/index.css index a2b349f..0baabf1 100644 --- a/src/index.css +++ b/src/index.css @@ -9,6 +9,7 @@ --control_dark_transparent_background: rgba(15, 15, 15, 0.8); --text_color: rgba(200, 205, 220, 0.75); + --text_color_error: rgba(203, 120, 120, 0.75); --text_color_hover: rgba(200, 205, 220, 0.75); --heading_text_color: rgba(140, 169, 203, 0.75); --heading_other_text_color: rgba(200, 205, 220, 0.75); @@ -17,7 +18,7 @@ * { font-family: 'Nunito', sans-serif; - font-size: 14px; + font-size: 5vh; } *::-moz-focus-inner { @@ -61,3 +62,10 @@ h1 { h2, h3 { color: var(--heading_other_text_color); } + +p { + margin: 0; + padding: 0; + font-weight: normal; + color: var(--text_color); +} diff --git a/src/index.js b/src/index.js index 46a1b71..a7d5c00 100644 --- a/src/index.js +++ b/src/index.js @@ -1,10 +1,20 @@ import React from 'react'; import ReactDOM from 'react-dom'; import './index.css'; - import App from './App'; -import registerServiceWorker from './registerServiceWorker'; import packageJson from '../package.json'; +import registerServiceWorker from './registerServiceWorker'; + +const Constants = require('./constants'); + +if (!process.versions.hasOwnProperty('electron')) { + const ipcRenderer = ((window && window.require) ? window.require('electron').ipcRenderer : null); + if (ipcRenderer) { + ipcRenderer.on(Constants.IPC_Get_Platform_Reply, (event, arg) => { + ReactDOM.render(, document.getElementById('root')); + registerServiceWorker(); + }); + ipcRenderer.send(Constants.IPC_Get_Platform); + } +} -ReactDOM.render(, document.getElementById('root')); -registerServiceWorker();