From f36bc30387ced02dc3f22965a7ce156593a3c0f1 Mon Sep 17 00:00:00 2001 From: DD <liudi08@gmail.com> Date: Mon, 16 Oct 2017 19:30:12 -0400 Subject: [PATCH] make a new component that only updates when the paint editor should update --- src/containers/costume-tab.jsx | 49 ++++--------- src/containers/paint-editor-wrapper.jsx | 93 +++++++++++++++++++++++++ 2 files changed, 107 insertions(+), 35 deletions(-) create mode 100644 src/containers/paint-editor-wrapper.jsx diff --git a/src/containers/costume-tab.jsx b/src/containers/costume-tab.jsx index c11deb2c7..d87d4964a 100644 --- a/src/containers/costume-tab.jsx +++ b/src/containers/costume-tab.jsx @@ -6,7 +6,7 @@ import VM from 'scratch-vm'; import AssetPanel from '../components/asset-panel/asset-panel.jsx'; import addCostumeIcon from '../components/asset-panel/icon--add-costume-lib.svg'; -import PaintEditor from 'scratch-paint'; +import PaintEditorWrapper from './paint-editor-wrapper.jsx'; import {connect} from 'react-redux'; @@ -20,8 +20,7 @@ class CostumeTab extends React.Component { super(props); bindAll(this, [ 'handleSelectCostume', - 'handleDeleteCostume', - 'handleUpdateSvg' + 'handleDeleteCostume' ]); this.state = {selectedCostumeIndex: 0}; } @@ -39,25 +38,6 @@ class CostumeTab extends React.Component { } } - shouldComponentUpdate (nextProps) { - const { - editingTarget, - sprites, - stage - } = nextProps; - const nextTarget = editingTarget && sprites[editingTarget] ? sprites[editingTarget] : stage; - const currentTarget = - this.props.editingTarget && this.props.sprites[this.props.editingTarget] ? - this.props.sprites[this.props.editingTarget] : - this.props.stage; - - if (this.props.editingTarget !== editingTarget || - currentTarget.currentCostume !== nextTarget.currentCostume) { - return true; - } - return false; - } - handleSelectCostume (costumeIndex) { this.props.vm.editingTarget.setCostume(costumeIndex); this.setState({selectedCostumeIndex: costumeIndex}); @@ -67,19 +47,20 @@ class CostumeTab extends React.Component { this.props.vm.deleteCostume(costumeIndex); } - handleUpdateSvg (svg, rotationCenterX, rotationCenterY) { - this.props.vm.updateSvg(this.state.selectedCostumeIndex, svg, rotationCenterX, rotationCenterY); - } - render () { + // For paint wrapper const { - editingTarget, - sprites, - stage, + onNewBackdropClick, onNewCostumeClick, - onNewBackdropClick + ...props } = this.props; + const { + editingTarget, + sprites, + stage + } = props; + const target = editingTarget && sprites[editingTarget] ? sprites[editingTarget] : stage; if (!target) { @@ -117,11 +98,9 @@ class CostumeTab extends React.Component { onItemClick={this.handleSelectCostume} > {target.costumes ? - <PaintEditor - rotationCenterX={target.costumes[this.state.selectedCostumeIndex].rotationCenterX} - rotationCenterY={target.costumes[this.state.selectedCostumeIndex].rotationCenterY} - svg={this.props.vm.getCostumeSvg(this.state.selectedCostumeIndex)} - onUpdateSvg={this.handleUpdateSvg} + <PaintEditorWrapper + {...props} + selectedCostumeIndex={this.state.selectedCostumeIndex} /> : null } diff --git a/src/containers/paint-editor-wrapper.jsx b/src/containers/paint-editor-wrapper.jsx new file mode 100644 index 000000000..0b7d81037 --- /dev/null +++ b/src/containers/paint-editor-wrapper.jsx @@ -0,0 +1,93 @@ +import PropTypes from 'prop-types'; +import React from 'react'; +import bindAll from 'lodash.bindall'; +import VM from 'scratch-vm'; + +import PaintEditor from 'scratch-paint'; + +import {connect} from 'react-redux'; + +class PaintEditorWrapper extends React.Component { + constructor (props) { + super(props); + bindAll(this, [ + 'handleUpdateSvg' + ]); + } + shouldComponentUpdate (nextProps) { + // Only update on sprite change or costume change. No need to push the SVG to the paint + // editor that it just exported; it causes the paint editor to lose some state. + const { + editingTarget, + sprites, + stage + } = nextProps; + const nextTarget = editingTarget && sprites[editingTarget] ? sprites[editingTarget] : stage; + const currentTarget = + this.props.editingTarget && this.props.sprites[this.props.editingTarget] ? + this.props.sprites[this.props.editingTarget] : + this.props.stage; + + if (this.props.editingTarget !== editingTarget || + currentTarget.currentCostume !== nextTarget.currentCostume) { + return true; + } + return false; + } + handleUpdateSvg (svg, rotationCenterX, rotationCenterY) { + this.props.vm.updateSvg(this.props.selectedCostumeIndex, svg, rotationCenterX, rotationCenterY); + } + render () { + const { + editingTarget, + sprites, + stage + } = this.props; + + const target = editingTarget && sprites[editingTarget] ? sprites[editingTarget] : stage; + + if (!target || !target.costumes) { + return null; + } + + return ( + <PaintEditor + rotationCenterX={target.costumes[this.props.selectedCostumeIndex].rotationCenterX} + rotationCenterY={target.costumes[this.props.selectedCostumeIndex].rotationCenterY} + svg={this.props.vm.getCostumeSvg(this.props.selectedCostumeIndex)} + onUpdateSvg={this.handleUpdateSvg} + /> + ); + } +} + +PaintEditorWrapper.propTypes = { + editingTarget: PropTypes.string, + selectedCostumeIndex: PropTypes.number.isRequired, + sprites: PropTypes.shape({ + id: PropTypes.shape({ + costumes: PropTypes.arrayOf(PropTypes.shape({ + url: PropTypes.string, + name: PropTypes.string.isRequired + })) + }) + }), + stage: PropTypes.shape({ + sounds: PropTypes.arrayOf(PropTypes.shape({ + name: PropTypes.string.isRequired + })) + }), + vm: PropTypes.instanceOf(VM) +}; + +const mapStateToProps = state => ({ + editingTarget: state.targets.editingTarget, + sprites: state.targets.sprites, + stage: state.targets.stage, + costumeLibraryVisible: state.modals.costumeLibrary, + backdropLibraryVisible: state.modals.backdropLibrary +}); + +export default connect( + mapStateToProps +)(PaintEditorWrapper); -- GitLab