diff --git a/src/components/menu-bar/confirm-replace-hoc.jsx b/src/components/menu-bar/confirm-replace-hoc.jsx new file mode 100644 index 0000000000000000000000000000000000000000..5631b800bb9e2d9b01cd5da61d6bc9d4683b28a9 --- /dev/null +++ b/src/components/menu-bar/confirm-replace-hoc.jsx @@ -0,0 +1,50 @@ +import {connect} from 'react-redux'; +import PropTypes from 'prop-types'; +import bindAll from 'lodash.bindall'; +import React from 'react'; + +const ConfirmReplaceHOC = function (WrappedComponent) { + class ConfirmReplaceProject extends React.PureComponent { + constructor (props) { + super(props); + + bindAll(this, [ + 'confirmReadyToReplaceProject' + ]); + } + + confirmReadyToReplaceProject (message) { + let readyToReplaceProject = true; + if (this.props.projectChanged && !this.props.canCreateNew) { + readyToReplaceProject = confirm(message); // eslint-disable-line no-alert + } + return readyToReplaceProject; + } + + render () { + const { + /* eslint-disable no-unused-vars */ + projectChanged, + /* eslint-enable no-unused-vars */ + ...props + } = this.props; + return (<WrappedComponent + confirmReadyToReplaceProject={this.confirmReadyToReplaceProject} + {...props} + />); + } + } + + ConfirmReplaceProject.propTypes = { + canCreateNew: PropTypes.bool, + projectChanged: PropTypes.bool + }; + + const _mapStateToProps = state => ({ + projectChanged: state.scratchGui.projectChanged + }); + + return connect(_mapStateToProps)(ConfirmReplaceProject); +}; + +export default ConfirmReplaceHOC; diff --git a/src/components/menu-bar/menu-bar.jsx b/src/components/menu-bar/menu-bar.jsx index eafa4578dacc6740a1f913cf12cb688f9b97333d..346b09b7b9718b11d4abfd6e8dcb7f972463767e 100644 --- a/src/components/menu-bar/menu-bar.jsx +++ b/src/components/menu-bar/menu-bar.jsx @@ -1,5 +1,6 @@ import classNames from 'classnames'; import {connect} from 'react-redux'; +import {compose} from 'redux'; import {defineMessages, FormattedMessage, injectIntl, intlShape} from 'react-intl'; import PropTypes from 'prop-types'; import bindAll from 'lodash.bindall'; @@ -27,6 +28,7 @@ import LoginDropdown from './login-dropdown.jsx'; import SB3Downloader from '../../containers/sb3-downloader.jsx'; import DeletionRestorer from '../../containers/deletion-restorer.jsx'; import TurboMode from '../../containers/turbo-mode.jsx'; +import ConfirmReplaceHOC from './confirm-replace-hoc.jsx'; import {openTipsLibrary} from '../../reducers/modals'; import {setPlayer} from '../../reducers/mode'; @@ -164,17 +166,14 @@ class MenuBar extends React.Component { document.removeEventListener('keydown', this.handleKeyPress); } handleClickNew () { - let readyToReplaceProject = true; // if the project is dirty, and user owns the project, we will autosave. // but if they are not logged in and can't save, user should consider // downloading or logging in first. // Note that if user is logged in and editing someone else's project, // they'll lose their work. - if (this.props.projectChanged && !this.props.canCreateNew) { - readyToReplaceProject = confirm( // eslint-disable-line no-alert - this.props.intl.formatMessage(sharedMessages.replaceProjectWarning) - ); - } + const readyToReplaceProject = this.props.confirmReadyToReplaceProject( + this.props.intl.formatMessage(sharedMessages.replaceProjectWarning) + ); this.props.onRequestCloseFile(); if (readyToReplaceProject) { this.props.onClickNew(this.props.canSave && this.props.canCreateNew); @@ -759,7 +758,6 @@ MenuBar.propTypes = { onShare: PropTypes.func, onToggleLoginOpen: PropTypes.func, onUpdateProjectTitle: PropTypes.func, - projectChanged: PropTypes.bool, projectTitle: PropTypes.string, renderLogin: PropTypes.func, sessionExists: PropTypes.bool, @@ -785,7 +783,6 @@ const mapStateToProps = (state, ownProps) => { languageMenuOpen: languageMenuOpen(state), locale: state.locales.locale, loginMenuOpen: loginMenuOpen(state), - projectChanged: state.scratchGui.projectChanged, projectTitle: state.scratchGui.projectTitle, sessionExists: state.session && typeof state.session.session !== 'undefined', username: user ? user.username : null, @@ -815,7 +812,11 @@ const mapDispatchToProps = dispatch => ({ onSeeCommunity: () => dispatch(setPlayer(true)) }); -export default injectIntl(connect( - mapStateToProps, - mapDispatchToProps -)(MenuBar)); +export default compose( + injectIntl, + ConfirmReplaceHOC, + connect( + mapStateToProps, + mapDispatchToProps + ) +)(MenuBar);