Skip to content
Snippets Groups Projects
Unverified Commit 1f23d093 authored by Paul Kaplan's avatar Paul Kaplan Committed by GitHub
Browse files

Merge pull request #2767 from paulkaplan/turbo-events

Turbo mode menu 
parents 0683d51b 0dff636a
No related branches found
No related tags found
No related merge requests found
...@@ -14,6 +14,7 @@ import ProjectLoader from '../../containers/project-loader.jsx'; ...@@ -14,6 +14,7 @@ import ProjectLoader from '../../containers/project-loader.jsx';
import Menu from '../../containers/menu.jsx'; import Menu from '../../containers/menu.jsx';
import {MenuItem, MenuSection} from '../menu/menu.jsx'; import {MenuItem, MenuSection} from '../menu/menu.jsx';
import ProjectSaver from '../../containers/project-saver.jsx'; import ProjectSaver from '../../containers/project-saver.jsx';
import TurboMode from '../../containers/turbo-mode.jsx';
import {openTipsLibrary} from '../../reducers/modals'; import {openTipsLibrary} from '../../reducers/modals';
import {setPlayer} from '../../reducers/mode'; import {setPlayer} from '../../reducers/mode';
...@@ -297,15 +298,23 @@ class MenuBar extends React.Component { ...@@ -297,15 +298,23 @@ class MenuBar extends React.Component {
</MenuItem> </MenuItem>
</MenuItemTooltip> </MenuItemTooltip>
<MenuSection> <MenuSection>
<MenuItemTooltip id="turbo"> <TurboMode>{(toggleTurboMode, {turboMode}) => (
<MenuItem> <MenuItem onClick={toggleTurboMode}>
<FormattedMessage {turboMode ? (
defaultMessage="Turbo mode" <FormattedMessage
description="Menu bar item for toggling turbo mode" defaultMessage="Turn off Turbo Mode"
id="gui.menuBar.turboMode" description="Menu bar item for turning off turbo mode"
/> id="gui.menuBar.turboModeOff"
/>
) : (
<FormattedMessage
defaultMessage="Turn on Turbo Mode"
description="Menu bar item for turning on turbo mode"
id="gui.menuBar.turboModeOn"
/>
)}
</MenuItem> </MenuItem>
</MenuItemTooltip> )}</TurboMode>
</MenuSection> </MenuSection>
</MenuBarMenu> </MenuBarMenu>
</div> </div>
......
...@@ -2,6 +2,7 @@ import bindAll from 'lodash.bindall'; ...@@ -2,6 +2,7 @@ import bindAll from 'lodash.bindall';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import React from 'react'; import React from 'react';
import VM from 'scratch-vm'; import VM from 'scratch-vm';
import {connect} from 'react-redux';
import analytics from '../lib/analytics'; import analytics from '../lib/analytics';
import ControlsComponent from '../components/controls/controls.jsx'; import ControlsComponent from '../components/controls/controls.jsx';
...@@ -11,34 +12,13 @@ class Controls extends React.Component { ...@@ -11,34 +12,13 @@ class Controls extends React.Component {
super(props); super(props);
bindAll(this, [ bindAll(this, [
'handleGreenFlagClick', 'handleGreenFlagClick',
'handleStopAllClick', 'handleStopAllClick'
'onProjectRunStart',
'onProjectRunStop'
]); ]);
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) { handleGreenFlagClick (e) {
e.preventDefault(); e.preventDefault();
if (e.shiftKey) { if (e.shiftKey) {
this.setState({turbo: !this.state.turbo}); this.props.vm.setTurboMode(!this.props.turbo);
this.props.vm.setTurboMode(!this.state.turbo);
} else { } else {
this.props.vm.greenFlag(); this.props.vm.greenFlag();
analytics.event({ analytics.event({
...@@ -58,13 +38,15 @@ class Controls extends React.Component { ...@@ -58,13 +38,15 @@ class Controls extends React.Component {
render () { render () {
const { const {
vm, // eslint-disable-line no-unused-vars vm, // eslint-disable-line no-unused-vars
projectRunning,
turbo,
...props ...props
} = this.props; } = this.props;
return ( return (
<ControlsComponent <ControlsComponent
{...props} {...props}
active={this.state.projectRunning} active={projectRunning}
turbo={this.state.turbo} turbo={turbo}
onGreenFlagClick={this.handleGreenFlagClick} onGreenFlagClick={this.handleGreenFlagClick}
onStopAllClick={this.handleStopAllClick} onStopAllClick={this.handleStopAllClick}
/> />
...@@ -73,7 +55,14 @@ class Controls extends React.Component { ...@@ -73,7 +55,14 @@ class Controls extends React.Component {
} }
Controls.propTypes = { Controls.propTypes = {
projectRunning: PropTypes.bool.isRequired,
turbo: PropTypes.bool.isRequired,
vm: PropTypes.instanceOf(VM) 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);
import bindAll from 'lodash.bindall';
import PropTypes from 'prop-types';
import React from 'react';
import {connect} from 'react-redux';
/**
* Turbo Mode component passes toggleTurboMode function to its child.
* It also includes `turboMode` in the props passed to the children.
* It expects this child to be a function with the signature
* function (toggleTurboMode, {turboMode, ...props}) {}
* The component can then be used to attach turbo mode setting functionality
* to any other component:
*
* <TurboMode>{(toggleTurboMode, props) => (
* <MyCoolComponent
* turboEnabled={props.turboMode}
* onClick={toggleTurboMode}
* {...props}
* />
* )}</TurboMode>
*/
class TurboMode extends React.Component {
constructor (props) {
super(props);
bindAll(this, [
'toggleTurboMode'
]);
}
toggleTurboMode () {
this.props.vm.setTurboMode(!this.props.turboMode);
}
render () {
const {
/* eslint-disable no-unused-vars */
children,
vm,
/* eslint-enable no-unused-vars */
...props
} = this.props;
return this.props.children(this.toggleTurboMode, props);
}
}
TurboMode.propTypes = {
children: PropTypes.func,
turboMode: PropTypes.bool,
vm: PropTypes.shape({
setTurboMode: PropTypes.func
})
};
const mapStateToProps = state => ({
vm: state.scratchGui.vm,
turboMode: state.scratchGui.vmStatus.turbo
});
export default connect(
mapStateToProps,
() => ({}) // omit dispatch prop
)(TurboMode);
...@@ -8,6 +8,7 @@ import {connect} from 'react-redux'; ...@@ -8,6 +8,7 @@ import {connect} from 'react-redux';
import {updateTargets} from '../reducers/targets'; import {updateTargets} from '../reducers/targets';
import {updateBlockDrag} from '../reducers/block-drag'; import {updateBlockDrag} from '../reducers/block-drag';
import {updateMonitors} from '../reducers/monitors'; import {updateMonitors} from '../reducers/monitors';
import {setRunningState, setTurboState} from '../reducers/vm-status';
/* /*
* Higher Order Component to manage events emitted by the VM * Higher Order Component to manage events emitted by the VM
...@@ -31,6 +32,10 @@ const vmListenerHOC = function (WrappedComponent) { ...@@ -31,6 +32,10 @@ const vmListenerHOC = function (WrappedComponent) {
this.props.vm.on('targetsUpdate', this.props.onTargetsUpdate); this.props.vm.on('targetsUpdate', this.props.onTargetsUpdate);
this.props.vm.on('MONITORS_UPDATE', this.props.onMonitorsUpdate); this.props.vm.on('MONITORS_UPDATE', this.props.onMonitorsUpdate);
this.props.vm.on('BLOCK_DRAG_UPDATE', this.props.onBlockDragUpdate); 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 () { componentDidMount () {
if (this.props.attachKeyboardEvents) { if (this.props.attachKeyboardEvents) {
...@@ -96,7 +101,11 @@ const vmListenerHOC = function (WrappedComponent) { ...@@ -96,7 +101,11 @@ const vmListenerHOC = function (WrappedComponent) {
onKeyDown: PropTypes.func, onKeyDown: PropTypes.func,
onKeyUp: PropTypes.func, onKeyUp: PropTypes.func,
onMonitorsUpdate: PropTypes.func.isRequired, onMonitorsUpdate: PropTypes.func.isRequired,
onProjectRunStart: PropTypes.func.isRequired,
onProjectRunStop: PropTypes.func.isRequired,
onTargetsUpdate: PropTypes.func.isRequired, onTargetsUpdate: PropTypes.func.isRequired,
onTurboModeOff: PropTypes.func.isRequired,
onTurboModeOn: PropTypes.func.isRequired,
username: PropTypes.string, username: PropTypes.string,
vm: PropTypes.instanceOf(VM).isRequired vm: PropTypes.instanceOf(VM).isRequired
}; };
...@@ -117,7 +126,11 @@ const vmListenerHOC = function (WrappedComponent) { ...@@ -117,7 +126,11 @@ const vmListenerHOC = function (WrappedComponent) {
}, },
onBlockDragUpdate: areBlocksOverGui => { onBlockDragUpdate: areBlocksOverGui => {
dispatch(updateBlockDrag(areBlocksOverGui)); dispatch(updateBlockDrag(areBlocksOverGui));
} },
onProjectRunStart: () => dispatch(setRunningState(true)),
onProjectRunStop: () => dispatch(setRunningState(false)),
onTurboModeOn: () => dispatch(setTurboState(true)),
onTurboModeOff: () => dispatch(setTurboState(false))
}); });
return connect( return connect(
mapStateToProps, mapStateToProps,
......
...@@ -15,6 +15,7 @@ import stageSizeReducer, {stageSizeInitialState} from './stage-size'; ...@@ -15,6 +15,7 @@ import stageSizeReducer, {stageSizeInitialState} from './stage-size';
import targetReducer, {targetsInitialState} from './targets'; import targetReducer, {targetsInitialState} from './targets';
import toolboxReducer, {toolboxInitialState} from './toolbox'; import toolboxReducer, {toolboxInitialState} from './toolbox';
import vmReducer, {vmInitialState} from './vm'; import vmReducer, {vmInitialState} from './vm';
import vmStatusReducer, {vmStatusInitialState} from './vm-status';
import throttle from 'redux-throttle'; import throttle from 'redux-throttle';
const guiMiddleware = compose(applyMiddleware(throttle(300, {leading: true, trailing: true}))); const guiMiddleware = compose(applyMiddleware(throttle(300, {leading: true, trailing: true})));
...@@ -35,7 +36,8 @@ const guiInitialState = { ...@@ -35,7 +36,8 @@ const guiInitialState = {
monitorLayout: monitorLayoutInitialState, monitorLayout: monitorLayoutInitialState,
targets: targetsInitialState, targets: targetsInitialState,
toolbox: toolboxInitialState, toolbox: toolboxInitialState,
vm: vmInitialState vm: vmInitialState,
vmStatus: vmStatusInitialState
}; };
const initPlayer = function (currentState) { const initPlayer = function (currentState) {
...@@ -75,7 +77,8 @@ const guiReducer = combineReducers({ ...@@ -75,7 +77,8 @@ const guiReducer = combineReducers({
monitorLayout: monitorLayoutReducer, monitorLayout: monitorLayoutReducer,
targets: targetReducer, targets: targetReducer,
toolbox: toolboxReducer, toolbox: toolboxReducer,
vm: vmReducer vm: vmReducer,
vmStatus: vmStatusReducer
}); });
export { export {
......
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
};
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment