Loading rendering code dynamically

This commit is contained in:
Jeff Avallone 2018-05-28 14:41:02 -04:00
parent d88defcc65
commit 8ba954c743
2 changed files with 112 additions and 17 deletions

View File

@ -2,12 +2,14 @@ import React from 'react';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import { translate } from 'react-i18next'; import { translate } from 'react-i18next';
import URLSearchParams from 'url-search-params'; import URLSearchParams from 'url-search-params';
import Raven from 'raven-js';
import LoaderIcon from 'feather-icons/dist/icons/loader.svg';
import style from './style.css'; import style from './style.css';
import Form from 'components/Form'; import Form from 'components/Form';
import Message from 'components/Message'; import Message from 'components/Message';
import SVG from 'components/SVG';
import { demoImage } from 'devel'; import { demoImage } from 'devel';
const syntaxes = { const syntaxes = {
@ -67,6 +69,34 @@ class App extends React.PureComponent {
} }
} }
async loadSVGComponent() {
if (this.state.SVG) {
return;
}
this.setState({
loading: true,
loadingFailed: false
});
try {
const SVG = await import(/* webpackChunkName: "render" */ 'components/SVG');
this.setState({
SVG: SVG.default,
loading: false
});
}
catch (e) {
Raven.captureException(e);
this.setState({
loading: false,
loadingFailed: e
});
throw e;
}
}
handleSubmit = ({expr, syntax}) => { handleSubmit = ({expr, syntax}) => {
if (expr) { if (expr) {
const params = new URLSearchParams({ syntax, expr }); const params = new URLSearchParams({ syntax, expr });
@ -74,7 +104,7 @@ class App extends React.PureComponent {
} }
} }
handleHashChange = () => { handleHashChange = async () => {
const query = document.location.hash.slice(1); const query = document.location.hash.slice(1);
const params = new URLSearchParams(query); const params = new URLSearchParams(query);
const { expr, syntax } = (() => { const { expr, syntax } = (() => {
@ -96,21 +126,32 @@ class App extends React.PureComponent {
return; return;
} }
console.log(syntax, expr); // eslint-disable-line no-console try {
this.setState({ await this.loadSVGComponent();
image: demoImage, console.log(syntax, expr); // eslint-disable-line no-console
permalinkUrl: document.location.toString(), this.setState({
syntax, image: demoImage,
expr permalinkUrl: document.location.toString(),
}, async () => { syntax,
await this.image.current.doReflow(); expr
this.setSvgUrl(); }, async () => {
this.setPngUrl(); await this.image.current.doReflow();
}); this.setSvgUrl();
this.setPngUrl();
});
}
catch (e) {
console.error(e); // eslint-disable-line no-console
}
}
handleRetry = async event => {
event.preventDefault();
this.handleHashChange();
} }
render() { render() {
const { svgUrl, pngUrl, permalinkUrl, syntax, expr, image } = this.state; const { SVG, loading, loadingFailed, svgUrl, pngUrl, permalinkUrl, syntax, expr, image } = this.state;
const downloadUrls = [ const downloadUrls = [
svgUrl, svgUrl,
pngUrl pngUrl
@ -130,9 +171,22 @@ class App extends React.PureComponent {
<Message type="warning" heading="Sample Warning"> <Message type="warning" heading="Sample Warning">
<p>Sample warning message</p> <p>Sample warning message</p>
</Message> </Message>
{ image && <div className={ style.render }> {
<SVG data={ image } ref={ this.image }/> loading && <div className={ style.loader }>
</div> } <LoaderIcon />
<div className={ style.message }>Loading...</div>
</div>
}
{
loadingFailed && <Message type="error" heading="Render Failure">
An error occurred while rendering the regular expression. <a href="#retry" onClick={ this.handleRetry }>Retry</a>
</Message>
}
{
image && <div className={ style.render }>
<SVG data={ image } ref={ this.image }/>
</div>
}
</React.Fragment>; </React.Fragment>;
} }
} }

View File

@ -13,3 +13,44 @@
margin: 0 auto; margin: 0 auto;
} }
} }
.loader {
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
width: 100%;
padding: 2rem;
background: var(--color-white);
color: var(--color-black);
& .message {
font-weight: bold;
font-size: 2.5rem;
padding: 0;
text-align: center;
}
& svg {
display: block;
transform: scaleZ(1); /* Move to separate render layer in Chrome */
width: 5rem;
height: 5rem;
stroke: var(--color-black);
animation: loader-spin 1s steps(8) infinite;
& line:nth-of-type(1) { stroke: color(var(--color-black) alpha(0.75)); }
& line:nth-of-type(3) { stroke: color(var(--color-black) alpha(0.50)); }
& line:nth-of-type(5) { stroke: color(var(--color-black) alpha(0.25)); }
& line:nth-of-type(7) { stroke: color(var(--color-black) alpha(0)); }
}
}
@keyframes loader-spin {
from {
transform: rotate(0deg);
}
to {
transform: rotate(360deg);
}
}