Skip to content

Commit 6974a98

Browse files
committed
introducing font loader hoc per DD's changes
1 parent a9f1e2e commit 6974a98

File tree

3 files changed

+78
-5
lines changed

3 files changed

+78
-5
lines changed

src/containers/gui.jsx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ import {
2020
closeBackdropLibrary
2121
} from '../reducers/modals';
2222

23+
import FontLoaderHOC from '../lib/font-loader-hoc.jsx';
2324
import ProjectFetcherHOC from '../lib/project-fetcher-hoc.jsx';
2425
import ProjectSaverHOC from '../lib/project-saver-hoc.jsx';
2526
import vmListenerHOC from '../lib/vm-listener-hoc.jsx';
@@ -132,6 +133,7 @@ const ConnectedGUI = connect(
132133
// ability to compose reducers.
133134
const WrappedGui = compose(
134135
ErrorBoundaryHOC('Top Level App'),
136+
FontLoaderHOC,
135137
ProjectFetcherHOC,
136138
ProjectSaverHOC,
137139
vmListenerHOC,

src/lib/font-loader-hoc.jsx

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
import React from 'react';
2+
3+
/* Higher Order Component to provide behavior for loading fonts.
4+
* @param {React.Component} WrappedComponent component to receive fontsLoaded prop
5+
* @returns {React.Component} component with font loading behavior
6+
*/
7+
const FontLoaderHOC = function (WrappedComponent) {
8+
class FontLoaderComponent extends React.Component {
9+
constructor (props) {
10+
super(props);
11+
this.state = {
12+
fontsLoaded: false
13+
};
14+
}
15+
componentDidMount () {
16+
const getFontPromises = () => {
17+
const fontPromises = [];
18+
// Browsers that support the font loader interface have an iterable document.fonts.values()
19+
// Firefox has a mocked out object that doesn't actually implement iterable, which is why
20+
// the deep safety check is necessary.
21+
if (document.fonts &&
22+
typeof document.fonts.values === 'function' &&
23+
typeof document.fonts.values()[Symbol.iterator] === 'function') {
24+
for (const fontFace of document.fonts.values()) {
25+
fontPromises.push(fontFace.loaded);
26+
fontFace.load();
27+
}
28+
}
29+
return fontPromises;
30+
};
31+
// Font promises must be gathered after the document is loaded, because on Mac Chrome, the promise
32+
// objects get replaced and the old ones never resolve.
33+
if (document.readyState === 'complete') {
34+
Promise.all(getFontPromises()).then(() => {
35+
this.setState({fontsLoaded: true});
36+
});
37+
} else {
38+
document.onreadystatechange = () => {
39+
if (document.readyState !== 'complete') return;
40+
document.onreadystatechange = null;
41+
Promise.all(getFontPromises()).then(() => {
42+
this.setState({fontsLoaded: true});
43+
});
44+
};
45+
}
46+
}
47+
render () {
48+
const {
49+
/* eslint-disable no-unused-vars */
50+
/* eslint-enable no-unused-vars */
51+
...componentProps
52+
} = this.props;
53+
return (
54+
<WrappedComponent
55+
fontsLoaded={this.state.fontsLoaded}
56+
{...componentProps}
57+
/>
58+
);
59+
}
60+
}
61+
return FontLoaderComponent;
62+
};
63+
64+
export {
65+
FontLoaderHOC as default
66+
};

src/lib/vm-manager-hoc.jsx

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,10 @@ import {connect} from 'react-redux';
55

66
import VM from 'scratch-vm';
77
import AudioEngine from 'scratch-audio';
8+
import Renderer from 'scratch-render';
9+
import VideoProvider from '../lib/video/video-provider';
10+
import {SVGRenderer as V2SVGAdapter} from 'scratch-svg-renderer';
11+
import {BitmapAdapter as V2BitmapAdapter} from 'scratch-svg-renderer';
812

913
import {
1014
LoadingStates,
@@ -38,7 +42,10 @@ const vmManagerHOC = function (WrappedComponent) {
3842
this.props.vm.initialized = true;
3943
}
4044
componentDidUpdate (prevProps) {
41-
if (this.props.isLoadingWithId && !prevProps.isLoadingWithId) {
45+
// if project state is LOADING variation, and fonts are loaded,
46+
// and that wasn't true until now, load project
47+
if (this.props.isLoadingWithId && this.props.fontsLoaded &&
48+
(!prevProps.isLoadingWithId || !prevProps.fontsLoaded)) {
4249
this.loadProject(this.props.projectData, this.props.loadingState);
4350
}
4451
}
@@ -56,6 +63,7 @@ const vmManagerHOC = function (WrappedComponent) {
5663
render () {
5764
const {
5865
/* eslint-disable no-unused-vars */
66+
fontsLoaded,
5967
onLoadedProject: onLoadedProjectProp,
6068
projectData,
6169
projectId,
@@ -65,10 +73,6 @@ const vmManagerHOC = function (WrappedComponent) {
6573
vm,
6674
...componentProps
6775
} = this.props;
68-
// don't display anything until we have data loaded
69-
if (!this.props.projectData) {
70-
return null;
71-
}
7276
return (
7377
<WrappedComponent
7478
errorMessage={this.state.errorMessage}
@@ -82,6 +86,7 @@ const vmManagerHOC = function (WrappedComponent) {
8286
}
8387

8488
VMManager.propTypes = {
89+
fontsLoaded: PropTypes.bool,
8590
isLoadingWithId: PropTypes.bool,
8691
loadingState: PropTypes.oneOf(LoadingStates),
8792
onLoadedProject: PropTypes.func,

0 commit comments

Comments
 (0)