From 3fdbfa85e2055e0ee92a1960f3dbc27b39588cab Mon Sep 17 00:00:00 2001 From: BryceLTaylor Date: Wed, 9 May 2018 15:59:48 -0400 Subject: [PATCH 01/23] Add instructions to PR template browser coverage section --- .github/PULL_REQUEST_TEMPLATE.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md index 0b7c6752b..f502d934a 100644 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -15,6 +15,8 @@ _Explain why these changes should be made_ _Please show how you have added tests to cover your changes_ ### Browser Coverage +Check the OS/browser combinations tested (At least 2) + Mac * [ ] Chrome * [ ] Firefox From 98999ab852eeddc7d816ca9054f5e9703d050b50 Mon Sep 17 00:00:00 2001 From: DD Date: Thu, 10 May 2018 11:01:43 -0400 Subject: [PATCH 02/23] Send svg renderer to vm --- src/containers/stage.jsx | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/containers/stage.jsx b/src/containers/stage.jsx index 57614135f..2bdaa8208 100644 --- a/src/containers/stage.jsx +++ b/src/containers/stage.jsx @@ -7,6 +7,7 @@ import {connect} from 'react-redux'; import {getEventXY} from '../lib/touch-utils'; import VideoProvider from '../lib/video/video-provider'; +import {SVGRenderer as V2SVGAdapter} from 'scratch-svg-renderer'; import StageComponent from '../components/stage/stage.jsx'; @@ -57,6 +58,7 @@ class Stage extends React.Component { this.updateRect(); this.renderer = new Renderer(this.canvas); this.props.vm.attachRenderer(this.renderer); + this.props.vm.attachV2SVGAdapter(new V2SVGAdapter()); this.props.vm.runtime.addListener('QUESTION', this.questionListener); this.props.vm.setVideoProvider(new VideoProvider()); } From b0dd9a9fdbecfc1622dc46da4784b300349c1e50 Mon Sep 17 00:00:00 2001 From: Paul Kaplan Date: Thu, 10 May 2018 10:54:34 -0400 Subject: [PATCH 03/23] Make slider and list monitors update variables in the VM --- src/components/monitor-list/monitor-list.jsx | 1 + src/components/monitor/list-monitor.jsx | 121 +++++++++--- src/components/monitor/monitor.css | 23 +++ src/components/monitor/monitor.jsx | 32 +--- src/components/monitor/slider-monitor.jsx | 5 +- src/containers/list-monitor-row.jsx | 0 src/containers/list-monitor.jsx | 182 +++++++++++++++++++ src/containers/monitor.jsx | 3 +- src/containers/slider-monitor.jsx | 59 ++++++ src/lib/variable-utils.js | 24 +++ 10 files changed, 398 insertions(+), 52 deletions(-) create mode 100644 src/containers/list-monitor-row.jsx create mode 100644 src/containers/list-monitor.jsx create mode 100644 src/containers/slider-monitor.jsx create mode 100644 src/lib/variable-utils.js diff --git a/src/components/monitor-list/monitor-list.jsx b/src/components/monitor-list/monitor-list.jsx index 50263220d..07b6a817b 100644 --- a/src/components/monitor-list/monitor-list.jsx +++ b/src/components/monitor-list/monitor-list.jsx @@ -24,6 +24,7 @@ const MonitorList = props => ( opcode={monitorData.opcode} params={monitorData.params} spriteName={monitorData.spriteName} + targetId={monitorData.targetId} value={monitorData.value} width={monitorData.width} x={monitorData.x} diff --git a/src/components/monitor/list-monitor.jsx b/src/components/monitor/list-monitor.jsx index c50cc5703..e40726043 100644 --- a/src/components/monitor/list-monitor.jsx +++ b/src/components/monitor/list-monitor.jsx @@ -1,8 +1,73 @@ import React from 'react'; import PropTypes from 'prop-types'; +import classNames from 'classnames'; import styles from './monitor.css'; -const ListMonitor = ({categoryColor, label, width, height, value}) => ( + +class ListMonitorRow extends React.Component { + constructor (props) { + super(props); + this.handleActivate = props.onActivate.bind(this, props.index); + } + render () { + return ( +
+
{this.props.index + 1 /* one indexed */}
+
+ {this.props.activeIndex === this.props.index ? ( +
+ +
+ {'✖︎'} +
+
+ + ) : ( +
{this.props.value}
+ )} +
+
+ ); + } +} + +ListMonitorRow.propTypes = { + index: PropTypes.number, + activeIndex: PropTypes.number, + activeValue: PropTypes.string, + value: PropTypes.string, + onRemove: PropTypes.func, + onKeyPress: PropTypes.func, + onFocus: PropTypes.func, + onInput: PropTypes.func, + onDeactivate: PropTypes.func, + categoryColor: PropTypes.string, + onActivate: PropTypes.func, + onKeyPress: PropTypes.func +}; + +const ListMonitor = ({label, width, height, value, onResizeMouseDown, onAdd, ...rowProps}) => (
( {label}
- {!value || value.length === 0 ? ( + {value.length === 0 ? (
- {'(empty)' /* @todo not translating, awaiting design */} + {'(empty)'}
) : value.map((v, i) => ( -
-
{i + 1 /* one indexed */}
-
-
{v}
-
-
+ ))}
-
- {/* @todo add button here */} +
+ {'+' /* TODO waiting on asset */}
- - {value.length} - + {`length ${value.length}`}
-
- {/* @todo resize handle */} +
+ {'=' /* TODO waiting on asset */}
); ListMonitor.propTypes = { + activeIndex: PropTypes.number, categoryColor: PropTypes.string.isRequired, height: PropTypes.number, label: PropTypes.string.isRequired, - value: PropTypes.arrayOf(PropTypes.oneOfType([ + onActivate: PropTypes.func, + value: PropTypes.oneOfType([ PropTypes.string, - PropTypes.number - ])), + PropTypes.number, + PropTypes.arrayOf(PropTypes.oneOfType([ + PropTypes.string, + PropTypes.number + ])) + ]), width: PropTypes.number }; ListMonitor.defaultProps = { - width: 80, + width: 110, height: 200 }; diff --git a/src/components/monitor/monitor.css b/src/components/monitor/monitor.css index 783cec706..078d24104 100644 --- a/src/components/monitor/monitor.css +++ b/src/components/monitor/monitor.css @@ -109,6 +109,7 @@ border-radius: calc($space / 2); border: 1px solid $ui-black-transparent; flex-grow: 1; + height: 22px; } .list-footer { @@ -137,3 +138,25 @@ padding: 3px 5px; min-height: 22px; } + +.list-input { + padding: 3px 5px; + border: 0; + background: rgba(0, 0, 0, 0.1); + color: $ui-white; + outline: none; + font-size: 0.75rem; + font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; +} + +.remove-button { + position: absolute; + top: 4px; + right: 3px; + cursor: pointer; + color: $ui-white; +} + +.add-button { + cursor: pointer; +} diff --git a/src/components/monitor/monitor.jsx b/src/components/monitor/monitor.jsx index 95387a1ec..a45fe5214 100644 --- a/src/components/monitor/monitor.jsx +++ b/src/components/monitor/monitor.jsx @@ -7,8 +7,8 @@ import {ContextMenu, MenuItem} from '../context-menu/context-menu.jsx'; import Box from '../box/box.jsx'; import DefaultMonitor from './default-monitor.jsx'; import LargeMonitor from './large-monitor.jsx'; -import SliderMonitor from './slider-monitor.jsx'; -import ListMonitor from './list-monitor.jsx'; +import SliderMonitor from '../../containers/slider-monitor.jsx'; +import ListMonitor from '../../containers/list-monitor.jsx'; import styles from './monitor.css'; @@ -29,7 +29,10 @@ const modes = { }; const MonitorComponent = props => ( - + ( componentRef={props.componentRef} onDoubleClick={props.mode === 'list' ? null : props.onNextMode} > - {(modes[props.mode] || modes.default)({ // Use default until other modes arrive + {React.createElement(modes[props.mode], { categoryColor: categories[props.category], - label: props.label, - value: props.value, - width: props.width, - height: props.height, - min: props.min, - max: props.max + ...props })} @@ -90,25 +88,13 @@ const monitorModes = Object.keys(modes); MonitorComponent.propTypes = { category: PropTypes.oneOf(Object.keys(categories)), componentRef: PropTypes.func.isRequired, - height: PropTypes.number, label: PropTypes.string.isRequired, - max: PropTypes.number, - min: PropTypes.number, mode: PropTypes.oneOf(monitorModes), onDragEnd: PropTypes.func.isRequired, onNextMode: PropTypes.func.isRequired, onSetModeToDefault: PropTypes.func.isRequired, onSetModeToLarge: PropTypes.func.isRequired, - onSetModeToSlider: PropTypes.func, - value: PropTypes.oneOfType([ - PropTypes.string, - PropTypes.number, - PropTypes.arrayOf(PropTypes.oneOfType([ - PropTypes.string, - PropTypes.number - ])) - ]), - width: PropTypes.number + onSetModeToSlider: PropTypes.func }; MonitorComponent.defaultProps = { diff --git a/src/components/monitor/slider-monitor.jsx b/src/components/monitor/slider-monitor.jsx index a6c410898..f8187cfee 100644 --- a/src/components/monitor/slider-monitor.jsx +++ b/src/components/monitor/slider-monitor.jsx @@ -2,7 +2,7 @@ import React from 'react'; import PropTypes from 'prop-types'; import styles from './monitor.css'; -const SliderMonitor = ({categoryColor, label, min, max, value}) => ( +const SliderMonitor = ({categoryColor, label, min, max, value, onSliderUpdate}) => (
@@ -22,6 +22,7 @@ const SliderMonitor = ({categoryColor, label, min, max, value}) => ( min={min} type="range" value={value} + onChange={onSliderUpdate} // @todo onChange callback />
@@ -34,7 +35,7 @@ SliderMonitor.propTypes = { label: PropTypes.string.isRequired, max: PropTypes.number, min: PropTypes.number, - // @todo callback for change events + onSliderUpdate: PropTypes.func.isRequired, value: PropTypes.oneOfType([ PropTypes.string, PropTypes.number diff --git a/src/containers/list-monitor-row.jsx b/src/containers/list-monitor-row.jsx new file mode 100644 index 000000000..e69de29bb diff --git a/src/containers/list-monitor.jsx b/src/containers/list-monitor.jsx new file mode 100644 index 000000000..3b5384c76 --- /dev/null +++ b/src/containers/list-monitor.jsx @@ -0,0 +1,182 @@ +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 {getEventXY} from '../lib/touch-utils'; +import {getVariableValue, setVariableValue} from '../lib/variable-utils'; +import ListMonitorComponent from '../components/monitor/list-monitor.jsx'; + +class ListMonitor extends React.Component { + constructor (props) { + super(props); + bindAll(this, [ + 'handleActivate', + 'handleDeactivate', + 'handleInput', + 'handleRemove', + 'handleKeyPress', + 'handleFocus', + 'handleAdd', + 'handleResizeMouseDown' + ]); + + this.state = { + activeIndex: null, + activeValue: null, + // TODO These will need to be sent back to the VM for saving + width: props.width || 80, + height: props.height || 200 + }; + } + + handleActivate (index) { + this.setState({ + activeIndex: index, + activeValue: this.props.value[index] + }); + } + + handleDeactivate () { + // Submit any in-progress value edits on blur + if (this.state.activeIndex !== null) { + const {vm, targetId, id: variableId} = this.props; + const newListValue = getVariableValue(vm, targetId, variableId); + newListValue[this.state.activeIndex] = this.state.activeValue; + setVariableValue(vm, targetId, variableId, newListValue); + this.setState({activeIndex: null, activeValue: null}); + } + } + + handleFocus (e) { + // Select all the text in the input when it is focused. + e.target.select(); + } + + handleKeyPress (e) { + // Special case for tab, arrow keys and enter. + // Tab / shift+tab navigate down / up the list. + // Arrow down / arrow up navigate down / up the list. + // Enter / shift+enter insert new blank item below / above. + const previouslyActiveIndex = this.state.activeIndex; + const {vm, targetId, id: variableId} = this.props; + + let navigateDirection = 0; + if (e.key === 'Tab') navigateDirection = e.shiftKey ? -1 : 1; + else if (e.key === 'ArrowUp') navigateDirection = -1; + else if (e.key === 'ArrowDown') navigateDirection = 1; + if (navigateDirection) { + this.handleDeactivate(); // Submit in-progress edits + const newIndex = (previouslyActiveIndex + navigateDirection) % this.props.value.length; + this.setState({ + activeIndex: newIndex, + activeValue: this.props.value[newIndex] + }); + e.preventDefault(); // Stop default tab behavior, handled by this state change + } else if (e.key === 'Enter') { + this.handleDeactivate(); // Submit in-progress edits + const newListItemValue = ''; // Enter adds a blank item + const newValueOffset = e.shiftKey ? 0 : 1; // Shift-enter inserts above + const listValue = getVariableValue(vm, targetId, variableId); + const newListValue = listValue.slice(0, previouslyActiveIndex + newValueOffset) + .concat([newListItemValue]) + .concat(listValue.slice(previouslyActiveIndex + newValueOffset)); + setVariableValue(vm, targetId, variableId, newListValue); + const newIndex = (previouslyActiveIndex + newValueOffset) % newListValue.length; + this.setState({ + activeIndex: newIndex, + activeValue: newListItemValue + }); + } + } + + handleInput (e) { + this.setState({activeValue: e.target.value}); + } + + handleRemove (e) { + e.preventDefault(); // Default would blur input, prevent that. + const {vm, targetId, id: variableId} = this.props; + const listValue = getVariableValue(vm, targetId, variableId); + const newListValue = listValue.slice(0, this.state.activeIndex) + .concat(listValue.slice(this.state.activeIndex + 1)); + setVariableValue(vm, targetId, variableId, newListValue); + // Selecting the next active is handled when event bubbles up to activate + } + + handleAdd () { + // Add button appends a blank value and switches to it + const {vm, targetId, id: variableId} = this.props; + const newListValue = getVariableValue(vm, targetId, variableId).concat(['']); + setVariableValue(vm, targetId, variableId, newListValue); + this.setState({activeIndex: newListValue.length - 1, activeValue: ''}); + } + + handleResizeMouseDown (e) { + this.initialPosition = getEventXY(e); + this.initialWidth = this.state.width; + this.initialHeight = this.state.height; + + const onMouseMove = ev => { + const newPosition = getEventXY(ev); + const dx = newPosition.x - this.initialPosition.x; + const dy = newPosition.y - this.initialPosition.y; + this.setState({ + width: Math.min(this.initialWidth + dx, 480), + height: Math.max(Math.min(this.initialHeight + dy, 360), 60) + }); + }; + + 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); + }; + + window.addEventListener('mousemove', onMouseMove); + window.addEventListener('mouseup', onMouseUp); + + } + render () { + const { + vm, // eslint-disable-line no-unused-vars + ...props + } = this.props; + return ( + + ); + } +} + +ListMonitor.propTypes = { + value: PropTypes.oneOfType([ + PropTypes.number, + PropTypes.string + ]), + vm: PropTypes.instanceOf(VM), + targetId: PropTypes.string, + id: PropTypes.string, + height: PropTypes.number, + width: PropTypes.number, + x: PropTypes.number, + y: PropTypes.number +}; + +const mapStateToProps = state => ({vm: state.vm}); + +export default connect(mapStateToProps)(ListMonitor); diff --git a/src/containers/monitor.jsx b/src/containers/monitor.jsx index cdb87f20e..c39b56302 100644 --- a/src/containers/monitor.jsx +++ b/src/containers/monitor.jsx @@ -107,12 +107,13 @@ class Monitor extends React.Component { max={this.props.max} min={this.props.min} mode={this.state.mode} - width={this.props.width} onDragEnd={this.handleDragEnd} onNextMode={this.handleNextMode} onSetModeToDefault={this.handleSetModeToDefault} onSetModeToLarge={this.handleSetModeToLarge} onSetModeToSlider={showSliderOption ? this.handleSetModeToSlider : null} + targetId={this.props.targetId} + width={this.props.width} /> ); } diff --git a/src/containers/slider-monitor.jsx b/src/containers/slider-monitor.jsx new file mode 100644 index 000000000..8df6f92a9 --- /dev/null +++ b/src/containers/slider-monitor.jsx @@ -0,0 +1,59 @@ +import bindAll from 'lodash.bindall'; +import PropTypes from 'prop-types'; +import React from 'react'; +import VM from 'scratch-vm'; +import {setVariableValue} from '../lib/variable-utils'; +import {connect} from 'react-redux'; + +import SliderMonitorComponent from '../components/monitor/slider-monitor.jsx'; + +class SliderMonitor extends React.Component { + constructor (props) { + super(props); + bindAll(this, [ + 'handleSliderUpdate' + ]); + + this.state = { + value: Number(props.value) + }; + } + componentWillReceiveProps (nextProps) { + if (this.state.value !== nextProps.value) { + this.setState({value: nextProps.value}); + } + } + handleSliderUpdate (e) { + this.setState({value: Number(e.target.value)}); + const {vm, targetId, id: variableId} = this.props; + setVariableValue(vm, targetId, variableId, Number(e.target.value)); + } + render () { + const { + vm, // eslint-disable-line no-unused-vars + value, // eslint-disable-line no-unused-vars + ...props + } = this.props; + return ( + + ); + } +} + +SliderMonitor.propTypes = { + id: PropTypes.string, + targetId: PropTypes.string, + value: PropTypes.oneOfType([ + PropTypes.number, + PropTypes.string + ]), + vm: PropTypes.instanceOf(VM) +}; + +const mapStateToProps = state => ({vm: state.vm}); + +export default connect(mapStateToProps)(SliderMonitor); diff --git a/src/lib/variable-utils.js b/src/lib/variable-utils.js new file mode 100644 index 000000000..29eacd617 --- /dev/null +++ b/src/lib/variable-utils.js @@ -0,0 +1,24 @@ +// Utility functions for updating variables in the VM +// TODO these should be moved to top-level VM API +const getVariable = (vm, targetId, variableId) => { + const target = targetId ? + vm.runtime.getTargetById(targetId) : + vm.runtime.getTargetForStage(); + return target.variables[variableId]; +}; + +const getVariableValue = (vm, targetId, variableId) => { + const variable = getVariable(vm, targetId, variableId); + // If array, return a new copy for mutating, ensuring that updates stay immutable. + if (variable.value instanceof Array) return variable.value.slice(); + return variable.value; +}; + +const setVariableValue = (vm, targetId, variableId, value) => { + getVariable(vm, targetId, variableId).value = value; +}; + +export { + getVariableValue, + setVariableValue +}; From 4d73709aa619779f6ae76b8644ca221d7b6f986b Mon Sep 17 00:00:00 2001 From: Paul Kaplan Date: Thu, 10 May 2018 13:18:13 -0400 Subject: [PATCH 04/23] Use a virtualized list to handle huge list editing --- package.json | 1 + .../monitor/list-monitor-scroller.jsx | 109 ++++++++++++++++++ src/components/monitor/list-monitor.jsx | 89 ++------------ src/containers/list-monitor.jsx | 3 +- 4 files changed, 123 insertions(+), 79 deletions(-) create mode 100644 src/components/monitor/list-monitor-scroller.jsx diff --git a/package.json b/package.json index cad8ee262..0def7bc26 100644 --- a/package.json +++ b/package.json @@ -84,6 +84,7 @@ "react-tabs": "2.2.1", "react-test-renderer": "16.2.0", "react-tooltip": "3.4.0", + "react-virtualized": "^9.18.5", "redux": "3.7.2", "redux-mock-store": "^1.2.3", "redux-throttle": "0.1.1", diff --git a/src/components/monitor/list-monitor-scroller.jsx b/src/components/monitor/list-monitor-scroller.jsx new file mode 100644 index 000000000..26676f4c1 --- /dev/null +++ b/src/components/monitor/list-monitor-scroller.jsx @@ -0,0 +1,109 @@ +import React from 'react'; +import PropTypes from 'prop-types'; +import classNames from 'classnames'; +import bindAll from 'lodash.bindall'; + +import styles from './monitor.css'; +import {List} from 'react-virtualized'; + +class ListMonitorScroller extends React.Component { + constructor (props) { + super(props); + bindAll(this, [ + 'rowRenderer', + 'noRowsRenderer', + 'handleEventFactory' + ]); + } + handleEventFactory (index) { + return () => this.props.onActivate(index); + } + noRowsRenderer () { + return ( +
+ {'(empty)' /* TODO waiting for design before translation */} +
+ ); + } + rowRenderer ({index, key, style}) { + return ( +
+
{index + 1 /* one indexed */}
+
+ {this.props.activeIndex === index ? ( +
+ +
+ {'✖︎'} +
+
+ + ) : ( +
{this.props.values[index]}
+ )} +
+
+ ); + } + render () { + const {height, values, width, activeIndex, activeValue} = this.props; + // Keep the active index in view if defined, else must be undefined for List component + const scrollToIndex = activeIndex === null ? undefined : activeIndex; /* eslint-disable-line no-undefined */ + return ( + + ); + } +} + +ListMonitorScroller.propTypes = { + activeIndex: PropTypes.number, + activeValue: PropTypes.string, + categoryColor: PropTypes.string, + height: PropTypes.number, + onActivate: PropTypes.func, + onDeactivate: PropTypes.func, + onFocus: PropTypes.func, + onInput: PropTypes.func, + onKeyPress: PropTypes.func, + onRemove: PropTypes.func, + values: PropTypes.arrayOf(PropTypes.oneOfType([ + PropTypes.string, + PropTypes.number + ])), + width: PropTypes.number +}; +export default ListMonitorScroller; diff --git a/src/components/monitor/list-monitor.jsx b/src/components/monitor/list-monitor.jsx index e40726043..a29afa283 100644 --- a/src/components/monitor/list-monitor.jsx +++ b/src/components/monitor/list-monitor.jsx @@ -2,95 +2,26 @@ import React from 'react'; import PropTypes from 'prop-types'; import classNames from 'classnames'; import styles from './monitor.css'; - - -class ListMonitorRow extends React.Component { - constructor (props) { - super(props); - this.handleActivate = props.onActivate.bind(this, props.index); - } - render () { - return ( -
-
{this.props.index + 1 /* one indexed */}
-
- {this.props.activeIndex === this.props.index ? ( -
- -
- {'✖︎'} -
-
- - ) : ( -
{this.props.value}
- )} -
-
- ); - } -} - -ListMonitorRow.propTypes = { - index: PropTypes.number, - activeIndex: PropTypes.number, - activeValue: PropTypes.string, - value: PropTypes.string, - onRemove: PropTypes.func, - onKeyPress: PropTypes.func, - onFocus: PropTypes.func, - onInput: PropTypes.func, - onDeactivate: PropTypes.func, - categoryColor: PropTypes.string, - onActivate: PropTypes.func, - onKeyPress: PropTypes.func -}; +import ListMonitorScroller from './list-monitor-scroller.jsx'; const ListMonitor = ({label, width, height, value, onResizeMouseDown, onAdd, ...rowProps}) => (
{label}
- {value.length === 0 ? ( -
- {'(empty)'} -
- ) : value.map((v, i) => ( - - ))} +
Date: Thu, 10 May 2018 14:32:41 -0400 Subject: [PATCH 05/23] Fix uint16 sound loading error --- src/lib/default-project/index.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/lib/default-project/index.js b/src/lib/default-project/index.js index 4f4b3f113..f1cacd365 100644 --- a/src/lib/default-project/index.js +++ b/src/lib/default-project/index.js @@ -19,12 +19,12 @@ export default [{ id: '83a9787d4cb6f3b7632b4ddfebf74367', assetType: 'Sound', dataFormat: 'WAV', - data: new Uint16Array(popWav) + data: new Uint8Array(popWav) }, { id: '83c36d806dc92327b9e7049a565c6bff', assetType: 'Sound', dataFormat: 'WAV', - data: new Uint16Array(meowWav) + data: new Uint8Array(meowWav) }, { id: '739b5e2a2435f6e1ec2993791b423146', assetType: 'ImageBitmap', From de6637e4915376b007269e18a2f09ca6b4632d2f Mon Sep 17 00:00:00 2001 From: Paul Kaplan Date: Thu, 10 May 2018 14:50:08 -0400 Subject: [PATCH 06/23] Fix linting --- src/containers/list-monitor.jsx | 6 +++--- src/containers/monitor.jsx | 5 +++-- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/src/containers/list-monitor.jsx b/src/containers/list-monitor.jsx index a4655f702..a20d60156 100644 --- a/src/containers/list-monitor.jsx +++ b/src/containers/list-monitor.jsx @@ -165,14 +165,14 @@ class ListMonitor extends React.Component { } ListMonitor.propTypes = { + height: PropTypes.number, + id: PropTypes.string, + targetId: PropTypes.string, value: PropTypes.oneOfType([ PropTypes.number, PropTypes.string ]), vm: PropTypes.instanceOf(VM), - targetId: PropTypes.string, - id: PropTypes.string, - height: PropTypes.number, width: PropTypes.number, x: PropTypes.number, y: PropTypes.number diff --git a/src/containers/monitor.jsx b/src/containers/monitor.jsx index c39b56302..b2480a412 100644 --- a/src/containers/monitor.jsx +++ b/src/containers/monitor.jsx @@ -107,13 +107,13 @@ class Monitor extends React.Component { max={this.props.max} min={this.props.min} mode={this.state.mode} + targetId={this.props.targetId} + width={this.props.width} onDragEnd={this.handleDragEnd} onNextMode={this.handleNextMode} onSetModeToDefault={this.handleSetModeToDefault} onSetModeToLarge={this.handleSetModeToLarge} onSetModeToSlider={showSliderOption ? this.handleSetModeToSlider : null} - targetId={this.props.targetId} - width={this.props.width} /> ); } @@ -136,6 +136,7 @@ Monitor.propTypes = { removeMonitorRect: PropTypes.func.isRequired, resizeMonitorRect: PropTypes.func.isRequired, spriteName: PropTypes.string, // eslint-disable-line react/no-unused-prop-types + targetId: PropTypes.string, value: PropTypes.oneOfType([ PropTypes.string, PropTypes.number, From a0493d4a0bdbcd1c08ecc391b843b10c4c58dec0 Mon Sep 17 00:00:00 2001 From: Paul Kaplan Date: Thu, 10 May 2018 15:12:56 -0400 Subject: [PATCH 07/23] Make lists have a minimum width --- src/containers/list-monitor.jsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/containers/list-monitor.jsx b/src/containers/list-monitor.jsx index a20d60156..1bedb34a6 100644 --- a/src/containers/list-monitor.jsx +++ b/src/containers/list-monitor.jsx @@ -123,7 +123,7 @@ class ListMonitor extends React.Component { const dx = newPosition.x - this.initialPosition.x; const dy = newPosition.y - this.initialPosition.y; this.setState({ - width: Math.min(this.initialWidth + dx, 480), + width: Math.max(Math.min(this.initialWidth + dx, 480), 80), height: Math.max(Math.min(this.initialHeight + dy, 360), 60) }); }; From 6905704f4f13196549ef458817341b27f19eb941 Mon Sep 17 00:00:00 2001 From: Paul Kaplan Date: Thu, 10 May 2018 15:16:54 -0400 Subject: [PATCH 08/23] Add an error boundary for monitors, now that they do a lot. --- src/containers/monitor-list.jsx | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/src/containers/monitor-list.jsx b/src/containers/monitor-list.jsx index 85a3b20e3..b3dcd5b7c 100644 --- a/src/containers/monitor-list.jsx +++ b/src/containers/monitor-list.jsx @@ -5,6 +5,8 @@ import PropTypes from 'prop-types'; import {connect} from 'react-redux'; import {moveMonitorRect} from '../reducers/monitor-layout'; +import errorBoundaryHOC from '../lib/error-boundary-hoc.jsx'; + import MonitorListComponent from '../components/monitor-list/monitor-list.jsx'; class MonitorList extends React.Component { @@ -37,7 +39,9 @@ const mapDispatchToProps = dispatch => ({ moveMonitorRect: (id, x, y) => dispatch(moveMonitorRect(id, x, y)) }); -export default connect( - mapStateToProps, - mapDispatchToProps -)(MonitorList); +export default errorBoundaryHOC('Monitors')( + connect( + mapStateToProps, + mapDispatchToProps + )(MonitorList) +); From b6ccf20bc9afa7b2763b6f781804dae5dc8c988b Mon Sep 17 00:00:00 2001 From: Paul Kaplan Date: Thu, 10 May 2018 17:03:49 -0400 Subject: [PATCH 09/23] Update vm and blocks for block visibility --- package.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index cad8ee262..7d6d129de 100644 --- a/package.json +++ b/package.json @@ -89,13 +89,13 @@ "redux-throttle": "0.1.1", "rimraf": "^2.6.1", "scratch-audio": "0.1.0-prerelease.1523977528", - "scratch-blocks": "0.1.0-prerelease.1525467275", + "scratch-blocks": "0.1.0-prerelease.1525981783", "scratch-l10n": "2.0.20180108132626", "scratch-paint": "0.2.0-prerelease.20180504180528", "scratch-render": "0.1.0-prerelease.20180508205430", "scratch-storage": "0.4.1", "scratch-svg-renderer": "0.1.0-prerelease.20180423193917", - "scratch-vm": "0.1.0-prerelease.1525901935", + "scratch-vm": "0.1.0-prerelease.1525981075", "selenium-webdriver": "3.6.0", "startaudiocontext": "1.2.1", "style-loader": "^0.21.0", From dd922d667e492ab9caeaa3f84ec9adfc5dc05f1d Mon Sep 17 00:00:00 2001 From: DD Date: Thu, 10 May 2018 17:15:01 -0400 Subject: [PATCH 10/23] Update fonts changes packages --- package.json | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/package.json b/package.json index 94658acec..8977f6fef 100644 --- a/package.json +++ b/package.json @@ -91,11 +91,11 @@ "scratch-audio": "0.1.0-prerelease.1523977528", "scratch-blocks": "0.1.0-prerelease.1525467275", "scratch-l10n": "2.0.20180108132626", - "scratch-paint": "0.2.0-prerelease.20180504180528", - "scratch-render": "0.1.0-prerelease.20180502115145", - "scratch-svg-renderer": "0.1.0-prerelease.20180423193917", + "scratch-paint": "0.2.0-prerelease.20180510175214", + "scratch-render": "0.1.0-prerelease.20180510210730", "scratch-storage": "0.4.1", - "scratch-vm": "0.1.0-prerelease.1525460669", + "scratch-svg-renderer": "0.1.0-prerelease.20180510171850", + "scratch-vm": "0.1.0-prerelease.1525975472", "selenium-webdriver": "3.6.0", "startaudiocontext": "1.2.1", "style-loader": "^0.20.0", From 109067690cedd03693722e1a671fed442b5c7d20 Mon Sep 17 00:00:00 2001 From: Paul Kaplan Date: Fri, 11 May 2018 11:15:25 -0400 Subject: [PATCH 11/23] Update in response to comments --- package.json | 2 +- src/components/monitor/list-monitor-scroller.jsx | 2 +- src/containers/list-monitor-row.jsx | 0 src/lib/variable-utils.js | 2 +- 4 files changed, 3 insertions(+), 3 deletions(-) delete mode 100644 src/containers/list-monitor-row.jsx diff --git a/package.json b/package.json index 0def7bc26..d711c8c8c 100644 --- a/package.json +++ b/package.json @@ -84,7 +84,7 @@ "react-tabs": "2.2.1", "react-test-renderer": "16.2.0", "react-tooltip": "3.4.0", - "react-virtualized": "^9.18.5", + "react-virtualized": "9.18.5", "redux": "3.7.2", "redux-mock-store": "^1.2.3", "redux-throttle": "0.1.1", diff --git a/src/components/monitor/list-monitor-scroller.jsx b/src/components/monitor/list-monitor-scroller.jsx index 26676f4c1..fd6da9bab 100644 --- a/src/components/monitor/list-monitor-scroller.jsx +++ b/src/components/monitor/list-monitor-scroller.jsx @@ -47,7 +47,7 @@ class ListMonitorScroller extends React.Component { className={classNames(styles.listInput, 'no-drag')} spellCheck={false} type="text" - value={this.props.activeValue} /* eslint-disable-line */ + value={this.props.activeValue} onBlur={this.props.onDeactivate} onChange={this.props.onInput} onFocus={this.props.onFocus} diff --git a/src/containers/list-monitor-row.jsx b/src/containers/list-monitor-row.jsx deleted file mode 100644 index e69de29bb..000000000 diff --git a/src/lib/variable-utils.js b/src/lib/variable-utils.js index 29eacd617..12bcf4704 100644 --- a/src/lib/variable-utils.js +++ b/src/lib/variable-utils.js @@ -1,5 +1,5 @@ // Utility functions for updating variables in the VM -// TODO these should be moved to top-level VM API +// TODO (VM#1145) these should be moved to top-level VM API const getVariable = (vm, targetId, variableId) => { const target = targetId ? vm.runtime.getTargetById(targetId) : From 2b7cdcc8cb2df8b9b390892b2348669b69c3bdad Mon Sep 17 00:00:00 2001 From: Paul Kaplan Date: Fri, 11 May 2018 11:25:47 -0400 Subject: [PATCH 12/23] Fix CSS for min width --- src/components/monitor/monitor.css | 11 ++++++++++- src/containers/list-monitor.jsx | 4 ++-- 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/src/components/monitor/monitor.css b/src/components/monitor/monitor.css index 078d24104..34d87aa27 100644 --- a/src/components/monitor/monitor.css +++ b/src/components/monitor/monitor.css @@ -61,7 +61,6 @@ } .list-monitor { - min-width: 80px; display: flex; flex-direction: column; } @@ -159,4 +158,14 @@ .add-button { cursor: pointer; + margin-right: 3px; +} + +.resize-handle { + cursor: nwse-resize; + margin-left: 3px; +} + +.footer-length { + text-align: center; } diff --git a/src/containers/list-monitor.jsx b/src/containers/list-monitor.jsx index 1bedb34a6..4b7cc80db 100644 --- a/src/containers/list-monitor.jsx +++ b/src/containers/list-monitor.jsx @@ -25,7 +25,7 @@ class ListMonitor extends React.Component { activeIndex: null, activeValue: null, // TODO These will need to be sent back to the VM for saving - width: props.width || 80, + width: props.width || 100, height: props.height || 200 }; } @@ -123,7 +123,7 @@ class ListMonitor extends React.Component { const dx = newPosition.x - this.initialPosition.x; const dy = newPosition.y - this.initialPosition.y; this.setState({ - width: Math.max(Math.min(this.initialWidth + dx, 480), 80), + width: Math.max(Math.min(this.initialWidth + dx, 480), 100), height: Math.max(Math.min(this.initialHeight + dy, 360), 60) }); }; From f00c3758af89b00393d42487b400ce939629f12f Mon Sep 17 00:00:00 2001 From: Ray Schamp Date: Fri, 11 May 2018 11:26:29 -0400 Subject: [PATCH 13/23] Update scratch-vm dependency This fixes the music manifest issue. --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 8a2e01892..ffe8167cc 100644 --- a/package.json +++ b/package.json @@ -95,7 +95,7 @@ "scratch-render": "0.1.0-prerelease.20180510210730", "scratch-storage": "0.4.1", "scratch-svg-renderer": "0.1.0-prerelease.20180510181711", - "scratch-vm": "0.1.0-prerelease.1525981075", + "scratch-vm": "0.1.0-prerelease.1526052228", "selenium-webdriver": "3.6.0", "startaudiocontext": "1.2.1", "style-loader": "^0.21.0", From ee8656d224d340e0fc2be6ee4c97d1b56b50b5b6 Mon Sep 17 00:00:00 2001 From: DD Date: Fri, 11 May 2018 11:26:12 -0400 Subject: [PATCH 14/23] Add dependencies that are updated by change to svg-renderer --- package.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/package.json b/package.json index ffe8167cc..ddc384449 100644 --- a/package.json +++ b/package.json @@ -91,10 +91,10 @@ "scratch-audio": "0.1.0-prerelease.1523977528", "scratch-blocks": "0.1.0-prerelease.1525981783", "scratch-l10n": "2.0.20180108132626", - "scratch-paint": "0.2.0-prerelease.20180510175214", - "scratch-render": "0.1.0-prerelease.20180510210730", + "scratch-paint": "0.2.0-prerelease.20180511152319", + "scratch-render": "0.1.0-prerelease.20180511151033", "scratch-storage": "0.4.1", - "scratch-svg-renderer": "0.1.0-prerelease.20180510181711", + "scratch-svg-renderer": "0.1.0-prerelease.20180511144653", "scratch-vm": "0.1.0-prerelease.1526052228", "selenium-webdriver": "3.6.0", "startaudiocontext": "1.2.1", From 3ea7b9e8a2cfaf6a2ba2e851c503362f1e0a9fd4 Mon Sep 17 00:00:00 2001 From: Paul Kaplan Date: Fri, 11 May 2018 13:34:36 -0400 Subject: [PATCH 15/23] Fixes from smoke test Including triple scrollbars on list monitors and fixing the say bubble fonts --- package.json | 2 +- src/components/monitor/monitor.css | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/package.json b/package.json index faf8b5817..18301500e 100644 --- a/package.json +++ b/package.json @@ -93,7 +93,7 @@ "scratch-blocks": "0.1.0-prerelease.1525981783", "scratch-l10n": "2.0.20180108132626", "scratch-paint": "0.2.0-prerelease.20180511152319", - "scratch-render": "0.1.0-prerelease.20180511151033", + "scratch-render": "0.1.0-prerelease.20180511173134", "scratch-storage": "0.4.1", "scratch-svg-renderer": "0.1.0-prerelease.20180511144653", "scratch-vm": "0.1.0-prerelease.1526052228", diff --git a/src/components/monitor/monitor.css b/src/components/monitor/monitor.css index 34d87aa27..348f11e0c 100644 --- a/src/components/monitor/monitor.css +++ b/src/components/monitor/monitor.css @@ -82,6 +82,7 @@ display: flex; flex-direction: column; overflow-y: scroll; + overflow-x: hidden; height: calc(100% - 44px); } From 4ccfae603a9f8608a8c0dc0ac137722dd827a3d3 Mon Sep 17 00:00:00 2001 From: Paul Kaplan Date: Fri, 11 May 2018 14:17:28 -0400 Subject: [PATCH 16/23] Update render to get empty sprite fix also --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 18301500e..a18257d84 100644 --- a/package.json +++ b/package.json @@ -93,7 +93,7 @@ "scratch-blocks": "0.1.0-prerelease.1525981783", "scratch-l10n": "2.0.20180108132626", "scratch-paint": "0.2.0-prerelease.20180511152319", - "scratch-render": "0.1.0-prerelease.20180511173134", + "scratch-render": "0.1.0-prerelease.20180511181411", "scratch-storage": "0.4.1", "scratch-svg-renderer": "0.1.0-prerelease.20180511144653", "scratch-vm": "0.1.0-prerelease.1526052228", From f8c8dfc0eb7c33002efcb03bd12cbd741eac8bf4 Mon Sep 17 00:00:00 2001 From: Paul Kaplan Date: Fri, 11 May 2018 14:50:53 -0400 Subject: [PATCH 17/23] Update scratch render again to fix speech bubbles again --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index a18257d84..756df383e 100644 --- a/package.json +++ b/package.json @@ -93,7 +93,7 @@ "scratch-blocks": "0.1.0-prerelease.1525981783", "scratch-l10n": "2.0.20180108132626", "scratch-paint": "0.2.0-prerelease.20180511152319", - "scratch-render": "0.1.0-prerelease.20180511181411", + "scratch-render": "0.1.0-prerelease.20180511184906", "scratch-storage": "0.4.1", "scratch-svg-renderer": "0.1.0-prerelease.20180511144653", "scratch-vm": "0.1.0-prerelease.1526052228", From 5974905a7a2b99107cdf2f32e764e5fbc632f708 Mon Sep 17 00:00:00 2001 From: Luke Schlangen Date: Sat, 12 May 2018 12:50:47 -0500 Subject: [PATCH 18/23] remove question event listener on stage unmount --- src/containers/stage.jsx | 1 + 1 file changed, 1 insertion(+) diff --git a/src/containers/stage.jsx b/src/containers/stage.jsx index f3444af1a..a783cf3fc 100644 --- a/src/containers/stage.jsx +++ b/src/containers/stage.jsx @@ -79,6 +79,7 @@ class Stage extends React.Component { this.detachMouseEvents(this.canvas); this.detachRectEvents(); this.stopColorPickingLoop(); + this.props.vm.runtime.removeListener('QUESTION', this.questionListener); } questionListener (question) { this.setState({question: question}); From 2464da2885e88fda4bd468f7bb4cbfdf9a8bcff4 Mon Sep 17 00:00:00 2001 From: Paul Kaplan Date: Sun, 13 May 2018 13:45:15 -0400 Subject: [PATCH 19/23] Fix linting errors from eslint-plugin-react --- src/.eslintrc.js | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/.eslintrc.js b/src/.eslintrc.js index 8dab3c69c..14b082cdf 100644 --- a/src/.eslintrc.js +++ b/src/.eslintrc.js @@ -13,5 +13,10 @@ module.exports = { 'import/no-amd': 'error', 'import/no-nodejs-modules': 'error', 'react/jsx-no-literals': 'error' + }, + settings: { + react: { + version: '16.2' // Prevent 16.3 lifecycle method errors + } } }; From 87e8e2f18df83e572d46cc8bceb65ebc757846cb Mon Sep 17 00:00:00 2001 From: "Michael \"Z\" Goddard" Date: Mon, 14 May 2018 11:38:45 -0400 Subject: [PATCH 20/23] Add missing quotes to .babelrc configuration --- .babelrc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.babelrc b/.babelrc index 66742d703..8f910cdf7 100644 --- a/.babelrc +++ b/.babelrc @@ -6,5 +6,5 @@ ["react-intl", { "messagesDir": "./translations/messages/" }]], - "presets": [["env", {"targets": {browsers: ["last 3 versions", "Safari >= 8", "iOS >= 8"]}}], "react"] + "presets": [["env", {"targets": {"browsers": ["last 3 versions", "Safari >= 8", "iOS >= 8"]}}], "react"] } From 8cbf46fe81a20c5824e819866caec80a8cca22de Mon Sep 17 00:00:00 2001 From: Paul Kaplan Date: Mon, 14 May 2018 13:30:45 -0400 Subject: [PATCH 21/23] Update scratch-render to get the babel-built version of scratch-render-fonts --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 756df383e..9da639d9d 100644 --- a/package.json +++ b/package.json @@ -93,7 +93,7 @@ "scratch-blocks": "0.1.0-prerelease.1525981783", "scratch-l10n": "2.0.20180108132626", "scratch-paint": "0.2.0-prerelease.20180511152319", - "scratch-render": "0.1.0-prerelease.20180511184906", + "scratch-render": "0.1.0-prerelease.20180514172756", "scratch-storage": "0.4.1", "scratch-svg-renderer": "0.1.0-prerelease.20180511144653", "scratch-vm": "0.1.0-prerelease.1526052228", From 278d837b8f5d39fa6981ea1f94356d622f1c197c Mon Sep 17 00:00:00 2001 From: "greenkeeper[bot]" Date: Mon, 14 May 2018 18:41:55 +0000 Subject: [PATCH 22/23] chore(package): update scratch-paint to version 0.2.0-prerelease.20180514184134 Closes #1949 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 9da639d9d..1d14bd4fc 100644 --- a/package.json +++ b/package.json @@ -92,7 +92,7 @@ "scratch-audio": "0.1.0-prerelease.1523977528", "scratch-blocks": "0.1.0-prerelease.1525981783", "scratch-l10n": "2.0.20180108132626", - "scratch-paint": "0.2.0-prerelease.20180511152319", + "scratch-paint": "0.2.0-prerelease.20180514184134", "scratch-render": "0.1.0-prerelease.20180514172756", "scratch-storage": "0.4.1", "scratch-svg-renderer": "0.1.0-prerelease.20180511144653", From 77e5d8c0ab28e52169f087cebc7f407493219129 Mon Sep 17 00:00:00 2001 From: Paul Kaplan Date: Mon, 14 May 2018 15:36:47 -0400 Subject: [PATCH 23/23] Update scratch-svg-renderer to fix IE11 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 9da639d9d..de2483192 100644 --- a/package.json +++ b/package.json @@ -95,7 +95,7 @@ "scratch-paint": "0.2.0-prerelease.20180511152319", "scratch-render": "0.1.0-prerelease.20180514172756", "scratch-storage": "0.4.1", - "scratch-svg-renderer": "0.1.0-prerelease.20180511144653", + "scratch-svg-renderer": "0.1.0-prerelease.20180514170126", "scratch-vm": "0.1.0-prerelease.1526052228", "selenium-webdriver": "3.6.0", "startaudiocontext": "1.2.1",