Merge pull request #3431 from chrisgarrity/issue/www2172-integrate-intl

Refactor IntlProvider in GUI to support integration with www
This commit is contained in:
chrisgarrity authored and GitHub committed 2018-10-22 11:57:36 -04:00
commit 92d51a5797
5 files changed
+71 -33

No files matched your search

+12 -3
View File
@@ -4,7 +4,7 @@ import {compose} from 'redux';
import {connect} from 'react-redux';
import ReactModal from 'react-modal';
import VM from 'scratch-vm';
import {injectIntl, intlShape} from 'react-intl';
import {defineMessages, injectIntl, intlShape} from 'react-intl';
import ErrorBoundaryHOC from '../lib/error-boundary-hoc.jsx';
import {openExtensionLibrary} from '../reducers/modals';
@@ -25,14 +25,22 @@ import {
} from '../reducers/modals';
import FontLoaderHOC from '../lib/font-loader-hoc.jsx';
import LocalizationHOC from '../lib/localization-hoc.jsx';
import ProjectFetcherHOC from '../lib/project-fetcher-hoc.jsx';
import ProjectSaverHOC from '../lib/project-saver-hoc.jsx';
import vmListenerHOC from '../lib/vm-listener-hoc.jsx';
import vmManagerHOC from '../lib/vm-manager-hoc.jsx';
import {defaultProjectTitleMessages} from '../reducers/project-title';
import GUIComponent from '../components/gui/gui.jsx';
const messages = defineMessages({
defaultProjectTitle: {
id: 'gui.gui.defaultProjectTitle',
description: 'Default title for project',
defaultMessage: 'Scratch Project'
}
});
class GUI extends React.Component {
componentDidMount () {
this.setReduxTitle(this.props.projectTitle);
@@ -48,7 +56,7 @@ class GUI extends React.Component {
setReduxTitle (newTitle) {
if (newTitle === null || typeof newTitle === 'undefined') {
this.props.onUpdateReduxProjectTitle(
this.props.intl.formatMessage(defaultProjectTitleMessages.defaultProjectTitle)
this.props.intl.formatMessage(messages.defaultProjectTitle)
);
} else {
this.props.onUpdateReduxProjectTitle(newTitle);
@@ -163,6 +171,7 @@ const ConnectedGUI = injectIntl(connect(
// the hierarchy of HOC constructor calls clearer here; it has nothing to do with redux's
// ability to compose reducers.
const WrappedGui = compose(
LocalizationHOC,
ErrorBoundaryHOC('Top Level App'),
FontLoaderHOC,
ProjectFetcherHOC,
+1 -4
View File
@@ -2,7 +2,6 @@ import React from 'react';
import PropTypes from 'prop-types';
import {Provider} from 'react-redux';
import {createStore, combineReducers, compose} from 'redux';
import ConnectedIntlProvider from './connected-intl-provider.jsx';
import localesReducer, {initLocale, localesInitialState} from '../reducers/locales';
@@ -108,9 +107,7 @@ const AppStateHOC = function (WrappedComponent, localesOnly) {
} = this.props;
return (
<Provider store={this.store}>
<ConnectedIntlProvider>
<WrappedComponent {...componentProps} />
</ConnectedIntlProvider>
<WrappedComponent {...componentProps} />
</Provider>
);
}
+55
View File
@@ -0,0 +1,55 @@
import React from 'react';
import PropTypes from 'prop-types';
import {connect} from 'react-redux';
import ConnectedIntlProvider from './connected-intl-provider.jsx';
/*
* Higher Order Component to provide localiztion state. Creates a nested IntlProvider
* to handle Gui intl context. The component accepts an onSetLanguage callback that is
* called when the locale chagnes.
* @param {React.Component} WrappedComponent - component to provide state for
* @returns {React.Component} component with intl state provided from redux
*/
const LocalizationHOC = function (WrappedComponent) {
class LocalizationWrapper extends React.Component {
componentDidUpdate (prevProps) {
if (prevProps.locale !== this.props.locale) {
this.props.onSetLanguage(this.props.locale);
}
}
render () {
const {
locale, // eslint-disable-line no-unused-vars
onSetLanguage, // eslint-disable-line no-unused-vars
...componentProps
} = this.props;
return (
<ConnectedIntlProvider>
<WrappedComponent {...componentProps} />
</ConnectedIntlProvider>
);
}
}
LocalizationWrapper.propTypes = {
locale: PropTypes.string,
onSetLanguage: PropTypes.func
};
LocalizationWrapper.defaultProps = {
onSetLanguage: () => {}
};
const mapStateToProps = state => ({
locale: state.locales.locale
});
const mapDispatchToProps = () => ({});
return connect(
mapStateToProps,
mapDispatchToProps
)(LocalizationWrapper);
};
export default LocalizationHOC;
+3 -15
View File
@@ -1,7 +1,5 @@
import React from 'react';
import bindAll from 'lodash.bindall';
import {intlShape, injectIntl} from 'react-intl';
import {defaultProjectTitleMessages} from '../reducers/project-title';
/* Higher Order Component to get and set the project title
* @param {React.Component} WrappedComponent component to receive project title related props
@@ -15,34 +13,24 @@ const TitledHOC = function (WrappedComponent) {
'handleUpdateProjectTitle'
]);
this.state = {
projectTitle: this.props.intl.formatMessage(defaultProjectTitleMessages.defaultProjectTitle)
projectTitle: null
};
}
handleUpdateProjectTitle (newTitle) {
this.setState({projectTitle: newTitle});
}
render () {
const {
/* eslint-disable no-unused-vars */
intl,
/* eslint-enable no-unused-vars */
...componentProps
} = this.props;
return (
<WrappedComponent
projectTitle={this.state.projectTitle}
onUpdateProjectTitle={this.handleUpdateProjectTitle}
{...componentProps}
{...this.props}
/>
);
}
}
TitledComponent.propTypes = {
intl: intlShape.isRequired
};
return injectIntl(TitledComponent);
return TitledComponent;
};
export {
-11
View File
@@ -1,19 +1,9 @@
import {defineMessages} from 'react-intl';
const SET_PROJECT_TITLE = 'projectTitle/SET_PROJECT_TITLE';
// we are initializing to a blank string instead of an actual title,
// because it would be hard to localize here
const initialState = '';
const defaultProjectTitleMessages = defineMessages({
defaultProjectTitle: {
id: 'gui.gui.defaultProjectTitle',
description: 'Default title for project',
defaultMessage: 'Scratch Project'
}
});
const reducer = function (state, action) {
if (typeof state === 'undefined') state = initialState;
switch (action.type) {
@@ -31,6 +21,5 @@ const setProjectTitle = title => ({
export {
reducer as default,
initialState as projectTitleInitialState,
defaultProjectTitleMessages,
setProjectTitle
};