Spaces:
Runtime error
Runtime error
| import PropTypes from 'prop-types'; | |
| import React from 'react'; | |
| import {compose} from 'redux'; | |
| import {connect} from 'react-redux'; | |
| import ReactModal from 'react-modal'; | |
| import VM from 'scratch-vm'; | |
| import {injectIntl, intlShape} from 'react-intl'; | |
| import ErrorBoundaryHOC from '../lib/error-boundary-hoc.jsx'; | |
| import { | |
| getIsError, | |
| getIsShowingProject | |
| } from '../reducers/project-state'; | |
| import { | |
| activateTab, | |
| BLOCKS_TAB_INDEX, | |
| COSTUMES_TAB_INDEX, | |
| SOUNDS_TAB_INDEX, | |
| VARIABLES_TAB_INDEX, | |
| FILES_TAB_INDEX | |
| } from '../reducers/editor-tab'; | |
| import { | |
| closeCostumeLibrary, | |
| closeBackdropLibrary, | |
| closeTelemetryModal, | |
| openExtensionLibrary | |
| } from '../reducers/modals'; | |
| import FontLoaderHOC from '../lib/font-loader-hoc.jsx'; | |
| import LocalizationHOC from '../lib/localization-hoc.jsx'; | |
| import SBFileUploaderHOC from '../lib/sb-file-uploader-hoc.jsx'; | |
| import ProjectFetcherHOC from '../lib/project-fetcher-hoc.jsx'; | |
| import TitledHOC from '../lib/titled-hoc.jsx'; | |
| import ProjectSaverHOC from '../lib/project-saver-hoc.jsx'; | |
| import QueryParserHOC from '../lib/query-parser-hoc.jsx'; | |
| import storage from '../lib/storage'; | |
| import vmListenerHOC from '../lib/vm-listener-hoc.jsx'; | |
| import vmManagerHOC from '../lib/vm-manager-hoc.jsx'; | |
| import cloudManagerHOC from '../lib/cloud-manager-hoc.jsx'; | |
| import TWFullScreenResizerHOC from '../lib/tw-fullscreen-resizer-hoc.jsx'; | |
| import GUIComponent from '../components/gui/gui.jsx'; | |
| import HomeCommunication from './home-communication.jsx'; | |
| import {setIsScratchDesktop} from '../lib/isScratchDesktop.js'; | |
| class GUI extends React.Component { | |
| componentDidMount () { | |
| setIsScratchDesktop(this.props.isScratchDesktop); | |
| this.props.onStorageInit(storage); | |
| this.props.onVmInit(this.props.vm); | |
| } | |
| componentDidUpdate (prevProps) { | |
| if (this.props.projectId !== prevProps.projectId && this.props.projectId !== null) { | |
| this.props.onUpdateProjectId(this.props.projectId); | |
| } | |
| if (this.props.isShowingProject && !prevProps.isShowingProject) { | |
| // this only notifies container when a project changes from not yet loaded to loaded | |
| // At this time the project view in www doesn't need to know when a project is unloaded | |
| this.props.onProjectLoaded(); | |
| } | |
| } | |
| render () { | |
| if (this.props.isError) { | |
| console.log('the below error was caught by the gui'); | |
| throw this.props.error; | |
| } | |
| const { | |
| /* eslint-disable no-unused-vars */ | |
| assetHost, | |
| cloudHost, | |
| error, | |
| isError, | |
| isScratchDesktop, | |
| isShowingProject, | |
| onProjectLoaded, | |
| onStorageInit, | |
| onUpdateProjectId, | |
| onVmInit, | |
| projectHost, | |
| projectId, | |
| /* eslint-enable no-unused-vars */ | |
| children, | |
| fetchingProject, | |
| isLoading, | |
| loadingStateVisible, | |
| isPlayground, | |
| ...componentProps | |
| } = this.props; | |
| return (<> | |
| <GUIComponent | |
| loading={fetchingProject || isLoading || loadingStateVisible} | |
| isPlayground={isPlayground} | |
| {...componentProps} | |
| > | |
| {children} | |
| </GUIComponent> | |
| <HomeCommunication | |
| projectId={projectId} | |
| isPlayground={isPlayground} | |
| /> | |
| </>); | |
| } | |
| } | |
| GUI.propTypes = { | |
| assetHost: PropTypes.string, | |
| children: PropTypes.node, | |
| cloudHost: PropTypes.string, | |
| error: PropTypes.oneOfType([PropTypes.object, PropTypes.string]), | |
| fetchingProject: PropTypes.bool, | |
| intl: intlShape, | |
| isError: PropTypes.bool, | |
| isEmbedded: PropTypes.bool, | |
| isFullScreen: PropTypes.bool, | |
| isLoading: PropTypes.bool, | |
| isScratchDesktop: PropTypes.bool, | |
| isShowingProject: PropTypes.bool, | |
| isPlayground: PropTypes.bool, | |
| loadingStateVisible: PropTypes.bool, | |
| onProjectLoaded: PropTypes.func, | |
| onSeeCommunity: PropTypes.func, | |
| onStorageInit: PropTypes.func, | |
| onUpdateProjectId: PropTypes.func, | |
| onVmInit: PropTypes.func, | |
| projectHost: PropTypes.string, | |
| projectId: PropTypes.oneOfType([PropTypes.string, PropTypes.number]), | |
| telemetryModalVisible: PropTypes.bool, | |
| vm: PropTypes.instanceOf(VM).isRequired | |
| }; | |
| GUI.defaultProps = { | |
| isScratchDesktop: false, | |
| isPlayground: false, | |
| onStorageInit: storageInstance => storageInstance.addOfficialScratchWebStores(), | |
| onProjectLoaded: () => {}, | |
| onUpdateProjectId: () => {}, | |
| onVmInit: (/* vm */) => {} | |
| }; | |
| const mapStateToProps = state => { | |
| const loadingState = state.scratchGui.projectState.loadingState; | |
| return { | |
| activeTabIndex: state.scratchGui.editorTab.activeTabIndex, | |
| alertsVisible: state.scratchGui.alerts.visible, | |
| backdropLibraryVisible: state.scratchGui.modals.backdropLibrary, | |
| blocksTabVisible: state.scratchGui.editorTab.activeTabIndex === BLOCKS_TAB_INDEX, | |
| cardsVisible: state.scratchGui.cards.visible, | |
| connectionModalVisible: state.scratchGui.modals.connectionModal, | |
| costumeLibraryVisible: state.scratchGui.modals.costumeLibrary, | |
| costumesTabVisible: state.scratchGui.editorTab.activeTabIndex === COSTUMES_TAB_INDEX, | |
| error: state.scratchGui.projectState.error, | |
| isError: getIsError(loadingState), | |
| isEmbedded: state.scratchGui.mode.isEmbedded, | |
| isFullScreen: state.scratchGui.mode.isFullScreen || state.scratchGui.mode.isEmbedded, | |
| isPlayerOnly: state.scratchGui.mode.isPlayerOnly, | |
| isRtl: state.locales.isRtl, | |
| isShowingProject: getIsShowingProject(loadingState), | |
| loadingStateVisible: state.scratchGui.modals.loadingProject, | |
| projectId: state.scratchGui.projectState.projectId, | |
| soundsTabVisible: state.scratchGui.editorTab.activeTabIndex === SOUNDS_TAB_INDEX, | |
| variablesTabVisible: state.scratchGui.editorTab.activeTabIndex === VARIABLES_TAB_INDEX, | |
| filesTabVisible: state.scratchGui.editorTab.activeTabIndex === FILES_TAB_INDEX, | |
| targetIsStage: ( | |
| state.scratchGui.targets.stage && | |
| state.scratchGui.targets.stage.id === state.scratchGui.targets.editingTarget | |
| ), | |
| telemetryModalVisible: state.scratchGui.modals.telemetryModal, | |
| tipsLibraryVisible: state.scratchGui.modals.tipsLibrary, | |
| usernameModalVisible: state.scratchGui.modals.usernameModal, | |
| settingsModalVisible: state.scratchGui.modals.settingsModal, | |
| customExtensionModalVisible: state.scratchGui.modals.customExtensionModal, | |
| fontsModalVisible: state.scratchGui.modals.fontsModal, | |
| vm: state.scratchGui.vm | |
| }; | |
| }; | |
| const mapDispatchToProps = dispatch => ({ | |
| onExtensionButtonClick: () => dispatch(openExtensionLibrary()), | |
| onActivateTab: tab => dispatch(activateTab(tab)), | |
| onActivateCostumesTab: () => dispatch(activateTab(COSTUMES_TAB_INDEX)), | |
| onActivateSoundsTab: () => dispatch(activateTab(SOUNDS_TAB_INDEX)), | |
| onActivateVariablesTab: () => dispatch(activateTab(VARIABLES_TAB_INDEX)), | |
| onActivateFilesTab: () => dispatch(activateTab(FILES_TAB_INDEX)), | |
| onRequestCloseBackdropLibrary: () => dispatch(closeBackdropLibrary()), | |
| onRequestCloseCostumeLibrary: () => dispatch(closeCostumeLibrary()), | |
| onRequestCloseTelemetryModal: () => dispatch(closeTelemetryModal()) | |
| }); | |
| const ConnectedGUI = injectIntl(connect( | |
| mapStateToProps, | |
| mapDispatchToProps, | |
| )(GUI)); | |
| // note that redux's 'compose' function is just being used as a general utility to make | |
| // the hierarchy of HOC constructor calls clearer here; it has nothing to do with redux's | |
| // ability to compose reducers. | |
| const WrappedGui = compose( | |
| LocalizationHOC, | |
| ErrorBoundaryHOC('Top Level App'), | |
| FontLoaderHOC, | |
| // QueryParserHOC, // tw: HOC is unused | |
| ProjectFetcherHOC, | |
| TitledHOC, | |
| ProjectSaverHOC, | |
| vmListenerHOC, | |
| vmManagerHOC, | |
| SBFileUploaderHOC, | |
| cloudManagerHOC, | |
| TWFullScreenResizerHOC | |
| )(ConnectedGUI); | |
| WrappedGui.setAppElement = ReactModal.setAppElement; | |
| export default WrappedGui; | |