Spaces:
Runtime error
Runtime error
| /** | |
| * Copyright (C) 2021 Thomas Weber | |
| * | |
| * This program is free software: you can redistribute it and/or modify | |
| * it under the terms of the GNU General Public License version 3 as | |
| * published by the Free Software Foundation. | |
| * | |
| * This program is distributed in the hope that it will be useful, | |
| * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
| * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
| * GNU General Public License for more details. | |
| * | |
| * You should have received a copy of the GNU General Public License | |
| * along with this program. If not, see <https://www.gnu.org/licenses/>. | |
| */ | |
| import classNames from 'classnames'; | |
| import PropTypes from 'prop-types'; | |
| import React from 'react'; | |
| import { connect } from 'react-redux'; | |
| import { compose } from 'redux'; | |
| import { FormattedMessage, defineMessages, injectIntl, intlShape } from 'react-intl'; | |
| import { getIsLoading } from '../reducers/project-state.js'; | |
| import DOMElementRenderer from '../containers/dom-element-renderer.jsx'; | |
| import AppStateHOC from '../lib/app-state-hoc.jsx'; | |
| import ErrorBoundaryHOC from '../lib/error-boundary-hoc.jsx'; | |
| import TWProjectMetaFetcherHOC from '../lib/tw-project-meta-fetcher-hoc.jsx'; | |
| import TWStateManagerHOC from '../lib/tw-state-manager-hoc.jsx'; | |
| import TWThemeHOC from '../lib/tw-theme-hoc.jsx'; | |
| import TWPackagerIntegrationHOC from '../lib/tw-packager-integration-hoc.jsx'; | |
| import SettingsStore from '../addons/settings-store-singleton'; | |
| import '../lib/tw-fix-history-api'; | |
| import GUI from './render-gui.jsx'; | |
| import AddonChannels from '../addons/channels'; | |
| import { loadServiceWorker } from './load-service-worker'; | |
| import runAddons from '../addons/entry'; | |
| import styles from './interface.css'; | |
| const messages = defineMessages({ | |
| defaultTitle: { | |
| defaultMessage: 'Playground', | |
| description: 'Title of homepage', | |
| id: 'pm.playgroundDefaultTitle' | |
| } | |
| }); | |
| if (AddonChannels.reloadChannel) { | |
| AddonChannels.reloadChannel.addEventListener('message', () => { | |
| location.reload(); | |
| }); | |
| } | |
| if (AddonChannels.changeChannel) { | |
| AddonChannels.changeChannel.addEventListener('message', e => { | |
| SettingsStore.setStoreWithVersionCheck(e.data); | |
| }); | |
| } | |
| runAddons(); | |
| class Interface extends React.Component { | |
| constructor(props) { | |
| super(props); | |
| this.handleUpdateProjectTitle = this.handleUpdateProjectTitle.bind(this); | |
| } | |
| componentDidUpdate(prevProps) { | |
| if (prevProps.isLoading && !this.props.isLoading) { | |
| loadServiceWorker(); | |
| } | |
| } | |
| handleUpdateProjectTitle(title, isDefault) { | |
| if (isDefault || !title) { | |
| document.title = `Scratch for School - ${this.props.intl.formatMessage(messages.defaultTitle)}`; | |
| } else { | |
| document.title = `${title} - Scratch for School`; | |
| } | |
| } | |
| render() { | |
| const { | |
| /* eslint-disable no-unused-vars */ | |
| intl, | |
| hasCloudVariables, | |
| description, | |
| isFullScreen, | |
| isLoading, | |
| isPlayerOnly, | |
| isRtl, | |
| onClickTheme, | |
| projectId, | |
| /* eslint-enable no-unused-vars */ | |
| ...props | |
| } = this.props; | |
| const isHomepage = false; | |
| const isEditor = true; | |
| return ( | |
| <div | |
| className={classNames(styles.container, { | |
| [styles.playerOnly]: isHomepage, | |
| [styles.editor]: isEditor | |
| })} | |
| > | |
| <div | |
| className={styles.center} | |
| style={isPlayerOnly ? ({ | |
| // add a couple pixels to account for border (TODO: remove weird hack) | |
| width: `${Math.max(480, props.customStageSize.width) + 2}px` | |
| }) : null} | |
| > | |
| <GUI | |
| onClickTheme={onClickTheme} | |
| isPlayground={true} | |
| onUpdateProjectTitle={this.handleUpdateProjectTitle} | |
| backpackVisible | |
| backpackHost="_local_" | |
| {...props} | |
| /> | |
| </div> | |
| </div> | |
| ); | |
| } | |
| } | |
| Interface.propTypes = { | |
| intl: intlShape, | |
| hasCloudVariables: PropTypes.bool, | |
| customStageSize: PropTypes.shape({ | |
| width: PropTypes.number, | |
| height: PropTypes.number | |
| }), | |
| description: PropTypes.shape({ | |
| credits: PropTypes.string, | |
| instructions: PropTypes.string | |
| }), | |
| isFullScreen: PropTypes.bool, | |
| isLoading: PropTypes.bool, | |
| isPlayerOnly: PropTypes.bool, | |
| isRtl: PropTypes.bool, | |
| onClickTheme: PropTypes.func, | |
| projectId: PropTypes.string | |
| }; | |
| const mapStateToProps = state => ({ | |
| hasCloudVariables: state.scratchGui.tw.hasCloudVariables, | |
| customStageSize: state.scratchGui.customStageSize, | |
| description: state.scratchGui.tw.description, | |
| isFullScreen: state.scratchGui.mode.isFullScreen, | |
| isLoading: getIsLoading(state.scratchGui.projectState.loadingState), | |
| isPlayerOnly: state.scratchGui.mode.isPlayerOnly, | |
| isRtl: state.locales.isRtl, | |
| projectId: state.scratchGui.projectState.projectId | |
| }); | |
| const mapDispatchToProps = () => ({}); | |
| const ConnectedInterface = injectIntl(connect( | |
| mapStateToProps, | |
| mapDispatchToProps | |
| )(Interface)); | |
| const WrappedInterface = compose( | |
| AppStateHOC, | |
| ErrorBoundaryHOC('TW Interface'), | |
| TWProjectMetaFetcherHOC, | |
| TWStateManagerHOC, | |
| TWThemeHOC, | |
| TWPackagerIntegrationHOC | |
| )(ConnectedInterface); | |
| export default WrappedInterface; | |