move project title management into titled hoc
This commit is contained in:
1 parent
91e2fc92f3
commit
b63ac51fb1
2 files changed
+90
-44
No files matched your search
+5
-36
@@ -4,15 +4,13 @@ import {compose} from 'redux';
|
||||
import {connect} from 'react-redux';
|
||||
import ReactModal from 'react-modal';
|
||||
import VM from 'scratch-vm';
|
||||
import {defineMessages, injectIntl, intlShape} from 'react-intl';
|
||||
import {injectIntl, intlShape} from 'react-intl';
|
||||
|
||||
import ErrorBoundaryHOC from '../lib/error-boundary-hoc.jsx';
|
||||
import {
|
||||
getIsError,
|
||||
getIsShowingProject,
|
||||
getIsShowingWithoutId
|
||||
getIsShowingProject
|
||||
} from '../reducers/project-state';
|
||||
import {setProjectTitle} from '../reducers/project-title';
|
||||
import {
|
||||
activateTab,
|
||||
BLOCKS_TAB_INDEX,
|
||||
@@ -30,6 +28,7 @@ import {
|
||||
import FontLoaderHOC from '../lib/font-loader-hoc.jsx';
|
||||
import LocalizationHOC from '../lib/localization-hoc.jsx';
|
||||
import ProjectFetcherHOC from '../lib/project-fetcher-hoc.jsx';
|
||||
import TitledHOC from '../lib/titled-hoc.jsx';
|
||||
import ProjectSaverHOC from '../lib/project-saver-hoc.jsx';
|
||||
import QueryParserHOC from '../lib/query-parser-hoc.jsx';
|
||||
import storage from '../lib/storage';
|
||||
@@ -40,18 +39,9 @@ import cloudManagerHOC from '../lib/cloud-manager-hoc.jsx';
|
||||
import GUIComponent from '../components/gui/gui.jsx';
|
||||
import {setIsScratchDesktop} from '../lib/isScratchDesktop.js';
|
||||
|
||||
const messages = defineMessages({
|
||||
defaultProjectTitle: {
|
||||
id: 'gui.gui.defaultProjectTitle',
|
||||
description: 'Default title for project',
|
||||
defaultMessage: 'Scratch Project'
|
||||
}
|
||||
});
|
||||
|
||||
class GUI extends React.Component {
|
||||
componentDidMount () {
|
||||
setIsScratchDesktop(this.props.isScratchDesktop);
|
||||
this.setReduxTitle(this.props.projectTitle);
|
||||
this.props.onStorageInit(storage);
|
||||
this.props.onVmInit(this.props.vm);
|
||||
}
|
||||
@@ -59,26 +49,11 @@ class GUI extends React.Component {
|
||||
if (this.props.projectId !== prevProps.projectId && this.props.projectId !== null) {
|
||||
this.props.onUpdateProjectId(this.props.projectId);
|
||||
}
|
||||
if (this.props.projectTitle !== prevProps.projectTitle) {
|
||||
this.setReduxTitle(this.props.projectTitle);
|
||||
}
|
||||
if (this.props.isShowingProject && !prevProps.isShowingProject) {
|
||||
// this only notifies container when a project changes from not yet loaded to loaded
|
||||
// At this time the project view in www doesn't need to know when a project is unloaded
|
||||
this.props.onProjectLoaded();
|
||||
}
|
||||
if (this.props.isShowingWithoutId && !prevProps.isShowingWithoutId) {
|
||||
this.props.onUpdateProjectTitle(this.props.intl.formatMessage(messages.defaultProjectTitle));
|
||||
}
|
||||
}
|
||||
setReduxTitle (newTitle) {
|
||||
if (newTitle === null || typeof newTitle === 'undefined') {
|
||||
this.props.onUpdateReduxProjectTitle(
|
||||
this.props.intl.formatMessage(messages.defaultProjectTitle)
|
||||
);
|
||||
} else {
|
||||
this.props.onUpdateReduxProjectTitle(newTitle);
|
||||
}
|
||||
}
|
||||
render () {
|
||||
if (this.props.isError) {
|
||||
@@ -96,11 +71,9 @@ class GUI extends React.Component {
|
||||
onProjectLoaded,
|
||||
onStorageInit,
|
||||
onUpdateProjectId,
|
||||
onUpdateReduxProjectTitle,
|
||||
onVmInit,
|
||||
projectHost,
|
||||
projectId,
|
||||
projectTitle,
|
||||
/* eslint-enable no-unused-vars */
|
||||
children,
|
||||
fetchingProject,
|
||||
@@ -137,11 +110,9 @@ GUI.propTypes = {
|
||||
onStorageInit: PropTypes.func,
|
||||
onUpdateProjectId: PropTypes.func,
|
||||
onUpdateProjectTitle: PropTypes.func,
|
||||
onUpdateReduxProjectTitle: PropTypes.func,
|
||||
onVmInit: PropTypes.func,
|
||||
projectHost: PropTypes.string,
|
||||
projectId: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
|
||||
projectTitle: PropTypes.string,
|
||||
telemetryModalVisible: PropTypes.bool,
|
||||
vm: PropTypes.instanceOf(VM).isRequired
|
||||
};
|
||||
@@ -151,7 +122,6 @@ GUI.defaultProps = {
|
||||
onStorageInit: storageInstance => storageInstance.addOfficialScratchWebStores(),
|
||||
onProjectLoaded: () => {},
|
||||
onUpdateProjectId: () => {},
|
||||
onUpdateProjectTitle: () => {},
|
||||
onVmInit: (/* vm */) => {}
|
||||
};
|
||||
|
||||
@@ -172,7 +142,6 @@ const mapStateToProps = state => {
|
||||
isPlayerOnly: state.scratchGui.mode.isPlayerOnly,
|
||||
isRtl: state.locales.isRtl,
|
||||
isShowingProject: getIsShowingProject(loadingState),
|
||||
isShowingWithoutId: getIsShowingWithoutId(loadingState),
|
||||
loadingStateVisible: state.scratchGui.modals.loadingProject,
|
||||
projectId: state.scratchGui.projectState.projectId,
|
||||
soundsTabVisible: state.scratchGui.editorTab.activeTabIndex === SOUNDS_TAB_INDEX,
|
||||
@@ -193,8 +162,7 @@ const mapDispatchToProps = dispatch => ({
|
||||
onActivateSoundsTab: () => dispatch(activateTab(SOUNDS_TAB_INDEX)),
|
||||
onRequestCloseBackdropLibrary: () => dispatch(closeBackdropLibrary()),
|
||||
onRequestCloseCostumeLibrary: () => dispatch(closeCostumeLibrary()),
|
||||
onRequestCloseTelemetryModal: () => dispatch(closeTelemetryModal()),
|
||||
onUpdateReduxProjectTitle: title => dispatch(setProjectTitle(title))
|
||||
onRequestCloseTelemetryModal: () => dispatch(closeTelemetryModal())
|
||||
});
|
||||
|
||||
const ConnectedGUI = injectIntl(connect(
|
||||
@@ -211,6 +179,7 @@ const WrappedGui = compose(
|
||||
FontLoaderHOC,
|
||||
QueryParserHOC,
|
||||
ProjectFetcherHOC,
|
||||
TitledHOC,
|
||||
ProjectSaverHOC,
|
||||
vmListenerHOC,
|
||||
vmManagerHOC,
|
||||
|
||||
+85
-8
@@ -1,5 +1,19 @@
|
||||
import PropTypes from 'prop-types';
|
||||
import React from 'react';
|
||||
import bindAll from 'lodash.bindall';
|
||||
import {connect} from 'react-redux';
|
||||
import {defineMessages, injectIntl, intlShape} from 'react-intl';
|
||||
|
||||
import {getIsShowingWithoutId} from '../reducers/project-state';
|
||||
import {setProjectTitle} from '../reducers/project-title';
|
||||
|
||||
const messages = defineMessages({
|
||||
defaultProjectTitle: {
|
||||
id: 'gui.gui.defaultProjectTitle',
|
||||
description: 'Default title for project',
|
||||
defaultMessage: 'Scratch Project'
|
||||
}
|
||||
});
|
||||
|
||||
/* Higher Order Component to get and set the project title
|
||||
* @param {React.Component} WrappedComponent component to receive project title related props
|
||||
@@ -12,26 +26,89 @@ const TitledHOC = function (WrappedComponent) {
|
||||
bindAll(this, [
|
||||
'handleUpdateProjectTitle'
|
||||
]);
|
||||
this.state = {
|
||||
projectTitle: null
|
||||
};
|
||||
}
|
||||
componentDidMount () {
|
||||
this.setReduxTitle(this.props.projectTitle);
|
||||
}
|
||||
componentDidUpdate (prevProps) {
|
||||
if (this.props.projectTitle !== prevProps.projectTitle) {
|
||||
this.setReduxTitle(this.props.projectTitle);
|
||||
}
|
||||
if (this.props.isShowingWithoutId && !prevProps.isShowingWithoutId) {
|
||||
const defaultProjectTitle = this.titleWithDefault();
|
||||
this.setReduxTitle(defaultProjectTitle);
|
||||
this.props.onUpdateProjectTitle(defaultProjectTitle);
|
||||
}
|
||||
}
|
||||
titleWithDefault (title) {
|
||||
if (title === null || typeof title === 'undefined') {
|
||||
return this.props.intl.formatMessage(messages.defaultProjectTitle);
|
||||
}
|
||||
return title;
|
||||
}
|
||||
setReduxTitle (newTitle) {
|
||||
if (newTitle === null || typeof newTitle === 'undefined') {
|
||||
this.props.onUpdateReduxProjectTitle(
|
||||
this.props.intl.formatMessage(messages.defaultProjectTitle)
|
||||
);
|
||||
} else {
|
||||
this.props.onUpdateReduxProjectTitle(newTitle);
|
||||
}
|
||||
}
|
||||
handleUpdateProjectTitle (newTitle) {
|
||||
this.setState({projectTitle: newTitle});
|
||||
this.setReduxTitle(newTitle);
|
||||
this.props.onUpdateProjectTitle(newTitle);
|
||||
}
|
||||
render () {
|
||||
const {
|
||||
/* eslint-disable no-unused-vars */
|
||||
intl,
|
||||
isShowingWithoutId,
|
||||
// for children, we replace onUpdateProjectTitle with our own
|
||||
onUpdateProjectTitle,
|
||||
onUpdateReduxProjectTitle,
|
||||
// we don't pass projectTitle prop to children -- they must use
|
||||
// redux value
|
||||
projectTitle,
|
||||
/* eslint-enable no-unused-vars */
|
||||
...componentProps
|
||||
} = this.props;
|
||||
return (
|
||||
<WrappedComponent
|
||||
canEditTitle
|
||||
projectTitle={this.state.projectTitle}
|
||||
onUpdateProjectTitle={this.handleUpdateProjectTitle}
|
||||
{...this.props}
|
||||
{...componentProps}
|
||||
/>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
return TitledComponent;
|
||||
TitledComponent.propTypes = {
|
||||
intl: intlShape,
|
||||
isShowingWithoutId: PropTypes.bool,
|
||||
onUpdateProjectTitle: PropTypes.func,
|
||||
onUpdateReduxProjectTitle: PropTypes.func,
|
||||
projectTitle: PropTypes.string
|
||||
};
|
||||
|
||||
TitledComponent.defaultProps = {
|
||||
onUpdateProjectTitle: () => {}
|
||||
};
|
||||
|
||||
const mapStateToProps = state => {
|
||||
const loadingState = state.scratchGui.projectState.loadingState;
|
||||
return {
|
||||
isShowingWithoutId: getIsShowingWithoutId(loadingState)
|
||||
};
|
||||
};
|
||||
|
||||
const mapDispatchToProps = dispatch => ({
|
||||
onUpdateReduxProjectTitle: title => dispatch(setProjectTitle(title))
|
||||
});
|
||||
|
||||
return injectIntl(connect(
|
||||
mapStateToProps,
|
||||
mapDispatchToProps,
|
||||
)(TitledComponent));
|
||||
};
|
||||
|
||||
export {
|
||||
|
||||
Reference in new issue
Block a user