Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
37 changes: 26 additions & 11 deletions src/lib/font-loader-hoc.jsx
Original file line number Diff line number Diff line change
@@ -1,18 +1,18 @@
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
* @returns {React.Component} component with font loading behavior
*/
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()
Expand All @@ -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 {
Expand Down
1 change: 1 addition & 0 deletions src/lib/vm-manager-hoc.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
23 changes: 23 additions & 0 deletions src/reducers/fonts-loaded.js
Original file line number Diff line number Diff line change
@@ -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
};
3 changes: 3 additions & 0 deletions src/reducers/gui.js
Original file line number Diff line number Diff line change
Expand Up @@ -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';
Expand Down Expand Up @@ -50,6 +51,7 @@ const guiInitialState = {
projectChanged: projectChangedInitialState,
projectState: projectStateInitialState,
projectTitle: projectTitleInitialState,
fontsLoaded: fontsLoadedInitialState,
restoreDeletion: restoreDeletionInitialState,
targets: targetsInitialState,
timeout: timeoutInitialState,
Expand Down Expand Up @@ -146,6 +148,7 @@ const guiReducer = combineReducers({
projectChanged: projectChangedReducer,
projectState: projectStateReducer,
projectTitle: projectTitleReducer,
fontsLoaded: fontsLoadedReducer,
restoreDeletion: restoreDeletionReducer,
targets: targetReducer,
timeout: timeoutReducer,
Expand Down
2 changes: 1 addition & 1 deletion src/reducers/project-state.js
Original file line number Diff line number Diff line change
Expand Up @@ -452,7 +452,7 @@ const onLoadedProject = (loadingState, canSave, success) => {
type: DONE_LOADING_VM_WITHOUT_ID
};
default:
break;
return;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't understand this change. It might help to add a comment explaining how you could get into this state, and what you are doing in that case.

}
}
return {
Expand Down