diff --git a/src/containers/gui.jsx b/src/containers/gui.jsx index ffc38e07f9fa5a5109d53e0005c2ce3c8209c91b..2d74e21c2428bed32fd42da05ae2a6a4450207bb 100644 --- a/src/containers/gui.jsx +++ b/src/containers/gui.jsx @@ -9,6 +9,7 @@ import {defineMessages, injectIntl, intlShape} from 'react-intl'; import ErrorBoundaryHOC from '../lib/error-boundary-hoc.jsx'; import {openExtensionLibrary} from '../reducers/modals'; import { + getIsError, getIsShowingProject } from '../reducers/project-state'; import {setProjectTitle} from '../reducers/project-title'; @@ -63,16 +64,16 @@ class GUI extends React.Component { } } render () { - if (this.props.loadingError) { + if (this.props.isError) { throw new Error( - `Failed to load project from server [id=${window.location.hash}]: ${this.props.errorMessage}`); + `Failed to load project from server [id=${window.location.hash}]: ${this.props.errStr}`); } const { /* eslint-disable no-unused-vars */ assetHost, - errorMessage, + errStr, hideIntro, - loadingError, + isError, isShowingProject, onUpdateProjectId, onUpdateReduxProjectTitle, @@ -100,14 +101,14 @@ class GUI extends React.Component { GUI.propTypes = { assetHost: PropTypes.string, children: PropTypes.node, - errorMessage: PropTypes.string, + errStr: PropTypes.string, fetchingProject: PropTypes.bool, hideIntro: PropTypes.bool, importInfoVisible: PropTypes.bool, + isError: PropTypes.bool, intl: intlShape, isLoading: PropTypes.bool, isShowingProject: PropTypes.bool, - loadingError: PropTypes.bool, loadingStateVisible: PropTypes.bool, onChangeProjectInfo: PropTypes.func, onSeeCommunity: PropTypes.func, @@ -135,7 +136,9 @@ const mapStateToProps = (state, ownProps) => { cardsVisible: state.scratchGui.cards.visible, costumeLibraryVisible: state.scratchGui.modals.costumeLibrary, costumesTabVisible: state.scratchGui.editorTab.activeTabIndex === COSTUMES_TAB_INDEX, + errStr: state.scratchGui.projectState.errStr, importInfoVisible: state.scratchGui.modals.importInfo, + isError: getIsError(loadingState), isPlayerOnly: state.scratchGui.mode.isPlayerOnly, isRtl: state.locales.isRtl, isShowingProject: getIsShowingProject(loadingState), diff --git a/src/lib/project-fetcher-hoc.jsx b/src/lib/project-fetcher-hoc.jsx index 6a29cf75db29a5ecef8e1ea6ccae618f72cc2dbf..20fb80602e771d7223aa533079b955d25661b3ea 100644 --- a/src/lib/project-fetcher-hoc.jsx +++ b/src/lib/project-fetcher-hoc.jsx @@ -8,6 +8,7 @@ import { LoadingStates, defaultProjectId, getIsFetchingWithId, + onError, onFetchedProjectData, setProjectId } from '../reducers/project-state'; @@ -74,6 +75,7 @@ const ProjectFetcherHOC = function (WrappedComponent) { } }) .catch(err => { + this.props.onError(`Saving the project failed with error: ${err}`); log.error(err); }); } @@ -106,6 +108,7 @@ const ProjectFetcherHOC = function (WrappedComponent) { intl: intlShape.isRequired, isFetchingWithId: PropTypes.bool, loadingState: PropTypes.oneOf(LoadingStates), + onError: PropTypes.func, onFetchedProjectData: PropTypes.func, projectHost: PropTypes.string, projectId: PropTypes.oneOfType([PropTypes.string, PropTypes.number]), @@ -123,6 +126,7 @@ const ProjectFetcherHOC = function (WrappedComponent) { reduxProjectId: state.scratchGui.projectState.projectId }); const mapDispatchToProps = dispatch => ({ + onError: errStr => dispatch(onError(errStr)), onFetchedProjectData: (projectData, loadingState) => dispatch(onFetchedProjectData(projectData, loadingState)), setProjectId: projectId => dispatch(setProjectId(projectId)) diff --git a/src/lib/vm-manager-hoc.jsx b/src/lib/vm-manager-hoc.jsx index cfc80bc97e066e0504a1fa5119bb81f8a526d355..20271706d4a584b5a34f598dd267726bab3e410c 100644 --- a/src/lib/vm-manager-hoc.jsx +++ b/src/lib/vm-manager-hoc.jsx @@ -8,6 +8,7 @@ import AudioEngine from 'scratch-audio'; import { LoadingStates, + onError, onLoadedProject, getIsLoadingWithId } from '../reducers/project-state'; @@ -24,10 +25,6 @@ const vmManagerHOC = function (WrappedComponent) { bindAll(this, [ 'loadProject' ]); - this.state = { - loadingError: false, - errorMessage: '' - }; } componentDidMount () { if (this.props.vm.initialized) return; @@ -51,9 +48,7 @@ const vmManagerHOC = function (WrappedComponent) { this.props.onLoadedProject(this.props.loadingState, this.props.canSave); }) .catch(e => { - // Need to catch this error and update component state so that - // error page gets rendered if project failed to load - this.setState({loadingError: true, errorMessage: e}); + this.props.onError(e); }); } render () { @@ -71,9 +66,7 @@ const vmManagerHOC = function (WrappedComponent) { } = this.props; return ( <WrappedComponent - errorMessage={this.state.errorMessage} isLoading={isLoadingWithIdProp} - loadingError={this.state.loadingError} vm={vm} {...componentProps} /> @@ -86,6 +79,7 @@ const vmManagerHOC = function (WrappedComponent) { fontsLoaded: PropTypes.bool, isLoadingWithId: PropTypes.bool, loadingState: PropTypes.oneOf(LoadingStates), + onError: PropTypes.func, onLoadedProject: PropTypes.func, projectData: PropTypes.oneOfType([PropTypes.object, PropTypes.string]), projectId: PropTypes.oneOfType([PropTypes.string, PropTypes.number]), @@ -103,6 +97,7 @@ const vmManagerHOC = function (WrappedComponent) { }; const mapDispatchToProps = dispatch => ({ + onError: errStr => dispatch(onError(errStr)), onLoadedProject: (loadingState, canSave) => dispatch(onLoadedProject(loadingState, canSave)) }); diff --git a/src/reducers/project-state.js b/src/reducers/project-state.js index de171edc5df734fb35e2d35c19e5f96a9271a000..1b80fd3e481ce92c6b55124273489dc92f7df41d 100644 --- a/src/reducers/project-state.js +++ b/src/reducers/project-state.js @@ -65,6 +65,9 @@ const getIsShowingWithId = loadingState => ( const getIsShowingWithoutId = loadingState => ( loadingState === LoadingState.SHOWING_WITHOUT_ID ); +const getIsError = loadingState => ( + loadingState === LoadingState.ERROR +); const initialState = { errStr: null, @@ -326,6 +329,7 @@ export { createProject, defaultProjectId, getIsCreating, + getIsError, getIsFetchingWithoutId, getIsFetchingWithId, getIsLoadingWithId,