diff --git a/package.json b/package.json index 0b5f8d28805..32c30f2431a 100644 --- a/package.json +++ b/package.json @@ -107,7 +107,7 @@ "scratch-render": "0.1.0-prerelease.20181102130522", "scratch-storage": "1.2.0", "scratch-svg-renderer": "0.2.0-prerelease.20181101210634", - "scratch-vm": "0.2.0-prerelease.20181113174211", + "scratch-vm": "0.2.0-prerelease.20181114192419", "selenium-webdriver": "3.6.0", "startaudiocontext": "1.2.1", "style-loader": "^0.23.0", diff --git a/src/components/monitor/monitor.jsx b/src/components/monitor/monitor.jsx index 7be0875e5bc..7e6156ff005 100644 --- a/src/components/monitor/monitor.jsx +++ b/src/components/monitor/monitor.jsx @@ -19,7 +19,8 @@ const categories = { sound: '#CF63CF', looks: '#9966FF', motion: '#4C97FF', - list: '#FC662C' + list: '#FC662C', + extension: '#0FBD8C' }; const modes = { @@ -106,7 +107,7 @@ MonitorComponent.propTypes = { }; MonitorComponent.defaultProps = { - category: 'data', + category: 'extension', mode: 'default' }; diff --git a/src/containers/list-monitor.jsx b/src/containers/list-monitor.jsx index f20fd614800..c8d06e511bd 100644 --- a/src/containers/list-monitor.jsx +++ b/src/containers/list-monitor.jsx @@ -6,6 +6,7 @@ import {connect} from 'react-redux'; import {getEventXY} from '../lib/touch-utils'; import {getVariableValue, setVariableValue} from '../lib/variable-utils'; import ListMonitorComponent from '../components/monitor/list-monitor.jsx'; +import {Map} from 'immutable'; class ListMonitor extends React.Component { constructor (props) { @@ -24,7 +25,6 @@ class ListMonitor extends React.Component { this.state = { activeIndex: null, activeValue: null, - // TODO These will need to be sent back to the VM for saving width: props.width || 100, height: props.height || 200 }; @@ -139,9 +139,13 @@ class ListMonitor extends React.Component { const onMouseUp = ev => { onMouseMove(ev); // Make sure width/height are up-to-date - // TODO send these new sizes to the VM for saving window.removeEventListener('mousemove', onMouseMove); window.removeEventListener('mouseup', onMouseUp); + this.props.vm.runtime.requestUpdateMonitor(Map({ + id: this.props.id, + height: this.state.height, + width: this.state.width + })); }; window.addEventListener('mousemove', onMouseMove); diff --git a/src/containers/monitor.jsx b/src/containers/monitor.jsx index 2f04cb51b7f..0a02e826856 100644 --- a/src/containers/monitor.jsx +++ b/src/containers/monitor.jsx @@ -7,6 +7,7 @@ import MonitorComponent, {monitorModes} from '../components/monitor/monitor.jsx' import {addMonitorRect, getInitialPosition, resizeMonitorRect, removeMonitorRect} from '../reducers/monitor-layout'; import {connect} from 'react-redux'; +import {Map} from 'immutable'; import VM from 'scratch-vm'; const availableModes = opcode => ( @@ -31,16 +32,17 @@ class Monitor extends React.Component { 'handleSetModeToSlider', 'setElement' ]); - - // @todo consume from VM, but need to store until there are APIs to update vm - this.state = { - mode: props.mode || 'default' - }; } componentDidMount () { let rect; + + const isNum = num => typeof num === 'number' && !isNaN(num); + // Load the VM provided position if not loaded already - if (this.props.x && this.props.y && !this.props.monitorLayout.savedMonitorPositions[this.props.id]) { + // If a monitor has numbers for the x and y positions, load the saved position. + // Otherwise, auto-position the monitor. + if (isNum(this.props.x) && isNum(this.props.y) && + !this.props.monitorLayout.savedMonitorPositions[this.props.id]) { rect = { upperStart: {x: this.props.x, y: this.props.y}, lowerEnd: {x: this.props.x + this.element.offsetWidth, y: this.props.y + this.element.offsetHeight} @@ -50,6 +52,11 @@ class Monitor extends React.Component { rect = getInitialPosition( this.props.monitorLayout, this.props.id, this.element.offsetWidth, this.element.offsetHeight); this.props.addMonitorRect(this.props.id, rect); + this.props.vm.runtime.requestUpdateMonitor(Map({ + id: this.props.id, + x: rect.upperStart.x, + y: rect.upperStart.y + })); } this.element.style.top = `${rect.upperStart.y}px`; this.element.style.left = `${rect.upperStart.x}px`; @@ -74,25 +81,45 @@ class Monitor extends React.Component { this.props.removeMonitorRect(this.props.id); } handleDragEnd (e, {x, y}) { + const newX = parseInt(this.element.style.left, 10) + x; + const newY = parseInt(this.element.style.top, 10) + y; this.props.onDragEnd( this.props.id, - parseInt(this.element.style.left, 10) + x, - parseInt(this.element.style.top, 10) + y + newX, + newY ); + this.props.vm.runtime.requestUpdateMonitor(Map({ + id: this.props.id, + x: newX, + y: newY + })); } handleNextMode () { const modes = availableModes(this.props.opcode); - const modeIndex = modes.indexOf(this.state.mode); - this.setState({mode: modes[(modeIndex + 1) % modes.length]}); + const modeIndex = modes.indexOf(this.props.mode); + const newMode = modes[(modeIndex + 1) % modes.length]; + this.props.vm.runtime.requestUpdateMonitor(Map({ + id: this.props.id, + mode: newMode + })); } handleSetModeToDefault () { - this.setState({mode: 'default'}); + this.props.vm.runtime.requestUpdateMonitor(Map({ + id: this.props.id, + mode: 'default' + })); } handleSetModeToLarge () { - this.setState({mode: 'large'}); + this.props.vm.runtime.requestUpdateMonitor(Map({ + id: this.props.id, + mode: 'large' + })); } handleSetModeToSlider () { - this.setState({mode: 'slider'}); + this.props.vm.runtime.requestUpdateMonitor(Map({ + id: this.props.id, + mode: 'slider' + })); } setElement (monitorElt) { this.element = monitorElt; @@ -108,7 +135,7 @@ class Monitor extends React.Component { height={this.props.height} max={this.props.max} min={this.props.min} - mode={this.state.mode} + mode={this.props.mode} targetId={this.props.targetId} width={this.props.width} onDragEnd={this.handleDragEnd} diff --git a/src/lib/opcode-labels.js b/src/lib/opcode-labels.js index 03c7e6ef969..a916fba9397 100644 --- a/src/lib/opcode-labels.js +++ b/src/lib/opcode-labels.js @@ -238,7 +238,7 @@ class OpcodeLabels { getLabel (opcode) { if (opcode in this._opcodeMap) return this._opcodeMap[opcode]; return { - category: 'data', + category: 'extension', label: opcode }; }