Spaces:
Running
Running
/** | |
* 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 = `PenguinMod - ${this.props.intl.formatMessage(messages.defaultTitle)}`; | |
} else { | |
document.title = `${title} - PenguinMod`; | |
} | |
} | |
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; | |