Skip to content
Snippets Groups Projects
Commit b63ac51f authored by Ben Wheeler's avatar Ben Wheeler
Browse files

move project title management into titled hoc

parent 91e2fc92
No related branches found
No related tags found
No related merge requests found
......@@ -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,
......
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 {
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment