diff --git a/src/containers/controls.jsx b/src/containers/controls.jsx index 1b4637d9900f3b929eb0f9a810d6dd830b5bbdfc..7cc52870fea7dad1e58b168d406019a4a4549162 100644 --- a/src/containers/controls.jsx +++ b/src/containers/controls.jsx @@ -2,6 +2,7 @@ import bindAll from 'lodash.bindall'; import PropTypes from 'prop-types'; import React from 'react'; import VM from 'scratch-vm'; +import {connect} from 'react-redux'; import analytics from '../lib/analytics'; import ControlsComponent from '../components/controls/controls.jsx'; @@ -11,34 +12,13 @@ class Controls extends React.Component { super(props); bindAll(this, [ 'handleGreenFlagClick', - 'handleStopAllClick', - 'onProjectRunStart', - 'onProjectRunStop' + 'handleStopAllClick' ]); - this.state = { - projectRunning: false, - turbo: false - }; - } - componentDidMount () { - this.props.vm.addListener('PROJECT_RUN_START', this.onProjectRunStart); - this.props.vm.addListener('PROJECT_RUN_STOP', this.onProjectRunStop); - } - componentWillUnmount () { - this.props.vm.removeListener('PROJECT_RUN_START', this.onProjectRunStart); - this.props.vm.removeListener('PROJECT_RUN_STOP', this.onProjectRunStop); - } - onProjectRunStart () { - this.setState({projectRunning: true}); - } - onProjectRunStop () { - this.setState({projectRunning: false}); } handleGreenFlagClick (e) { e.preventDefault(); if (e.shiftKey) { - this.setState({turbo: !this.state.turbo}); - this.props.vm.setTurboMode(!this.state.turbo); + this.props.vm.setTurboMode(!this.props.turbo); } else { this.props.vm.greenFlag(); analytics.event({ @@ -58,13 +38,15 @@ class Controls extends React.Component { render () { const { vm, // eslint-disable-line no-unused-vars + projectRunning, + turbo, ...props } = this.props; return ( <ControlsComponent {...props} - active={this.state.projectRunning} - turbo={this.state.turbo} + active={projectRunning} + turbo={turbo} onGreenFlagClick={this.handleGreenFlagClick} onStopAllClick={this.handleStopAllClick} /> @@ -73,7 +55,14 @@ class Controls extends React.Component { } Controls.propTypes = { + projectRunning: PropTypes.bool.isRequired, + turbo: PropTypes.bool.isRequired, vm: PropTypes.instanceOf(VM) }; -export default Controls; +const mapStateToProps = state => ({ + projectRunning: state.scratchGui.vmStatus.running, + turbo: state.scratchGui.vmStatus.turbo +}); + +export default connect(mapStateToProps)(Controls); diff --git a/src/lib/vm-listener-hoc.jsx b/src/lib/vm-listener-hoc.jsx index 28f578b371b89bb717cf8dffa01c4a752530d464..b2256b82a4ace77d8d2bec3a426bb02852cd3464 100644 --- a/src/lib/vm-listener-hoc.jsx +++ b/src/lib/vm-listener-hoc.jsx @@ -8,6 +8,7 @@ import {connect} from 'react-redux'; import {updateTargets} from '../reducers/targets'; import {updateBlockDrag} from '../reducers/block-drag'; import {updateMonitors} from '../reducers/monitors'; +import {setRunningState, setTurboState} from '../reducers/vm-status'; /* * Higher Order Component to manage events emitted by the VM @@ -31,6 +32,10 @@ const vmListenerHOC = function (WrappedComponent) { this.props.vm.on('targetsUpdate', this.props.onTargetsUpdate); this.props.vm.on('MONITORS_UPDATE', this.props.onMonitorsUpdate); this.props.vm.on('BLOCK_DRAG_UPDATE', this.props.onBlockDragUpdate); + this.props.vm.on('TURBO_MODE_ON', this.props.onTurboModeOn); + this.props.vm.on('TURBO_MODE_OFF', this.props.onTurboModeOff); + this.props.vm.on('PROJECT_RUN_START', this.props.onProjectRunStart); + this.props.vm.on('PROJECT_RUN_STOP', this.props.onProjectRunStop); } componentDidMount () { if (this.props.attachKeyboardEvents) { @@ -96,7 +101,11 @@ const vmListenerHOC = function (WrappedComponent) { onKeyDown: PropTypes.func, onKeyUp: PropTypes.func, onMonitorsUpdate: PropTypes.func.isRequired, + onProjectRunStart: PropTypes.func.isRequired, + onProjectRunStop: PropTypes.func.isRequired, onTargetsUpdate: PropTypes.func.isRequired, + onTurboModeOff: PropTypes.func.isRequired, + onTurboModeOn: PropTypes.func.isRequired, username: PropTypes.string, vm: PropTypes.instanceOf(VM).isRequired }; @@ -117,7 +126,11 @@ const vmListenerHOC = function (WrappedComponent) { }, onBlockDragUpdate: areBlocksOverGui => { dispatch(updateBlockDrag(areBlocksOverGui)); - } + }, + onProjectRunStart: () => dispatch(setRunningState(true)), + onProjectRunStop: () => dispatch(setRunningState(false)), + onTurboModeOn: () => dispatch(setTurboState(true)), + onTurboModeOff: () => dispatch(setTurboState(false)) }); return connect( mapStateToProps, diff --git a/src/reducers/gui.js b/src/reducers/gui.js index 7d98ae2f3f74a757bc101910bbabe6fd491fc192..2c5642416a52b1e65a4324fee3ad0019ffb52e8b 100644 --- a/src/reducers/gui.js +++ b/src/reducers/gui.js @@ -15,6 +15,7 @@ import stageSizeReducer, {stageSizeInitialState} from './stage-size'; import targetReducer, {targetsInitialState} from './targets'; import toolboxReducer, {toolboxInitialState} from './toolbox'; import vmReducer, {vmInitialState} from './vm'; +import vmStatusReducer, {vmStatusInitialState} from './vm-status'; import throttle from 'redux-throttle'; const guiMiddleware = compose(applyMiddleware(throttle(300, {leading: true, trailing: true}))); @@ -35,7 +36,8 @@ const guiInitialState = { monitorLayout: monitorLayoutInitialState, targets: targetsInitialState, toolbox: toolboxInitialState, - vm: vmInitialState + vm: vmInitialState, + vmStatus: vmStatusInitialState }; const initPlayer = function (currentState) { @@ -75,7 +77,8 @@ const guiReducer = combineReducers({ monitorLayout: monitorLayoutReducer, targets: targetReducer, toolbox: toolboxReducer, - vm: vmReducer + vm: vmReducer, + vmStatus: vmStatusReducer }); export { diff --git a/src/reducers/vm-status.js b/src/reducers/vm-status.js new file mode 100644 index 0000000000000000000000000000000000000000..8e965199232d322d386ce53c3f57fb243be6151c --- /dev/null +++ b/src/reducers/vm-status.js @@ -0,0 +1,44 @@ +const SET_RUNNING_STATE = 'scratch-gui/vm-status/SET_RUNNING_STATE'; +const SET_TURBO_STATE = 'scratch-gui/vm-status/SET_TURBO_STATE'; + +const initialState = { + running: false, + turbo: false +}; + +const reducer = function (state, action) { + if (typeof state === 'undefined') state = initialState; + switch (action.type) { + case SET_RUNNING_STATE: + return Object.assign({}, state, { + running: action.running + }); + case SET_TURBO_STATE: + return Object.assign({}, state, { + turbo: action.turbo + }); + default: + return state; + } +}; + +const setRunningState = function (running) { + return { + type: SET_RUNNING_STATE, + running: running + }; +}; + +const setTurboState = function (turbo) { + return { + type: SET_TURBO_STATE, + turbo: turbo + }; +}; + +export { + reducer as default, + initialState as vmStatusInitialState, + setRunningState, + setTurboState +};