99 lines
2.6 KiB
JavaScript
Executable file
99 lines
2.6 KiB
JavaScript
Executable file
import React from 'react';
|
|
import hoistNonReactStatic from 'hoist-non-react-statics';
|
|
import {loadImage} from '../utils/ImageLoaderUtils';
|
|
|
|
const URL_REGEX = /url\(['"](.*)['"]\)/;
|
|
|
|
function getURL(url) {
|
|
if (!url || url === 'none') {
|
|
return null;
|
|
}
|
|
const match = url.match(URL_REGEX);
|
|
if (match) {
|
|
return match[1];
|
|
}
|
|
return url;
|
|
}
|
|
|
|
function makeUrlString(url) {
|
|
if (!url || url === 'none') {
|
|
return 'none';
|
|
}
|
|
return `url(${url})`;
|
|
}
|
|
|
|
export function backgroundImagePreloader(WrappedComponent) {
|
|
class BackgroundImagePreloader extends React.Component {
|
|
constructor(props) {
|
|
super(props);
|
|
const {style} = props;
|
|
// Always assume the initial asset is loaded
|
|
const cached = style ? getURL(style.backgroundImage) : null;
|
|
this.cached = [cached];
|
|
this.state = {
|
|
cached,
|
|
loaded: true,
|
|
};
|
|
}
|
|
|
|
componentWillReceiveProps(nextProps) {
|
|
const {cached} = this.state;
|
|
const {style} = nextProps;
|
|
const newURL = style ? getURL(style.backgroundImage) : null;
|
|
// Non urls require no caching
|
|
if (!newURL && newURL !== cached) {
|
|
this.setState({loaded: true, cached: newURL});
|
|
} else if (this.cached.indexOf(newURL) >= 0) {
|
|
this.setState({loaded: true, cached: newURL});
|
|
} else if (newURL && newURL !== cached) {
|
|
// We have a new URL and must load it
|
|
this.setState({loaded: false}, () => this.preloadURL(newURL));
|
|
}
|
|
}
|
|
|
|
preloadURL(url) {
|
|
if (this.canceller) {
|
|
this.canceller();
|
|
}
|
|
this.canceller = loadImage(url, err => {
|
|
if (this.canceller) {
|
|
this.canceller = null;
|
|
}
|
|
if (!err) {
|
|
this.cached.push(url);
|
|
this.setState({cached: url, loaded: true});
|
|
}
|
|
const {onBackgroundImageLoad} = this.props;
|
|
onBackgroundImageLoad && onBackgroundImageLoad(err, url);
|
|
});
|
|
}
|
|
|
|
componentWillUnmount() {
|
|
if (this.canceller) {
|
|
this.canceller();
|
|
}
|
|
this.cached.length = 0;
|
|
}
|
|
|
|
render() {
|
|
// eslint-disable-next-line no-unused-vars
|
|
let {style, onBackgroundImageLoad, ...props} = this.props;
|
|
const {loaded, cached} = this.state;
|
|
if (!loaded && style) {
|
|
style = {
|
|
...style,
|
|
backgroundImage: makeUrlString(cached),
|
|
};
|
|
}
|
|
return <WrappedComponent style={style} {...props} />;
|
|
}
|
|
}
|
|
|
|
hoistNonReactStatic(BackgroundImagePreloader, WrappedComponent);
|
|
return BackgroundImagePreloader;
|
|
}
|
|
|
|
|
|
|
|
// WEBPACK FOOTER //
|
|
// ./discord_app/containers/backgroundImagePreloader.js
|