import AudioEngine from 'scratch-audio'; import PropTypes from 'prop-types'; import React from 'react'; import VM from 'scratch-vm'; import {connect} from 'react-redux'; import {openExtensionLibrary} from '../reducers/modals'; import { activateTab, BLOCKS_TAB_INDEX, COSTUMES_TAB_INDEX, SOUNDS_TAB_INDEX } from '../reducers/editor-tab'; import vmListenerHOC from '../lib/vm-listener-hoc.jsx'; import GUIComponent from '../components/gui/gui.jsx'; class GUI extends React.Component { constructor (props) { super(props); this.state = { loading: true, loadingError: false, errorMessage: '' }; } componentDidMount () { this.audioEngine = new AudioEngine(); this.props.vm.attachAudioEngine(this.audioEngine); this.props.vm.loadProject(this.props.projectData) .then(() => { this.setState({loading: false}, () => { this.props.vm.setCompatibilityMode(true); this.props.vm.start(); }); }) .catch(e => { // Need to catch this error and update component state so that // error page gets rendered if project failed to load this.setState({loadingError: true, errorMessage: e}); }); } componentWillReceiveProps (nextProps) { if (this.props.projectData !== nextProps.projectData) { this.setState({loading: true}, () => { this.props.vm.loadProject(nextProps.projectData) .then(() => { this.setState({loading: false}); }) .catch(e => { // Need to catch this error and update component state so that // error page gets rendered if project failed to load this.setState({loadingError: true, errorMessage: e}); }); }); } } componentWillUnmount () { this.props.vm.stopAll(); } render () { if (this.state.loadingError) throw new Error(`Failed to load project: ${this.state.errorMessage}`); const { children, fetchingProject, loadingStateVisible, projectData, // eslint-disable-line no-unused-vars vm, ...componentProps } = this.props; return ( <GUIComponent loading={fetchingProject || this.state.loading || loadingStateVisible} vm={vm} {...componentProps} > {children} </GUIComponent> ); } } GUI.propTypes = { ...GUIComponent.propTypes, feedbackFormVisible: PropTypes.bool, fetchingProject: PropTypes.bool, importInfoVisible: PropTypes.bool, loadingStateVisible: PropTypes.bool, previewInfoVisible: PropTypes.bool, projectData: PropTypes.string, vm: PropTypes.instanceOf(VM) }; GUI.defaultProps = GUIComponent.defaultProps; const mapStateToProps = state => ({ activeTabIndex: state.editorTab.activeTabIndex, blocksTabVisible: state.editorTab.activeTabIndex === BLOCKS_TAB_INDEX, costumesTabVisible: state.editorTab.activeTabIndex === COSTUMES_TAB_INDEX, feedbackFormVisible: state.modals.feedbackForm, importInfoVisible: state.modals.importInfo, loadingStateVisible: state.modals.loadingProject, previewInfoVisible: state.modals.previewInfo, soundsTabVisible: state.editorTab.activeTabIndex === SOUNDS_TAB_INDEX }); const mapDispatchToProps = dispatch => ({ onExtensionButtonClick: () => dispatch(openExtensionLibrary()), onActivateTab: tab => dispatch(activateTab(tab)), onActivateCostumesTab: () => dispatch(activateTab(COSTUMES_TAB_INDEX)), onActivateSoundsTab: () => dispatch(activateTab(SOUNDS_TAB_INDEX)) }); const ConnectedGUI = connect( mapStateToProps, mapDispatchToProps, )(GUI); export default vmListenerHOC(ConnectedGUI);