Skip to content

Commit fc8c242

Browse files
committed
separate projectChanged, MenuBar doesn't need it to render
Rendering the MenuBar does not depend on projectChanged. Some of its event handling does. Abstracting that dependency we can handle some behaviour in MenuBar without extra renders.
1 parent 6d5183f commit fc8c242

File tree

2 files changed

+63
-12
lines changed

2 files changed

+63
-12
lines changed
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
import {connect} from 'react-redux';
2+
import PropTypes from 'prop-types';
3+
import bindAll from 'lodash.bindall';
4+
import React from 'react';
5+
6+
const ConfirmReplaceHOC = function (WrappedComponent) {
7+
class ConfirmReplaceProject extends React.PureComponent {
8+
constructor (props) {
9+
super(props);
10+
11+
bindAll(this, [
12+
'confirmReadyToReplaceProject'
13+
]);
14+
}
15+
16+
confirmReadyToReplaceProject (message) {
17+
let readyToReplaceProject = true;
18+
if (this.props.projectChanged && !this.props.canCreateNew) {
19+
readyToReplaceProject = confirm(message); // eslint-disable-line no-alert
20+
}
21+
return readyToReplaceProject;
22+
}
23+
24+
render () {
25+
const {
26+
/* eslint-disable no-unused-vars */
27+
projectChanged,
28+
/* eslint-enable no-unused-vars */
29+
...props
30+
} = this.props;
31+
return (<WrappedComponent
32+
confirmReadyToReplaceProject={this.confirmReadyToReplaceProject}
33+
{...props}
34+
/>);
35+
}
36+
}
37+
38+
ConfirmReplaceProject.propTypes = {
39+
canCreateNew: PropTypes.bool,
40+
projectChanged: PropTypes.bool
41+
};
42+
43+
const _mapStateToProps = state => ({
44+
projectChanged: state.scratchGui.projectChanged
45+
});
46+
47+
return connect(_mapStateToProps)(ConfirmReplaceProject);
48+
};
49+
50+
export default ConfirmReplaceHOC;

src/components/menu-bar/menu-bar.jsx

Lines changed: 13 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import classNames from 'classnames';
22
import {connect} from 'react-redux';
3+
import {compose} from 'redux';
34
import {defineMessages, FormattedMessage, injectIntl, intlShape} from 'react-intl';
45
import PropTypes from 'prop-types';
56
import bindAll from 'lodash.bindall';
@@ -25,6 +26,7 @@ import LoginDropdown from './login-dropdown.jsx';
2526
import SB3Downloader from '../../containers/sb3-downloader.jsx';
2627
import DeletionRestorer from '../../containers/deletion-restorer.jsx';
2728
import TurboMode from '../../containers/turbo-mode.jsx';
29+
import ConfirmReplaceHOC from './confirm-replace-hoc.jsx';
2830

2931
import {openTipsLibrary} from '../../reducers/modals';
3032
import {setPlayer} from '../../reducers/mode';
@@ -160,17 +162,14 @@ class MenuBar extends React.Component {
160162
document.removeEventListener('keydown', this.handleKeyPress);
161163
}
162164
handleClickNew () {
163-
let readyToReplaceProject = true;
164165
// if the project is dirty, and user owns the project, we will autosave.
165166
// but if they are not logged in and can't save, user should consider
166167
// downloading or logging in first.
167168
// Note that if user is logged in and editing someone else's project,
168169
// they'll lose their work.
169-
if (this.props.projectChanged && !this.props.canCreateNew) {
170-
readyToReplaceProject = confirm( // eslint-disable-line no-alert
171-
this.props.intl.formatMessage(sharedMessages.replaceProjectWarning)
172-
);
173-
}
170+
const readyToReplaceProject = this.props.confirmReadyToReplaceProject(
171+
this.props.intl.formatMessage(sharedMessages.replaceProjectWarning)
172+
);
174173
this.props.onRequestCloseFile();
175174
if (readyToReplaceProject) {
176175
this.props.onClickNew(this.props.canSave && this.props.canCreateNew);
@@ -752,7 +751,6 @@ MenuBar.propTypes = {
752751
onShare: PropTypes.func,
753752
onToggleLoginOpen: PropTypes.func,
754753
onUpdateProjectTitle: PropTypes.func,
755-
projectChanged: PropTypes.bool,
756754
projectTitle: PropTypes.string,
757755
renderLogin: PropTypes.func,
758756
sessionExists: PropTypes.bool,
@@ -776,7 +774,6 @@ const mapStateToProps = state => {
776774
isShowingProject: getIsShowingProject(loadingState),
777775
languageMenuOpen: languageMenuOpen(state),
778776
loginMenuOpen: loginMenuOpen(state),
779-
projectChanged: state.scratchGui.projectChanged,
780777
projectTitle: state.scratchGui.projectTitle,
781778
sessionExists: state.session && typeof state.session.session !== 'undefined',
782779
username: user ? user.username : null
@@ -803,7 +800,11 @@ const mapDispatchToProps = dispatch => ({
803800
onSeeCommunity: () => dispatch(setPlayer(true))
804801
});
805802

806-
export default injectIntl(connect(
807-
mapStateToProps,
808-
mapDispatchToProps
809-
)(MenuBar));
803+
export default compose(
804+
injectIntl,
805+
ConfirmReplaceHOC,
806+
connect(
807+
mapStateToProps,
808+
mapDispatchToProps
809+
)
810+
)(MenuBar);

0 commit comments

Comments
 (0)