diff --git a/src/App.js b/src/App.js
index ab5d6c7..2f46cb3 100644
--- a/src/App.js
+++ b/src/App.js
@@ -19,6 +19,7 @@ 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';
+import {notifyError} from './redux/actions/error_actions';
const Constants = require('./constants');
const Scheduler = require('node-schedule');
@@ -32,10 +33,6 @@ class App extends IPCContainer {
}
state = {
- DisplayError: false,
- Error: null,
- ErrorAction: null,
- ErrorCritical: false,
MissingDependencies: [],
InstalledVersion: 'none',
};
@@ -56,21 +53,6 @@ class App extends IPCContainer {
}
};
- closeErrorDisplay = () => {
- if (this.state.ErrorAction) {
- this.state.ErrorAction();
- }
-
- if (this.state.ErrorCritical) {
- this.sendRequest(Constants.IPC_Shutdown);
- } else {
- this.setState({
- DisplayError: false,
- Error: null,
- });
- }
- };
-
componentDidMount() {
this.sendRequest(Constants.IPC_Get_State);
this.scheduledUpdateJob = Scheduler.scheduleJob('23 11 * * *', this.updateCheckScheduledJob);
@@ -180,7 +162,7 @@ class App extends IPCContainer {
if (arg.data.Success) {
action();
} else {
- this.setErrorState(arg.data.Error, action);
+ this.props.notifyError(arg.data.Error, false, action);
}
};
@@ -197,7 +179,7 @@ class App extends IPCContainer {
this.installUpgrade(result);
break;
default:
- this.setErrorState('Unknown download type: ' + type, null, false);
+ this.props.notifyError('Unknown download type: ' + type);
break;
}
}
@@ -237,14 +219,16 @@ class App extends IPCContainer {
onInstallUpgradeComplete = (source, result) => {
if (this.isMounted() && !result.Success) {
- this.setErrorState(result.Error, () => {
- // TODO Prompt to verify
- if (result.AllowSkipVerification) {
- this.installUpgrade( {
- SkipVerification: true,
- Source: source,
- Success: true,
- });
+ this.props.notifyError(result.Error, false,() => {
+ if (this.isMounted()) {
+ // TODO Prompt to verify
+ if (result.AllowSkipVerification) {
+ this.installUpgrade({
+ SkipVerification: true,
+ Source: source,
+ Success: true,
+ });
+ }
}
}, false);
}
@@ -267,17 +251,6 @@ class App extends IPCContainer {
}
};
- setErrorState = (error, action, critical) => {
- this.setState({
- DisplayError: true,
- Error: error,
- ErrorAction: action,
- ErrorCritical: critical,
- }, () => {
- this.sendRequest(Constants.IPC_Show_Window);
- });
- };
-
updateCheckScheduledJob = () => {
if (this.props.AppPlatform !== 'unknown') {
this.detectUpgrades();
@@ -333,7 +306,7 @@ class App extends IPCContainer {
allowConfig;
const showUpgrade = this.props.UpgradeAvailable &&
- !this.state.DisplayError &&
+ !this.props.DisplayError &&
!showConfig &&
!this.props.DownloadActive &&
!this.props.UpgradeDismissed;
@@ -343,12 +316,10 @@ class App extends IPCContainer {
!this.props.DownloadActive;
let errorDisplay = null;
- if (this.state.DisplayError) {
+ if (this.props.DisplayError) {
errorDisplay = (
-
+
);
}
@@ -357,8 +328,7 @@ class App extends IPCContainer {
if (showConfig) {
configDisplay = (
-
+
);
}
@@ -412,7 +382,6 @@ class App extends IPCContainer {
));
@@ -466,6 +435,7 @@ const mapStateToProps = state => {
AppPlatform: state.common.AppPlatform,
AppReady: state.common.AppReady,
DisplayConfiguration: state.mounts.DisplayConfiguration,
+ DisplayError: state.error.DisplayError,
DownloadActive: state.download.DownloadActive,
DownloadType: state.download.DownloadType,
InstallActive: state.install.InstallActive,
@@ -492,6 +462,7 @@ const mapDispatchToProps = dispatch => {
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()),
+ notifyError: (msg, critical, callback) => dispatch(notifyError(msg, critical, callback)),
setActiveRelease: (release, version) => dispatch(setActiveRelease(release, version)),
setAllowDownload: allow => dispatch(setAllowDownload(allow)),
setDismissUIUpgrade: dismiss => dispatch(setDismissUIUpgrade(dismiss)),
diff --git a/src/components/ErrorDetails/ErrorDetails.js b/src/components/ErrorDetails/ErrorDetails.js
index 6ccd730..571367b 100644
--- a/src/components/ErrorDetails/ErrorDetails.js
+++ b/src/components/ErrorDetails/ErrorDetails.js
@@ -1,16 +1,30 @@
import React from 'react';
+import {dismissError} from '../../redux/actions/error_actions';
+import {connect} from 'react-redux';
import Box from '../UI/Box/Box';
import Button from '../UI/Button/Button';
import './ErrorDetails.css';
-export default props => {
+const mapStateToProps = state => {
+ return {
+ ErrorMessage: state.error.ErrorStack.length > 0 ? state.error.ErrorStack[0] : '',
+ };
+};
+
+const mapDispatchToProps = dispatch => {
+ return {
+ dismissError: () => dispatch(dismissError()),
+ };
+};
+
+export default connect(mapStateToProps, mapDispatchToProps)(props => {
return (
Application Error
-
{props.error.toString()}
+
{props.ErrorMessage}
-
+
);
-};
\ No newline at end of file
+});
\ No newline at end of file
diff --git a/src/containers/Configuration/Configuration.js b/src/containers/Configuration/Configuration.js
index 1bca79b..a66f4a2 100644
--- a/src/containers/Configuration/Configuration.js
+++ b/src/containers/Configuration/Configuration.js
@@ -7,20 +7,17 @@ import ConfigurationItem from '../../components/ConfigurationItem/ConfigurationI
import Modal from '../../components/UI/Modal/Modal';
import IPCContainer from '../IPCContainer/IPCContainer';
import {displayConfiguration} from '../../redux/actions/mount_actions';
+import {notifyError} from '../../redux/actions/error_actions';
const Constants = require('../../constants');
class Configuration extends IPCContainer {
constructor(props) {
super(props);
+
this.setRequestHandler(Constants.IPC_Get_Config_Template_Reply, this.onGetConfigTemplateReply);
this.setRequestHandler(Constants.IPC_Get_Config_Reply, this.onGetConfigReply);
this.setRequestHandler(Constants.IPC_Set_Config_Values_Reply, this.onSetConfigValuesReply);
-
- this.sendRequest(Constants.IPC_Get_Config_Template, {
- Provider: this.props.DisplayConfiguration,
- Version: this.props.version,
- });
}
state = {
@@ -72,6 +69,13 @@ class Configuration extends IPCContainer {
}
};
+ componentDidMount() {
+ this.sendRequest(Constants.IPC_Get_Config_Template, {
+ Provider: this.props.DisplayConfiguration,
+ Version: this.props.version,
+ });
+ }
+
createItemList = (config, template) => {
const objectList = [];
const itemList = Object
@@ -142,7 +146,7 @@ class Configuration extends IPCContainer {
OriginalObjectLookup: objectLookupCopy,
});
} else {
- this.props.errorHandler(arg.data.Error);
+ this.props.notifyError(arg.data.Error);
}
};
@@ -157,8 +161,10 @@ class Configuration extends IPCContainer {
});
});
} else {
- this.props.errorHandler(arg.data.Error, () => {
- this.props.hideConfiguration();
+ this.props.notifyError(arg.data.Error, false, () => {
+ if (this.isMounted()) {
+ this.props.hideConfiguration();
+ }
});
}
};
@@ -283,6 +289,7 @@ const mapStateToProps = state => {
const mapDispatchToProps = dispatch => {
return {
+ notifyError: (msg, critical, callback) => dispatch(notifyError(msg, critical, callback)),
hideConfiguration: () => dispatch(displayConfiguration(null)),
}
};
diff --git a/src/containers/MountItems/MountItems.js b/src/containers/MountItems/MountItems.js
index 749756e..47c2d9a 100644
--- a/src/containers/MountItems/MountItems.js
+++ b/src/containers/MountItems/MountItems.js
@@ -14,6 +14,7 @@ import {
setMountState,
setProviderState
} from '../../redux/actions/mount_actions';
+import {notifyError} from '../../redux/actions/error_actions';
const Constants = require('../../constants');
@@ -101,7 +102,7 @@ class MountItems extends IPCContainer {
handleMountUnMount = (provider, mount, location) => {
if (!location || (location.trim().length === 0)) {
- this.props.errorHandler('Mount location is not set');
+ this.props.notifyError('Mount location is not set');
} else {
let allowAction = true;
if (mount) {
@@ -117,22 +118,22 @@ class MountItems extends IPCContainer {
});
if (!result.Success) {
allowAction = false;
- this.props.errorHandler(result.Error.toString());
+ this.props.notifyError(result.Error.toString());
}
}
} else {
allowAction = false;
if (result.Code === (new Uint32Array([-1]))[0]) {
- this.props.errorHandler('Failed to connect to ' + provider + ' daemon');
+ this.props.notifyError('Failed to connect to ' + provider + ' daemon');
} else if (result.Code === (new Uint32Array([-3]))[0]) {
- this.props.errorHandler('Incompatible ' + provider + ' daemon. Please upgrade ' + provider);
+ this.props.notifyError('Incompatible ' + provider + ' daemon. Please upgrade ' + provider);
} else {
- this.props.errorHandler('Version check failed: ' + result.Error);
+ this.props.notifyError('Version check failed: ' + result.Error);
}
}
} else {
allowAction = false;
- this.props.errorHandler(result.Error.toString());
+ this.props.notifyError(result.Error.toString());
}
}
@@ -201,7 +202,7 @@ class MountItems extends IPCContainer {
this.props.setAutoMountProcessed(true);
} else {
- this.props.errorHandler(arg.data.Error);
+ this.props.notifyError(arg.data.Error);
}
};
@@ -316,6 +317,7 @@ const mapStateToProps = state => {
const mapDispatchToProps = dispatch => {
return {
+ notifyError: (msg, critical, callback) => dispatch(notifyError(msg, critical, callback)),
setAllowMount: (provider, allow) => dispatch(setAllowMount(provider, allow)),
setAutoMountProcessed: processed => dispatch(setAutoMountProcessed(processed)),
setMounted: (provider, mounted) => dispatch(setMounted(provider, mounted)),
diff --git a/src/redux/actions/common_actions.js b/src/redux/actions/common_actions.js
index 04e57ea..a33c93f 100644
--- a/src/redux/actions/common_actions.js
+++ b/src/redux/actions/common_actions.js
@@ -1,3 +1,26 @@
+import * as Constants from '../../constants';
import {createAction} from 'redux-starter-kit';
-export const setApplicationReady = createAction('common/setApplicationReady');
\ No newline at end of file
+let ipcRenderer;
+if (!process.versions.hasOwnProperty('electron')) {
+ ipcRenderer = ((window && window.require) ? window.require('electron').ipcRenderer : null);
+}
+
+export const setApplicationReady = createAction('common/setApplicationReady');
+
+export const showWindow = () => {
+ return dispatch => {
+ if (ipcRenderer) {
+ ipcRenderer.send(Constants.IPC_Show_Window);
+ }
+ };
+};
+
+export const shutdownApplication = () => {
+ return dispatch => {
+ dispatch(setApplicationReady(false));
+ if (ipcRenderer) {
+ ipcRenderer.send(Constants.IPC_Shutdown);
+ }
+ };
+};
\ No newline at end of file
diff --git a/src/redux/actions/error_actions.js b/src/redux/actions/error_actions.js
new file mode 100644
index 0000000..00da4a4
--- /dev/null
+++ b/src/redux/actions/error_actions.js
@@ -0,0 +1,45 @@
+import {showWindow, shutdownApplication} from './common_actions';
+
+let ErrorActions = [];
+
+export const CLEAR_ERROR = 'error/clearError';
+export const clearError = () => {
+ return {
+ type: CLEAR_ERROR,
+ payload: null,
+ };
+};
+
+export const dismissError = () => {
+ return (dispatch, getState) => {
+ dispatch(clearError());
+ const errorAction = ErrorActions[0];
+ ErrorActions = ErrorActions.splice(1);
+ if (errorAction) {
+ errorAction();
+ }
+ if (getState().error.ErrorCritical) {
+ dispatch(shutdownApplication());
+ }
+ };
+};
+
+export const notifyError = (msg, critical, callback) => {
+ return dispatch => {
+ ErrorActions = [callback, ...ErrorActions];
+ msg = msg.toString();
+ dispatch(setErrorInfo(msg, critical));
+ dispatch(showWindow());
+ };
+};
+
+export const SET_ERROR_INFO = 'error/setErrorInfo';
+export const setErrorInfo = (msg, critical) => {
+ return {
+ type: SET_ERROR_INFO,
+ payload: {
+ msg,
+ critical
+ }
+ }
+};
\ No newline at end of file
diff --git a/src/redux/actions/install_actions.js b/src/redux/actions/install_actions.js
index 75f9ee9..2c964bc 100644
--- a/src/redux/actions/install_actions.js
+++ b/src/redux/actions/install_actions.js
@@ -76,6 +76,5 @@ export const installUpgrade = (source, sha256, signature, skipVerification, comp
};
};
-
export const setInstallActive = createAction('install/setInstallActive');
export const setInstallComplete = createAction('install/setInstallComplete');
diff --git a/src/redux/reducers/error_reducer.js b/src/redux/reducers/error_reducer.js
new file mode 100644
index 0000000..f091548
--- /dev/null
+++ b/src/redux/reducers/error_reducer.js
@@ -0,0 +1,26 @@
+import {createReducer} from 'redux-starter-kit';
+import {CLEAR_ERROR, SET_ERROR_INFO} from '../actions/error_actions';
+
+export const errorReducer = createReducer({
+ DisplayError: false,
+ ErrorCritical: false,
+ ErrorStack: [],
+}, {
+ [CLEAR_ERROR]: state => {
+ const errorStack = (state.ErrorStack.length > 0) ? state.ErrorStack.slice(1) : [];
+ return {
+ ...state,
+ DisplayError: (errorStack.length > 0),
+ ErrorStack: errorStack,
+ }
+ },
+ [SET_ERROR_INFO]: (state, action) => {
+ const errorStack = [action.payload.msg, ...state.ErrorStack];
+ return {
+ ...state,
+ DisplayError: true,
+ ErrorCritical: state.ErrorCritical || action.payload.critical,
+ ErrorStack: errorStack,
+ }
+ }
+});
\ No newline at end of file
diff --git a/src/redux/store/createAppStore.js b/src/redux/store/createAppStore.js
index 9191959..acb659c 100644
--- a/src/redux/store/createAppStore.js
+++ b/src/redux/store/createAppStore.js
@@ -1,6 +1,7 @@
import {configureStore, getDefaultMiddleware} from 'redux-starter-kit';
import {createCommonReducer} from '../reducers/common_reducer';
import {downloadReducer} from '../reducers/download_reducer';
+import {errorReducer} from '../reducers/error_reducer';
import {installReducer} from '../reducers/install_reducer';
import {mountReducer} from '../reducers/mount_reducer';
import {releaseVersionReducer} from '../reducers/release_version_reducer';
@@ -9,6 +10,7 @@ export default function createAppStore(platform, appPlatform, version) {
const reducer = {
common: createCommonReducer(platform, appPlatform, version),
download: downloadReducer,
+ error: errorReducer,
install: installReducer,
mounts: mountReducer,
relver: releaseVersionReducer,