diff --git a/src/lib/font-loader-hoc.jsx b/src/lib/font-loader-hoc.jsx index cbb7856c31fb3c95c3e8990d41e2cbd21922330f..ea05143b9292583a3b685df22d0d0cd16e6e1c51 100644 --- a/src/lib/font-loader-hoc.jsx +++ b/src/lib/font-loader-hoc.jsx @@ -1,4 +1,8 @@ import React from 'react'; +import PropTypes from 'prop-types'; +import omit from 'lodash.omit'; +import {connect} from 'react-redux'; +import {setFontsLoaded} from '../reducers/fonts-loaded'; /* Higher Order Component to provide behavior for loading fonts. * @param {React.Component} WrappedComponent component to receive fontsLoaded prop @@ -6,13 +10,9 @@ import React from 'react'; */ const FontLoaderHOC = function (WrappedComponent) { class FontLoaderComponent extends React.Component { - constructor (props) { - super(props); - this.state = { - fontsLoaded: false - }; - } componentDidMount () { + if (this.props.fontsLoaded) return; + const getFontPromises = () => { const fontPromises = []; // Browsers that support the font loader interface have an iterable document.fonts.values() @@ -32,28 +32,43 @@ const FontLoaderHOC = function (WrappedComponent) { // objects get replaced and the old ones never resolve. if (document.readyState === 'complete') { Promise.all(getFontPromises()).then(() => { - this.setState({fontsLoaded: true}); + this.props.onSetFontsLoaded(); }); } else { document.onreadystatechange = () => { if (document.readyState !== 'complete') return; document.onreadystatechange = null; Promise.all(getFontPromises()).then(() => { - this.setState({fontsLoaded: true}); + this.props.onSetFontsLoaded(); }); }; } } render () { + const componentProps = omit(this.props, ['onSetFontsLoaded']); return ( <WrappedComponent - fontsLoaded={this.state.fontsLoaded} - {...this.props} + {...componentProps} /> ); } } - return FontLoaderComponent; + + + FontLoaderComponent.propTypes = { + fontsLoaded: PropTypes.bool.isRequired, + onSetFontsLoaded: PropTypes.func.isRequired + }; + const mapStateToProps = state => ({ + fontsLoaded: state.scratchGui.fontsLoaded + }); + const mapDispatchToProps = dispatch => ({ + onSetFontsLoaded: () => dispatch(setFontsLoaded()) + }); + return connect( + mapStateToProps, + mapDispatchToProps + )(FontLoaderComponent); }; export { diff --git a/src/lib/vm-manager-hoc.jsx b/src/lib/vm-manager-hoc.jsx index f344907807e1def1370f78d813d62d84a262ab3e..926c25cd74540fc96329fb1ecb37c1951c5350fa 100644 --- a/src/lib/vm-manager-hoc.jsx +++ b/src/lib/vm-manager-hoc.jsx @@ -117,6 +117,7 @@ const vmManagerHOC = function (WrappedComponent) { const mapStateToProps = state => { const loadingState = state.scratchGui.projectState.loadingState; return { + fontsLoaded: state.scratchGui.fontsLoaded, isLoadingWithId: getIsLoadingWithId(loadingState), projectData: state.scratchGui.projectState.projectData, projectId: state.scratchGui.projectState.projectId, diff --git a/src/reducers/fonts-loaded.js b/src/reducers/fonts-loaded.js new file mode 100644 index 0000000000000000000000000000000000000000..fcfdc58fa8ee417597f34ded09dddb36c89c7b14 --- /dev/null +++ b/src/reducers/fonts-loaded.js @@ -0,0 +1,23 @@ +const SET_FONTS_LOADED = 'fontsLoaded/SET_FONTS_LOADED'; + +const initialState = false; + +const reducer = function (state, action) { + if (typeof state === 'undefined') state = initialState; + switch (action.type) { + case SET_FONTS_LOADED: + return action.loaded; + default: + return state; + } +}; +const setFontsLoaded = () => ({ + type: SET_FONTS_LOADED, + loaded: true +}); + +export { + reducer as default, + initialState as fontsLoadedInitialState, + setFontsLoaded +}; diff --git a/src/reducers/gui.js b/src/reducers/gui.js index 3aa24e7d864cb497d1db14833ff7c8db8f70096f..268817d3f1667604065f3a2a79d2771a2855b0b5 100644 --- a/src/reducers/gui.js +++ b/src/reducers/gui.js @@ -17,6 +17,7 @@ import monitorLayoutReducer, {monitorLayoutInitialState} from './monitor-layout' import projectChangedReducer, {projectChangedInitialState} from './project-changed'; import projectStateReducer, {projectStateInitialState} from './project-state'; import projectTitleReducer, {projectTitleInitialState} from './project-title'; +import fontsLoadedReducer, {fontsLoadedInitialState} from './fonts-loaded'; import restoreDeletionReducer, {restoreDeletionInitialState} from './restore-deletion'; import stageSizeReducer, {stageSizeInitialState} from './stage-size'; import targetReducer, {targetsInitialState} from './targets'; @@ -50,6 +51,7 @@ const guiInitialState = { projectChanged: projectChangedInitialState, projectState: projectStateInitialState, projectTitle: projectTitleInitialState, + fontsLoaded: fontsLoadedInitialState, restoreDeletion: restoreDeletionInitialState, targets: targetsInitialState, timeout: timeoutInitialState, @@ -146,6 +148,7 @@ const guiReducer = combineReducers({ projectChanged: projectChangedReducer, projectState: projectStateReducer, projectTitle: projectTitleReducer, + fontsLoaded: fontsLoadedReducer, restoreDeletion: restoreDeletionReducer, targets: targetReducer, timeout: timeoutReducer, diff --git a/src/reducers/project-state.js b/src/reducers/project-state.js index 84c956b72cb39b7556ae6899f128575e67895f8e..7ea21bd3a047acc9f26f0731b2407cebb193cfa7 100644 --- a/src/reducers/project-state.js +++ b/src/reducers/project-state.js @@ -452,7 +452,7 @@ const onLoadedProject = (loadingState, canSave, success) => { type: DONE_LOADING_VM_WITHOUT_ID }; default: - break; + return; } } return {