From 6974a9860c7573e90e7272248653284d8e1029ee Mon Sep 17 00:00:00 2001 From: Ben Wheeler <wheeler.benjamin@gmail.com> Date: Tue, 16 Oct 2018 13:08:37 -0400 Subject: [PATCH] introducing font loader hoc per DD's changes --- src/containers/gui.jsx | 2 ++ src/lib/font-loader-hoc.jsx | 66 +++++++++++++++++++++++++++++++++++++ src/lib/vm-manager-hoc.jsx | 15 ++++++--- 3 files changed, 78 insertions(+), 5 deletions(-) create mode 100644 src/lib/font-loader-hoc.jsx diff --git a/src/containers/gui.jsx b/src/containers/gui.jsx index ea705596f..49b29672d 100644 --- a/src/containers/gui.jsx +++ b/src/containers/gui.jsx @@ -20,6 +20,7 @@ import { closeBackdropLibrary } from '../reducers/modals'; +import FontLoaderHOC from '../lib/font-loader-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'; @@ -132,6 +133,7 @@ const ConnectedGUI = connect( // ability to compose reducers. const WrappedGui = compose( ErrorBoundaryHOC('Top Level App'), + FontLoaderHOC, ProjectFetcherHOC, ProjectSaverHOC, vmListenerHOC, diff --git a/src/lib/font-loader-hoc.jsx b/src/lib/font-loader-hoc.jsx new file mode 100644 index 000000000..22193f3a9 --- /dev/null +++ b/src/lib/font-loader-hoc.jsx @@ -0,0 +1,66 @@ +import React from 'react'; + +/* 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 () { + const getFontPromises = () => { + const fontPromises = []; + // Browsers that support the font loader interface have an iterable document.fonts.values() + // Firefox has a mocked out object that doesn't actually implement iterable, which is why + // the deep safety check is necessary. + if (document.fonts && + typeof document.fonts.values === 'function' && + typeof document.fonts.values()[Symbol.iterator] === 'function') { + for (const fontFace of document.fonts.values()) { + fontPromises.push(fontFace.loaded); + fontFace.load(); + } + } + return fontPromises; + }; + // Font promises must be gathered after the document is loaded, because on Mac Chrome, the promise + // objects get replaced and the old ones never resolve. + if (document.readyState === 'complete') { + Promise.all(getFontPromises()).then(() => { + this.setState({fontsLoaded: true}); + }); + } else { + document.onreadystatechange = () => { + if (document.readyState !== 'complete') return; + document.onreadystatechange = null; + Promise.all(getFontPromises()).then(() => { + this.setState({fontsLoaded: true}); + }); + }; + } + } + render () { + const { + /* eslint-disable no-unused-vars */ + /* eslint-enable no-unused-vars */ + ...componentProps + } = this.props; + return ( + <WrappedComponent + fontsLoaded={this.state.fontsLoaded} + {...componentProps} + /> + ); + } + } + return FontLoaderComponent; +}; + +export { + FontLoaderHOC as default +}; diff --git a/src/lib/vm-manager-hoc.jsx b/src/lib/vm-manager-hoc.jsx index 449bff0ee..251670dd8 100644 --- a/src/lib/vm-manager-hoc.jsx +++ b/src/lib/vm-manager-hoc.jsx @@ -5,6 +5,10 @@ import {connect} from 'react-redux'; import VM from 'scratch-vm'; import AudioEngine from 'scratch-audio'; +import Renderer from 'scratch-render'; +import VideoProvider from '../lib/video/video-provider'; +import {SVGRenderer as V2SVGAdapter} from 'scratch-svg-renderer'; +import {BitmapAdapter as V2BitmapAdapter} from 'scratch-svg-renderer'; import { LoadingStates, @@ -38,7 +42,10 @@ const vmManagerHOC = function (WrappedComponent) { this.props.vm.initialized = true; } componentDidUpdate (prevProps) { - if (this.props.isLoadingWithId && !prevProps.isLoadingWithId) { + // if project state is LOADING variation, and fonts are loaded, + // and that wasn't true until now, load project + if (this.props.isLoadingWithId && this.props.fontsLoaded && + (!prevProps.isLoadingWithId || !prevProps.fontsLoaded)) { this.loadProject(this.props.projectData, this.props.loadingState); } } @@ -56,6 +63,7 @@ const vmManagerHOC = function (WrappedComponent) { render () { const { /* eslint-disable no-unused-vars */ + fontsLoaded, onLoadedProject: onLoadedProjectProp, projectData, projectId, @@ -65,10 +73,6 @@ const vmManagerHOC = function (WrappedComponent) { vm, ...componentProps } = this.props; - // don't display anything until we have data loaded - if (!this.props.projectData) { - return null; - } return ( <WrappedComponent errorMessage={this.state.errorMessage} @@ -82,6 +86,7 @@ const vmManagerHOC = function (WrappedComponent) { } VMManager.propTypes = { + fontsLoaded: PropTypes.bool, isLoadingWithId: PropTypes.bool, loadingState: PropTypes.oneOf(LoadingStates), onLoadedProject: PropTypes.func, -- GitLab