import React from 'react'; import {defineMessages, FormattedMessage, intlShape, injectIntl} from 'react-intl'; import classNames from 'classnames'; import styles from './loader.css'; import PropTypes from 'prop-types'; import bindAll from 'lodash.bindall'; import topBlock from './top-block.svg'; import middleBlock from './middle-block.svg'; import bottomBlock from './bottom-block.svg'; import * as progressMonitor from './tw-progress-monitor'; import isScratchDesktop from '../../lib/isScratchDesktop'; // tw: // we make some rather large changes here: // - remove random message, replaced with message dependent on what is actually being loaded // - add a progress bar // - bring in intl so that we can translate everything // The way of doing this is extremely unusual and weird compared to how things are typically done for performance. // This is because react updates are too performance crippling to handle the progress bar rapidly updating. const mainMessages = { 'gui.loader.headline': ( ), 'gui.loader.creating': ( ), 'gui.loader.playground': ( ) }; const messages = defineMessages({ generic: { defaultMessage: 'Loading project …', description: 'Initial generic loading message', id: 'tw.loader.generic' }, projectData: { defaultMessage: 'Downloading project data …', description: 'Appears when loading project data', id: 'tw.loader.data' }, assetsKnown: { defaultMessage: 'Downloading assets ({complete}/{total}) …', description: 'Appears when loading project assets and amount of assets is known', id: 'tw.loader.assets.known' }, assetsUnknown: { defaultMessage: 'Downloading assets …', description: 'Appears when loading project assets but amount of assets is unknown', id: 'tw.loader.assets.unknown' } }); class LoaderComponent extends React.Component { constructor (props) { super(props); this._state = 0; this.progress = 0; this.complete = 0; this.total = 0; bindAll(this, [ 'barInnerRef', 'handleProgressChange', 'messageRef' ]); } componentDidMount () { if (!isScratchDesktop()) { progressMonitor.setProgressHandler(this.handleProgressChange); } this.updateMessage(); } componentDidUpdate () { this.update(); } componentWillUnmount () { progressMonitor.setProgressHandler(() => {}); } handleProgressChange (state, progress, complete, total) { if (state !== this._state) { this._state = state; this.updateMessage(); } this.progress = progress; this.complete = complete; this.total = total; this.update(); } update () { if (this.barInner) { this.barInner.style.width = `${this.progress * 100}%`; } if (this._state === 2) { this.updateMessage(); } } updateMessage () { if (this._state === 0) { this.message.textContent = this.props.intl.formatMessage(messages.generic); } else if (this._state === 1) { this.message.textContent = this.props.intl.formatMessage(messages.projectData); } else if (this.total > 0) { this.message.textContent = this.props.intl.formatMessage(messages.assetsKnown, { complete: this.complete, total: this.total }); } else { this.message.textContent = this.props.intl.formatMessage(messages.assetsUnknown); } } barInnerRef (element) { this.barInner = element; } messageRef (element) { this.message = element; } render () { return (
{mainMessages[this.props.messageId]}
{!isScratchDesktop() && (
)}
); } } LoaderComponent.propTypes = { isFullScreen: PropTypes.bool, intl: intlShape.isRequired, messageId: PropTypes.string }; LoaderComponent.defaultProps = { isFullScreen: false, messageId: 'gui.loader.headline' }; export default injectIntl(LoaderComponent);