Merge pull request #9 from rschamp/lint
eslint-config-scratch: React + ES6 Edition
This commit is contained in:
commit
cdbf45ae91
31 files changed
+383
-332
No files matched your search
@@ -1,25 +0,0 @@
|
||||
{
|
||||
"parser": "babel-eslint",
|
||||
"rules": {
|
||||
"curly": [2, "multi-line"],
|
||||
"eol-last": [2],
|
||||
"indent": [2, 4],
|
||||
"linebreak-style": [2, "unix"],
|
||||
"max-len": [2, 120, 4],
|
||||
"no-trailing-spaces": [2, { "skipBlankLines": true }],
|
||||
"no-unused-vars": [2, {"args": "after-used", "varsIgnorePattern": "^_"}],
|
||||
"quotes": [2, "single"],
|
||||
"semi": [2, "always"],
|
||||
"space-before-function-paren": [2, "always"],
|
||||
"strict": [2, "never"]
|
||||
},
|
||||
"env": {
|
||||
"browser": true,
|
||||
"es6": true,
|
||||
"node": true
|
||||
},
|
||||
"plugins": [
|
||||
"react"
|
||||
],
|
||||
"extends": ["eslint:recommended", "plugin:react/recommended"]
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
module.exports = {
|
||||
env: {
|
||||
node: true
|
||||
}
|
||||
};
|
||||
+7
-2
@@ -18,6 +18,9 @@
|
||||
"start": "webpack-dev-server --port $npm_package_config_port --content-base=./build",
|
||||
"test": "npm run lint && npm run build"
|
||||
},
|
||||
"eslintConfig": {
|
||||
"extends": ["scratch"]
|
||||
},
|
||||
"author": "Massachusetts Institute of Technology",
|
||||
"license": "BSD-3-Clause",
|
||||
"homepage": "https://github.com/LLK/scratch-gui#readme",
|
||||
@@ -31,14 +34,15 @@
|
||||
},
|
||||
"devDependencies": {
|
||||
"babel-core": "6.14.0",
|
||||
"babel-eslint": "6.1.2",
|
||||
"babel-eslint": "7.0.0",
|
||||
"babel-loader": "6.2.5",
|
||||
"babel-plugin-transform-object-rest-spread": "6.16.0",
|
||||
"babel-preset-es2015": "6.14.0",
|
||||
"babel-preset-react": "6.11.1",
|
||||
"copy-webpack-plugin": "3.0.1",
|
||||
"eslint": "3.5.0",
|
||||
"eslint-plugin-react": "6.2.1",
|
||||
"eslint-config-scratch": "^1.0.0",
|
||||
"eslint-plugin-react": "6.4.1",
|
||||
"gh-pages": "0.11.0",
|
||||
"html-webpack-plugin": "2.22.0",
|
||||
"husky": "0.11.9",
|
||||
@@ -50,6 +54,7 @@
|
||||
"react": "15.3.2",
|
||||
"react-dom": "15.3.2",
|
||||
"react-modal": "1.5.2",
|
||||
"react-style-proptype": "1.2.0",
|
||||
"scratch-blocks": "latest",
|
||||
"scratch-render": "latest",
|
||||
"scratch-vm": "latest",
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
module.exports = {
|
||||
env: {
|
||||
node: false,
|
||||
browser: true
|
||||
},
|
||||
extends: ['scratch/es6', 'scratch/react']
|
||||
};
|
||||
@@ -8,8 +8,8 @@ class BlocksComponent extends React.Component {
|
||||
} = this.props;
|
||||
return (
|
||||
<div
|
||||
ref={componentRef}
|
||||
className="scratch-blocks"
|
||||
ref={componentRef}
|
||||
style={{
|
||||
position: 'absolute',
|
||||
top: 0,
|
||||
@@ -16,46 +16,54 @@ class CostumeCanvas extends React.Component {
|
||||
componentDidUpdate (prevProps) {
|
||||
if (prevProps.url !== this.props.url) {
|
||||
this.load();
|
||||
} else {
|
||||
if (prevProps.width !== this.props.width ||
|
||||
prevProps.height !== this.props.height ||
|
||||
prevProps.direction !== this.props.direction) {
|
||||
this.draw();
|
||||
}
|
||||
} else if (
|
||||
prevProps.width !== this.props.width ||
|
||||
prevProps.height !== this.props.height ||
|
||||
prevProps.direction !== this.props.direction
|
||||
) {
|
||||
this.draw();
|
||||
}
|
||||
}
|
||||
draw () {
|
||||
if (!this.refs.costumeCanvas) {
|
||||
if (!this.canvas) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Draw the costume to the rendered canvas.
|
||||
const img = this.img;
|
||||
const context = this.refs.costumeCanvas.getContext('2d');
|
||||
const context = this.canvas.getContext('2d');
|
||||
|
||||
// Scale to fit.
|
||||
let scale;
|
||||
|
||||
// Choose the larger dimension to scale by.
|
||||
if (img.width > img.height) {
|
||||
scale = this.refs.costumeCanvas.width / img.width;
|
||||
scale = this.canvas.width / img.width;
|
||||
} else {
|
||||
scale = this.refs.costumeCanvas.height / img.height;
|
||||
scale = this.canvas.height / img.height;
|
||||
}
|
||||
|
||||
// Rotate by the Scratch-value direction.
|
||||
const angle = (-90 + this.props.direction) * Math.PI / 180;
|
||||
|
||||
// Rotation origin point will be center of the canvas.
|
||||
const contextTranslateX = this.refs.costumeCanvas.width / 2;
|
||||
const contextTranslateY = this.refs.costumeCanvas.height / 2;
|
||||
const contextTranslateX = this.canvas.width / 2;
|
||||
const contextTranslateY = this.canvas.height / 2;
|
||||
|
||||
// First, clear the canvas.
|
||||
context.clearRect(0, 0,
|
||||
this.refs.costumeCanvas.width, this.refs.costumeCanvas.height);
|
||||
this.canvas.width, this.canvas.height);
|
||||
|
||||
// Translate the context to the center of the canvas,
|
||||
// then rotate canvas drawing by `angle`.
|
||||
context.translate(contextTranslateX, contextTranslateY);
|
||||
context.rotate(angle);
|
||||
context.drawImage(img,
|
||||
0, 0, img.width, img.height,
|
||||
-(scale * img.width / 2), -(scale * img.height / 2),
|
||||
-(scale * img.width / 2), -(scale * img.height / 2),
|
||||
scale * img.width,
|
||||
scale * img.height);
|
||||
|
||||
// Reset the canvas rotation and translation to 0, (0, 0).
|
||||
context.rotate(-angle);
|
||||
context.translate(-contextTranslateX, -contextTranslateY);
|
||||
@@ -72,8 +80,8 @@ class CostumeCanvas extends React.Component {
|
||||
url: url
|
||||
}, (err, response, body) => {
|
||||
if (!err) {
|
||||
svgToImage(body, (err, img) => {
|
||||
if (!err) {
|
||||
svgToImage(body, (svgErr, img) => {
|
||||
if (!svgErr) {
|
||||
this.img = img;
|
||||
this.draw();
|
||||
}
|
||||
@@ -84,7 +92,7 @@ class CostumeCanvas extends React.Component {
|
||||
|
||||
} else {
|
||||
// Raster graphics: create Image and draw it.
|
||||
let img = new Image();
|
||||
const img = new Image();
|
||||
img.src = url;
|
||||
img.onload = () => {
|
||||
this.img = img;
|
||||
@@ -93,11 +101,13 @@ class CostumeCanvas extends React.Component {
|
||||
}
|
||||
}
|
||||
render () {
|
||||
return <canvas
|
||||
ref='costumeCanvas'
|
||||
width={this.props.width}
|
||||
height={this.props.height}
|
||||
/>;
|
||||
return (
|
||||
<canvas
|
||||
height={this.props.height}
|
||||
width={this.props.width}
|
||||
ref={this._getCanvas} // eslint-disable-line react/jsx-sort-props
|
||||
/>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -108,10 +118,10 @@ CostumeCanvas.defaultProps = {
|
||||
};
|
||||
|
||||
CostumeCanvas.propTypes = {
|
||||
url: React.PropTypes.string,
|
||||
width: React.PropTypes.number,
|
||||
direction: React.PropTypes.number,
|
||||
height: React.PropTypes.number,
|
||||
direction: React.PropTypes.number
|
||||
url: React.PropTypes.string,
|
||||
width: React.PropTypes.number
|
||||
};
|
||||
|
||||
module.exports = CostumeCanvas;
|
||||
File renamed without changes.
File renamed without changes.
@@ -1,13 +1,26 @@
|
||||
const bindAll = require('lodash.bindall');
|
||||
const React = require('react');
|
||||
const stylePropType = require('react-style-proptype');
|
||||
|
||||
const CostumeCanvas = require('./costume-canvas');
|
||||
const CostumeCanvas = require('./costume-canvas.jsx');
|
||||
|
||||
class LibraryItem extends React.Component {
|
||||
constructor (props) {
|
||||
super(props);
|
||||
bindAll(this, ['handleClick']);
|
||||
}
|
||||
handleClick (e) {
|
||||
this.props.onSelect(this.props.id);
|
||||
e.preventDefault();
|
||||
}
|
||||
render () {
|
||||
let style = (this.props.selected) ?
|
||||
const style = (this.props.selected) ?
|
||||
this.props.selectedGridTileStyle : this.props.gridTileStyle;
|
||||
return (
|
||||
<div style={style} onClick={() => this.props.onSelect(this.props.id)}>
|
||||
<div
|
||||
style={style}
|
||||
onClick={this.handleClick}
|
||||
>
|
||||
<CostumeCanvas url={this.props.iconURL} />
|
||||
<p>{this.props.name}</p>
|
||||
</div>
|
||||
@@ -37,13 +50,13 @@ LibraryItem.defaultProps = {
|
||||
};
|
||||
|
||||
LibraryItem.propTypes = {
|
||||
name: React.PropTypes.string,
|
||||
gridTileStyle: stylePropType,
|
||||
iconURL: React.PropTypes.string,
|
||||
gridTileStyle: React.PropTypes.object,
|
||||
selectedGridTileStyle: React.PropTypes.object,
|
||||
selected: React.PropTypes.bool,
|
||||
id: React.PropTypes.number,
|
||||
name: React.PropTypes.string,
|
||||
onSelect: React.PropTypes.func,
|
||||
id: React.PropTypes.number
|
||||
selected: React.PropTypes.bool,
|
||||
selectedGridTileStyle: stylePropType
|
||||
};
|
||||
|
||||
module.exports = LibraryItem;
|
||||
@@ -1,69 +0,0 @@
|
||||
const bindAll = require('lodash.bindall');
|
||||
const React = require('react');
|
||||
|
||||
const LibraryItem = require('./library-item');
|
||||
const ModalComponent = require('./modal');
|
||||
|
||||
class LibraryComponent extends React.Component {
|
||||
constructor (props) {
|
||||
super(props);
|
||||
bindAll(this, ['onSelect']);
|
||||
this.state = {selectedItem: null};
|
||||
}
|
||||
onSelect (id) {
|
||||
if (this.state.selectedItem == id) {
|
||||
// Double select: select as the library's value.
|
||||
this.props.onRequestClose();
|
||||
this.props.onItemSelected(this.props.data[id]);
|
||||
}
|
||||
this.setState({selectedItem: id});
|
||||
}
|
||||
render () {
|
||||
let itemId = 0;
|
||||
let gridItems = this.props.data.map((dataItem) => {
|
||||
let id = itemId;
|
||||
itemId++;
|
||||
const scratchURL = (dataItem.md5) ? 'https://cdn.assets.scratch.mit.edu/internalapi/asset/' +
|
||||
dataItem.md5 + '/get/' : dataItem.rawURL;
|
||||
return <LibraryItem
|
||||
name={dataItem.name}
|
||||
iconURL={scratchURL}
|
||||
key={'item_' + id}
|
||||
selected={this.state.selectedItem == id}
|
||||
onSelect={this.onSelect}
|
||||
id={id}
|
||||
/>;
|
||||
});
|
||||
|
||||
const scrollGridStyle = {
|
||||
overflow: 'scroll',
|
||||
position: 'absolute',
|
||||
top: '70px',
|
||||
bottom: '20px',
|
||||
left: '30px',
|
||||
right: '30px'
|
||||
};
|
||||
|
||||
return (
|
||||
<ModalComponent
|
||||
onRequestClose={this.props.onRequestClose}
|
||||
visible={this.props.visible}
|
||||
>
|
||||
<h1>{this.props.title}</h1>
|
||||
<div style={scrollGridStyle}>
|
||||
{gridItems}
|
||||
</div>
|
||||
</ModalComponent>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
LibraryComponent.propTypes = {
|
||||
title: React.PropTypes.string,
|
||||
data: React.PropTypes.array,
|
||||
visible: React.PropTypes.bool,
|
||||
onRequestClose: React.PropTypes.func,
|
||||
onItemSelected: React.PropTypes.func
|
||||
};
|
||||
|
||||
module.exports = LibraryComponent;
|
||||
@@ -0,0 +1,74 @@
|
||||
const bindAll = require('lodash.bindall');
|
||||
const React = require('react');
|
||||
|
||||
const LibraryItem = require('./library-item.jsx');
|
||||
const ModalComponent = require('./modal.jsx');
|
||||
|
||||
class LibraryComponent extends React.Component {
|
||||
constructor (props) {
|
||||
super(props);
|
||||
bindAll(this, ['handleSelect']);
|
||||
this.state = {selectedItem: null};
|
||||
}
|
||||
handleSelect (id) {
|
||||
if (this.state.selectedItem === id) {
|
||||
// Double select: select as the library's value.
|
||||
this.props.onRequestClose();
|
||||
this.props.onItemSelected(this.props.data[id]);
|
||||
}
|
||||
this.setState({selectedItem: id});
|
||||
}
|
||||
render () {
|
||||
const scrollGridStyle = {
|
||||
overflow: 'scroll',
|
||||
position: 'absolute',
|
||||
top: '70px',
|
||||
bottom: '20px',
|
||||
left: '30px',
|
||||
right: '30px'
|
||||
};
|
||||
return (
|
||||
<ModalComponent
|
||||
visible={this.props.visible}
|
||||
onRequestClose={this.props.onRequestClose}
|
||||
>
|
||||
<h1>{this.props.title}</h1>
|
||||
<div style={scrollGridStyle}>
|
||||
{this.props.data.map((dataItem, itemId) => {
|
||||
const scratchURL = dataItem.md5 ?
|
||||
`https://cdn.assets.scratch.mit.edu/internalapi/asset/${dataItem.md5}/get/` :
|
||||
dataItem.rawURL;
|
||||
return (
|
||||
<LibraryItem
|
||||
iconURL={scratchURL}
|
||||
id={itemId}
|
||||
key={`item_${itemId}`}
|
||||
name={dataItem.name}
|
||||
selected={this.state.selectedItem === itemId}
|
||||
onSelect={this.handleSelect}
|
||||
/>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
</ModalComponent>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
LibraryComponent.propTypes = {
|
||||
data: React.PropTypes.arrayOf(
|
||||
/* eslint-disable react/no-unused-prop-types, lines-around-comment */
|
||||
React.PropTypes.shape({
|
||||
md5: React.PropTypes.string,
|
||||
name: React.PropTypes.string,
|
||||
rawURL: React.PropTypes.string,
|
||||
})
|
||||
/* eslint-enable react/no-unused-prop-types, lines-around-comment */
|
||||
),
|
||||
onItemSelected: React.PropTypes.func,
|
||||
onRequestClose: React.PropTypes.func,
|
||||
title: React.PropTypes.string,
|
||||
visible: React.PropTypes.bool
|
||||
};
|
||||
|
||||
module.exports = LibraryComponent;
|
||||
@@ -1,20 +1,21 @@
|
||||
const React = require('react');
|
||||
const ReactModal = require('react-modal');
|
||||
const stylePropType = require('react-style-proptype');
|
||||
|
||||
class ModalComponent extends React.Component {
|
||||
render () {
|
||||
return (
|
||||
<ReactModal
|
||||
ref="modal"
|
||||
style={this.props.modalStyle}
|
||||
isOpen={this.props.visible}
|
||||
ref={m => (this.modal = m)}
|
||||
style={this.props.modalStyle}
|
||||
onRequestClose={this.props.onRequestClose}
|
||||
>
|
||||
<div
|
||||
onClick={this.props.onRequestClose}
|
||||
style={this.props.closeButtonStyle}
|
||||
onClick={this.props.onRequestClose}
|
||||
>
|
||||
x
|
||||
{'x'}
|
||||
</div>
|
||||
{this.props.children}
|
||||
</ReactModal>
|
||||
@@ -61,8 +62,8 @@ ModalComponent.defaultProps = {
|
||||
|
||||
ModalComponent.propTypes = {
|
||||
children: React.PropTypes.node,
|
||||
modalStyle: React.PropTypes.object,
|
||||
closeButtonStyle: React.PropTypes.object,
|
||||
closeButtonStyle: stylePropType,
|
||||
modalStyle: stylePropType,
|
||||
onRequestClose: React.PropTypes.func,
|
||||
visible: React.PropTypes.bool
|
||||
};
|
||||
@@ -26,7 +26,10 @@ class SpriteSelectorComponent extends React.Component {
|
||||
onChange={onChange}
|
||||
>
|
||||
{sprites.map(sprite => (
|
||||
<option value={sprite.id} key={sprite.id}>
|
||||
<option
|
||||
key={sprite.id}
|
||||
value={sprite.id}
|
||||
>
|
||||
{sprite.name}
|
||||
</option>
|
||||
))}
|
||||
@@ -43,16 +46,16 @@ class SpriteSelectorComponent extends React.Component {
|
||||
|
||||
SpriteSelectorComponent.propTypes = {
|
||||
onChange: React.PropTypes.func,
|
||||
openNewBackdrop: React.PropTypes.func,
|
||||
openNewCostume: React.PropTypes.func,
|
||||
openNewSprite: React.PropTypes.func,
|
||||
sprites: React.PropTypes.arrayOf(
|
||||
React.PropTypes.shape({
|
||||
id: React.PropTypes.string,
|
||||
name: React.PropTypes.string
|
||||
})
|
||||
),
|
||||
value: React.PropTypes.arrayOf(React.PropTypes.string),
|
||||
openNewSprite: React.PropTypes.func,
|
||||
openNewCostume: React.PropTypes.func,
|
||||
openNewBackdrop: React.PropTypes.func
|
||||
value: React.PropTypes.arrayOf(React.PropTypes.string)
|
||||
};
|
||||
|
||||
module.exports = SpriteSelectorComponent;
|
||||
@@ -27,12 +27,12 @@ class StageComponent extends React.Component {
|
||||
|
||||
StageComponent.propTypes = {
|
||||
canvasRef: React.PropTypes.func,
|
||||
width: React.PropTypes.number,
|
||||
height: React.PropTypes.number
|
||||
height: React.PropTypes.number,
|
||||
width: React.PropTypes.number
|
||||
};
|
||||
|
||||
StageComponent.defaultProps = {
|
||||
canvasRef: function () {},
|
||||
canvasRef: () => {},
|
||||
width: 480,
|
||||
height: 360
|
||||
};
|
||||
File renamed without changes.
@@ -3,13 +3,13 @@ const React = require('react');
|
||||
const VM = require('scratch-vm');
|
||||
const MediaLibrary = require('../lib/media-library');
|
||||
|
||||
const LibaryComponent = require('../components/library');
|
||||
const LibaryComponent = require('../components/library.jsx');
|
||||
|
||||
|
||||
class BackdropLibrary extends React.Component {
|
||||
constructor (props) {
|
||||
super(props);
|
||||
bindAll(this, ['setData', 'selectItem']);
|
||||
bindAll(this, ['setData', 'handleItemSelect']);
|
||||
this.state = {backdropData: []};
|
||||
}
|
||||
componentWillReceiveProps (nextProps) {
|
||||
@@ -20,9 +20,9 @@ class BackdropLibrary extends React.Component {
|
||||
setData (data) {
|
||||
this.setState({backdropData: data});
|
||||
}
|
||||
selectItem (item) {
|
||||
var vmBackdrop = {
|
||||
skin: 'https://cdn.assets.scratch.mit.edu/internalapi/asset/' + item.md5 + '/get/',
|
||||
handleItemSelect (item) {
|
||||
const vmBackdrop = {
|
||||
skin: `https://cdn.assets.scratch.mit.edu/internalapi/asset/${item.md5}/get/`,
|
||||
name: item.name,
|
||||
rotationCenterX: item.info[0],
|
||||
rotationCenterY: item.info[1]
|
||||
@@ -33,21 +33,23 @@ class BackdropLibrary extends React.Component {
|
||||
this.props.vm.addBackdrop(vmBackdrop);
|
||||
}
|
||||
render () {
|
||||
return <LibaryComponent
|
||||
title="Backdrop Library"
|
||||
visible={this.props.visible}
|
||||
data={this.state.backdropData}
|
||||
onRequestClose={this.props.onRequestClose}
|
||||
onItemSelected={this.selectItem}
|
||||
/>;
|
||||
return (
|
||||
<LibaryComponent
|
||||
data={this.state.backdropData}
|
||||
title="Backdrop Library"
|
||||
visible={this.props.visible}
|
||||
onItemSelected={this.handleItemSelect}
|
||||
onRequestClose={this.props.onRequestClose}
|
||||
/>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
BackdropLibrary.propTypes = {
|
||||
vm: React.PropTypes.instanceOf(VM).isRequired,
|
||||
mediaLibrary: React.PropTypes.instanceOf(MediaLibrary),
|
||||
onRequestClose: React.PropTypes.func,
|
||||
visible: React.PropTypes.bool,
|
||||
onRequestClose: React.PropTypes.func
|
||||
vm: React.PropTypes.instanceOf(VM).isRequired
|
||||
};
|
||||
|
||||
module.exports = BackdropLibrary;
|
||||
@@ -4,7 +4,7 @@ const React = require('react');
|
||||
const ScratchBlocks = require('scratch-blocks');
|
||||
const VM = require('scratch-vm');
|
||||
|
||||
const BlocksComponent = require('../components/blocks');
|
||||
const BlocksComponent = require('../components/blocks.jsx');
|
||||
|
||||
class Blocks extends React.Component {
|
||||
constructor (props) {
|
||||
@@ -21,7 +21,7 @@ class Blocks extends React.Component {
|
||||
]);
|
||||
}
|
||||
componentDidMount () {
|
||||
let workspaceConfig = defaultsDeep({}, Blocks.defaultOptions, this.props.options);
|
||||
const workspaceConfig = defaultsDeep({}, Blocks.defaultOptions, this.props.options);
|
||||
this.workspace = ScratchBlocks.inject(this.blocks, workspaceConfig);
|
||||
this.attachVM();
|
||||
}
|
||||
@@ -31,9 +31,10 @@ class Blocks extends React.Component {
|
||||
}
|
||||
attachVM () {
|
||||
this.workspace.addChangeListener(this.props.vm.blockListener);
|
||||
this.workspace.getFlyout().getWorkspace().addChangeListener(
|
||||
this.props.vm.flyoutBlockListener
|
||||
);
|
||||
this.workspace
|
||||
.getFlyout()
|
||||
.getWorkspace()
|
||||
.addChangeListener(this.props.vm.flyoutBlockListener);
|
||||
this.props.vm.on('STACK_GLOW_ON', this.onStackGlowOn);
|
||||
this.props.vm.on('STACK_GLOW_OFF', this.onStackGlowOff);
|
||||
this.props.vm.on('BLOCK_GLOW_ON', this.onBlockGlowOn);
|
||||
@@ -79,7 +80,7 @@ class Blocks extends React.Component {
|
||||
} = this.props;
|
||||
return (
|
||||
<BlocksComponent
|
||||
componentRef={c => this.blocks = c}
|
||||
componentRef={c => (this.blocks = c)}
|
||||
{...props}
|
||||
/>
|
||||
);
|
||||
@@ -3,13 +3,13 @@ const React = require('react');
|
||||
const VM = require('scratch-vm');
|
||||
const MediaLibrary = require('../lib/media-library');
|
||||
|
||||
const LibaryComponent = require('../components/library');
|
||||
const LibaryComponent = require('../components/library.jsx');
|
||||
|
||||
|
||||
class CostumeLibrary extends React.Component {
|
||||
constructor (props) {
|
||||
super(props);
|
||||
bindAll(this, ['setData', 'selectItem']);
|
||||
bindAll(this, ['setData', 'handleItemSelected']);
|
||||
this.state = {costumeData: []};
|
||||
}
|
||||
componentWillReceiveProps (nextProps) {
|
||||
@@ -20,9 +20,9 @@ class CostumeLibrary extends React.Component {
|
||||
setData (data) {
|
||||
this.setState({costumeData: data});
|
||||
}
|
||||
selectItem (item) {
|
||||
var vmCostume = {
|
||||
skin: 'https://cdn.assets.scratch.mit.edu/internalapi/asset/' + item.md5 + '/get/',
|
||||
handleItemSelected (item) {
|
||||
const vmCostume = {
|
||||
skin: `https://cdn.assets.scratch.mit.edu/internalapi/asset/$(item.md5)/get/`,
|
||||
name: item.name,
|
||||
rotationCenterX: item.info[0],
|
||||
rotationCenterY: item.info[1]
|
||||
@@ -33,21 +33,23 @@ class CostumeLibrary extends React.Component {
|
||||
this.props.vm.addCostume(vmCostume);
|
||||
}
|
||||
render () {
|
||||
return <LibaryComponent
|
||||
title="Costume Library"
|
||||
visible={this.props.visible}
|
||||
data={this.state.costumeData}
|
||||
onRequestClose={this.props.onRequestClose}
|
||||
onItemSelected={this.selectItem}
|
||||
/>;
|
||||
return (
|
||||
<LibaryComponent
|
||||
data={this.state.costumeData}
|
||||
title="Costume Library"
|
||||
visible={this.props.visible}
|
||||
onItemSelected={this.handleItemSelected}
|
||||
onRequestClose={this.props.onRequestClose}
|
||||
/>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
CostumeLibrary.propTypes = {
|
||||
vm: React.PropTypes.instanceOf(VM).isRequired,
|
||||
mediaLibrary: React.PropTypes.instanceOf(MediaLibrary),
|
||||
onRequestClose: React.PropTypes.func,
|
||||
visible: React.PropTypes.bool,
|
||||
onRequestClose: React.PropTypes.func
|
||||
vm: React.PropTypes.instanceOf(VM).isRequired
|
||||
};
|
||||
|
||||
module.exports = CostumeLibrary;
|
||||
@@ -1,14 +1,16 @@
|
||||
const bindAll = require('lodash.bindall');
|
||||
const React = require('react');
|
||||
|
||||
const GreenFlagComponent = require('../components/green-flag');
|
||||
const VM = require('scratch-vm');
|
||||
|
||||
const GreenFlagComponent = require('../components/green-flag.jsx');
|
||||
|
||||
class GreenFlag extends React.Component {
|
||||
constructor (props) {
|
||||
super(props);
|
||||
bindAll(this, ['onClick']);
|
||||
bindAll(this, ['handleClick']);
|
||||
}
|
||||
onClick (e) {
|
||||
handleClick (e) {
|
||||
e.preventDefault();
|
||||
this.props.vm.greenFlag();
|
||||
}
|
||||
@@ -19,7 +21,7 @@ class GreenFlag extends React.Component {
|
||||
} = this.props;
|
||||
return (
|
||||
<GreenFlagComponent
|
||||
onClick={this.onClick}
|
||||
onClick={this.handleClick}
|
||||
{...props}
|
||||
/>
|
||||
);
|
||||
@@ -27,7 +29,7 @@ class GreenFlag extends React.Component {
|
||||
}
|
||||
|
||||
GreenFlag.propTypes = {
|
||||
vm: React.PropTypes.object
|
||||
vm: React.PropTypes.instanceOf(VM)
|
||||
};
|
||||
|
||||
module.exports = GreenFlag;
|
||||
@@ -5,17 +5,18 @@ const VM = require('scratch-vm');
|
||||
|
||||
const VMManager = require('../lib/vm-manager');
|
||||
const MediaLibrary = require('../lib/media-library');
|
||||
const shapeFromPropTypes = require('../lib/shape-from-prop-types');
|
||||
|
||||
const Blocks = require('./blocks');
|
||||
const GUIComponent = require('../components/gui');
|
||||
const GreenFlag = require('./green-flag');
|
||||
const SpriteSelector = require('./sprite-selector');
|
||||
const Stage = require('./stage');
|
||||
const StopAll = require('./stop-all');
|
||||
const Blocks = require('./blocks.jsx');
|
||||
const GUIComponent = require('../components/gui.jsx');
|
||||
const GreenFlag = require('./green-flag.jsx');
|
||||
const SpriteSelector = require('./sprite-selector.jsx');
|
||||
const Stage = require('./stage.jsx');
|
||||
const StopAll = require('./stop-all.jsx');
|
||||
|
||||
const SpriteLibrary = require('./sprite-library');
|
||||
const CostumeLibrary = require('./costume-library');
|
||||
const BackdropLibrary = require('./backdrop-library');
|
||||
const SpriteLibrary = require('./sprite-library.jsx');
|
||||
const CostumeLibrary = require('./costume-library.jsx');
|
||||
const BackdropLibrary = require('./backdrop-library.jsx');
|
||||
|
||||
class GUI extends React.Component {
|
||||
constructor (props) {
|
||||
@@ -30,15 +31,15 @@ class GUI extends React.Component {
|
||||
this.props.vm.loadProject(this.props.projectData);
|
||||
this.props.vm.start();
|
||||
}
|
||||
componentWillUnmount () {
|
||||
this.vmManager.detachKeyboardEvents();
|
||||
this.props.vm.stopAll();
|
||||
}
|
||||
componentWillReceiveProps (nextProps) {
|
||||
if (this.props.projectData !== nextProps.projectData) {
|
||||
this.props.vm.loadProject(nextProps.projectData);
|
||||
}
|
||||
}
|
||||
componentWillUnmount () {
|
||||
this.vmManager.detachKeyboardEvents();
|
||||
this.props.vm.stopAll();
|
||||
}
|
||||
openModal (modalName) {
|
||||
this.setState({currentModal: modalName});
|
||||
}
|
||||
@@ -60,67 +61,68 @@ class GUI extends React.Component {
|
||||
vm,
|
||||
...guiProps
|
||||
} = this.props;
|
||||
backdropLibraryProps = defaultsDeep({}, backdropLibraryProps, {
|
||||
mediaLibrary: this.mediaLibrary,
|
||||
onRequestClose: this.closeModal,
|
||||
visible: this.state.currentModal === 'backdrop-library'
|
||||
});
|
||||
blocksProps = defaultsDeep({}, blocksProps, {
|
||||
options: {
|
||||
media: basePath + 'static/blocks-media/'
|
||||
media: `${basePath}static/blocks-media/`
|
||||
}
|
||||
});
|
||||
costumeLibraryProps = defaultsDeep({}, costumeLibraryProps, {
|
||||
mediaLibrary: this.mediaLibrary,
|
||||
onRequestClose: this.closeModal,
|
||||
visible: this.state.currentModal === 'costume-library'
|
||||
});
|
||||
spriteLibraryProps = defaultsDeep({}, spriteLibraryProps, {
|
||||
mediaLibrary: this.mediaLibrary,
|
||||
onRequestClose: this.closeModal,
|
||||
visible: this.state.currentModal === 'sprite-library'
|
||||
});
|
||||
spriteSelectorProps = defaultsDeep({}, spriteSelectorProps, {
|
||||
openNewBackdrop: () => this.openModal('backdrop-library'),
|
||||
openNewCostume: () => this.openModal('costume-library'),
|
||||
openNewSprite: () => this.openModal('sprite-library')
|
||||
});
|
||||
spriteLibraryProps = defaultsDeep({}, spriteLibraryProps, {
|
||||
mediaLibrary: this.mediaLibrary,
|
||||
onRequestClose: this.closeModal,
|
||||
visible: this.state.currentModal == 'sprite-library'
|
||||
});
|
||||
costumeLibraryProps = defaultsDeep({}, costumeLibraryProps, {
|
||||
mediaLibrary: this.mediaLibrary,
|
||||
onRequestClose: this.closeModal,
|
||||
visible: this.state.currentModal == 'costume-library'
|
||||
});
|
||||
backdropLibraryProps = defaultsDeep({}, backdropLibraryProps, {
|
||||
mediaLibrary: this.mediaLibrary,
|
||||
onRequestClose: this.closeModal,
|
||||
visible: this.state.currentModal == 'backdrop-library'
|
||||
});
|
||||
if (this.props.children) {
|
||||
return (
|
||||
<GUIComponent {... guiProps}>
|
||||
{this.props.children}
|
||||
</GUIComponent>
|
||||
);
|
||||
} else {
|
||||
return (
|
||||
<GUIComponent {... guiProps}>
|
||||
<GreenFlag vm={vm} {...greenFlagProps} />
|
||||
<StopAll vm={vm} {...stopAllProps} />
|
||||
<Stage vm={vm} {...stageProps} />
|
||||
<SpriteSelector vm={vm} {... spriteSelectorProps} />
|
||||
<Blocks vm={vm} {... blocksProps} />
|
||||
<SpriteLibrary vm={vm} {...spriteLibraryProps} />
|
||||
<CostumeLibrary vm={vm} {...costumeLibraryProps} />
|
||||
<BackdropLibrary vm={vm} {...backdropLibraryProps} />
|
||||
</GUIComponent>
|
||||
);
|
||||
}
|
||||
/* eslint-disable react/jsx-max-props-per-line, lines-around-comment */
|
||||
return (
|
||||
<GUIComponent {... guiProps}>
|
||||
<GreenFlag vm={vm} {...greenFlagProps} />
|
||||
<StopAll vm={vm} {...stopAllProps} />
|
||||
<Stage vm={vm} {...stageProps} />
|
||||
<SpriteSelector vm={vm} {... spriteSelectorProps} />
|
||||
<Blocks vm={vm} {... blocksProps} />
|
||||
<SpriteLibrary vm={vm} {...spriteLibraryProps} />
|
||||
<CostumeLibrary vm={vm} {...costumeLibraryProps} />
|
||||
<BackdropLibrary vm={vm} {...backdropLibraryProps} />
|
||||
</GUIComponent>
|
||||
);
|
||||
/* eslint-enable react/jsx-max-props-per-line, lines-around-comment */
|
||||
}
|
||||
}
|
||||
|
||||
GUI.propTypes = {
|
||||
backdropLibraryProps: React.PropTypes.object,
|
||||
backdropLibraryProps: shapeFromPropTypes(BackdropLibrary.propTypes, {omit: ['vm']}),
|
||||
basePath: React.PropTypes.string,
|
||||
blocksProps: React.PropTypes.object,
|
||||
costumeLibraryProps: React.PropTypes.object,
|
||||
blocksProps: shapeFromPropTypes(Blocks.propTypes, {omit: ['vm']}),
|
||||
children: React.PropTypes.node,
|
||||
greenFlagProps: React.PropTypes.object,
|
||||
costumeLibraryProps: shapeFromPropTypes(CostumeLibrary.propTypes, {omit: ['vm']}),
|
||||
greenFlagProps: shapeFromPropTypes(GreenFlag.propTypes, {omit: ['vm']}),
|
||||
projectData: React.PropTypes.string,
|
||||
spriteLibraryProps: React.PropTypes.object,
|
||||
spriteSelectorProps: React.PropTypes.object,
|
||||
stageProps: React.PropTypes.object,
|
||||
stopAllProps: React.PropTypes.object,
|
||||
vm: React.PropTypes.object,
|
||||
spriteLibraryProps: shapeFromPropTypes(SpriteLibrary.propTypes, {omit: ['vm']}),
|
||||
spriteSelectorProps: shapeFromPropTypes(SpriteSelector.propTypes, {omit: ['vm']}),
|
||||
stageProps: shapeFromPropTypes(Stage.propTypes, {omit: ['vm']}),
|
||||
stopAllProps: shapeFromPropTypes(StopAll.propTypes, {omit: ['vm']}),
|
||||
vm: React.PropTypes.instanceOf(VM),
|
||||
};
|
||||
|
||||
GUI.defaultProps = {
|
||||
@@ -1,61 +0,0 @@
|
||||
const bindAll = require('lodash.bindall');
|
||||
const React = require('react');
|
||||
const VM = require('scratch-vm');
|
||||
const MediaLibrary = require('../lib/media-library');
|
||||
|
||||
const LibaryComponent = require('../components/library');
|
||||
|
||||
class SpriteLibrary extends React.Component {
|
||||
constructor (props) {
|
||||
super(props);
|
||||
bindAll(this, ['setData', 'selectItem', 'setSpriteData']);
|
||||
this.state = {data: [], spriteData: {}};
|
||||
}
|
||||
componentWillReceiveProps (nextProps) {
|
||||
if (nextProps.visible && this.state.data.length === 0) {
|
||||
this.props.mediaLibrary.getMediaLibrary('sprite', this.setData);
|
||||
}
|
||||
}
|
||||
setData (data) {
|
||||
this.setState({data: data});
|
||||
for (let sprite of data) {
|
||||
this.props.mediaLibrary.getSprite(sprite.md5, this.setSpriteData);
|
||||
}
|
||||
}
|
||||
setSpriteData (md5, data) {
|
||||
let spriteData = this.state.spriteData;
|
||||
spriteData[md5] = data;
|
||||
this.setState({spriteData: spriteData});
|
||||
}
|
||||
selectItem (item) {
|
||||
var spriteData = JSON.stringify(this.state.spriteData[item.json]);
|
||||
this.props.vm.addSprite2(spriteData);
|
||||
}
|
||||
render () {
|
||||
let libraryData = Object.keys(this.state.spriteData).map((libraryKey) => {
|
||||
let libraryItem = this.state.spriteData[libraryKey];
|
||||
return {
|
||||
name: libraryItem.objName,
|
||||
md5: libraryItem.costumes[0].baseLayerMD5,
|
||||
json: libraryKey
|
||||
};
|
||||
});
|
||||
return <LibaryComponent
|
||||
title="Sprite Library"
|
||||
visible={this.props.visible}
|
||||
data={libraryData}
|
||||
mediaLibrary={this.props.mediaLibrary}
|
||||
onRequestClose={this.props.onRequestClose}
|
||||
onItemSelected={this.selectItem}
|
||||
/>;
|
||||
}
|
||||
}
|
||||
|
||||
SpriteLibrary.propTypes = {
|
||||
vm: React.PropTypes.instanceOf(VM).isRequired,
|
||||
mediaLibrary: React.PropTypes.instanceOf(MediaLibrary),
|
||||
visible: React.PropTypes.bool,
|
||||
onRequestClose: React.PropTypes.func
|
||||
};
|
||||
|
||||
module.exports = SpriteLibrary;
|
||||
@@ -0,0 +1,62 @@
|
||||
const bindAll = require('lodash.bindall');
|
||||
const React = require('react');
|
||||
const VM = require('scratch-vm');
|
||||
const MediaLibrary = require('../lib/media-library');
|
||||
|
||||
const LibaryComponent = require('../components/library.jsx');
|
||||
|
||||
class SpriteLibrary extends React.Component {
|
||||
constructor (props) {
|
||||
super(props);
|
||||
bindAll(this, ['setData', 'handleItemSelect', 'setSpriteData']);
|
||||
this.state = {data: [], spriteData: {}};
|
||||
}
|
||||
componentWillReceiveProps (nextProps) {
|
||||
if (nextProps.visible && this.state.data.length === 0) {
|
||||
this.props.mediaLibrary.getMediaLibrary('sprite', this.setData);
|
||||
}
|
||||
}
|
||||
setData (data) {
|
||||
this.setState({data: data});
|
||||
for (const sprite of data) {
|
||||
this.props.mediaLibrary.getSprite(sprite.md5, this.setSpriteData);
|
||||
}
|
||||
}
|
||||
setSpriteData (md5, data) {
|
||||
this.setState({
|
||||
spriteData: Object.assign({}, this.state.spriteData, {[md5]: data})
|
||||
});
|
||||
}
|
||||
handleItemSelect (item) {
|
||||
const spriteData = JSON.stringify(this.state.spriteData[item.json]);
|
||||
this.props.vm.addSprite2(spriteData);
|
||||
}
|
||||
render () {
|
||||
return (
|
||||
<LibaryComponent
|
||||
data={Object.keys(this.state.spriteData).map(libraryKey => {
|
||||
const libraryItem = this.state.spriteData[libraryKey];
|
||||
return {
|
||||
name: libraryItem.objName,
|
||||
md5: libraryItem.costumes[0].baseLayerMD5,
|
||||
json: libraryKey
|
||||
};
|
||||
})}
|
||||
mediaLibrary={this.props.mediaLibrary}
|
||||
title="Sprite Library"
|
||||
visible={this.props.visible}
|
||||
onItemSelected={this.handleItemSelect}
|
||||
onRequestClose={this.props.onRequestClose}
|
||||
/>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
SpriteLibrary.propTypes = {
|
||||
mediaLibrary: React.PropTypes.instanceOf(MediaLibrary),
|
||||
onRequestClose: React.PropTypes.func,
|
||||
visible: React.PropTypes.bool,
|
||||
vm: React.PropTypes.instanceOf(VM).isRequired
|
||||
};
|
||||
|
||||
module.exports = SpriteLibrary;
|
||||
@@ -1,12 +1,13 @@
|
||||
const bindAll = require('lodash.bindall');
|
||||
const React = require('react');
|
||||
const VM = require('scratch-vm');
|
||||
|
||||
const SpriteSelectorComponent = require('../components/sprite-selector');
|
||||
const SpriteSelectorComponent = require('../components/sprite-selector.jsx');
|
||||
|
||||
class SpriteSelector extends React.Component {
|
||||
constructor (props) {
|
||||
super(props);
|
||||
bindAll(this, ['onChange', 'targetsUpdate']);
|
||||
bindAll(this, ['handleChange', 'targetsUpdate']);
|
||||
this.state = {
|
||||
targets: {
|
||||
targetList: []
|
||||
@@ -16,7 +17,7 @@ class SpriteSelector extends React.Component {
|
||||
componentDidMount () {
|
||||
this.props.vm.on('targetsUpdate', this.targetsUpdate);
|
||||
}
|
||||
onChange (event) {
|
||||
handleChange (event) {
|
||||
this.props.vm.setEditingTarget(event.target.value);
|
||||
}
|
||||
targetsUpdate (data) {
|
||||
@@ -32,17 +33,17 @@ class SpriteSelector extends React.Component {
|
||||
} = this.props;
|
||||
return (
|
||||
<SpriteSelectorComponent
|
||||
value={this.state.targets.editingTarget && [this.state.targets.editingTarget]}
|
||||
onChange={this.onChange}
|
||||
openNewSprite={openNewSprite}
|
||||
openNewCostume={openNewCostume}
|
||||
openNewBackdrop={openNewBackdrop}
|
||||
openNewCostume={openNewCostume}
|
||||
openNewSprite={openNewSprite}
|
||||
sprites={this.state.targets.targetList.map(target => (
|
||||
{
|
||||
id: target[0],
|
||||
name: target[1]
|
||||
}
|
||||
))}
|
||||
value={this.state.targets.editingTarget && [this.state.targets.editingTarget]}
|
||||
onChange={this.handleChange}
|
||||
{...props}
|
||||
/>
|
||||
);
|
||||
@@ -50,10 +51,10 @@ class SpriteSelector extends React.Component {
|
||||
}
|
||||
|
||||
SpriteSelector.propTypes = {
|
||||
vm: React.PropTypes.object.isRequired,
|
||||
openNewSprite: React.PropTypes.func,
|
||||
openNewBackdrop: React.PropTypes.func,
|
||||
openNewCostume: React.PropTypes.func,
|
||||
openNewBackdrop: React.PropTypes.func
|
||||
openNewSprite: React.PropTypes.func,
|
||||
vm: React.PropTypes.instanceOf(VM)
|
||||
};
|
||||
|
||||
module.exports = SpriteSelector;
|
||||
@@ -3,7 +3,7 @@ const React = require('react');
|
||||
const Renderer = require('scratch-render');
|
||||
const VM = require('scratch-vm');
|
||||
|
||||
const StageComponent = require('../components/stage');
|
||||
const StageComponent = require('../components/stage.jsx');
|
||||
|
||||
class Stage extends React.Component {
|
||||
constructor (props) {
|
||||
@@ -40,8 +40,8 @@ class Stage extends React.Component {
|
||||
canvas.removeEventListener('mousedown', this.onMouseDown);
|
||||
}
|
||||
onMouseMove (e) {
|
||||
let rect = this.canvas.getBoundingClientRect();
|
||||
let coordinates = {
|
||||
const rect = this.canvas.getBoundingClientRect();
|
||||
const coordinates = {
|
||||
x: e.clientX - rect.left,
|
||||
y: e.clientY - rect.top,
|
||||
canvasWidth: rect.width,
|
||||
@@ -50,8 +50,8 @@ class Stage extends React.Component {
|
||||
this.props.vm.postIOData('mouse', coordinates);
|
||||
}
|
||||
onMouseUp (e) {
|
||||
let rect = this.canvas.getBoundingClientRect();
|
||||
let data = {
|
||||
const rect = this.canvas.getBoundingClientRect();
|
||||
const data = {
|
||||
isDown: false,
|
||||
x: e.clientX - rect.left,
|
||||
y: e.clientY - rect.top,
|
||||
@@ -62,8 +62,8 @@ class Stage extends React.Component {
|
||||
e.preventDefault();
|
||||
}
|
||||
onMouseDown (e) {
|
||||
let rect = this.canvas.getBoundingClientRect();
|
||||
let data = {
|
||||
const rect = this.canvas.getBoundingClientRect();
|
||||
const data = {
|
||||
isDown: true,
|
||||
x: e.clientX - rect.left,
|
||||
y: e.clientY - rect.top,
|
||||
@@ -90,7 +90,7 @@ class Stage extends React.Component {
|
||||
} = this.props;
|
||||
return (
|
||||
<StageComponent
|
||||
canvasRef={canvas => this.canvas = canvas}
|
||||
canvasRef={canvas => (this.canvas = canvas)}
|
||||
{...props}
|
||||
/>
|
||||
);
|
||||
@@ -1,14 +1,15 @@
|
||||
const bindAll = require('lodash.bindall');
|
||||
const React = require('react');
|
||||
const VM = require('scratch-vm');
|
||||
|
||||
const StopAllComponent = require('../components/stop-all');
|
||||
const StopAllComponent = require('../components/stop-all.jsx');
|
||||
|
||||
class StopAll extends React.Component {
|
||||
constructor (props) {
|
||||
super(props);
|
||||
bindAll(this, ['onClick']);
|
||||
bindAll(this, ['handleClick']);
|
||||
}
|
||||
onClick (e) {
|
||||
handleClick (e) {
|
||||
e.preventDefault();
|
||||
this.props.vm.stopAll();
|
||||
}
|
||||
@@ -19,7 +20,7 @@ class StopAll extends React.Component {
|
||||
} = this.props;
|
||||
return (
|
||||
<StopAllComponent
|
||||
onClick={this.onClick}
|
||||
onClick={this.handleClick}
|
||||
{...props}
|
||||
/>
|
||||
);
|
||||
@@ -27,7 +28,7 @@ class StopAll extends React.Component {
|
||||
}
|
||||
|
||||
StopAll.propTypes = {
|
||||
vm: React.PropTypes.object
|
||||
vm: React.PropTypes.instanceOf(VM)
|
||||
};
|
||||
|
||||
module.exports = StopAll;
|
||||
@@ -1,6 +1,6 @@
|
||||
const React = require('react');
|
||||
const ReactDOM = require('react-dom');
|
||||
const GUI = require('./containers/gui');
|
||||
const GUI = require('./containers/gui.jsx');
|
||||
const log = require('./lib/log');
|
||||
const ProjectLoader = require('./lib/project-loader');
|
||||
|
||||
@@ -25,7 +25,7 @@ class App extends React.Component {
|
||||
return location.hash.substring(1);
|
||||
}
|
||||
updateProject () {
|
||||
let projectId = this.fetchProjectId();
|
||||
const projectId = this.fetchProjectId();
|
||||
if (projectId !== this.state.projectId) {
|
||||
if (projectId.length < 1) {
|
||||
return this.setState({
|
||||
+2
-2
@@ -1,4 +1,4 @@
|
||||
var minilog = require('minilog');
|
||||
const minilog = require('minilog');
|
||||
minilog.enable();
|
||||
|
||||
module.exports = minilog('www');
|
||||
module.exports = minilog('gui');
|
||||
@@ -3,9 +3,9 @@ const xhr = require('xhr');
|
||||
const LIBRARY_PREFIX = 'https://cdn.scratch.mit.edu/scratchr2/static/' +
|
||||
'__8d9c95eb5aa1272a311775ca32568417__/medialibraries/';
|
||||
const LIBRARY_URL = {
|
||||
sprite: LIBRARY_PREFIX + 'spriteLibrary.json',
|
||||
costume: LIBRARY_PREFIX + 'costumeLibrary.json',
|
||||
backdrop: LIBRARY_PREFIX + 'backdropLibrary.json'
|
||||
sprite: `${LIBRARY_PREFIX}spriteLibrary.json`,
|
||||
costume: `${LIBRARY_PREFIX}costumeLibrary.json`,
|
||||
backdrop: `${LIBRARY_PREFIX}backdropLibrary.json`
|
||||
};
|
||||
const SPRITE_OBJECT_PREFIX = 'https://cdn.assets.scratch.mit.edu/internalapi/asset/';
|
||||
const SPRITE_OBJECT_SUFFIX = '/get/';
|
||||
@@ -44,7 +44,7 @@ class MediaLibrary {
|
||||
url: LIBRARY_URL[libraryType]
|
||||
}, (err, response, body) => {
|
||||
if (!err) {
|
||||
let data = JSON.parse(body);
|
||||
const data = JSON.parse(body);
|
||||
this._libraryData[libraryType] = data;
|
||||
callback(this._libraryData[libraryType]);
|
||||
}
|
||||
@@ -68,7 +68,7 @@ class MediaLibrary {
|
||||
url: SPRITE_OBJECT_PREFIX + url + SPRITE_OBJECT_SUFFIX
|
||||
}, (err, response, body) => {
|
||||
if (!err) {
|
||||
let data = JSON.parse(body);
|
||||
const data = JSON.parse(body);
|
||||
this._spriteData[url] = data;
|
||||
callback(url, data);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
const React = require('react');
|
||||
|
||||
module.exports = function shapeFromPropTypes (propTypes, opts) {
|
||||
opts = Object.assign({}, opts, {omit: []});
|
||||
const shape = Object
|
||||
.keys(propTypes)
|
||||
.filter(key => opts.omit.indexOf(key) !== -1)
|
||||
.reduce((newPropTypes, key) => {
|
||||
newPropTypes[key] = propTypes[key];
|
||||
return newPropTypes;
|
||||
}, {});
|
||||
return React.PropTypes.shape(shape);
|
||||
};
|
||||
@@ -21,7 +21,7 @@ class VMManager {
|
||||
}
|
||||
onKeyDown (e) {
|
||||
// Don't capture keys intended for Blockly inputs.
|
||||
if (e.target != document && e.target != document.body) {
|
||||
if (e.target !== document && e.target !== document.body) {
|
||||
return;
|
||||
}
|
||||
this.vm.postIOData('keyboard', {
|
||||
@@ -37,8 +37,9 @@ class VMManager {
|
||||
keyCode: e.keyCode,
|
||||
isDown: false
|
||||
});
|
||||
|
||||
// E.g., prevent scroll.
|
||||
if (e.target != document && e.target != document.body) {
|
||||
if (e.target !== document && e.target !== document.body) {
|
||||
e.preventDefault();
|
||||
}
|
||||
}
|
||||
|
||||
+4
-3
@@ -2,10 +2,11 @@ var path = require('path');
|
||||
var CopyWebpackPlugin = require('copy-webpack-plugin');
|
||||
var HtmlWebpackPlugin = require('html-webpack-plugin');
|
||||
var webpack = require('webpack');
|
||||
|
||||
module.exports = {
|
||||
entry: {
|
||||
vendor: ['react', 'react-dom'],
|
||||
gui: './src/index.js'
|
||||
gui: './src/index.jsx'
|
||||
},
|
||||
output: {
|
||||
path: path.resolve(__dirname, 'build'),
|
||||
@@ -17,7 +18,7 @@ module.exports = {
|
||||
ReactDOM: 'react-dom'
|
||||
},
|
||||
loaders: [{
|
||||
test: /\.js$/,
|
||||
test: /\.jsx?$/,
|
||||
loader: 'babel-loader',
|
||||
include: path.resolve(__dirname, 'src'),
|
||||
query: {
|
||||
@@ -45,7 +46,7 @@ module.exports = {
|
||||
from: 'node_modules/scratch-blocks/media',
|
||||
to: 'static/blocks-media'
|
||||
}])
|
||||
].concat(process.env.NODE_ENV == 'production' ? [
|
||||
].concat(process.env.NODE_ENV === 'production' ? [
|
||||
new webpack.optimize.UglifyJsPlugin({
|
||||
include: /\.min\.js$/,
|
||||
minimize: true,
|
||||
|
||||
Reference in new issue
Block a user