From f73fb880b015eefd01bc0dcf4ab01f8217808581 Mon Sep 17 00:00:00 2001 From: Florrie Date: Wed, 31 Jan 2018 14:32:40 -0400 Subject: [PATCH 001/108] (gui) Make sensing "key pressed" block input droppable --- src/lib/make-toolbox-xml.js | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/lib/make-toolbox-xml.js b/src/lib/make-toolbox-xml.js index 306c5b548..89e622541 100644 --- a/src/lib/make-toolbox-xml.js +++ b/src/lib/make-toolbox-xml.js @@ -431,7 +431,11 @@ const sensing = function (isStage) { ${blockSeparator} - + + + + + From b7d2e287adb12052f600f471fed2a18c4565fb8b Mon Sep 17 00:00:00 2001 From: kyleplo <31634240+kyleplo@users.noreply.github.com> Date: Sun, 25 Feb 2018 13:14:56 -0500 Subject: [PATCH 002/108] Update make-toolbox-xml.js --- src/lib/make-toolbox-xml.js | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/lib/make-toolbox-xml.js b/src/lib/make-toolbox-xml.js index 306c5b548..4a4027203 100644 --- a/src/lib/make-toolbox-xml.js +++ b/src/lib/make-toolbox-xml.js @@ -234,9 +234,6 @@ const looks = function (isStage, targetId) { ${blockSeparator} - - - ${blockSeparator} ${isStage ? '' : ` @@ -247,6 +244,8 @@ const looks = function (isStage, targetId) { ${blockSeparator} + + `} ${isStage ? ` From 8747315ab29c0aaa68da4d52b79023c9806ac07c Mon Sep 17 00:00:00 2001 From: Paul Kaplan Date: Mon, 26 Feb 2018 15:14:39 -0500 Subject: [PATCH 003/108] Don't update load and save buttons. This use of shouldComponentUpdate is wrapping the incorrect use of bind in the mapStateToProps call. --- src/containers/load-button.jsx | 3 +++ src/containers/save-button.jsx | 3 +++ 2 files changed, 6 insertions(+) diff --git a/src/containers/load-button.jsx b/src/containers/load-button.jsx index a7b78a638..4d7ca30b0 100644 --- a/src/containers/load-button.jsx +++ b/src/containers/load-button.jsx @@ -14,6 +14,9 @@ class LoadButton extends React.Component { 'handleClick' ]); } + shouldComponentUpdate () { + return false; + } handleChange (e) { const reader = new FileReader(); reader.onload = () => this.props.loadProject(reader.result); diff --git a/src/containers/save-button.jsx b/src/containers/save-button.jsx index f2ae497de..5516ba2c7 100644 --- a/src/containers/save-button.jsx +++ b/src/containers/save-button.jsx @@ -14,6 +14,9 @@ class SaveButton extends React.Component { 'handleClick' ]); } + shouldComponentUpdate () { + return false; + } handleClick () { const json = this.props.saveProjectSb3(); From 9842655b1effa6b420e3719cac53fff96c682558 Mon Sep 17 00:00:00 2001 From: Andrew Sliwinski Date: Mon, 26 Feb 2018 15:19:09 -0500 Subject: [PATCH 004/108] Minor fixes to sprite library. Resolves GH-1330 GH-1355 GH-1437 GH-1442 GH-1507 --- src/lib/libraries/costumes.json | 276 ++++++++++++++------- src/lib/libraries/sprites.json | 418 +++++++++++++++++++++++--------- 2 files changed, 500 insertions(+), 194 deletions(-) diff --git a/src/lib/libraries/costumes.json b/src/lib/libraries/costumes.json index 30c305182..641166986 100644 --- a/src/lib/libraries/costumes.json +++ b/src/lib/libraries/costumes.json @@ -615,6 +615,17 @@ 1 ] }, + { + "name": "Cat1", + "md5": "09dc888b0b7df19f70d81588ae73420e.svg", + "type": "costume", + "tags": [], + "info": [ + 47, + 55, + 1 + ] + }, { "name": "Cat1 Flying-a", "md5": "1e81725d2d2c7de4a2dd4a145198a43c.svg", @@ -637,6 +648,17 @@ 1 ] }, + { + "name": "Cat2", + "md5": "3696356a03a8d938318876a593572843.svg", + "type": "costume", + "tags": [], + "info": [ + 47, + 55, + 1 + ] + }, { "name": "Cloud-a", "md5": "c7d7de8e29179407f03b054fa640f4d0.svg", @@ -681,28 +703,6 @@ 1 ] }, - { - "name": "Costume1", - "md5": "09dc888b0b7df19f70d81588ae73420e.svg", - "type": "costume", - "tags": [], - "info": [ - 47, - 55, - 1 - ] - }, - { - "name": "Costume2", - "md5": "3696356a03a8d938318876a593572843.svg", - "type": "costume", - "tags": [], - "info": [ - 47, - 55, - 1 - ] - }, { "name": "Crab-a", "md5": "114249a5660f7948663d95de575cfd8d.svg", @@ -1244,12 +1244,12 @@ }, { "name": "Drum-snare-a", - "md5": "31a81bb560abf30cbc44bcdd581d5ccc.svg", + "md5": "b0255be93e3c8be6ac687f4199a25c4b.svg", "type": "costume", "tags": [], "info": [ - 40, - 69, + 23, + 50, 1 ] }, @@ -1266,12 +1266,12 @@ }, { "name": "Drum-snare-c", - "md5": "878ea646cbbd2a9e24fdeb8d98c3e24f.svg", + "md5": "0b50639f4aac75a7e1061083401e0c40.svg", "type": "costume", "tags": [], "info": [ - 40, - 69, + 37, + 61, 1 ] }, @@ -1913,61 +1913,6 @@ 1 ] }, - { - "name": "Jez-b", - "md5": "f1e74f3c02333e9e2068e8baf4e77aa0.svg", - "type": "costume", - "tags": [], - "info": [ - 67, - 95, - 1 - ] - }, - { - "name": "Jez-c", - "md5": "e2482cf509c312935f08be0e2e2c9d84.svg", - "type": "costume", - "tags": [], - "info": [ - 67, - 95, - 1 - ] - }, - { - "name": "Jez-d", - "md5": "569e736b519199efddfbae2572f7e92b.svg", - "type": "costume", - "tags": [], - "info": [ - 67, - 95, - 1 - ] - }, - { - "name": "Jez-e", - "md5": "2261bed0f2cc819def17969158297b4f.svg", - "type": "costume", - "tags": [], - "info": [ - 77, - 95, - 1 - ] - }, - { - "name": "Jez-f", - "md5": "d7f44adb3dc7906b9dfb3599a028e0d6.svg", - "type": "costume", - "tags": [], - "info": [ - 62, - 94, - 1 - ] - }, { "name": "Jordyn-a", "md5": "8dd2a2abbb8e639da8576b6e72ef9e59.svg", @@ -2056,6 +2001,61 @@ 1 ] }, + { + "name": "Kiran-b", + "md5": "f1e74f3c02333e9e2068e8baf4e77aa0.svg", + "type": "costume", + "tags": [], + "info": [ + 67, + 95, + 1 + ] + }, + { + "name": "Kiran-c", + "md5": "e2482cf509c312935f08be0e2e2c9d84.svg", + "type": "costume", + "tags": [], + "info": [ + 67, + 95, + 1 + ] + }, + { + "name": "Kiran-d", + "md5": "569e736b519199efddfbae2572f7e92b.svg", + "type": "costume", + "tags": [], + "info": [ + 67, + 95, + 1 + ] + }, + { + "name": "Kiran-e", + "md5": "2261bed0f2cc819def17969158297b4f.svg", + "type": "costume", + "tags": [], + "info": [ + 77, + 95, + 1 + ] + }, + { + "name": "Kiran-f", + "md5": "d7f44adb3dc7906b9dfb3599a028e0d6.svg", + "type": "costume", + "tags": [], + "info": [ + 62, + 94, + 1 + ] + }, { "name": "Knight", "md5": "f2c5e8bc24d001b81566879dbf2f1a13.svg", @@ -2551,6 +2551,61 @@ 1 ] }, + { + "name": "Penguin1 Talk-a", + "md5": "35fec7aa5f60cca945fe0615413f1f08.svg", + "type": "costume", + "tags": [], + "info": [ + 48, + 62, + 1 + ] + }, + { + "name": "Penguin1 Talk-b", + "md5": "18fa51a64ebd5518f0c5c465525346e5.svg", + "type": "costume", + "tags": [], + "info": [ + 48, + 61, + 1 + ] + }, + { + "name": "Penguin2", + "md5": "eaaaa7068e78a51d73ba437f1ec5763e.svg", + "type": "costume", + "tags": [], + "info": [ + 49, + 79, + 1 + ] + }, + { + "name": "Penguin2 Talk-a", + "md5": "5a80f4b2fd20d43e4f7cb4189c08d99c.svg", + "type": "costume", + "tags": [], + "info": [ + 45, + 79, + 1 + ] + }, + { + "name": "Penguin2 Talk-b", + "md5": "394e79f5f9a462064ece2a9a6606a07d.svg", + "type": "costume", + "tags": [], + "info": [ + 50, + 78, + 1 + ] + }, { "name": "Pico-a", "md5": "0579fe60bb3717c49dfd7743caa84ada.svg", @@ -2936,6 +2991,39 @@ 1 ] }, + { + "name": "Shark-a ", + "md5": "7c0a907eae79462f69f8e2af8e7df828.svg", + "type": "costume", + "tags": [], + "info": [ + 75, + 75, + 1 + ] + }, + { + "name": "Shark-b ", + "md5": "cff9ae87a93294693a0650b38a7a33d2.svg", + "type": "costume", + "tags": [], + "info": [ + 75, + 75, + 1 + ] + }, + { + "name": "Shark-c ", + "md5": "afeae3f998598424f7c50918507f6ce6.svg", + "type": "costume", + "tags": [], + "info": [ + 77, + 37, + 1 + ] + }, { "name": "Snake-a", "md5": "4d06e12d90479461303d828f0970f2d4.svg", @@ -3057,6 +3145,28 @@ 1 ] }, + { + "name": "Starfish-a", + "md5": "3d1101bbc24ae292a36356af325f660c.svg", + "type": "costume", + "tags": [], + "info": [ + 75, + 75, + 1 + ] + }, + { + "name": "Starfish-b ", + "md5": "ad8007f4e63693984d4adc466ffa3ad2.svg", + "type": "costume", + "tags": [], + "info": [ + 53, + 60, + 1 + ] + }, { "name": "Strawberry-a", "md5": "734556fb8e14740f2cbc971238b71d47.svg", diff --git a/src/lib/libraries/sprites.json b/src/lib/libraries/sprites.json index 349bc3064..385167dc6 100644 --- a/src/lib/libraries/sprites.json +++ b/src/lib/libraries/sprites.json @@ -62,7 +62,7 @@ "direction": 90, "rotationStyle": "normal", "isDraggable": false, - "indexInLibrary": 10, + "indexInLibrary": 11, "visible": true, "spriteInfo": {} } @@ -456,7 +456,7 @@ } }, { - "name": "Bat3", + "name": "Bat2", "md5": "647d4bd53163f94a7dabf623ccab7fd3.svg", "type": "sprite", "tags": [], @@ -466,7 +466,7 @@ 1 ], "json": { - "objName": "Bat3", + "objName": "Bat2", "sounds": [ { "soundName": "pop", @@ -502,7 +502,7 @@ "direction": 90, "rotationStyle": "normal", "isDraggable": false, - "indexInLibrary": 12, + "indexInLibrary": 10, "visible": true, "spriteInfo": {} } @@ -546,7 +546,7 @@ "direction": 90, "rotationStyle": "normal", "isDraggable": false, - "indexInLibrary": 11, + "indexInLibrary": 12, "visible": true, "spriteInfo": {} } @@ -1169,7 +1169,7 @@ "objName": "Cake", "sounds": [ { - "soundName": "birthday song", + "soundName": "birthday", "soundID": -1, "md5": "89691587a169d935a58c48c3d4e78534.wav", "sampleCount": 161408, @@ -1299,7 +1299,7 @@ ], "costumes": [ { - "costumeName": "costume1", + "costumeName": "cat1", "baseLayerID": -1, "baseLayerMD5": "09dc888b0b7df19f70d81588ae73420e.svg", "bitmapResolution": 1, @@ -1307,7 +1307,7 @@ "rotationCenterY": 55 }, { - "costumeName": "costume2", + "costumeName": "cat2", "baseLayerID": -1, "baseLayerMD5": "3696356a03a8d938318876a593572843.svg", "bitmapResolution": 1, @@ -1315,7 +1315,7 @@ "rotationCenterY": 55 } ], - "currentCostumeIndex": 0, + "currentCostumeIndex": 1, "scratchX": 0, "scratchY": 0, "scale": 1, @@ -2465,7 +2465,7 @@ }, { "name": "Drum-snare", - "md5": "31a81bb560abf30cbc44bcdd581d5ccc.svg", + "md5": "b0255be93e3c8be6ac687f4199a25c4b.svg", "type": "sprite", "tags": [], "info": [ @@ -2504,15 +2504,15 @@ "costumes": [ { "costumeName": "drum-snare-a", - "baseLayerID": -1, - "baseLayerMD5": "31a81bb560abf30cbc44bcdd581d5ccc.svg", + "baseLayerID": 0, + "baseLayerMD5": "b0255be93e3c8be6ac687f4199a25c4b.svg", "bitmapResolution": 1, - "rotationCenterX": 40, - "rotationCenterY": 69 + "rotationCenterX": 23, + "rotationCenterY": 50 }, { "costumeName": "drum-snare-b", - "baseLayerID": 0, + "baseLayerID": -1, "baseLayerMD5": "f6d2f2a6e1055dab6262336625ddf652.svg", "bitmapResolution": 1, "rotationCenterX": 36, @@ -2520,14 +2520,14 @@ }, { "costumeName": "drum-snare-c", - "baseLayerID": -1, - "baseLayerMD5": "878ea646cbbd2a9e24fdeb8d98c3e24f.svg", + "baseLayerID": 1, + "baseLayerMD5": "0b50639f4aac75a7e1061083401e0c40.svg", "bitmapResolution": 1, - "rotationCenterX": 40, - "rotationCenterY": 69 + "rotationCenterX": 37, + "rotationCenterY": 61 } ], - "currentCostumeIndex": 1, + "currentCostumeIndex": 0, "scratchX": 45, "scratchY": -33, "scale": 1, @@ -3711,17 +3711,25 @@ "info": [ 0, 2, - 1 + 2 ], "json": { "objName": "Horse1", "sounds": [ { - "soundName": "meow", + "soundName": "horse", "soundID": -1, - "md5": "83c36d806dc92327b9e7049a565c6bff.wav", - "sampleCount": 18688, - "rate": 22050, + "md5": "45ffcf97ee2edca0199ff5aa71a5b72e.wav", + "sampleCount": 14464, + "rate": 11025, + "format": "" + }, + { + "soundName": "horse gallop", + "soundID": -1, + "md5": "058a34b5fb8b57178b5322d994b6b8c8.wav", + "sampleCount": 38336, + "rate": 11025, "format": "" } ], @@ -3891,90 +3899,6 @@ "spriteInfo": {} } }, - { - "name": "Jez", - "md5": "9de23c4a7a7fbb67136b539241346854.svg", - "type": "sprite", - "tags": [], - "info": [ - 0, - 6, - 1 - ], - "json": { - "objName": "jez", - "sounds": [ - { - "soundName": "pop", - "soundID": -1, - "md5": "83a9787d4cb6f3b7632b4ddfebf74367.wav", - "sampleCount": 258, - "rate": 11025, - "format": "" - } - ], - "costumes": [ - { - "costumeName": "kiran-a", - "baseLayerID": -1, - "baseLayerMD5": "9de23c4a7a7fbb67136b539241346854.svg", - "bitmapResolution": 1, - "rotationCenterX": 67, - "rotationCenterY": 95 - }, - { - "costumeName": "jez-b", - "baseLayerID": -1, - "baseLayerMD5": "f1e74f3c02333e9e2068e8baf4e77aa0.svg", - "bitmapResolution": 1, - "rotationCenterX": 67, - "rotationCenterY": 95 - }, - { - "costumeName": "jez-c", - "baseLayerID": -1, - "baseLayerMD5": "e2482cf509c312935f08be0e2e2c9d84.svg", - "bitmapResolution": 1, - "rotationCenterX": 67, - "rotationCenterY": 95 - }, - { - "costumeName": "jez-d", - "baseLayerID": -1, - "baseLayerMD5": "569e736b519199efddfbae2572f7e92b.svg", - "bitmapResolution": 1, - "rotationCenterX": 67, - "rotationCenterY": 95 - }, - { - "costumeName": "jez-e", - "baseLayerID": -1, - "baseLayerMD5": "2261bed0f2cc819def17969158297b4f.svg", - "bitmapResolution": 1, - "rotationCenterX": 77, - "rotationCenterY": 95 - }, - { - "costumeName": "jez-f", - "baseLayerID": -1, - "baseLayerMD5": "d7f44adb3dc7906b9dfb3599a028e0d6.svg", - "bitmapResolution": 1, - "rotationCenterX": 62, - "rotationCenterY": 94 - } - ], - "currentCostumeIndex": 0, - "scratchX": 57, - "scratchY": -42, - "scale": 0.8, - "direction": 90, - "rotationStyle": "normal", - "isDraggable": false, - "indexInLibrary": 3, - "visible": true, - "spriteInfo": {} - } - }, { "name": "Jordyn", "md5": "8dd2a2abbb8e639da8576b6e72ef9e59.svg", @@ -4159,6 +4083,90 @@ "spriteInfo": {} } }, + { + "name": "Kiran", + "md5": "9de23c4a7a7fbb67136b539241346854.svg", + "type": "sprite", + "tags": [], + "info": [ + 0, + 6, + 1 + ], + "json": { + "objName": "kiran", + "sounds": [ + { + "soundName": "pop", + "soundID": -1, + "md5": "83a9787d4cb6f3b7632b4ddfebf74367.wav", + "sampleCount": 258, + "rate": 11025, + "format": "" + } + ], + "costumes": [ + { + "costumeName": "kiran-a", + "baseLayerID": -1, + "baseLayerMD5": "9de23c4a7a7fbb67136b539241346854.svg", + "bitmapResolution": 1, + "rotationCenterX": 67, + "rotationCenterY": 95 + }, + { + "costumeName": "kiran-b", + "baseLayerID": -1, + "baseLayerMD5": "f1e74f3c02333e9e2068e8baf4e77aa0.svg", + "bitmapResolution": 1, + "rotationCenterX": 67, + "rotationCenterY": 95 + }, + { + "costumeName": "kiran-c", + "baseLayerID": -1, + "baseLayerMD5": "e2482cf509c312935f08be0e2e2c9d84.svg", + "bitmapResolution": 1, + "rotationCenterX": 67, + "rotationCenterY": 95 + }, + { + "costumeName": "kiran-d", + "baseLayerID": -1, + "baseLayerMD5": "569e736b519199efddfbae2572f7e92b.svg", + "bitmapResolution": 1, + "rotationCenterX": 67, + "rotationCenterY": 95 + }, + { + "costumeName": "kiran-e", + "baseLayerID": -1, + "baseLayerMD5": "2261bed0f2cc819def17969158297b4f.svg", + "bitmapResolution": 1, + "rotationCenterX": 77, + "rotationCenterY": 95 + }, + { + "costumeName": "kiran-f", + "baseLayerID": -1, + "baseLayerMD5": "d7f44adb3dc7906b9dfb3599a028e0d6.svg", + "bitmapResolution": 1, + "rotationCenterX": 62, + "rotationCenterY": 94 + } + ], + "currentCostumeIndex": 0, + "scratchX": 57, + "scratchY": -42, + "scale": 0.8, + "direction": 90, + "rotationStyle": "normal", + "isDraggable": false, + "indexInLibrary": 3, + "visible": true, + "spriteInfo": {} + } + }, { "name": "Knight", "md5": "f2c5e8bc24d001b81566879dbf2f1a13.svg", @@ -5086,7 +5094,7 @@ "tags": [], "info": [ 0, - 1, + 3, 1 ], "json": { @@ -5109,9 +5117,25 @@ "bitmapResolution": 1, "rotationCenterX": 54, "rotationCenterY": 61 + }, + { + "costumeName": "penguin1 talk-a", + "baseLayerID": -1, + "baseLayerMD5": "35fec7aa5f60cca945fe0615413f1f08.svg", + "bitmapResolution": 1, + "rotationCenterX": 48, + "rotationCenterY": 62 + }, + { + "costumeName": "penguin1 talk-b", + "baseLayerID": -1, + "baseLayerMD5": "18fa51a64ebd5518f0c5c465525346e5.svg", + "bitmapResolution": 1, + "rotationCenterX": 48, + "rotationCenterY": 61 } ], - "currentCostumeIndex": 0, + "currentCostumeIndex": 1, "scratchX": -58, "scratchY": -19, "scale": 1, @@ -5123,6 +5147,66 @@ "spriteInfo": {} } }, + { + "name": "Penguin2", + "md5": "eaaaa7068e78a51d73ba437f1ec5763e.svg", + "type": "sprite", + "tags": [], + "info": [ + 0, + 3, + 1 + ], + "json": { + "objName": "Penguin2", + "sounds": [ + { + "soundName": "pop", + "soundID": -1, + "md5": "83a9787d4cb6f3b7632b4ddfebf74367.wav", + "sampleCount": 258, + "rate": 11025, + "format": "" + } + ], + "costumes": [ + { + "costumeName": "penguin2", + "baseLayerID": -1, + "baseLayerMD5": "eaaaa7068e78a51d73ba437f1ec5763e.svg", + "bitmapResolution": 1, + "rotationCenterX": 49, + "rotationCenterY": 79 + }, + { + "costumeName": "penguin2 talk-a", + "baseLayerID": -1, + "baseLayerMD5": "5a80f4b2fd20d43e4f7cb4189c08d99c.svg", + "bitmapResolution": 1, + "rotationCenterX": 45, + "rotationCenterY": 79 + }, + { + "costumeName": "penguin2 talk-b", + "baseLayerID": -1, + "baseLayerMD5": "394e79f5f9a462064ece2a9a6606a07d.svg", + "bitmapResolution": 1, + "rotationCenterX": 50, + "rotationCenterY": 78 + } + ], + "currentCostumeIndex": 0, + "scratchX": 95, + "scratchY": 44, + "scale": 1, + "direction": 90, + "rotationStyle": "normal", + "isDraggable": false, + "indexInLibrary": 62, + "visible": true, + "spriteInfo": {} + } + }, { "name": "Pico", "md5": "0579fe60bb3717c49dfd7743caa84ada.svg", @@ -5791,6 +5875,66 @@ "spriteInfo": {} } }, + { + "name": "Shark", + "md5": "7c0a907eae79462f69f8e2af8e7df828.svg", + "type": "sprite", + "tags": [], + "info": [ + 0, + 3, + 1 + ], + "json": { + "objName": "Shark", + "sounds": [ + { + "soundName": "pop", + "soundID": -1, + "md5": "83a9787d4cb6f3b7632b4ddfebf74367.wav", + "sampleCount": 258, + "rate": 11025, + "format": "" + } + ], + "costumes": [ + { + "costumeName": "shark-a ", + "baseLayerID": -1, + "baseLayerMD5": "7c0a907eae79462f69f8e2af8e7df828.svg", + "bitmapResolution": 1, + "rotationCenterX": 75, + "rotationCenterY": 75 + }, + { + "costumeName": "shark-b ", + "baseLayerID": -1, + "baseLayerMD5": "cff9ae87a93294693a0650b38a7a33d2.svg", + "bitmapResolution": 1, + "rotationCenterX": 75, + "rotationCenterY": 75 + }, + { + "costumeName": "shark-c ", + "baseLayerID": -1, + "baseLayerMD5": "afeae3f998598424f7c50918507f6ce6.svg", + "bitmapResolution": 1, + "rotationCenterX": 77, + "rotationCenterY": 37 + } + ], + "currentCostumeIndex": 0, + "scratchX": 41, + "scratchY": -15, + "scale": 1, + "direction": 90, + "rotationStyle": "normal", + "isDraggable": false, + "indexInLibrary": 63, + "visible": true, + "spriteInfo": {} + } + }, { "name": "Snake", "md5": "4d06e12d90479461303d828f0970f2d4.svg", @@ -6359,6 +6503,58 @@ "spriteInfo": {} } }, + { + "name": "Starfish", + "md5": "3d1101bbc24ae292a36356af325f660c.svg", + "type": "sprite", + "tags": [], + "info": [ + 0, + 2, + 1 + ], + "json": { + "objName": "Starfish", + "sounds": [ + { + "soundName": "pop", + "soundID": -1, + "md5": "83a9787d4cb6f3b7632b4ddfebf74367.wav", + "sampleCount": 258, + "rate": 11025, + "format": "" + } + ], + "costumes": [ + { + "costumeName": "starfish-a", + "baseLayerID": -1, + "baseLayerMD5": "3d1101bbc24ae292a36356af325f660c.svg", + "bitmapResolution": 1, + "rotationCenterX": 75, + "rotationCenterY": 75 + }, + { + "costumeName": "starfish-b ", + "baseLayerID": -1, + "baseLayerMD5": "ad8007f4e63693984d4adc466ffa3ad2.svg", + "bitmapResolution": 1, + "rotationCenterX": 53, + "rotationCenterY": 60 + } + ], + "currentCostumeIndex": 1, + "scratchX": -37, + "scratchY": 38, + "scale": 1, + "direction": 90, + "rotationStyle": "normal", + "isDraggable": false, + "indexInLibrary": 64, + "visible": true, + "spriteInfo": {} + } + }, { "name": "Strawberry", "md5": "734556fb8e14740f2cbc971238b71d47.svg", From 5a9679fa40ebbbde3425b4cf4f073e0d6c262e50 Mon Sep 17 00:00:00 2001 From: Paul Kaplan Date: Mon, 26 Feb 2018 15:27:04 -0500 Subject: [PATCH 005/108] Don't use bind in mapStateToProps --- src/containers/load-button.jsx | 13 ++++++------- src/containers/save-button.jsx | 14 ++++++-------- 2 files changed, 12 insertions(+), 15 deletions(-) diff --git a/src/containers/load-button.jsx b/src/containers/load-button.jsx index 4d7ca30b0..ad6ba9d4e 100644 --- a/src/containers/load-button.jsx +++ b/src/containers/load-button.jsx @@ -14,12 +14,9 @@ class LoadButton extends React.Component { 'handleClick' ]); } - shouldComponentUpdate () { - return false; - } handleChange (e) { const reader = new FileReader(); - reader.onload = () => this.props.loadProject(reader.result); + reader.onload = () => this.props.vm.fromJSON(reader.result); reader.readAsText(e.target.files[0]); } handleClick () { @@ -30,7 +27,7 @@ class LoadButton extends React.Component { } render () { const { - loadProject, // eslint-disable-line no-unused-vars + vm, // eslint-disable-line no-unused-vars ...props } = this.props; return ( @@ -45,11 +42,13 @@ class LoadButton extends React.Component { } LoadButton.propTypes = { - loadProject: PropTypes.func.isRequired + vm: PropTypes.shape({ + fromJSON: PropTypes.func + }) }; const mapStateToProps = state => ({ - loadProject: state.vm.fromJSON.bind(state.vm) + vm: state.vm }); export default connect( diff --git a/src/containers/save-button.jsx b/src/containers/save-button.jsx index 5516ba2c7..8e130fbf5 100644 --- a/src/containers/save-button.jsx +++ b/src/containers/save-button.jsx @@ -14,11 +14,8 @@ class SaveButton extends React.Component { 'handleClick' ]); } - shouldComponentUpdate () { - return false; - } handleClick () { - const json = this.props.saveProjectSb3(); + const json = this.props.vm.saveProjectSb3(); // Download project data into a file - create link element, // simulate click on it, and then remove it. @@ -39,7 +36,7 @@ class SaveButton extends React.Component { } render () { const { - saveProjectSb3, // eslint-disable-line no-unused-vars + vm, // eslint-disable-line no-unused-vars ...props } = this.props; return ( @@ -60,11 +57,12 @@ class SaveButton extends React.Component { } SaveButton.propTypes = { - saveProjectSb3: PropTypes.func.isRequired -}; + vm: PropTypes.shape({ + saveProjectSb3: PropTypes.func + })}; const mapStateToProps = state => ({ - saveProjectSb3: state.vm.saveProjectSb3.bind(state.vm) + vm: state.vm }); export default connect( From b046a224fe7551468b340e30fdd935a0bbddd6df Mon Sep 17 00:00:00 2001 From: Paul Kaplan Date: Mon, 26 Feb 2018 15:27:28 -0500 Subject: [PATCH 006/108] Pass in only the props that the paint editor needs to prevent rerender --- src/containers/costume-tab.jsx | 1 - src/containers/paint-editor-wrapper.jsx | 3 ++- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/containers/costume-tab.jsx b/src/containers/costume-tab.jsx index 2e897c451..c54f2667f 100644 --- a/src/containers/costume-tab.jsx +++ b/src/containers/costume-tab.jsx @@ -218,7 +218,6 @@ class CostumeTab extends React.Component { > {target.costumes ? : null diff --git a/src/containers/paint-editor-wrapper.jsx b/src/containers/paint-editor-wrapper.jsx index 38cb3aa4a..52bb5708f 100644 --- a/src/containers/paint-editor-wrapper.jsx +++ b/src/containers/paint-editor-wrapper.jsx @@ -59,7 +59,8 @@ const mapStateToProps = (state, {selectedCostumeIndex}) => { name: costume && costume.name, rotationCenterX: costume && costume.rotationCenterX, rotationCenterY: costume && costume.rotationCenterY, - svgId: editingTarget && `${editingTarget}${costume.skinId}` + svgId: editingTarget && `${editingTarget}${costume.skinId}`, + vm: state.vm }; }; From bfdc1db2e0c4a09b6836e2fefed3eb2ee82db57f Mon Sep 17 00:00:00 2001 From: Paul Kaplan Date: Mon, 26 Feb 2018 15:41:08 -0500 Subject: [PATCH 007/108] Don't bind in mapStateToProps to prevent sound editor re-render --- src/containers/sound-editor.jsx | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/src/containers/sound-editor.jsx b/src/containers/sound-editor.jsx index bbe032c0b..de10ebc2c 100644 --- a/src/containers/sound-editor.jsx +++ b/src/containers/sound-editor.jsx @@ -89,7 +89,7 @@ class SoundEditor extends React.Component { } this.resetState(samples, sampleRate); - this.props.onUpdateSoundBuffer( + this.props.vm.updateSoundBuffer( this.props.soundIndex, this.audioBufferPlayer.buffer, wavBuffer ? new Uint8Array(wavBuffer) : new Uint8Array()); @@ -112,7 +112,7 @@ class SoundEditor extends React.Component { this.setState({playhead}); } handleChangeName (name) { - this.props.onRenameSound(this.props.soundIndex, name); + this.props.vm.renameSound(this.props.soundIndex, name); } handleActivateTrim () { if (this.state.trimStart === null && this.state.trimEnd === null) { @@ -200,12 +200,14 @@ class SoundEditor extends React.Component { SoundEditor.propTypes = { name: PropTypes.string.isRequired, - onRenameSound: PropTypes.func.isRequired, - onUpdateSoundBuffer: PropTypes.func.isRequired, sampleRate: PropTypes.number, samples: PropTypes.instanceOf(Float32Array), soundId: PropTypes.string, - soundIndex: PropTypes.number + soundIndex: PropTypes.number, + vm: PropTypes.shape({ + updateSoundBuffer: PropTypes.func, + renameSound: PropTypes.func + }) }; const mapStateToProps = (state, {soundIndex}) => { @@ -219,8 +221,7 @@ const mapStateToProps = (state, {soundIndex}) => { sampleRate: audioBuffer.sampleRate, samples: audioBuffer.getChannelData(0), name: sound.name, - onRenameSound: state.vm.renameSound.bind(state.vm), - onUpdateSoundBuffer: state.vm.updateSoundBuffer.bind(state.vm) + vm: state.vm }; }; From 92f1d6447335fb0241aeac795eead32f52b79f60 Mon Sep 17 00:00:00 2001 From: Paul Kaplan Date: Tue, 27 Feb 2018 09:33:46 -0500 Subject: [PATCH 008/108] Cache Renderer.isSupported because it takes 30ms every time --- src/components/gui/gui.jsx | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/components/gui/gui.jsx b/src/components/gui/gui.jsx index 488e705e8..da08720d1 100644 --- a/src/components/gui/gui.jsx +++ b/src/components/gui/gui.jsx @@ -33,6 +33,10 @@ const messages = defineMessages({ } }); +// Cache this value to only retreive it once the first time. +// Assume that it doesn't change for a session. +let isRendererSupported = null; + const GUIComponent = props => { const { activeTabIndex, @@ -66,7 +70,9 @@ const GUIComponent = props => { tabSelected: classNames(tabStyles.reactTabsTabSelected, styles.isSelected) }; - const isRendererSupported = Renderer.isSupported(); + if (isRendererSupported === null) { + isRendererSupported = Renderer.isSupported(); + } return ( Date: Wed, 28 Feb 2018 15:29:36 -0500 Subject: [PATCH 009/108] onMouseUp should tell the vm that the mouse is up even if a drag just ended. --- src/containers/stage.jsx | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/src/containers/stage.jsx b/src/containers/stage.jsx index c386112b3..8687923e5 100644 --- a/src/containers/stage.jsx +++ b/src/containers/stage.jsx @@ -188,16 +188,15 @@ class Stage extends React.Component { }); if (this.state.isDragging) { this.onStopDrag(); - } else { - const data = { - isDown: false, - x: x - this.rect.left, - y: y - this.rect.top, - canvasWidth: this.rect.width, - canvasHeight: this.rect.height - }; - this.props.vm.postIOData('mouse', data); } + const data = { + isDown: false, + x: x - this.rect.left, + y: y - this.rect.top, + canvasWidth: this.rect.width, + canvasHeight: this.rect.height + }; + this.props.vm.postIOData('mouse', data); } onMouseDown (e) { this.updateRect(); From ff37a347d09864d959e87015b9bac37ce024cc24 Mon Sep 17 00:00:00 2001 From: Karishma Chadha Date: Wed, 28 Feb 2018 16:34:35 -0500 Subject: [PATCH 010/108] Send flag to vm to indicate that mouse-up event was also the end of a drag. VM should use this flag to selectively activate the sprite click hat. --- src/containers/stage.jsx | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/containers/stage.jsx b/src/containers/stage.jsx index 8687923e5..a56ae7330 100644 --- a/src/containers/stage.jsx +++ b/src/containers/stage.jsx @@ -186,9 +186,6 @@ class Stage extends React.Component { mouseDown: false, mouseDownPosition: null }); - if (this.state.isDragging) { - this.onStopDrag(); - } const data = { isDown: false, x: x - this.rect.left, @@ -196,6 +193,10 @@ class Stage extends React.Component { canvasWidth: this.rect.width, canvasHeight: this.rect.height }; + if (this.state.isDragging) { + this.onStopDrag(); + data.wasDragged = true; + } this.props.vm.postIOData('mouse', data); } onMouseDown (e) { From d87b34cd0ae5efc3023be921f2e4963c9fabf025 Mon Sep 17 00:00:00 2001 From: DD Date: Fri, 2 Mar 2018 13:50:36 -0500 Subject: [PATCH 011/108] Switch to the correct costume number when switching sprites --- src/containers/costume-tab.jsx | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/containers/costume-tab.jsx b/src/containers/costume-tab.jsx index 2e897c451..30d138406 100644 --- a/src/containers/costume-tab.jsx +++ b/src/containers/costume-tab.jsx @@ -90,7 +90,14 @@ class CostumeTab extends React.Component { } = nextProps; const target = editingTarget && sprites[editingTarget] ? sprites[editingTarget] : stage; - if (target && target.costumes && this.state.selectedCostumeIndex > target.costumes.length - 1) { + if (!target || !target.costumes) { + return; + } + + // If switching editing targets, update the costume index + if (this.props.editingTarget !== editingTarget) { + this.setState({selectedCostumeIndex: target.currentCostume}); + } else if (this.state.selectedCostumeIndex > target.costumes.length - 1) { this.setState({selectedCostumeIndex: target.costumes.length - 1}); } } From 4da72835fe8246154df44c0435b12b2cadeca672 Mon Sep 17 00:00:00 2001 From: DD Date: Fri, 2 Mar 2018 14:01:51 -0500 Subject: [PATCH 012/108] Set index for sounds too. Reseting to sound 0 matches scratch 2 behavior --- src/containers/sound-tab.jsx | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/containers/sound-tab.jsx b/src/containers/sound-tab.jsx index 471ebe99e..b0b4e3d22 100644 --- a/src/containers/sound-tab.jsx +++ b/src/containers/sound-tab.jsx @@ -46,8 +46,14 @@ class SoundTab extends React.Component { } = nextProps; const target = editingTarget && sprites[editingTarget] ? sprites[editingTarget] : stage; + if (!target || !target.sounds) { + return; + } - if (target && target.sounds && this.state.selectedSoundIndex > target.sounds.length - 1) { + // If switching editing targets, reset the sound index + if (this.props.editingTarget !== editingTarget) { + this.setState({selectedSoundIndex: 0}); + } else if (this.state.selectedSoundIndex > target.sounds.length - 1) { this.setState({selectedSoundIndex: Math.max(target.sounds.length - 1, 0)}); } } From 1adf6b24f53bd3691de240e5601b190bcf82a7cf Mon Sep 17 00:00:00 2001 From: Karishma Chadha Date: Sun, 4 Mar 2018 16:45:51 -0500 Subject: [PATCH 013/108] allow http url in import modal --- src/containers/import-modal.jsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/containers/import-modal.jsx b/src/containers/import-modal.jsx index 1c2ddbefb..0731098f1 100644 --- a/src/containers/import-modal.jsx +++ b/src/containers/import-modal.jsx @@ -51,7 +51,7 @@ class ImportModal extends React.Component { this.setState({inputValue: e.target.value, hasValidationError: false}); } validate (input) { - const urlMatches = input.match(/^(?:https:\/\/)?scratch\.mit\.edu\/projects\/(\d+)/); + const urlMatches = input.match(/^(?:https?:\/\/)?scratch\.mit\.edu\/projects\/(\d+)/); if (urlMatches && urlMatches.length > 0) { return urlMatches[1]; } From 8641ae2ab37d941c32d816bfa9a8320d5f2978d1 Mon Sep 17 00:00:00 2001 From: Karishma Chadha Date: Tue, 13 Feb 2018 10:54:01 -0500 Subject: [PATCH 014/108] Update save button to download zip of project json + serialized assets (costumes and sounds). --- package.json | 1 + src/containers/save-button.jsx | 43 +++++++++++++++++++++++++--------- 2 files changed, 33 insertions(+), 11 deletions(-) diff --git a/package.json b/package.json index b8649d8c1..f621d12f2 100644 --- a/package.json +++ b/package.json @@ -55,6 +55,7 @@ "html-webpack-plugin": "^2.30.0", "immutable": "3.8.2", "jest": "^21.0.0", + "jszip": "^3.1.5", "lodash.bindall": "4.4.0", "lodash.debounce": "4.0.8", "lodash.defaultsdeep": "4.6.0", diff --git a/src/containers/save-button.jsx b/src/containers/save-button.jsx index f2ae497de..e64ade4b1 100644 --- a/src/containers/save-button.jsx +++ b/src/containers/save-button.jsx @@ -2,6 +2,7 @@ import bindAll from 'lodash.bindall'; import PropTypes from 'prop-types'; import React from 'react'; import {connect} from 'react-redux'; +import JSZip from 'jszip'; import ButtonComponent from '../components/button/button.jsx'; import {ComingSoonTooltip} from '../components/coming-soon/coming-soon.jsx'; @@ -15,24 +16,44 @@ class SaveButton extends React.Component { ]); } handleClick () { - const json = this.props.saveProjectSb3(); + const zip = new JSZip(); + // Get the serialized project and assets from vm + const projectInfo = this.props.saveProjectSb3(); + + const json = projectInfo.projectJson; + const sounds = projectInfo.sounds; + const costumes = projectInfo.costumes; + + // Put everything in a zip file + zip.file('project.json', json); + for (let i = 0; i < sounds.length; i++) { + const currSound = sounds[i]; + zip.file(currSound.fileName, currSound.fileContent); + } + for (let i = 0; i < costumes.length; i++) { + const currCostume = costumes[i]; + zip.file(currCostume.fileName, currCostume.fileContent); + } // Download project data into a file - create link element, // simulate click on it, and then remove it. const saveLink = document.createElement('a'); document.body.appendChild(saveLink); - const data = new Blob([json], {type: 'text'}); - const url = window.URL.createObjectURL(data); - saveLink.href = url; + zip.generateAsync({type: 'blob'}).then(content => { + const url = window.URL.createObjectURL(content); - // File name: project-DATE-TIME - const date = new Date(); - const timestamp = `${date.toLocaleDateString()}-${date.toLocaleTimeString()}`; - saveLink.download = `project-${timestamp}.json`; - saveLink.click(); - window.URL.revokeObjectURL(url); - document.body.removeChild(saveLink); + saveLink.href = url; + + // TODO Project name/location should be chosen by user + // File name: project-DATE-TIME + const date = new Date(); + const timestamp = `${date.toLocaleDateString()}-${date.toLocaleTimeString()}`; + saveLink.download = `project-${timestamp}.zip`; + saveLink.click(); + window.URL.revokeObjectURL(url); + document.body.removeChild(saveLink); + }); } render () { const { From 1c2c79e62fccb156d7900116d2061a9dcda9338e Mon Sep 17 00:00:00 2001 From: Karishma Chadha Date: Thu, 15 Feb 2018 23:13:49 -0500 Subject: [PATCH 015/108] Loading sb3 projects via load button that were saved via save button. --- src/containers/load-button.jsx | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/containers/load-button.jsx b/src/containers/load-button.jsx index a7b78a638..e5ec39154 100644 --- a/src/containers/load-button.jsx +++ b/src/containers/load-button.jsx @@ -2,6 +2,7 @@ import bindAll from 'lodash.bindall'; import PropTypes from 'prop-types'; import React from 'react'; import {connect} from 'react-redux'; +import JSZip from 'jszip'; import LoadButtonComponent from '../components/load-button/load-button.jsx'; @@ -16,8 +17,11 @@ class LoadButton extends React.Component { } handleChange (e) { const reader = new FileReader(); - reader.onload = () => this.props.loadProject(reader.result); - reader.readAsText(e.target.files[0]); + reader.onload = () => { + JSZip.loadAsync(reader.result) + .then(zip => this.props.loadProject(zip)); + }; + reader.readAsArrayBuffer(e.target.files[0]); } handleClick () { this.fileInput.click(); @@ -46,7 +50,7 @@ LoadButton.propTypes = { }; const mapStateToProps = state => ({ - loadProject: state.vm.fromJSON.bind(state.vm) + loadProject: state.vm.loadProjectLocal.bind(state.vm) }); export default connect( From aad877209f517045c56e6bda3505cab61774dee3 Mon Sep 17 00:00:00 2001 From: "greenkeeper[bot]" Date: Mon, 5 Mar 2018 15:37:44 +0000 Subject: [PATCH 016/108] chore(package): update scratch-paint to version 0.2.0-prerelease.20180305152706 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index b8649d8c1..960c39766 100644 --- a/package.json +++ b/package.json @@ -91,7 +91,7 @@ "scratch-audio": "0.1.0-prerelease.1516198804", "scratch-blocks": "0.1.0-prerelease.1519256473", "scratch-l10n": "2.0.20180108132626", - "scratch-paint": "0.2.0-prerelease.20180302160120", + "scratch-paint": "0.2.0-prerelease.20180305152706", "scratch-render": "0.1.0-prerelease.1516837442", "scratch-storage": "0.4.0", "scratch-vm": "0.1.0-prerelease.1519681201-prerelease.1519681262", From 3b99a0802cbcffb57fd051538fcb9a2e1f5c3131 Mon Sep 17 00:00:00 2001 From: "greenkeeper[bot]" Date: Mon, 5 Mar 2018 17:14:51 +0000 Subject: [PATCH 017/108] chore(package): update scratch-vm to version 0.1.0-prerelease.1520269961-prerelease.1520269983 Closes #1534 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index b8649d8c1..8e42c90bb 100644 --- a/package.json +++ b/package.json @@ -94,7 +94,7 @@ "scratch-paint": "0.2.0-prerelease.20180302160120", "scratch-render": "0.1.0-prerelease.1516837442", "scratch-storage": "0.4.0", - "scratch-vm": "0.1.0-prerelease.1519681201-prerelease.1519681262", + "scratch-vm": "0.1.0-prerelease.1520269961-prerelease.1520269983", "selenium-webdriver": "3.6.0", "startaudiocontext": "1.2.1", "style-loader": "^0.20.0", From 56ffff20a6edb6436293fcc7e857b12c9a13d1f0 Mon Sep 17 00:00:00 2001 From: Paul Kaplan Date: Tue, 27 Feb 2018 09:33:46 -0500 Subject: [PATCH 018/108] Cache Renderer.isSupported because it takes 30ms every time --- src/components/gui/gui.jsx | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/components/gui/gui.jsx b/src/components/gui/gui.jsx index b7f2a0acd..2ec53402b 100644 --- a/src/components/gui/gui.jsx +++ b/src/components/gui/gui.jsx @@ -34,6 +34,10 @@ const messages = defineMessages({ } }); +// Cache this value to only retreive it once the first time. +// Assume that it doesn't change for a session. +let isRendererSupported = null; + const GUIComponent = props => { const { activeTabIndex, @@ -69,7 +73,9 @@ const GUIComponent = props => { tabSelected: classNames(tabStyles.reactTabsTabSelected, styles.isSelected) }; - const isRendererSupported = Renderer.isSupported(); + if (isRendererSupported === null) { + isRendererSupported = Renderer.isSupported(); + } return ( Date: Mon, 5 Mar 2018 21:38:05 +0000 Subject: [PATCH 019/108] chore(package): update scratch-blocks to version 0.1.0-prerelease.1520285704 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index b8649d8c1..c8a380483 100644 --- a/package.json +++ b/package.json @@ -89,7 +89,7 @@ "redux-throttle": "0.1.1", "rimraf": "^2.6.1", "scratch-audio": "0.1.0-prerelease.1516198804", - "scratch-blocks": "0.1.0-prerelease.1519256473", + "scratch-blocks": "0.1.0-prerelease.1520285704", "scratch-l10n": "2.0.20180108132626", "scratch-paint": "0.2.0-prerelease.20180302160120", "scratch-render": "0.1.0-prerelease.1516837442", From fe6078cce12dd64b0c4079ac39809ddcf71316c9 Mon Sep 17 00:00:00 2001 From: DD Date: Fri, 2 Mar 2018 13:30:02 -0500 Subject: [PATCH 020/108] Move backdrop library back to costumes tab --- src/components/stage-selector/stage-selector.jsx | 4 ++-- src/components/target-pane/target-pane.jsx | 11 ----------- src/containers/backdrop-library.jsx | 2 +- src/containers/costume-tab.jsx | 14 ++++++++++++++ src/containers/target-pane.jsx | 7 +------ src/index.ejs | 2 +- 6 files changed, 19 insertions(+), 21 deletions(-) diff --git a/src/components/stage-selector/stage-selector.jsx b/src/components/stage-selector/stage-selector.jsx index 073ca257c..8016caeca 100644 --- a/src/components/stage-selector/stage-selector.jsx +++ b/src/components/stage-selector/stage-selector.jsx @@ -94,12 +94,12 @@ const StageSelector = props => { }, { title: intl.formatMessage(messages.addBackdropFromSurprise), img: surpriseIcon, - onClick: onSurpriseBackdropClick // TODO NEED REAL FUNCTION + onClick: onSurpriseBackdropClick }, { title: intl.formatMessage(messages.addBackdropFromPaint), img: paintIcon, - onClick: onEmptyBackdropClick // TODO NEED REAL FUNCTION + onClick: onEmptyBackdropClick } ]} title={intl.formatMessage(messages.addBackdropFromLibrary)} diff --git a/src/components/target-pane/target-pane.jsx b/src/components/target-pane/target-pane.jsx index 1044073a1..7cc7a1ed2 100644 --- a/src/components/target-pane/target-pane.jsx +++ b/src/components/target-pane/target-pane.jsx @@ -4,7 +4,6 @@ import React from 'react'; import VM from 'scratch-vm'; import SpriteLibrary from '../../containers/sprite-library.jsx'; -import BackdropLibrary from '../../containers/backdrop-library.jsx'; import SpriteSelectorComponent from '../sprite-selector/sprite-selector.jsx'; import StageSelector from '../../containers/stage-selector.jsx'; @@ -17,7 +16,6 @@ import styles from './target-pane.css'; * @returns {React.Component} rendered component */ const TargetPane = ({ - backdropLibraryVisible, editingTarget, hoveredTarget, spriteLibraryVisible, @@ -33,7 +31,6 @@ const TargetPane = ({ onSurpriseSpriteClick, onPaintSpriteClick, onRequestCloseSpriteLibrary, - onRequestCloseBackdropLibrary, onSelectSprite, raiseSprites, stage, @@ -83,12 +80,6 @@ const TargetPane = ({ onRequestClose={onRequestCloseSpriteLibrary} /> ) : null} - {backdropLibraryVisible ? ( - - ) : null} @@ -113,7 +104,6 @@ const spriteShape = PropTypes.shape({ }); TargetPane.propTypes = { - backdropLibraryVisible: PropTypes.bool, editingTarget: PropTypes.string, extensionLibraryVisible: PropTypes.bool, hoveredTarget: PropTypes.shape({ @@ -130,7 +120,6 @@ TargetPane.propTypes = { onDuplicateSprite: PropTypes.func, onNewSpriteClick: PropTypes.func, onPaintSpriteClick: PropTypes.func, - onRequestCloseBackdropLibrary: PropTypes.func, onRequestCloseExtensionLibrary: PropTypes.func, onRequestCloseSpriteLibrary: PropTypes.func, onSelectSprite: PropTypes.func, diff --git a/src/containers/backdrop-library.jsx b/src/containers/backdrop-library.jsx index e6b7d4d39..68f373ece 100644 --- a/src/containers/backdrop-library.jsx +++ b/src/containers/backdrop-library.jsx @@ -47,7 +47,7 @@ class BackdropLibrary extends React.Component { } BackdropLibrary.propTypes = { - onNewBackdrop: PropTypes.func, + onNewBackdrop: PropTypes.func.isRequired, onRequestClose: PropTypes.func, vm: PropTypes.instanceOf(VM).isRequired }; diff --git a/src/containers/costume-tab.jsx b/src/containers/costume-tab.jsx index 2e897c451..d0e3f9e42 100644 --- a/src/containers/costume-tab.jsx +++ b/src/containers/costume-tab.jsx @@ -7,10 +7,12 @@ import VM from 'scratch-vm'; import AssetPanel from '../components/asset-panel/asset-panel.jsx'; import PaintEditorWrapper from './paint-editor-wrapper.jsx'; import CostumeLibrary from './costume-library.jsx'; +import BackdropLibrary from './backdrop-library.jsx'; import {connect} from 'react-redux'; import { closeCostumeLibrary, + closeBackdropLibrary, openCostumeLibrary, openBackdropLibrary } from '../reducers/modals'; @@ -160,7 +162,9 @@ class CostumeTab extends React.Component { intl, onNewLibraryBackdropClick, onNewLibraryCostumeClick, + backdropLibraryVisible, costumeLibraryVisible, + onRequestCloseBackdropLibrary, onRequestCloseCostumeLibrary, ...props } = this.props; @@ -230,6 +234,13 @@ class CostumeTab extends React.Component { onRequestClose={onRequestCloseCostumeLibrary} /> ) : null} + {backdropLibraryVisible ? ( + + ) : null} ); } @@ -278,6 +289,9 @@ const mapDispatchToProps = dispatch => ({ e.preventDefault(); dispatch(openCostumeLibrary()); }, + onRequestCloseBackdropLibrary: () => { + dispatch(closeBackdropLibrary()); + }, onRequestCloseCostumeLibrary: () => { dispatch(closeCostumeLibrary()); } diff --git a/src/containers/target-pane.jsx b/src/containers/target-pane.jsx index 889d84185..e2bad31b7 100644 --- a/src/containers/target-pane.jsx +++ b/src/containers/target-pane.jsx @@ -5,7 +5,6 @@ import {connect} from 'react-redux'; import { openSpriteLibrary, - closeBackdropLibrary, closeSpriteLibrary } from '../reducers/modals'; @@ -132,8 +131,7 @@ const mapStateToProps = state => ({ }, {}), stage: state.targets.stage, raiseSprites: state.blockDrag, - spriteLibraryVisible: state.modals.spriteLibrary, - backdropLibraryVisible: state.modals.backdropLibrary + spriteLibraryVisible: state.modals.spriteLibrary }); const mapDispatchToProps = dispatch => ({ onNewSpriteClick: e => { @@ -143,9 +141,6 @@ const mapDispatchToProps = dispatch => ({ onRequestCloseSpriteLibrary: () => { dispatch(closeSpriteLibrary()); }, - onRequestCloseBackdropLibrary: () => { - dispatch(closeBackdropLibrary()); - }, onActivateTab: tabIndex => { dispatch(activateTab(tabIndex)); }, diff --git a/src/index.ejs b/src/index.ejs index 3f824efb0..964efa23c 100644 --- a/src/index.ejs +++ b/src/index.ejs @@ -9,7 +9,7 @@ From afd73dcfd81c8df12a0bc5ad8de3adf709c03141 Mon Sep 17 00:00:00 2001 From: DD Date: Mon, 5 Mar 2018 16:48:26 -0500 Subject: [PATCH 021/108] Uncomment raven --- src/index.ejs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/index.ejs b/src/index.ejs index 964efa23c..3f824efb0 100644 --- a/src/index.ejs +++ b/src/index.ejs @@ -9,7 +9,7 @@ From 588273a991207caea134bcc663f8c3fdf97f440c Mon Sep 17 00:00:00 2001 From: Karishma Chadha Date: Mon, 5 Mar 2018 17:07:07 -0500 Subject: [PATCH 022/108] Let vm do the heavy lifting and give gui the file to download. --- src/containers/save-button.jsx | 26 +++----------------------- 1 file changed, 3 insertions(+), 23 deletions(-) diff --git a/src/containers/save-button.jsx b/src/containers/save-button.jsx index e64ade4b1..45795c1d8 100644 --- a/src/containers/save-button.jsx +++ b/src/containers/save-button.jsx @@ -16,39 +16,19 @@ class SaveButton extends React.Component { ]); } handleClick () { - const zip = new JSZip(); - // Get the serialized project and assets from vm - const projectInfo = this.props.saveProjectSb3(); - - const json = projectInfo.projectJson; - const sounds = projectInfo.sounds; - const costumes = projectInfo.costumes; - - // Put everything in a zip file - zip.file('project.json', json); - for (let i = 0; i < sounds.length; i++) { - const currSound = sounds[i]; - zip.file(currSound.fileName, currSound.fileContent); - } - for (let i = 0; i < costumes.length; i++) { - const currCostume = costumes[i]; - zip.file(currCostume.fileName, currCostume.fileContent); - } - - // Download project data into a file - create link element, - // simulate click on it, and then remove it. const saveLink = document.createElement('a'); document.body.appendChild(saveLink); - zip.generateAsync({type: 'blob'}).then(content => { + this.props.saveProjectSb3().then(content => { const url = window.URL.createObjectURL(content); saveLink.href = url; - // TODO Project name/location should be chosen by user + // TODO user-friendly project name // File name: project-DATE-TIME const date = new Date(); const timestamp = `${date.toLocaleDateString()}-${date.toLocaleTimeString()}`; + // TODO change extension to sb3 saveLink.download = `project-${timestamp}.zip`; saveLink.click(); window.URL.revokeObjectURL(url); From 64ee4c7e86e7ab35133216ac3c1d7615be892772 Mon Sep 17 00:00:00 2001 From: Karishma Chadha Date: Mon, 5 Mar 2018 17:13:40 -0500 Subject: [PATCH 023/108] Remove unused import. --- src/containers/save-button.jsx | 1 - 1 file changed, 1 deletion(-) diff --git a/src/containers/save-button.jsx b/src/containers/save-button.jsx index 45795c1d8..014c5d5b9 100644 --- a/src/containers/save-button.jsx +++ b/src/containers/save-button.jsx @@ -2,7 +2,6 @@ import bindAll from 'lodash.bindall'; import PropTypes from 'prop-types'; import React from 'react'; import {connect} from 'react-redux'; -import JSZip from 'jszip'; import ButtonComponent from '../components/button/button.jsx'; import {ComingSoonTooltip} from '../components/coming-soon/coming-soon.jsx'; From e3dab37699ebfd16a4ba57c303430f112a5ca7ab Mon Sep 17 00:00:00 2001 From: "greenkeeper[bot]" Date: Sat, 3 Mar 2018 01:10:43 +0000 Subject: [PATCH 024/108] chore(package): update autoprefixer to version 8.1.0 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 4368dd81e..b6c5db87d 100644 --- a/package.json +++ b/package.json @@ -27,7 +27,7 @@ "react-dom": "^16.0.0" }, "devDependencies": { - "autoprefixer": "^7.1.3", + "autoprefixer": "^8.1.0", "babel-core": "^6.23.1", "babel-eslint": "^8.0.1", "babel-loader": "^7.1.0", From 2a6a9fb280a37e40a7a45f46ae72d97ef5c17ffd Mon Sep 17 00:00:00 2001 From: "greenkeeper[bot]" Date: Tue, 6 Mar 2018 12:31:19 +0000 Subject: [PATCH 025/108] chore(package): update html-webpack-plugin to version 3.0.5 Closes #1533 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index b6c5db87d..5e08f0c12 100644 --- a/package.json +++ b/package.json @@ -52,7 +52,7 @@ "get-float-time-domain-data": "0.1.0", "get-user-media-promise": "1.1.1", "gh-pages": "github:rschamp/gh-pages#publish-branch-to-subfolder", - "html-webpack-plugin": "^2.30.0", + "html-webpack-plugin": "^3.0.5", "immutable": "3.8.2", "jest": "^21.0.0", "lodash.bindall": "4.4.0", From bd74a9e4dbd9ecbe832b7fc922d91cb366c73752 Mon Sep 17 00:00:00 2001 From: "greenkeeper[bot]" Date: Thu, 1 Mar 2018 23:17:51 +0000 Subject: [PATCH 026/108] chore(package): update file-loader to version 1.1.11 Closes #1515 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 5e08f0c12..ab3f72d22 100644 --- a/package.json +++ b/package.json @@ -48,7 +48,7 @@ "eslint-config-scratch": "^5.0.0", "eslint-plugin-import": "^2.8.0", "eslint-plugin-react": "^7.5.1", - "file-loader": "1.1.9", + "file-loader": "1.1.11", "get-float-time-domain-data": "0.1.0", "get-user-media-promise": "1.1.1", "gh-pages": "github:rschamp/gh-pages#publish-branch-to-subfolder", From c9840b5f2a6110ffe302524c425bfaa81e03d95d Mon Sep 17 00:00:00 2001 From: Karishma Chadha Date: Tue, 6 Mar 2018 10:09:24 -0500 Subject: [PATCH 027/108] Updating save and load buttons to not use bind in mapStateToProps --- src/containers/load-button.jsx | 10 ++++++---- src/containers/save-button.jsx | 10 ++++++---- 2 files changed, 12 insertions(+), 8 deletions(-) diff --git a/src/containers/load-button.jsx b/src/containers/load-button.jsx index e5ec39154..3e6f7f42b 100644 --- a/src/containers/load-button.jsx +++ b/src/containers/load-button.jsx @@ -19,7 +19,7 @@ class LoadButton extends React.Component { const reader = new FileReader(); reader.onload = () => { JSZip.loadAsync(reader.result) - .then(zip => this.props.loadProject(zip)); + .then(zip => this.props.vm.loadProjectLocal(zip)); }; reader.readAsArrayBuffer(e.target.files[0]); } @@ -31,7 +31,7 @@ class LoadButton extends React.Component { } render () { const { - loadProject, // eslint-disable-line no-unused-vars + vm, // eslint-disable-line no-unused-vars ...props } = this.props; return ( @@ -46,11 +46,13 @@ class LoadButton extends React.Component { } LoadButton.propTypes = { - loadProject: PropTypes.func.isRequired + vm: PropTypes.shape({ + loadProjectLocal: PropTypes.func + }) }; const mapStateToProps = state => ({ - loadProject: state.vm.loadProjectLocal.bind(state.vm) + vm: state.vm }); export default connect( diff --git a/src/containers/save-button.jsx b/src/containers/save-button.jsx index 014c5d5b9..a56de86a1 100644 --- a/src/containers/save-button.jsx +++ b/src/containers/save-button.jsx @@ -18,7 +18,7 @@ class SaveButton extends React.Component { const saveLink = document.createElement('a'); document.body.appendChild(saveLink); - this.props.saveProjectSb3().then(content => { + this.props.vm.saveProjectSb3().then(content => { const url = window.URL.createObjectURL(content); saveLink.href = url; @@ -36,7 +36,7 @@ class SaveButton extends React.Component { } render () { const { - saveProjectSb3, // eslint-disable-line no-unused-vars + vm, // eslint-disable-line no-unused-vars ...props } = this.props; return ( @@ -57,11 +57,13 @@ class SaveButton extends React.Component { } SaveButton.propTypes = { - saveProjectSb3: PropTypes.func.isRequired + vm: PropTypes.shape({ + saveProjectSb3: PropTypes.func + }) }; const mapStateToProps = state => ({ - saveProjectSb3: state.vm.saveProjectSb3.bind(state.vm) + vm: state.vm }); export default connect( From c1780800c2756f12d762fd504f737c9dc37d6c3c Mon Sep 17 00:00:00 2001 From: DD Date: Tue, 6 Mar 2018 11:00:54 -0500 Subject: [PATCH 028/108] Switch to costumes tab on open backdrop library --- src/containers/stage-selector.jsx | 1 + 1 file changed, 1 insertion(+) diff --git a/src/containers/stage-selector.jsx b/src/containers/stage-selector.jsx index 27075cef8..bc75c3490 100644 --- a/src/containers/stage-selector.jsx +++ b/src/containers/stage-selector.jsx @@ -83,6 +83,7 @@ const mapStateToProps = (state, {assetId}) => ({ const mapDispatchToProps = dispatch => ({ onNewBackdropClick: e => { e.preventDefault(); + dispatch(activateTab(COSTUMES_TAB_INDEX)); dispatch(openBackdropLibrary()); }, onActivateTab: tabIndex => { From 3f987097ffd08410893a6289e3ee9591c764885f Mon Sep 17 00:00:00 2001 From: DD Date: Tue, 6 Mar 2018 15:43:47 -0500 Subject: [PATCH 029/108] Add switching to costumes tab to surprise button also. All backdrop adding buttons should switch tabs. --- src/containers/stage-selector.jsx | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/containers/stage-selector.jsx b/src/containers/stage-selector.jsx index bc75c3490..bf749c12a 100644 --- a/src/containers/stage-selector.jsx +++ b/src/containers/stage-selector.jsx @@ -38,7 +38,9 @@ class StageSelector extends React.Component { handleSurpriseBackdrop () { // @todo should this not add a backdrop you already have? const item = backdropLibraryContent[Math.floor(Math.random() * backdropLibraryContent.length)]; - this.addBackdropFromLibraryItem(item); + this.addBackdropFromLibraryItem(item).then(() => { + this.props.onActivateTab(COSTUMES_TAB_INDEX); + }); } handleEmptyBackdrop () { // @todo this is brittle, will need to be refactored for localized libraries From bc755b38f36551ad1553ef12a06917ef6b53081e Mon Sep 17 00:00:00 2001 From: Andrew Sliwinski Date: Tue, 6 Mar 2018 16:27:48 -0500 Subject: [PATCH 030/108] Additional fixes to libraries --- src/lib/libraries/costumes.json | 144 ++------------------------------ src/lib/libraries/sounds.json | 27 +++--- src/lib/libraries/sprites.json | 136 +++++------------------------- 3 files changed, 36 insertions(+), 271 deletions(-) diff --git a/src/lib/libraries/costumes.json b/src/lib/libraries/costumes.json index 641166986..1ac8e24d9 100644 --- a/src/lib/libraries/costumes.json +++ b/src/lib/libraries/costumes.json @@ -1132,17 +1132,6 @@ 1 ] }, - { - "name": "Drum-c", - "md5": "50cf928f06481ff823e18e70c01df807.svg", - "type": "costume", - "tags": [], - "info": [ - 43, - 60, - 1 - ] - }, { "name": "Drum-cymbal-a", "md5": "d6d41862fda966df1455d2dbff5e1988.svg", @@ -1165,17 +1154,6 @@ 1 ] }, - { - "name": "Drum-cymbal-c", - "md5": "0e85f690e8eaf153ae20cbbbb88ca60c.svg", - "type": "costume", - "tags": [], - "info": [ - 30, - 74, - 1 - ] - }, { "name": "Drum-highhat-a", "md5": "81fb79151a63cb096258607451cc2cf5.svg", @@ -1198,17 +1176,6 @@ 1 ] }, - { - "name": "Drum-highhat-c", - "md5": "c6f2467a5226f7d372d15669c5099a41.svg", - "type": "costume", - "tags": [], - "info": [ - 33, - 73, - 1 - ] - }, { "name": "Drum-kit", "md5": "131d040d86ecea62ccd175a8709c7866.svg", @@ -1231,17 +1198,6 @@ 1 ] }, - { - "name": "Drum-kit-c", - "md5": "4ca5c6eee4d907b98fb62340bd4a2cde.svg", - "type": "costume", - "tags": [], - "info": [ - 58, - 78, - 1 - ] - }, { "name": "Drum-snare-a", "md5": "b0255be93e3c8be6ac687f4199a25c4b.svg", @@ -1264,17 +1220,6 @@ 1 ] }, - { - "name": "Drum-snare-c", - "md5": "0b50639f4aac75a7e1061083401e0c40.svg", - "type": "costume", - "tags": [], - "info": [ - 37, - 61, - 1 - ] - }, { "name": "Duck", "md5": "c3baf7eedfbdac8cd1e4f1f1f779dc0c.svg", @@ -1649,17 +1594,6 @@ 1 ] }, - { - "name": "Guitar-c", - "md5": "5cfe9faacb98d35a702cfa633967a5b5.svg", - "type": "costume", - "tags": [], - "info": [ - 47, - 83, - 1 - ] - }, { "name": "Guitar-electric1-a", "md5": "b2b469b9d11fd23bdd671eab94dc58ff.svg", @@ -1682,17 +1616,6 @@ 1 ] }, - { - "name": "Guitar-electric1-c", - "md5": "4cb069d2a290c0a153f196de725d357c.svg", - "type": "costume", - "tags": [], - "info": [ - 42, - 85, - 1 - ] - }, { "name": "Guitar-electric2-a", "md5": "1fc433b89038f9e16092c9f4d7514cca.svg", @@ -1715,17 +1638,6 @@ 1 ] }, - { - "name": "Guitar-electric2-c", - "md5": "7f5f8b6d772657566e3dee24c9a9c538.svg", - "type": "costume", - "tags": [], - "info": [ - 38, - 94, - 1 - ] - }, { "name": "Hedgehog-a", "md5": "32416e6b2ef8e45fb5fd10778c1b9a9f.svg", @@ -1979,17 +1891,6 @@ 1 ] }, - { - "name": "Keyboard-c", - "md5": "4ee5e7c6d0463d9b50e0c593e70e1e31.svg", - "type": "costume", - "tags": [], - "info": [ - 72, - 68, - 1 - ] - }, { "name": "Kiran-a", "md5": "9de23c4a7a7fbb67136b539241346854.svg", @@ -2199,17 +2100,6 @@ 1 ] }, - { - "name": "Microphone-c", - "md5": "021d6da78b7bda374da4bdb50d4cbc4f.svg", - "type": "costume", - "tags": [], - "info": [ - 40, - 88, - 1 - ] - }, { "name": "Milk-a", "md5": "e6a7964bc4ea38c79a5a31d6ddfb5ba9.svg", @@ -2541,7 +2431,7 @@ ] }, { - "name": "Penguin1", + "name": "Penguin1-a", "md5": "c17d9e4bdb59c574e0c34aa70af516da.svg", "type": "costume", "tags": [], @@ -2552,7 +2442,7 @@ ] }, { - "name": "Penguin1 Talk-a", + "name": "Penguin1-b", "md5": "35fec7aa5f60cca945fe0615413f1f08.svg", "type": "costume", "tags": [], @@ -2563,7 +2453,7 @@ ] }, { - "name": "Penguin1 Talk-b", + "name": "Penguin1-c", "md5": "18fa51a64ebd5518f0c5c465525346e5.svg", "type": "costume", "tags": [], @@ -2574,7 +2464,7 @@ ] }, { - "name": "Penguin2", + "name": "Penguin2-a", "md5": "eaaaa7068e78a51d73ba437f1ec5763e.svg", "type": "costume", "tags": [], @@ -2585,7 +2475,7 @@ ] }, { - "name": "Penguin2 Talk-a", + "name": "Penguin2-b", "md5": "5a80f4b2fd20d43e4f7cb4189c08d99c.svg", "type": "costume", "tags": [], @@ -2596,7 +2486,7 @@ ] }, { - "name": "Penguin2 Talk-b", + "name": "Penguin2-c", "md5": "394e79f5f9a462064ece2a9a6606a07d.svg", "type": "costume", "tags": [], @@ -2980,17 +2870,6 @@ 1 ] }, - { - "name": "Saxophone-c", - "md5": "29751826f768bc1568092f267525ae8b.svg", - "type": "costume", - "tags": [], - "info": [ - 47, - 80, - 1 - ] - }, { "name": "Shark-a ", "md5": "7c0a907eae79462f69f8e2af8e7df828.svg", @@ -3376,17 +3255,6 @@ 1 ] }, - { - "name": "Trumpet-c", - "md5": "680dd004c24690af1e95c4beb22cd615.svg", - "type": "costume", - "tags": [], - "info": [ - 37, - 73, - 1 - ] - }, { "name": "Unicorn", "md5": "a04def38351e7fd805226345cac4fbfe.svg", diff --git a/src/lib/libraries/sounds.json b/src/lib/libraries/sounds.json index 4f146abdc..aafa6f01e 100644 --- a/src/lib/libraries/sounds.json +++ b/src/lib/libraries/sounds.json @@ -470,10 +470,10 @@ }, { "name": "Cheer", - "md5": "4b36eebf22be4667fc2f15b78c805b4c.wav", - "sampleCount": 62528, + "md5": "170e05c29d50918ae0b482c2955768c0.wav", + "sampleCount": 108864, "rate": 22050, - "format": "" + "format": "adpcm" }, { "name": "Chirp", @@ -553,19 +553,12 @@ "format": "" }, { - "name": "Computer Beeps1", + "name": "Computer Beep2", "md5": "1da43f6d52d0615da8a250e28100a80d.wav", "sampleCount": 19200, "rate": 11025, "format": "" }, - { - "name": "Computer Beeps2", - "md5": "28c76b6bebd04be1383fe9ba4933d263.wav", - "sampleCount": 9536, - "rate": 11025, - "format": "" - }, { "name": "Connect", "md5": "9aad12085708ccd279297d4bea9c5ae0.wav", @@ -1842,10 +1835,10 @@ }, { "name": "Screech", - "md5": "3676f478e5e3496034cf100d239160df.wav", - "sampleCount": 28928, - "rate": 11025, - "format": "" + "md5": "10644c5cc83a9a2dd3ab466deb0eb03d.wav", + "sampleCount": 12907, + "rate": 22050, + "format": "adpcm" }, { "name": "Seagulls", @@ -2269,8 +2262,8 @@ }, { "name": "Water Drop", - "md5": "aa488de9e2c871e9d4faecd246ed737a.wav", - "sampleCount": 8136, + "md5": "e133e625fd367d269e76964d4b722fc2.wav", + "sampleCount": 15131, "rate": 22050, "format": "adpcm" }, diff --git a/src/lib/libraries/sprites.json b/src/lib/libraries/sprites.json index 385167dc6..2c12e02cd 100644 --- a/src/lib/libraries/sprites.json +++ b/src/lib/libraries/sprites.json @@ -2166,7 +2166,7 @@ "tags": [], "info": [ 0, - 3, + 2, 2 ], "json": { @@ -2205,14 +2205,6 @@ "bitmapResolution": 1, "rotationCenterX": 43, "rotationCenterY": 60 - }, - { - "costumeName": "drum-c", - "baseLayerID": -1, - "baseLayerMD5": "50cf928f06481ff823e18e70c01df807.svg", - "bitmapResolution": 1, - "rotationCenterX": 43, - "rotationCenterY": 60 } ], "currentCostumeIndex": 0, @@ -2234,7 +2226,7 @@ "tags": [], "info": [ 0, - 3, + 2, 5 ], "json": { @@ -2297,14 +2289,6 @@ "bitmapResolution": 1, "rotationCenterX": 58, "rotationCenterY": 78 - }, - { - "costumeName": "drum-kit-c", - "baseLayerID": -1, - "baseLayerMD5": "4ca5c6eee4d907b98fb62340bd4a2cde.svg", - "bitmapResolution": 1, - "rotationCenterX": 58, - "rotationCenterY": 78 } ], "currentCostumeIndex": 0, @@ -2326,7 +2310,7 @@ "tags": [], "info": [ 0, - 3, + 2, 4 ], "json": { @@ -2381,14 +2365,6 @@ "bitmapResolution": 1, "rotationCenterX": 30, "rotationCenterY": 74 - }, - { - "costumeName": "drum-cymbal-c", - "baseLayerID": -1, - "baseLayerMD5": "0e85f690e8eaf153ae20cbbbb88ca60c.svg", - "bitmapResolution": 1, - "rotationCenterX": 30, - "rotationCenterY": 74 } ], "currentCostumeIndex": 0, @@ -2410,7 +2386,7 @@ "tags": [], "info": [ 0, - 3, + 2, 1 ], "json": { @@ -2441,14 +2417,6 @@ "bitmapResolution": 1, "rotationCenterX": 33, "rotationCenterY": 73 - }, - { - "costumeName": "drum-highhat-c", - "baseLayerID": -1, - "baseLayerMD5": "c6f2467a5226f7d372d15669c5099a41.svg", - "bitmapResolution": 1, - "rotationCenterX": 33, - "rotationCenterY": 73 } ], "currentCostumeIndex": 0, @@ -2470,7 +2438,7 @@ "tags": [], "info": [ 0, - 3, + 2, 3 ], "json": { @@ -2504,7 +2472,7 @@ "costumes": [ { "costumeName": "drum-snare-a", - "baseLayerID": 0, + "baseLayerID": -1, "baseLayerMD5": "b0255be93e3c8be6ac687f4199a25c4b.svg", "bitmapResolution": 1, "rotationCenterX": 23, @@ -2517,14 +2485,6 @@ "bitmapResolution": 1, "rotationCenterX": 36, "rotationCenterY": 66 - }, - { - "costumeName": "drum-snare-c", - "baseLayerID": 1, - "baseLayerMD5": "0b50639f4aac75a7e1061083401e0c40.svg", - "bitmapResolution": 1, - "rotationCenterX": 37, - "rotationCenterY": 61 } ], "currentCostumeIndex": 0, @@ -3234,7 +3194,7 @@ "tags": [], "info": [ 0, - 3, + 2, 8 ], "json": { @@ -3321,14 +3281,6 @@ "bitmapResolution": 1, "rotationCenterX": 47, "rotationCenterY": 83 - }, - { - "costumeName": "guitar-c", - "baseLayerID": -1, - "baseLayerMD5": "5cfe9faacb98d35a702cfa633967a5b5.svg", - "bitmapResolution": 1, - "rotationCenterX": 47, - "rotationCenterY": 83 } ], "currentCostumeIndex": 0, @@ -3350,7 +3302,7 @@ "tags": [], "info": [ 0, - 3, + 2, 8 ], "json": { @@ -3437,14 +3389,6 @@ "bitmapResolution": 1, "rotationCenterX": 38, "rotationCenterY": 94 - }, - { - "costumeName": "guitar-electric2-c", - "baseLayerID": -1, - "baseLayerMD5": "7f5f8b6d772657566e3dee24c9a9c538.svg", - "bitmapResolution": 1, - "rotationCenterX": 38, - "rotationCenterY": 94 } ], "currentCostumeIndex": 0, @@ -3466,7 +3410,7 @@ "tags": [], "info": [ 0, - 3, + 2, 8 ], "json": { @@ -3553,14 +3497,6 @@ "bitmapResolution": 1, "rotationCenterX": 42, "rotationCenterY": 85 - }, - { - "costumeName": "guitar-electric1-c", - "baseLayerID": -1, - "baseLayerMD5": "4cb069d2a290c0a153f196de725d357c.svg", - "bitmapResolution": 1, - "rotationCenterX": 42, - "rotationCenterY": 85 } ], "currentCostumeIndex": 0, @@ -3974,7 +3910,7 @@ "tags": [], "info": [ 0, - 3, + 2, 8 ], "json": { @@ -4061,14 +3997,6 @@ "bitmapResolution": 1, "rotationCenterX": 72, "rotationCenterY": 68 - }, - { - "costumeName": "keyboard-c", - "baseLayerID": -1, - "baseLayerMD5": "4ee5e7c6d0463d9b50e0c593e70e1e31.svg", - "bitmapResolution": 1, - "rotationCenterX": 72, - "rotationCenterY": 68 } ], "currentCostumeIndex": 0, @@ -4442,7 +4370,7 @@ "tags": [], "info": [ 0, - 3, + 2, 9 ], "json": { @@ -4537,14 +4465,6 @@ "bitmapResolution": 1, "rotationCenterX": 40, "rotationCenterY": 88 - }, - { - "costumeName": "microphone-c", - "baseLayerID": -1, - "baseLayerMD5": "021d6da78b7bda374da4bdb50d4cbc4f.svg", - "bitmapResolution": 1, - "rotationCenterX": 40, - "rotationCenterY": 88 } ], "currentCostumeIndex": 0, @@ -5111,7 +5031,7 @@ ], "costumes": [ { - "costumeName": "penguin1", + "costumeName": "penguin1-a", "baseLayerID": -1, "baseLayerMD5": "c17d9e4bdb59c574e0c34aa70af516da.svg", "bitmapResolution": 1, @@ -5119,7 +5039,7 @@ "rotationCenterY": 61 }, { - "costumeName": "penguin1 talk-a", + "costumeName": "penguin1-b", "baseLayerID": -1, "baseLayerMD5": "35fec7aa5f60cca945fe0615413f1f08.svg", "bitmapResolution": 1, @@ -5127,7 +5047,7 @@ "rotationCenterY": 62 }, { - "costumeName": "penguin1 talk-b", + "costumeName": "penguin1-c", "baseLayerID": -1, "baseLayerMD5": "18fa51a64ebd5518f0c5c465525346e5.svg", "bitmapResolution": 1, @@ -5135,7 +5055,7 @@ "rotationCenterY": 61 } ], - "currentCostumeIndex": 1, + "currentCostumeIndex": 0, "scratchX": -58, "scratchY": -19, "scale": 1, @@ -5171,7 +5091,7 @@ ], "costumes": [ { - "costumeName": "penguin2", + "costumeName": "penguin2-a", "baseLayerID": -1, "baseLayerMD5": "eaaaa7068e78a51d73ba437f1ec5763e.svg", "bitmapResolution": 1, @@ -5179,7 +5099,7 @@ "rotationCenterY": 79 }, { - "costumeName": "penguin2 talk-a", + "costumeName": "penguin2-b", "baseLayerID": -1, "baseLayerMD5": "5a80f4b2fd20d43e4f7cb4189c08d99c.svg", "bitmapResolution": 1, @@ -5187,7 +5107,7 @@ "rotationCenterY": 79 }, { - "costumeName": "penguin2 talk-b", + "costumeName": "penguin2-c", "baseLayerID": -1, "baseLayerMD5": "394e79f5f9a462064ece2a9a6606a07d.svg", "bitmapResolution": 1, @@ -5766,7 +5686,7 @@ "tags": [], "info": [ 0, - 3, + 2, 8 ], "json": { @@ -5853,14 +5773,6 @@ "bitmapResolution": 1, "rotationCenterX": 47, "rotationCenterY": 80 - }, - { - "costumeName": "saxophone-c", - "baseLayerID": -1, - "baseLayerMD5": "29751826f768bc1568092f267525ae8b.svg", - "bitmapResolution": 1, - "rotationCenterX": 47, - "rotationCenterY": 80 } ], "currentCostumeIndex": 0, @@ -6842,7 +6754,7 @@ "tags": [], "info": [ 0, - 3, + 2, 8 ], "json": { @@ -6929,14 +6841,6 @@ "bitmapResolution": 1, "rotationCenterX": 37, "rotationCenterY": 73 - }, - { - "costumeName": "trumpet-c", - "baseLayerID": -1, - "baseLayerMD5": "680dd004c24690af1e95c4beb22cd615.svg", - "bitmapResolution": 1, - "rotationCenterX": 37, - "rotationCenterY": 73 } ], "currentCostumeIndex": 0, From 6d02635d96fb85e0b7f2f1ce4c9ab8ad1d6b0a18 Mon Sep 17 00:00:00 2001 From: "greenkeeper[bot]" Date: Tue, 6 Mar 2018 21:30:07 +0000 Subject: [PATCH 031/108] chore(package): update scratch-paint to version 0.2.0-prerelease.20180306212946 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index ab3f72d22..2721fe0d5 100644 --- a/package.json +++ b/package.json @@ -91,7 +91,7 @@ "scratch-audio": "0.1.0-prerelease.1516198804", "scratch-blocks": "0.1.0-prerelease.1520285704", "scratch-l10n": "2.0.20180108132626", - "scratch-paint": "0.2.0-prerelease.20180305152706", + "scratch-paint": "0.2.0-prerelease.20180306212946", "scratch-render": "0.1.0-prerelease.1516837442", "scratch-storage": "0.4.0", "scratch-vm": "0.1.0-prerelease.1520269961-prerelease.1520269983", From f375ea445d2d6eefbd37e1a303a139cefb72e048 Mon Sep 17 00:00:00 2001 From: "greenkeeper[bot]" Date: Tue, 6 Mar 2018 21:44:32 +0000 Subject: [PATCH 032/108] chore(package): update scratch-vm to version 0.1.0-prerelease.1520372503-prerelease.1520372519 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index ab3f72d22..180b4718c 100644 --- a/package.json +++ b/package.json @@ -94,7 +94,7 @@ "scratch-paint": "0.2.0-prerelease.20180305152706", "scratch-render": "0.1.0-prerelease.1516837442", "scratch-storage": "0.4.0", - "scratch-vm": "0.1.0-prerelease.1520269961-prerelease.1520269983", + "scratch-vm": "0.1.0-prerelease.1520372503-prerelease.1520372519", "selenium-webdriver": "3.6.0", "startaudiocontext": "1.2.1", "style-loader": "^0.20.0", From 73289a798e613eabcaca136dc2a30c7198c264d5 Mon Sep 17 00:00:00 2001 From: DD Date: Tue, 6 Mar 2018 15:36:53 -0500 Subject: [PATCH 033/108] Costume tab detects added costume and switches to the current costume of the edit target --- src/containers/costume-tab.jsx | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/src/containers/costume-tab.jsx b/src/containers/costume-tab.jsx index 3668a94fb..cdf2cf3ac 100644 --- a/src/containers/costume-tab.jsx +++ b/src/containers/costume-tab.jsx @@ -99,7 +99,20 @@ class CostumeTab extends React.Component { // If switching editing targets, update the costume index if (this.props.editingTarget !== editingTarget) { this.setState({selectedCostumeIndex: target.currentCostume}); - } else if (this.state.selectedCostumeIndex > target.costumes.length - 1) { + } else { + // Switch to a newly added costume if there is one + const oldTarget = this.props.sprites[editingTarget] ? + this.props.sprites[editingTarget] : this.props.stage; + // @todo: Check that the costume is actually new by making sure it doesn't + // exist in the old costume list. This is blocked by + // https://github.com/LLK/scratch-vm/issues/967 + if (oldTarget.costumeCount < target.costumeCount) { + this.setState({selectedCostumeIndex: target.currentCostume}); + } + } + + // In case of deleted costumes + if (this.state.selectedCostumeIndex > target.costumes.length - 1) { this.setState({selectedCostumeIndex: target.costumes.length - 1}); } } From b8891c275aeb12d2a62b1f6c98cd52ff240e89d9 Mon Sep 17 00:00:00 2001 From: DD Date: Wed, 7 Mar 2018 11:03:55 -0500 Subject: [PATCH 034/108] fix lint --- src/containers/costume-tab.jsx | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/containers/costume-tab.jsx b/src/containers/costume-tab.jsx index cdf2cf3ac..3ce07dd02 100644 --- a/src/containers/costume-tab.jsx +++ b/src/containers/costume-tab.jsx @@ -96,10 +96,7 @@ class CostumeTab extends React.Component { return; } - // If switching editing targets, update the costume index - if (this.props.editingTarget !== editingTarget) { - this.setState({selectedCostumeIndex: target.currentCostume}); - } else { + if (this.props.editingTarget === editingTarget) { // Switch to a newly added costume if there is one const oldTarget = this.props.sprites[editingTarget] ? this.props.sprites[editingTarget] : this.props.stage; @@ -109,6 +106,9 @@ class CostumeTab extends React.Component { if (oldTarget.costumeCount < target.costumeCount) { this.setState({selectedCostumeIndex: target.currentCostume}); } + } else { + // If switching editing targets, update the costume index + this.setState({selectedCostumeIndex: target.currentCostume}); } // In case of deleted costumes From d70716befb9910134e9540f50c3c8833330d8f91 Mon Sep 17 00:00:00 2001 From: "greenkeeper[bot]" Date: Wed, 7 Mar 2018 16:07:09 +0000 Subject: [PATCH 035/108] chore(package): update chromedriver to version 2.36.0 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 6380fe289..355f2a86d 100644 --- a/package.json +++ b/package.json @@ -37,7 +37,7 @@ "babel-preset-es2015": "^6.22.0", "babel-preset-react": "^6.22.0", "buffer-loader": "0.0.1", - "chromedriver": "2.35.0", + "chromedriver": "2.36.0", "classnames": "2.2.5", "copy-webpack-plugin": "^4.3.0", "css-loader": "^0.28.7", From 778b1a83df3b2884bef9665751402b28b2a4617b Mon Sep 17 00:00:00 2001 From: Paul Kaplan Date: Wed, 7 Mar 2018 11:42:51 -0500 Subject: [PATCH 036/108] Try using headless chrome for integration tests --- .travis.yml | 3 --- test/helpers/selenium-helper.js | 3 +++ 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.travis.yml b/.travis.yml index 991c69bba..dc5bb7a90 100644 --- a/.travis.yml +++ b/.travis.yml @@ -3,9 +3,6 @@ sudo: required dist: trusty addons: chrome: stable -before_script: - - "export DISPLAY=:99.0" - - "sh -e /etc/init.d/xvfb start" node_js: - 6 cache: diff --git a/test/helpers/selenium-helper.js b/test/helpers/selenium-helper.js index b63ea2bf6..b18f35651 100644 --- a/test/helpers/selenium-helper.js +++ b/test/helpers/selenium-helper.js @@ -34,8 +34,11 @@ class SeleniumHelper { } getDriver () { + const chromeCapabilities = webdriver.Capabilities.chrome(); + chromeCapabilities.set('chromeOptions', {args: ['--headless']}); this.driver = new webdriver.Builder() .forBrowser('chrome') + .withCapabilities(chromeCapabilities) .build(); return this.driver; } From a57aad36d2bd0d076277c565c47d03198c830571 Mon Sep 17 00:00:00 2001 From: kchadha Date: Wed, 7 Mar 2018 13:23:37 -0500 Subject: [PATCH 037/108] Code cleanup addressing PR comment. --- src/containers/stage.jsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/containers/stage.jsx b/src/containers/stage.jsx index a56ae7330..cf10d5001 100644 --- a/src/containers/stage.jsx +++ b/src/containers/stage.jsx @@ -191,11 +191,11 @@ class Stage extends React.Component { x: x - this.rect.left, y: y - this.rect.top, canvasWidth: this.rect.width, - canvasHeight: this.rect.height + canvasHeight: this.rect.height, + wasDragged: this.state.isDragging }; if (this.state.isDragging) { this.onStopDrag(); - data.wasDragged = true; } this.props.vm.postIOData('mouse', data); } From 8de78ca9d31bcce27ea392d95735ab518c237e8e Mon Sep 17 00:00:00 2001 From: "greenkeeper[bot]" Date: Wed, 7 Mar 2018 18:57:13 +0000 Subject: [PATCH 038/108] chore(package): update react-responsive to version 4.0.5 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 355f2a86d..8adbd7ed4 100644 --- a/package.json +++ b/package.json @@ -79,7 +79,7 @@ "react-intl-redux": "0.7.0", "react-modal": "3.3.1", "react-redux": "5.0.7", - "react-responsive": "4.0.3", + "react-responsive": "4.0.5", "react-style-proptype": "3.2.0", "react-tabs": "2.2.1", "react-test-renderer": "16.2.0", From b3d5d2c65fb4eb5bedeb720b63db4d091a45d8cb Mon Sep 17 00:00:00 2001 From: "greenkeeper[bot]" Date: Thu, 8 Mar 2018 00:41:02 +0000 Subject: [PATCH 039/108] chore(package): update scratch-paint to version 0.2.0-prerelease.20180307192639 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 8adbd7ed4..d7c0fa363 100644 --- a/package.json +++ b/package.json @@ -91,7 +91,7 @@ "scratch-audio": "0.1.0-prerelease.1516198804", "scratch-blocks": "0.1.0-prerelease.1520285704", "scratch-l10n": "2.0.20180108132626", - "scratch-paint": "0.2.0-prerelease.20180306212946", + "scratch-paint": "0.2.0-prerelease.20180307192639", "scratch-render": "0.1.0-prerelease.1516837442", "scratch-storage": "0.4.0", "scratch-vm": "0.1.0-prerelease.1520372503-prerelease.1520372519", From 9a9b60d74f9c2a9c6f38f250d3203424141e99ca Mon Sep 17 00:00:00 2001 From: kyleplo <31634240+kyleplo@users.noreply.github.com> Date: Thu, 8 Mar 2018 08:09:56 -0500 Subject: [PATCH 040/108] Update make-toolbox-xml.js --- src/lib/make-toolbox-xml.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/lib/make-toolbox-xml.js b/src/lib/make-toolbox-xml.js index 4a4027203..677dc2efa 100644 --- a/src/lib/make-toolbox-xml.js +++ b/src/lib/make-toolbox-xml.js @@ -235,6 +235,9 @@ const looks = function (isStage, targetId) { ${blockSeparator} ${isStage ? '' : ` + + + ${blockSeparator} @@ -243,9 +246,6 @@ const looks = function (isStage, targetId) { - ${blockSeparator} - - `} ${isStage ? ` From 9bccf20d6420dba9e40cae76daf9fa00d115d06b Mon Sep 17 00:00:00 2001 From: "greenkeeper[bot]" Date: Thu, 8 Mar 2018 14:33:56 +0000 Subject: [PATCH 041/108] chore(package): update scratch-blocks to version 0.1.0-prerelease.1520519504 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index d7c0fa363..e1f574da0 100644 --- a/package.json +++ b/package.json @@ -89,7 +89,7 @@ "redux-throttle": "0.1.1", "rimraf": "^2.6.1", "scratch-audio": "0.1.0-prerelease.1516198804", - "scratch-blocks": "0.1.0-prerelease.1520285704", + "scratch-blocks": "0.1.0-prerelease.1520519504", "scratch-l10n": "2.0.20180108132626", "scratch-paint": "0.2.0-prerelease.20180307192639", "scratch-render": "0.1.0-prerelease.1516837442", From c647ad6286d818d121a1882119a3fa79f1f131f3 Mon Sep 17 00:00:00 2001 From: kchadha Date: Thu, 8 Mar 2018 10:21:35 -0500 Subject: [PATCH 042/108] Removing JSZip dependency. VM will unpack the zip (for now, until this functionality gets moved to scratch-storage). --- package.json | 1 - src/containers/load-button.jsx | 6 +----- 2 files changed, 1 insertion(+), 6 deletions(-) diff --git a/package.json b/package.json index e091fe05e..ab3f72d22 100644 --- a/package.json +++ b/package.json @@ -55,7 +55,6 @@ "html-webpack-plugin": "^3.0.5", "immutable": "3.8.2", "jest": "^21.0.0", - "jszip": "^3.1.5", "lodash.bindall": "4.4.0", "lodash.debounce": "4.0.8", "lodash.defaultsdeep": "4.6.0", diff --git a/src/containers/load-button.jsx b/src/containers/load-button.jsx index 3e6f7f42b..da88c6ebe 100644 --- a/src/containers/load-button.jsx +++ b/src/containers/load-button.jsx @@ -2,7 +2,6 @@ import bindAll from 'lodash.bindall'; import PropTypes from 'prop-types'; import React from 'react'; import {connect} from 'react-redux'; -import JSZip from 'jszip'; import LoadButtonComponent from '../components/load-button/load-button.jsx'; @@ -17,10 +16,7 @@ class LoadButton extends React.Component { } handleChange (e) { const reader = new FileReader(); - reader.onload = () => { - JSZip.loadAsync(reader.result) - .then(zip => this.props.vm.loadProjectLocal(zip)); - }; + reader.onload = () => this.props.vm.loadProjectLocal(reader.result); reader.readAsArrayBuffer(e.target.files[0]); } handleClick () { From 551445e334221dbb729bd2ddb9c9d0bdb3b9144c Mon Sep 17 00:00:00 2001 From: "greenkeeper[bot]" Date: Thu, 8 Mar 2018 16:10:51 +0000 Subject: [PATCH 043/108] chore(package): update react-style-proptype to version 3.2.1 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index e1f574da0..7fec62aa7 100644 --- a/package.json +++ b/package.json @@ -80,7 +80,7 @@ "react-modal": "3.3.1", "react-redux": "5.0.7", "react-responsive": "4.0.5", - "react-style-proptype": "3.2.0", + "react-style-proptype": "3.2.1", "react-tabs": "2.2.1", "react-test-renderer": "16.2.0", "react-tooltip": "3.4.0", From 22ac2c4d37516fc8d2a7cc74da33f8cb93637a2a Mon Sep 17 00:00:00 2001 From: "greenkeeper[bot]" Date: Thu, 8 Mar 2018 20:46:45 +0000 Subject: [PATCH 044/108] chore(package): update scratch-paint to version 0.2.0-prerelease.20180308191417 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 7fec62aa7..94cd098b7 100644 --- a/package.json +++ b/package.json @@ -91,7 +91,7 @@ "scratch-audio": "0.1.0-prerelease.1516198804", "scratch-blocks": "0.1.0-prerelease.1520519504", "scratch-l10n": "2.0.20180108132626", - "scratch-paint": "0.2.0-prerelease.20180307192639", + "scratch-paint": "0.2.0-prerelease.20180308191417", "scratch-render": "0.1.0-prerelease.1516837442", "scratch-storage": "0.4.0", "scratch-vm": "0.1.0-prerelease.1520372503-prerelease.1520372519", From 76c0155bc55b8777794a781e9f2f3e32833f8874 Mon Sep 17 00:00:00 2001 From: DD Date: Thu, 8 Mar 2018 16:37:19 -0500 Subject: [PATCH 045/108] Clean up some unused warnings --- src/containers/costume-tab.jsx | 7 +------ src/containers/target-pane.jsx | 1 + src/lib/vm-listener-hoc.jsx | 4 +--- 3 files changed, 3 insertions(+), 9 deletions(-) diff --git a/src/containers/costume-tab.jsx b/src/containers/costume-tab.jsx index 3668a94fb..405048f85 100644 --- a/src/containers/costume-tab.jsx +++ b/src/containers/costume-tab.jsx @@ -164,7 +164,6 @@ class CostumeTab extends React.Component { }); } render () { - // For paint wrapper const { intl, onNewLibraryBackdropClick, @@ -173,15 +172,11 @@ class CostumeTab extends React.Component { costumeLibraryVisible, onRequestCloseBackdropLibrary, onRequestCloseCostumeLibrary, - ...props - } = this.props; - - const { editingTarget, sprites, stage, vm - } = props; + } = this.props; const target = editingTarget && sprites[editingTarget] ? sprites[editingTarget] : stage; diff --git a/src/containers/target-pane.jsx b/src/containers/target-pane.jsx index e2bad31b7..0b8062336 100644 --- a/src/containers/target-pane.jsx +++ b/src/containers/target-pane.jsx @@ -87,6 +87,7 @@ class TargetPane extends React.Component { render () { const { onActivateTab, // eslint-disable-line no-unused-vars + onReceivedBlocks, // eslint-disable-line no-unused-vars ...componentProps } = this.props; return ( diff --git a/src/lib/vm-listener-hoc.jsx b/src/lib/vm-listener-hoc.jsx index 8e7a0ca17..ab1649cbc 100644 --- a/src/lib/vm-listener-hoc.jsx +++ b/src/lib/vm-listener-hoc.jsx @@ -99,9 +99,7 @@ const vmListenerHOC = function (WrappedComponent) { attachKeyboardEvents: true }; const mapStateToProps = state => ({ - vm: state.vm, - hoveredSprite: state.hoveredTarget.sprite, - editingTarget: state.targets.editingTarget + vm: state.vm }); const mapDispatchToProps = dispatch => ({ onTargetsUpdate: data => { From 4f167c60ccd2653ca0b9892c5a7fe2327e193043 Mon Sep 17 00:00:00 2001 From: "greenkeeper[bot]" Date: Fri, 9 Mar 2018 14:46:29 +0000 Subject: [PATCH 046/108] chore(package): update scratch-vm to version 0.1.0-prerelease.1520606673-prerelease.1520606691 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 94cd098b7..9c7b3a677 100644 --- a/package.json +++ b/package.json @@ -94,7 +94,7 @@ "scratch-paint": "0.2.0-prerelease.20180308191417", "scratch-render": "0.1.0-prerelease.1516837442", "scratch-storage": "0.4.0", - "scratch-vm": "0.1.0-prerelease.1520372503-prerelease.1520372519", + "scratch-vm": "0.1.0-prerelease.1520606673-prerelease.1520606691", "selenium-webdriver": "3.6.0", "startaudiocontext": "1.2.1", "style-loader": "^0.20.0", From ff3becd3044a0b90624121622c866d404d3ef067 Mon Sep 17 00:00:00 2001 From: "greenkeeper[bot]" Date: Fri, 9 Mar 2018 17:04:05 +0000 Subject: [PATCH 047/108] chore(package): update scratch-paint to version 0.2.0-prerelease.20180309170325 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 9c7b3a677..27814ab0c 100644 --- a/package.json +++ b/package.json @@ -91,7 +91,7 @@ "scratch-audio": "0.1.0-prerelease.1516198804", "scratch-blocks": "0.1.0-prerelease.1520519504", "scratch-l10n": "2.0.20180108132626", - "scratch-paint": "0.2.0-prerelease.20180308191417", + "scratch-paint": "0.2.0-prerelease.20180309170325", "scratch-render": "0.1.0-prerelease.1516837442", "scratch-storage": "0.4.0", "scratch-vm": "0.1.0-prerelease.1520606673-prerelease.1520606691", From b6cf7d894f4d042d16fcce8727ebef91772e0f1d Mon Sep 17 00:00:00 2001 From: Paul Kaplan Date: Mon, 12 Mar 2018 09:16:53 -0400 Subject: [PATCH 048/108] Fix proptype warnings for asset panel buttons --- src/components/asset-panel/selector.jsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/components/asset-panel/selector.jsx b/src/components/asset-panel/selector.jsx index f2ab58cae..cc5abed4d 100644 --- a/src/components/asset-panel/selector.jsx +++ b/src/components/asset-panel/selector.jsx @@ -59,9 +59,9 @@ const Selector = props => { Selector.propTypes = { buttons: PropTypes.arrayOf(PropTypes.shape({ - message: PropTypes.string.isRequired, + title: PropTypes.string.isRequired, img: PropTypes.string.isRequired, - onClick: PropTypes.func.isRequired + onClick: PropTypes.func })), items: PropTypes.arrayOf(PropTypes.shape({ url: PropTypes.string, From b0101fe4f96e3d56496b3b86ab599820928aa51f Mon Sep 17 00:00:00 2001 From: kchadha Date: Mon, 12 Mar 2018 13:42:15 -0400 Subject: [PATCH 049/108] Fix reload button on error page so that it goes to the correct url (including the pathname). --- src/containers/error-boundary.jsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/containers/error-boundary.jsx b/src/containers/error-boundary.jsx index d7f558c16..d7083f052 100644 --- a/src/containers/error-boundary.jsx +++ b/src/containers/error-boundary.jsx @@ -30,7 +30,7 @@ class ErrorBoundary extends React.Component { } handleReload () { - window.location.replace(window.location.origin); + window.location.replace(window.location.origin + window.location.pathname); } render () { From 36a19bfa1b92972b2c3658dc1859ea884d26ba2c Mon Sep 17 00:00:00 2001 From: Paul Kaplan Date: Mon, 12 Mar 2018 14:23:32 -0400 Subject: [PATCH 050/108] Allow new sprite to propagate before selecting costume tab --- src/containers/target-pane.jsx | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/containers/target-pane.jsx b/src/containers/target-pane.jsx index e2bad31b7..317cfcbb3 100644 --- a/src/containers/target-pane.jsx +++ b/src/containers/target-pane.jsx @@ -74,7 +74,9 @@ class TargetPane extends React.Component { const emptyItem = spriteLibraryContent.find(item => item.name === 'Empty'); if (emptyItem) { this.props.vm.addSprite2(JSON.stringify(emptyItem.json)).then(() => { - this.props.onActivateTab(COSTUMES_TAB_INDEX); + setTimeout(() => { // Wait for targets update to propagate before tab switching + this.props.onActivateTab(COSTUMES_TAB_INDEX); + }); }); } } From 4969fb7ed9929660c50aba5b9568946a8f45615f Mon Sep 17 00:00:00 2001 From: "greenkeeper[bot]" Date: Tue, 13 Mar 2018 01:17:18 +0000 Subject: [PATCH 051/108] chore(package): update react-modal to version 3.3.2 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 27814ab0c..6b9f99f67 100644 --- a/package.json +++ b/package.json @@ -77,7 +77,7 @@ "react-ga": "2.4.1", "react-intl": "2.4.0", "react-intl-redux": "0.7.0", - "react-modal": "3.3.1", + "react-modal": "3.3.2", "react-redux": "5.0.7", "react-responsive": "4.0.5", "react-style-proptype": "3.2.1", From a7a0260808d46d51d953585dea935ecfd5bb39d0 Mon Sep 17 00:00:00 2001 From: kchadha Date: Wed, 14 Mar 2018 10:14:50 -0400 Subject: [PATCH 052/108] Gui should catch vm load errors and render error page if project failed to load. --- src/containers/gui.jsx | 33 ++++++++++++++++++++++++--------- 1 file changed, 24 insertions(+), 9 deletions(-) diff --git a/src/containers/gui.jsx b/src/containers/gui.jsx index 320eedcdb..5e0cf1720 100644 --- a/src/containers/gui.jsx +++ b/src/containers/gui.jsx @@ -20,25 +20,39 @@ class GUI extends React.Component { constructor (props) { super(props); this.state = { - loading: true + loading: true, + loadingError: false, + errorMessage: '' }; } componentDidMount () { this.audioEngine = new AudioEngine(); this.props.vm.attachAudioEngine(this.audioEngine); - this.props.vm.loadProject(this.props.projectData).then(() => { - this.setState({loading: false}, () => { - this.props.vm.setCompatibilityMode(true); - this.props.vm.start(); + this.props.vm.loadProject(this.props.projectData) + .then(() => { + this.setState({loading: false}, () => { + this.props.vm.setCompatibilityMode(true); + this.props.vm.start(); + }); + }) + .catch(e => { + // Need to catch this error and update component state so that + // error page gets rendered if project failed to load + this.setState({loadingError: true, errorMessage: e}); }); - }); } componentWillReceiveProps (nextProps) { if (this.props.projectData !== nextProps.projectData) { this.setState({loading: true}, () => { - this.props.vm.loadProject(nextProps.projectData).then(() => { - this.setState({loading: false}); - }); + this.props.vm.loadProject(nextProps.projectData) + .then(() => { + this.setState({loading: false}); + }) + .catch(e => { + // Need to catch this error and update component state so that + // error page gets rendered if project failed to load + this.setState({loadingError: true, errorMessage: e}); + }); }); } } @@ -46,6 +60,7 @@ class GUI extends React.Component { this.props.vm.stopAll(); } render () { + if (this.state.loadingError) throw new Error(`Failed to load project: ${this.state.errorMessage}`); const { children, fetchingProject, From dff72b62dc0ef5a2f3d2c653a226bf9d5dd277ae Mon Sep 17 00:00:00 2001 From: kchadha Date: Wed, 14 Mar 2018 11:50:56 -0400 Subject: [PATCH 053/108] Trigger loading animation and loading error states from load button. --- src/containers/gui.jsx | 4 +++- src/containers/load-button.jsx | 30 ++++++++++++++++++++++++++++-- src/reducers/modals.js | 11 +++++++++++ 3 files changed, 42 insertions(+), 3 deletions(-) diff --git a/src/containers/gui.jsx b/src/containers/gui.jsx index 5e0cf1720..7d0f30020 100644 --- a/src/containers/gui.jsx +++ b/src/containers/gui.jsx @@ -70,7 +70,7 @@ class GUI extends React.Component { } = this.props; return ( @@ -85,6 +85,7 @@ GUI.propTypes = { feedbackFormVisible: PropTypes.bool, fetchingProject: PropTypes.bool, importInfoVisible: PropTypes.bool, + loadingStateVisible: PropTypes.bool, previewInfoVisible: PropTypes.bool, projectData: PropTypes.string, vm: PropTypes.instanceOf(VM) @@ -98,6 +99,7 @@ const mapStateToProps = state => ({ costumesTabVisible: state.editorTab.activeTabIndex === COSTUMES_TAB_INDEX, feedbackFormVisible: state.modals.feedbackForm, importInfoVisible: state.modals.importInfo, + loadingStateVisible: state.modals.loadingProject, previewInfoVisible: state.modals.previewInfo, soundsTabVisible: state.editorTab.activeTabIndex === SOUNDS_TAB_INDEX }); diff --git a/src/containers/load-button.jsx b/src/containers/load-button.jsx index da88c6ebe..b3804d8c5 100644 --- a/src/containers/load-button.jsx +++ b/src/containers/load-button.jsx @@ -5,6 +5,11 @@ import {connect} from 'react-redux'; import LoadButtonComponent from '../components/load-button/load-button.jsx'; +import { + openLoadingProject, + closeLoadingProject +} from '../reducers/modals'; + class LoadButton extends React.Component { constructor (props) { super(props); @@ -13,10 +18,21 @@ class LoadButton extends React.Component { 'handleChange', 'handleClick' ]); + this.state = { + loadingError: false, + errorMessage: '' + }; } handleChange (e) { + this.props.openLoadingState(); const reader = new FileReader(); - reader.onload = () => this.props.vm.loadProjectLocal(reader.result); + reader.onload = () => this.props.vm.loadProjectLocal(reader.result) + .then(() => { + this.props.closeLoadingState(); + }) + .catch(error => { + this.setState({loadingError: true, errorMessage: error}); + }); reader.readAsArrayBuffer(e.target.files[0]); } handleClick () { @@ -26,7 +42,10 @@ class LoadButton extends React.Component { this.fileInput = input; } render () { + if (this.state.loadingError) throw new Error(`Failed to load project: ${this.state.errorMessage}`); const { + closeLoadingState, // eslint-disable-line no-unused-vars + openLoadingState, // eslint-disable-line no-unused-vars vm, // eslint-disable-line no-unused-vars ...props } = this.props; @@ -42,6 +61,8 @@ class LoadButton extends React.Component { } LoadButton.propTypes = { + closeLoadingState: PropTypes.func, + openLoadingState: PropTypes.func, vm: PropTypes.shape({ loadProjectLocal: PropTypes.func }) @@ -51,7 +72,12 @@ const mapStateToProps = state => ({ vm: state.vm }); +const mapDispatchToProps = dispatch => ({ + closeLoadingState: () => dispatch(closeLoadingProject()), + openLoadingState: () => dispatch(openLoadingProject()) +}); + export default connect( mapStateToProps, - () => ({}) // omit dispatch prop + mapDispatchToProps )(LoadButton); diff --git a/src/reducers/modals.js b/src/reducers/modals.js index ba038ff34..2a3772e59 100644 --- a/src/reducers/modals.js +++ b/src/reducers/modals.js @@ -8,6 +8,7 @@ const MODAL_COSTUME_LIBRARY = 'costumeLibrary'; const MODAL_EXTENSION_LIBRARY = 'extensionLibrary'; const MODAL_FEEDBACK_FORM = 'feedbackForm'; const MODAL_IMPORT_INFO = 'importInfo'; +const MODAL_LOADING_PROJECT = 'loadingProject'; const MODAL_PREVIEW_INFO = 'previewInfo'; const MODAL_SOUND_LIBRARY = 'soundLibrary'; const MODAL_SPRITE_LIBRARY = 'spriteLibrary'; @@ -20,6 +21,7 @@ const initialState = { [MODAL_EXTENSION_LIBRARY]: false, [MODAL_FEEDBACK_FORM]: false, [MODAL_IMPORT_INFO]: false, + [MODAL_LOADING_PROJECT]: false, [MODAL_PREVIEW_INFO]: true, [MODAL_SOUND_LIBRARY]: false, [MODAL_SPRITE_LIBRARY]: false, @@ -73,6 +75,10 @@ const openImportInfo = function () { analytics.pageview('modals/import'); return openModal(MODAL_IMPORT_INFO); }; +const openLoadingProject = function () { + analytics.pageview('modals/loading'); + return openModal(MODAL_LOADING_PROJECT); +}; const openPreviewInfo = function () { analytics.pageview('/modals/preview'); return openModal(MODAL_PREVIEW_INFO); @@ -104,6 +110,9 @@ const closeFeedbackForm = function () { const closeImportInfo = function () { return closeModal(MODAL_IMPORT_INFO); }; +const closeLoadingProject = function () { + return closeModal(MODAL_LOADING_PROJECT); +}; const closePreviewInfo = function () { return closeModal(MODAL_PREVIEW_INFO); }; @@ -123,6 +132,7 @@ export { openExtensionLibrary, openFeedbackForm, openImportInfo, + openLoadingProject, openPreviewInfo, openSoundLibrary, openSpriteLibrary, @@ -132,6 +142,7 @@ export { closeExtensionLibrary, closeFeedbackForm, closeImportInfo, + closeLoadingProject, closePreviewInfo, closeSpriteLibrary, closeSoundLibrary, From 03310e42a3a7a113dfe8b2322f642fe30c62bcdd Mon Sep 17 00:00:00 2001 From: kchadha Date: Wed, 14 Mar 2018 15:16:19 -0400 Subject: [PATCH 054/108] Load button file input should only accept specific file extensions. Update load button to use new revamped loadProject function from VM. Loading a project via load button should clear the url hash (without triggering a reload or the project-loader-hoc). --- src/components/load-button/load-button.jsx | 1 + src/containers/load-button.jsx | 6 ++++-- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/src/components/load-button/load-button.jsx b/src/components/load-button/load-button.jsx index 0f580278c..2623b7118 100644 --- a/src/components/load-button/load-button.jsx +++ b/src/components/load-button/load-button.jsx @@ -25,6 +25,7 @@ const LoadButtonComponent = ({ {title} this.props.vm.loadProjectLocal(reader.result) + reader.onload = () => this.props.vm.loadProject(reader.result) .then(() => { this.props.closeLoadingState(); }) @@ -64,7 +66,7 @@ LoadButton.propTypes = { closeLoadingState: PropTypes.func, openLoadingState: PropTypes.func, vm: PropTypes.shape({ - loadProjectLocal: PropTypes.func + loadProject: PropTypes.func }) }; From 5cbec2e12718d8c2f974218118f0867e425804c2 Mon Sep 17 00:00:00 2001 From: Karishma Chadha Date: Thu, 15 Mar 2018 11:10:42 -0400 Subject: [PATCH 055/108] Moving shorthand prop ('disabled') first, according to react lint rules. --- src/components/load-button/load-button.jsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/load-button/load-button.jsx b/src/components/load-button/load-button.jsx index 2623b7118..65c400120 100644 --- a/src/components/load-button/load-button.jsx +++ b/src/components/load-button/load-button.jsx @@ -25,8 +25,8 @@ const LoadButtonComponent = ({ {title} Date: Thu, 15 Mar 2018 19:51:41 +0000 Subject: [PATCH 056/108] chore(package): update scratch-blocks to version 0.1.0-prerelease.1521142086 Closes #1603 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 27814ab0c..4e83821d8 100644 --- a/package.json +++ b/package.json @@ -89,7 +89,7 @@ "redux-throttle": "0.1.1", "rimraf": "^2.6.1", "scratch-audio": "0.1.0-prerelease.1516198804", - "scratch-blocks": "0.1.0-prerelease.1520519504", + "scratch-blocks": "0.1.0-prerelease.1521142086", "scratch-l10n": "2.0.20180108132626", "scratch-paint": "0.2.0-prerelease.20180309170325", "scratch-render": "0.1.0-prerelease.1516837442", From ed1eee713fa814337272825bb90ec264a6276e5e Mon Sep 17 00:00:00 2001 From: Eric Rosenbaum Date: Wed, 14 Mar 2018 21:01:08 -0400 Subject: [PATCH 057/108] hold scroll position on switching sprites --- src/containers/blocks.jsx | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/containers/blocks.jsx b/src/containers/blocks.jsx index bedbbdbad..504291036 100644 --- a/src/containers/blocks.jsx +++ b/src/containers/blocks.jsx @@ -95,9 +95,11 @@ class Blocks extends React.Component { } if (prevProps.toolboxXML !== this.props.toolboxXML) { - const selectedCategoryName = this.workspace.toolbox_.getSelectedItem().name_; + const categoryName = this.workspace.toolbox_.getSelectedCategoryName(); + const offset = this.workspace.toolbox_.getCategoryScrollOffset(); this.workspace.updateToolbox(this.props.toolboxXML); - this.workspace.toolbox_.setSelectedCategoryByName(selectedCategoryName); + const currentCategoryPos = this.workspace.toolbox_.getCategoryPositionByName(categoryName); + this.workspace.toolbox_.setFlyoutScrollPos(currentCategoryPos + offset); } if (this.props.isVisible === prevProps.isVisible) { return; From 447b2b551a9449f9e831a4abb6bd175863d70bfe Mon Sep 17 00:00:00 2001 From: Karishma Chadha Date: Fri, 16 Mar 2018 15:13:19 -0400 Subject: [PATCH 058/108] Code cleanup to remove warning for loadingStateVisible property. --- src/containers/gui.jsx | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/containers/gui.jsx b/src/containers/gui.jsx index 7d0f30020..85b3a7acd 100644 --- a/src/containers/gui.jsx +++ b/src/containers/gui.jsx @@ -64,13 +64,14 @@ class GUI extends React.Component { const { children, fetchingProject, + loadingStateVisible, projectData, // eslint-disable-line no-unused-vars vm, ...componentProps } = this.props; return ( From a0bf60cd741a50fa4bd9326488f0e3c4c507fe3c Mon Sep 17 00:00:00 2001 From: "greenkeeper[bot]" Date: Fri, 16 Mar 2018 23:08:59 +0000 Subject: [PATCH 059/108] chore(package): update scratch-paint to version 0.2.0-prerelease.20180316191214 Closes #1628 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 4e83821d8..f9fef042d 100644 --- a/package.json +++ b/package.json @@ -91,7 +91,7 @@ "scratch-audio": "0.1.0-prerelease.1516198804", "scratch-blocks": "0.1.0-prerelease.1521142086", "scratch-l10n": "2.0.20180108132626", - "scratch-paint": "0.2.0-prerelease.20180309170325", + "scratch-paint": "0.2.0-prerelease.20180316191214", "scratch-render": "0.1.0-prerelease.1516837442", "scratch-storage": "0.4.0", "scratch-vm": "0.1.0-prerelease.1520606673-prerelease.1520606691", From baf86ab23c9517ab618b8ce1004d02d309630216 Mon Sep 17 00:00:00 2001 From: DD Date: Mon, 19 Mar 2018 12:07:02 -0400 Subject: [PATCH 060/108] Don't prevent default on keyboard events --- src/lib/vm-listener-hoc.jsx | 5 ----- 1 file changed, 5 deletions(-) diff --git a/src/lib/vm-listener-hoc.jsx b/src/lib/vm-listener-hoc.jsx index 8e7a0ca17..917f57e9c 100644 --- a/src/lib/vm-listener-hoc.jsx +++ b/src/lib/vm-listener-hoc.jsx @@ -52,11 +52,6 @@ const vmListenerHOC = function (WrappedComponent) { keyCode: e.keyCode, isDown: true }); - - // Don't stop browser keyboard shortcuts - if (e.metaKey || e.altKey || e.ctrlKey) return; - - e.preventDefault(); } handleKeyUp (e) { // Always capture up events, From 4440ea065c3d40d60a78d551048de3203c2ce204 Mon Sep 17 00:00:00 2001 From: "greenkeeper[bot]" Date: Mon, 19 Mar 2018 17:45:50 +0000 Subject: [PATCH 061/108] chore(package): update scratch-vm to version 0.1.0-prerelease.1521481406-prerelease.1521481427 Closes #1619 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 4e83821d8..40907dc1e 100644 --- a/package.json +++ b/package.json @@ -94,7 +94,7 @@ "scratch-paint": "0.2.0-prerelease.20180309170325", "scratch-render": "0.1.0-prerelease.1516837442", "scratch-storage": "0.4.0", - "scratch-vm": "0.1.0-prerelease.1520606673-prerelease.1520606691", + "scratch-vm": "0.1.0-prerelease.1521481406-prerelease.1521481427", "selenium-webdriver": "3.6.0", "startaudiocontext": "1.2.1", "style-loader": "^0.20.0", From 71e4da8e7c2c47497bc1cecde20967c7d184acce Mon Sep 17 00:00:00 2001 From: Paul Kaplan Date: Tue, 20 Mar 2018 10:42:33 -0400 Subject: [PATCH 062/108] Conditionally use "when stage clicked" vs "when this sprite clicked" --- src/lib/make-toolbox-xml.js | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/lib/make-toolbox-xml.js b/src/lib/make-toolbox-xml.js index f5dcb5dc4..4bfb8b2e5 100644 --- a/src/lib/make-toolbox-xml.js +++ b/src/lib/make-toolbox-xml.js @@ -310,13 +310,17 @@ const sound = function () { `; }; -const events = function () { +const events = function (isStage) { return ` - + ${isStage ? ` + + ` : ` + + `} ${blockSeparator} From e70b906afefc66afa8747afe53792ee9ae537dec Mon Sep 17 00:00:00 2001 From: "greenkeeper[bot]" Date: Tue, 20 Mar 2018 15:40:00 +0000 Subject: [PATCH 063/108] chore(package): update scratch-blocks to version 0.1.0-prerelease.1521560313 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 8ed741f2a..2ed5ff0e8 100644 --- a/package.json +++ b/package.json @@ -89,7 +89,7 @@ "redux-throttle": "0.1.1", "rimraf": "^2.6.1", "scratch-audio": "0.1.0-prerelease.1516198804", - "scratch-blocks": "0.1.0-prerelease.1521142086", + "scratch-blocks": "0.1.0-prerelease.1521560313", "scratch-l10n": "2.0.20180108132626", "scratch-paint": "0.2.0-prerelease.20180316191214", "scratch-render": "0.1.0-prerelease.1516837442", From 5f17d70e196cfe4a7bed59833b2cd6491ae3be0c Mon Sep 17 00:00:00 2001 From: "greenkeeper[bot]" Date: Tue, 20 Mar 2018 18:46:24 +0000 Subject: [PATCH 064/108] chore(package): update chromedriver to version 2.37.0 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 2ed5ff0e8..49a4f62cc 100644 --- a/package.json +++ b/package.json @@ -37,7 +37,7 @@ "babel-preset-es2015": "^6.22.0", "babel-preset-react": "^6.22.0", "buffer-loader": "0.0.1", - "chromedriver": "2.36.0", + "chromedriver": "2.37.0", "classnames": "2.2.5", "copy-webpack-plugin": "^4.3.0", "css-loader": "^0.28.7", From 680399cad2e937ce3e15d7b60821db0090d48120 Mon Sep 17 00:00:00 2001 From: "greenkeeper[bot]" Date: Tue, 20 Mar 2018 19:31:49 +0000 Subject: [PATCH 065/108] chore(package): update scratch-paint to version 0.2.0-prerelease.20180320181154 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 2ed5ff0e8..043bbcd5a 100644 --- a/package.json +++ b/package.json @@ -91,7 +91,7 @@ "scratch-audio": "0.1.0-prerelease.1516198804", "scratch-blocks": "0.1.0-prerelease.1521560313", "scratch-l10n": "2.0.20180108132626", - "scratch-paint": "0.2.0-prerelease.20180316191214", + "scratch-paint": "0.2.0-prerelease.20180320181154", "scratch-render": "0.1.0-prerelease.1516837442", "scratch-storage": "0.4.0", "scratch-vm": "0.1.0-prerelease.1521481406-prerelease.1521481427", From 5f8ce77b7d91e5c73be451055f11b0f350b954b7 Mon Sep 17 00:00:00 2001 From: Paul Kaplan Date: Wed, 21 Mar 2018 08:53:51 -0400 Subject: [PATCH 066/108] Make the loader message update every 5 seconds --- src/components/loader/loader.css | 21 ++- src/components/loader/loader.jsx | 293 +++++++++++++++++-------------- 2 files changed, 179 insertions(+), 135 deletions(-) diff --git a/src/components/loader/loader.css b/src/components/loader/loader.css index 68f8e5f4f..8ebbdb5cf 100644 --- a/src/components/loader/loader.css +++ b/src/components/loader/loader.css @@ -29,19 +29,18 @@ margin-top: -4px; } -.topBlock { +.top-block { animation: top-slide-in 1.5s ease infinite; } -.middleBlock { +.middle-block { animation: middle-slide-in 1.5s ease infinite; } -.bottomBlock { +.bottom-block { animation: bottom-slide-in 1.5s ease infinite; } - @keyframes top-slide-in { 0% { transform: translateY(50px); @@ -87,3 +86,17 @@ opacity: 1; } } + +.message-container-outer { + height: 30px; + overflow: hidden; +} + +.message-container-inner { + transition: transform 0.5s; +} + +.message { + height: 20px; + margin: 5px 0; +} diff --git a/src/components/loader/loader.jsx b/src/components/loader/loader.jsx index 8a93e5c36..d95e3ba7b 100644 --- a/src/components/loader/loader.jsx +++ b/src/components/loader/loader.jsx @@ -5,140 +5,171 @@ import styles from './loader.css'; import topBlock from './top-block.svg'; import middleBlock from './middle-block.svg'; import bottomBlock from './bottom-block.svg'; - -const LoaderComponent = () => { - const messages = [ - { - message: ( - - ), - weight: 50 - }, - { - message: ( - - ), - weight: 50 - }, - { - message: ( - - ), - weight: 50 - }, - { - message: ( - - ), - weight: 50 - }, - { - message: ( - - ), - weight: 20 - }, - { - message: ( - - ), - weight: 1 - }, - { - message: ( - - ), - weight: 1 - }, - { - message: ( - - ), - weight: 1 - }, - { - message: ( - - ), - weight: 1 - } - ]; - - let message; - const sum = messages.reduce((acc, m) => acc + m.weight, 0); - let rand = sum * Math.random(); - for (let i = 0; i < messages.length; i++) { - rand -= messages[i].weight; - if (rand <= 0) { - message = messages[i].message; - break; - } +const messages = [ + { + message: ( + + ), + weight: 50 + }, + { + message: ( + + ), + weight: 50 + }, + { + message: ( + + ), + weight: 50 + }, + { + message: ( + + ), + weight: 50 + }, + { + message: ( + + ), + weight: 20 + }, + { + message: ( + + ), + weight: 1 + }, + { + message: ( + + ), + weight: 1 + }, + { + message: ( + + ), + weight: 1 + }, + { + message: ( + + ), + weight: 1 } +]; - return ( -
-
-
- - - +class LoaderComponent extends React.Component { + constructor (props) { + super(props); + this.state = { + messageNumber: 0 + }; + } + componentDidMount () { + this.chooseRandomMessage(); + + // Start an interval to choose a new message every 5 seconds + this.intervalId = setInterval(() => { + this.chooseRandomMessage(); + }, 5000); + } + componentWillUnmount () { + clearInterval(this.intervalId); + } + chooseRandomMessage () { + let messageNumber; + const sum = messages.reduce((acc, m) => acc + m.weight, 0); + let rand = sum * Math.random(); + for (let i = 0; i < messages.length; i++) { + rand -= messages[i].weight; + if (rand <= 0) { + messageNumber = i; + break; + } + } + this.setState({messageNumber}); + } + render () { + return ( +
+
+
+ + + +
+

+ +

+
+
+ {messages.map(m => ( +
+ {m.message} +
+ ))} +
+
-

- -

-

{message}

-
- ); -}; + ); + } +} export default LoaderComponent; From dee7195fac4c947402b9d3422942d48dcffe2449 Mon Sep 17 00:00:00 2001 From: Karishma Chadha Date: Wed, 21 Mar 2018 11:16:34 -0400 Subject: [PATCH 067/108] Rename md5 property in default sb3 project to md5ext to reflect it's actual contents. --- src/lib/default-project/project.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lib/default-project/project.json b/src/lib/default-project/project.json index c1ae335d8..c5d9cb5c7 100755 --- a/src/lib/default-project/project.json +++ b/src/lib/default-project/project.json @@ -1 +1 @@ -{"targets":[{"id":"`jEk@4|i[#Fk?(8x)AV.","name":"Stage","isStage":true,"x":0,"y":0,"size":100,"direction":90,"draggable":false,"currentCostume":0,"costume":{"name":"backdrop1","bitmapResolution":1,"rotationCenterX":240,"rotationCenterY":180,"skinId":2,"dataFormat":"png","assetId":"739b5e2a2435f6e1ec2993791b423146"},"costumeCount":1,"visible":true,"rotationStyle":"all around","blocks":{},"variables":{"`jEk@4|i[#Fk?(8x)AV.-my variable":{"id":"`jEk@4|i[#Fk?(8x)AV.-my variable","name":"my variable","type":"","isCloud":false,"value":0}},"lists":{},"costumes":[{"name":"backdrop1","bitmapResolution":1,"rotationCenterX":240,"rotationCenterY":180,"skinId":2,"dataFormat":"png","assetId":"739b5e2a2435f6e1ec2993791b423146"}],"sounds":[{"name":"pop","format":"","rate":11025,"sampleCount":258,"soundID":1,"md5":"83a9787d4cb6f3b7632b4ddfebf74367.wav","data":null,"dataFormat":"wav","assetId":"83a9787d4cb6f3b7632b4ddfebf74367","soundId":"p=i?*Zt*I]@]x_*V`mut"}]},{"id":"9xJ@2eKXvx:/*Q^3Rib#","name":"Sprite1","isStage":false,"x":0,"y":0,"size":100,"direction":90,"draggable":false,"currentCostume":0,"costume":{"name":"costume1","bitmapResolution":1,"rotationCenterX":47,"rotationCenterY":55,"skinId":0,"dataFormat":"svg","assetId":"09dc888b0b7df19f70d81588ae73420e"},"costumeCount":2,"visible":true,"rotationStyle":"all around","blocks":{},"variables":{},"lists":{},"costumes":[{"name":"costume1","bitmapResolution":1,"rotationCenterX":47,"rotationCenterY":55,"skinId":0,"dataFormat":"svg","assetId":"09dc888b0b7df19f70d81588ae73420e"},{"name":"costume2","bitmapResolution":1,"rotationCenterX":47,"rotationCenterY":55,"skinId":1,"dataFormat":"svg","assetId":"3696356a03a8d938318876a593572843"}],"sounds":[{"name":"Meow","format":"","rate":22050,"sampleCount":18688,"soundID":0,"md5":"83c36d806dc92327b9e7049a565c6bff.wav","data":null,"dataFormat":"wav","assetId":"83c36d806dc92327b9e7049a565c6bff","soundId":"]z6@jLeJ2W%gr/eA1HB+"}]}],"meta":{"semver":"3.0.0","vm":"0.1.0","agent":"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/64.0.3282.186 Safari/537.36"}} \ No newline at end of file +{"targets":[{"id":"`jEk@4|i[#Fk?(8x)AV.","name":"Stage","isStage":true,"x":0,"y":0,"size":100,"direction":90,"draggable":false,"currentCostume":0,"costume":{"name":"backdrop1","bitmapResolution":1,"rotationCenterX":240,"rotationCenterY":180,"skinId":2,"dataFormat":"png","assetId":"739b5e2a2435f6e1ec2993791b423146"},"costumeCount":1,"visible":true,"rotationStyle":"all around","blocks":{},"variables":{"`jEk@4|i[#Fk?(8x)AV.-my variable":{"id":"`jEk@4|i[#Fk?(8x)AV.-my variable","name":"my variable","type":"","isCloud":false,"value":0}},"lists":{},"costumes":[{"name":"backdrop1","bitmapResolution":1,"rotationCenterX":240,"rotationCenterY":180,"skinId":2,"dataFormat":"png","assetId":"739b5e2a2435f6e1ec2993791b423146"}],"sounds":[{"name":"pop","format":"","rate":11025,"sampleCount":258,"soundID":1,"md5ext":"83a9787d4cb6f3b7632b4ddfebf74367.wav","data":null,"dataFormat":"wav","assetId":"83a9787d4cb6f3b7632b4ddfebf74367","soundId":"p=i?*Zt*I]@]x_*V`mut"}]},{"id":"9xJ@2eKXvx:/*Q^3Rib#","name":"Sprite1","isStage":false,"x":0,"y":0,"size":100,"direction":90,"draggable":false,"currentCostume":0,"costume":{"name":"costume1","bitmapResolution":1,"rotationCenterX":47,"rotationCenterY":55,"skinId":0,"dataFormat":"svg","assetId":"09dc888b0b7df19f70d81588ae73420e"},"costumeCount":2,"visible":true,"rotationStyle":"all around","blocks":{},"variables":{},"lists":{},"costumes":[{"name":"costume1","bitmapResolution":1,"rotationCenterX":47,"rotationCenterY":55,"skinId":0,"dataFormat":"svg","assetId":"09dc888b0b7df19f70d81588ae73420e"},{"name":"costume2","bitmapResolution":1,"rotationCenterX":47,"rotationCenterY":55,"skinId":1,"dataFormat":"svg","assetId":"3696356a03a8d938318876a593572843"}],"sounds":[{"name":"Meow","format":"","rate":22050,"sampleCount":18688,"soundID":0,"md5ext":"83c36d806dc92327b9e7049a565c6bff.wav","data":null,"dataFormat":"wav","assetId":"83c36d806dc92327b9e7049a565c6bff","soundId":"]z6@jLeJ2W%gr/eA1HB+"}]}],"meta":{"semver":"3.0.0","vm":"0.1.0","agent":"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/64.0.3282.186 Safari/537.36"}} From 8861eca99b6ab0ceecf23a1e9c911c2f4395b0ca Mon Sep 17 00:00:00 2001 From: chrisgarrity Date: Wed, 21 Mar 2018 11:17:07 -0400 Subject: [PATCH 068/108] Add more browsers to the unsupported list MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Added: - Opera (including Opera Mini) - Silk Not Added: - Vivialdi - appears to be ‘Chrome’ in `platform.name` --- src/components/browser-modal/browser-modal.jsx | 4 ++-- src/containers/error-boundary.jsx | 7 ++++++- src/containers/preview-modal.jsx | 5 +---- 3 files changed, 9 insertions(+), 7 deletions(-) diff --git a/src/components/browser-modal/browser-modal.jsx b/src/components/browser-modal/browser-modal.jsx index c410f7f62..9052d5f57 100644 --- a/src/components/browser-modal/browser-modal.jsx +++ b/src/components/browser-modal/browser-modal.jsx @@ -9,7 +9,7 @@ import styles from './browser-modal.css'; const messages = defineMessages({ label: { id: 'gui.unsupportedBrowser.label', - defaultMessage: 'Internet Explorer is not supported', + defaultMessage: 'Browser is not supported', description: '' } }); @@ -31,7 +31,7 @@ const BrowserModal = ({intl, ...props}) => (

{ /* eslint-disable max-len */ } diff --git a/src/containers/error-boundary.jsx b/src/containers/error-boundary.jsx index d7083f052..4c473a737 100644 --- a/src/containers/error-boundary.jsx +++ b/src/containers/error-boundary.jsx @@ -35,7 +35,12 @@ class ErrorBoundary extends React.Component { render () { if (this.state.hasError) { - if (platform.name === 'IE') { + // don't use array.includes because that's something that causes IE to crash. + if ( + platform.name === 'IE' || + platform.name === 'Opera' || + platform.name === 'Opera Mini' || + platform.name === 'Silk') { return ; } return ; diff --git a/src/containers/preview-modal.jsx b/src/containers/preview-modal.jsx index 1209f251f..3fa6c8f03 100644 --- a/src/containers/preview-modal.jsx +++ b/src/containers/preview-modal.jsx @@ -36,10 +36,7 @@ class PreviewModal extends React.Component { this.props.onViewProject(); } supportedBrowser () { - if (platform.name === 'IE') { - return false; - } - return true; + return !['IE', 'Opera', 'Opera Mini', 'Silk', 'Vivaldi'].includes(platform.name); } render () { return (this.supportedBrowser() ? From 73ec43d0b33b12974ca7404c73ba324bfecb9213 Mon Sep 17 00:00:00 2001 From: Karishma Chadha Date: Wed, 21 Mar 2018 12:38:55 -0400 Subject: [PATCH 069/108] Revert "Rename md5 property in default sb3 project to md5ext to reflect it's actual contents." scratch-audio depends on sound property being called md5 even though it refers to md5+file ext, so this property cannot be renamed just yet. This reverts commit dee7195fac4c947402b9d3422942d48dcffe2449. --- src/lib/default-project/project.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lib/default-project/project.json b/src/lib/default-project/project.json index c5d9cb5c7..c1ae335d8 100755 --- a/src/lib/default-project/project.json +++ b/src/lib/default-project/project.json @@ -1 +1 @@ -{"targets":[{"id":"`jEk@4|i[#Fk?(8x)AV.","name":"Stage","isStage":true,"x":0,"y":0,"size":100,"direction":90,"draggable":false,"currentCostume":0,"costume":{"name":"backdrop1","bitmapResolution":1,"rotationCenterX":240,"rotationCenterY":180,"skinId":2,"dataFormat":"png","assetId":"739b5e2a2435f6e1ec2993791b423146"},"costumeCount":1,"visible":true,"rotationStyle":"all around","blocks":{},"variables":{"`jEk@4|i[#Fk?(8x)AV.-my variable":{"id":"`jEk@4|i[#Fk?(8x)AV.-my variable","name":"my variable","type":"","isCloud":false,"value":0}},"lists":{},"costumes":[{"name":"backdrop1","bitmapResolution":1,"rotationCenterX":240,"rotationCenterY":180,"skinId":2,"dataFormat":"png","assetId":"739b5e2a2435f6e1ec2993791b423146"}],"sounds":[{"name":"pop","format":"","rate":11025,"sampleCount":258,"soundID":1,"md5ext":"83a9787d4cb6f3b7632b4ddfebf74367.wav","data":null,"dataFormat":"wav","assetId":"83a9787d4cb6f3b7632b4ddfebf74367","soundId":"p=i?*Zt*I]@]x_*V`mut"}]},{"id":"9xJ@2eKXvx:/*Q^3Rib#","name":"Sprite1","isStage":false,"x":0,"y":0,"size":100,"direction":90,"draggable":false,"currentCostume":0,"costume":{"name":"costume1","bitmapResolution":1,"rotationCenterX":47,"rotationCenterY":55,"skinId":0,"dataFormat":"svg","assetId":"09dc888b0b7df19f70d81588ae73420e"},"costumeCount":2,"visible":true,"rotationStyle":"all around","blocks":{},"variables":{},"lists":{},"costumes":[{"name":"costume1","bitmapResolution":1,"rotationCenterX":47,"rotationCenterY":55,"skinId":0,"dataFormat":"svg","assetId":"09dc888b0b7df19f70d81588ae73420e"},{"name":"costume2","bitmapResolution":1,"rotationCenterX":47,"rotationCenterY":55,"skinId":1,"dataFormat":"svg","assetId":"3696356a03a8d938318876a593572843"}],"sounds":[{"name":"Meow","format":"","rate":22050,"sampleCount":18688,"soundID":0,"md5ext":"83c36d806dc92327b9e7049a565c6bff.wav","data":null,"dataFormat":"wav","assetId":"83c36d806dc92327b9e7049a565c6bff","soundId":"]z6@jLeJ2W%gr/eA1HB+"}]}],"meta":{"semver":"3.0.0","vm":"0.1.0","agent":"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/64.0.3282.186 Safari/537.36"}} +{"targets":[{"id":"`jEk@4|i[#Fk?(8x)AV.","name":"Stage","isStage":true,"x":0,"y":0,"size":100,"direction":90,"draggable":false,"currentCostume":0,"costume":{"name":"backdrop1","bitmapResolution":1,"rotationCenterX":240,"rotationCenterY":180,"skinId":2,"dataFormat":"png","assetId":"739b5e2a2435f6e1ec2993791b423146"},"costumeCount":1,"visible":true,"rotationStyle":"all around","blocks":{},"variables":{"`jEk@4|i[#Fk?(8x)AV.-my variable":{"id":"`jEk@4|i[#Fk?(8x)AV.-my variable","name":"my variable","type":"","isCloud":false,"value":0}},"lists":{},"costumes":[{"name":"backdrop1","bitmapResolution":1,"rotationCenterX":240,"rotationCenterY":180,"skinId":2,"dataFormat":"png","assetId":"739b5e2a2435f6e1ec2993791b423146"}],"sounds":[{"name":"pop","format":"","rate":11025,"sampleCount":258,"soundID":1,"md5":"83a9787d4cb6f3b7632b4ddfebf74367.wav","data":null,"dataFormat":"wav","assetId":"83a9787d4cb6f3b7632b4ddfebf74367","soundId":"p=i?*Zt*I]@]x_*V`mut"}]},{"id":"9xJ@2eKXvx:/*Q^3Rib#","name":"Sprite1","isStage":false,"x":0,"y":0,"size":100,"direction":90,"draggable":false,"currentCostume":0,"costume":{"name":"costume1","bitmapResolution":1,"rotationCenterX":47,"rotationCenterY":55,"skinId":0,"dataFormat":"svg","assetId":"09dc888b0b7df19f70d81588ae73420e"},"costumeCount":2,"visible":true,"rotationStyle":"all around","blocks":{},"variables":{},"lists":{},"costumes":[{"name":"costume1","bitmapResolution":1,"rotationCenterX":47,"rotationCenterY":55,"skinId":0,"dataFormat":"svg","assetId":"09dc888b0b7df19f70d81588ae73420e"},{"name":"costume2","bitmapResolution":1,"rotationCenterX":47,"rotationCenterY":55,"skinId":1,"dataFormat":"svg","assetId":"3696356a03a8d938318876a593572843"}],"sounds":[{"name":"Meow","format":"","rate":22050,"sampleCount":18688,"soundID":0,"md5":"83c36d806dc92327b9e7049a565c6bff.wav","data":null,"dataFormat":"wav","assetId":"83c36d806dc92327b9e7049a565c6bff","soundId":"]z6@jLeJ2W%gr/eA1HB+"}]}],"meta":{"semver":"3.0.0","vm":"0.1.0","agent":"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/64.0.3282.186 Safari/537.36"}} \ No newline at end of file From 47e2bbbdc79afacf86cf5deedf5c04db2a001c76 Mon Sep 17 00:00:00 2001 From: Karishma Chadha Date: Wed, 21 Mar 2018 16:36:30 -0400 Subject: [PATCH 070/108] Pretty print default project json. --- src/lib/default-project/project.json | 129 ++++++++++++++++++++++++++- 1 file changed, 128 insertions(+), 1 deletion(-) diff --git a/src/lib/default-project/project.json b/src/lib/default-project/project.json index c1ae335d8..fb75aceeb 100755 --- a/src/lib/default-project/project.json +++ b/src/lib/default-project/project.json @@ -1 +1,128 @@ -{"targets":[{"id":"`jEk@4|i[#Fk?(8x)AV.","name":"Stage","isStage":true,"x":0,"y":0,"size":100,"direction":90,"draggable":false,"currentCostume":0,"costume":{"name":"backdrop1","bitmapResolution":1,"rotationCenterX":240,"rotationCenterY":180,"skinId":2,"dataFormat":"png","assetId":"739b5e2a2435f6e1ec2993791b423146"},"costumeCount":1,"visible":true,"rotationStyle":"all around","blocks":{},"variables":{"`jEk@4|i[#Fk?(8x)AV.-my variable":{"id":"`jEk@4|i[#Fk?(8x)AV.-my variable","name":"my variable","type":"","isCloud":false,"value":0}},"lists":{},"costumes":[{"name":"backdrop1","bitmapResolution":1,"rotationCenterX":240,"rotationCenterY":180,"skinId":2,"dataFormat":"png","assetId":"739b5e2a2435f6e1ec2993791b423146"}],"sounds":[{"name":"pop","format":"","rate":11025,"sampleCount":258,"soundID":1,"md5":"83a9787d4cb6f3b7632b4ddfebf74367.wav","data":null,"dataFormat":"wav","assetId":"83a9787d4cb6f3b7632b4ddfebf74367","soundId":"p=i?*Zt*I]@]x_*V`mut"}]},{"id":"9xJ@2eKXvx:/*Q^3Rib#","name":"Sprite1","isStage":false,"x":0,"y":0,"size":100,"direction":90,"draggable":false,"currentCostume":0,"costume":{"name":"costume1","bitmapResolution":1,"rotationCenterX":47,"rotationCenterY":55,"skinId":0,"dataFormat":"svg","assetId":"09dc888b0b7df19f70d81588ae73420e"},"costumeCount":2,"visible":true,"rotationStyle":"all around","blocks":{},"variables":{},"lists":{},"costumes":[{"name":"costume1","bitmapResolution":1,"rotationCenterX":47,"rotationCenterY":55,"skinId":0,"dataFormat":"svg","assetId":"09dc888b0b7df19f70d81588ae73420e"},{"name":"costume2","bitmapResolution":1,"rotationCenterX":47,"rotationCenterY":55,"skinId":1,"dataFormat":"svg","assetId":"3696356a03a8d938318876a593572843"}],"sounds":[{"name":"Meow","format":"","rate":22050,"sampleCount":18688,"soundID":0,"md5":"83c36d806dc92327b9e7049a565c6bff.wav","data":null,"dataFormat":"wav","assetId":"83c36d806dc92327b9e7049a565c6bff","soundId":"]z6@jLeJ2W%gr/eA1HB+"}]}],"meta":{"semver":"3.0.0","vm":"0.1.0","agent":"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/64.0.3282.186 Safari/537.36"}} \ No newline at end of file +{ + "targets": [ + { + "id": "`jEk@4|i[#Fk?(8x)AV.", + "name": "Stage", + "isStage": true, + "x": 0, + "y": 0, + "size": 100, + "direction": 90, + "draggable": false, + "currentCostume": 0, + "costume": { + "name": "backdrop1", + "bitmapResolution": 1, + "rotationCenterX": 240, + "rotationCenterY": 180, + "skinId": 2, + "dataFormat": "png", + "assetId": "739b5e2a2435f6e1ec2993791b423146" + }, + "costumeCount": 1, + "visible": true, + "rotationStyle": "all around", + "blocks": {}, + "variables": { + "`jEk@4|i[#Fk?(8x)AV.-my variable": { + "id": "`jEk@4|i[#Fk?(8x)AV.-my variable", + "name": "my variable", + "type": "", + "isCloud": false, + "value": 0 + } + }, + "lists": {}, + "costumes": [ + { + "name": "backdrop1", + "bitmapResolution": 1, + "rotationCenterX": 240, + "rotationCenterY": 180, + "skinId": 2, + "dataFormat": "png", + "assetId": "739b5e2a2435f6e1ec2993791b423146" + } + ], + "sounds": [ + { + "name": "pop", + "format": "", + "rate": 11025, + "sampleCount": 258, + "soundID": 1, + "md5": "83a9787d4cb6f3b7632b4ddfebf74367.wav", + "data": null, + "dataFormat": "wav", + "assetId": "83a9787d4cb6f3b7632b4ddfebf74367", + "soundId": "p=i?*Zt*I]@]x_*V`mut" + } + ] + }, + { + "id": "9xJ@2eKXvx:/*Q^3Rib#", + "name": "Sprite1", + "isStage": false, + "x": 0, + "y": 0, + "size": 100, + "direction": 90, + "draggable": false, + "currentCostume": 0, + "costume": { + "name": "costume1", + "bitmapResolution": 1, + "rotationCenterX": 47, + "rotationCenterY": 55, + "skinId": 0, + "dataFormat": "svg", + "assetId": "09dc888b0b7df19f70d81588ae73420e" + }, + "costumeCount": 2, + "visible": true, + "rotationStyle": "all around", + "blocks": {}, + "variables": {}, + "lists": {}, + "costumes": [ + { + "name": "costume1", + "bitmapResolution": 1, + "rotationCenterX": 47, + "rotationCenterY": 55, + "skinId": 0, + "dataFormat": "svg", + "assetId": "09dc888b0b7df19f70d81588ae73420e" + }, + { + "name": "costume2", + "bitmapResolution": 1, + "rotationCenterX": 47, + "rotationCenterY": 55, + "skinId": 1, + "dataFormat": "svg", + "assetId": "3696356a03a8d938318876a593572843" + } + ], + "sounds": [ + { + "name": "Meow", + "format": "", + "rate": 22050, + "sampleCount": 18688, + "soundID": 0, + "md5": "83c36d806dc92327b9e7049a565c6bff.wav", + "data": null, + "dataFormat": "wav", + "assetId": "83c36d806dc92327b9e7049a565c6bff", + "soundId": "]z6@jLeJ2W%gr/eA1HB+" + } + ] + } + ], + "meta": { + "semver": "3.0.0", + "vm": "0.1.0", + "agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/64.0.3282.186 Safari/537.36" + } +} From bb3a4572c9d7744367eb4586da472793100d8909 Mon Sep 17 00:00:00 2001 From: Karishma Chadha Date: Wed, 21 Mar 2018 16:52:58 -0400 Subject: [PATCH 071/108] Default project should have correct property names for md5+ext. --- src/lib/default-project/project.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/lib/default-project/project.json b/src/lib/default-project/project.json index fb75aceeb..fc3e21a9c 100755 --- a/src/lib/default-project/project.json +++ b/src/lib/default-project/project.json @@ -51,7 +51,7 @@ "rate": 11025, "sampleCount": 258, "soundID": 1, - "md5": "83a9787d4cb6f3b7632b4ddfebf74367.wav", + "md5ext": "83a9787d4cb6f3b7632b4ddfebf74367.wav", "data": null, "dataFormat": "wav", "assetId": "83a9787d4cb6f3b7632b4ddfebf74367", @@ -111,7 +111,7 @@ "rate": 22050, "sampleCount": 18688, "soundID": 0, - "md5": "83c36d806dc92327b9e7049a565c6bff.wav", + "md5ext": "83c36d806dc92327b9e7049a565c6bff.wav", "data": null, "dataFormat": "wav", "assetId": "83c36d806dc92327b9e7049a565c6bff", From 6aec034acd5cfafd2ea099fb49fec17002943daa Mon Sep 17 00:00:00 2001 From: Karishma Chadha Date: Wed, 21 Mar 2018 18:03:38 -0400 Subject: [PATCH 072/108] Remove .sb from file browser filter since we can't support them yet. Remove .zip from the same. Save project as .sb3 (and untitled-project). --- src/components/load-button/load-button.jsx | 2 +- src/containers/save-button.jsx | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/components/load-button/load-button.jsx b/src/components/load-button/load-button.jsx index 65c400120..d437a9c02 100644 --- a/src/components/load-button/load-button.jsx +++ b/src/components/load-button/load-button.jsx @@ -26,7 +26,7 @@ const LoadButtonComponent = ({ Date: Thu, 22 Mar 2018 10:52:26 -0400 Subject: [PATCH 073/108] Implement Pauls suggestion and remove promises --- src/containers/backdrop-library.jsx | 7 +----- src/containers/costume-library.jsx | 5 +--- src/containers/costume-tab.jsx | 38 +++++++---------------------- 3 files changed, 11 insertions(+), 39 deletions(-) diff --git a/src/containers/backdrop-library.jsx b/src/containers/backdrop-library.jsx index 68f373ece..8f796225e 100644 --- a/src/containers/backdrop-library.jsx +++ b/src/containers/backdrop-library.jsx @@ -23,11 +23,7 @@ class BackdropLibrary extends React.Component { bitmapResolution: item.info.length > 2 ? item.info[2] : 1, skinId: null }; - this.props.vm.addBackdrop(item.md5, vmBackdrop).then(() => { - if (this.props.onNewBackdrop) { - this.props.onNewBackdrop(); - } - }); + this.props.vm.addBackdrop(item.md5, vmBackdrop); analytics.event({ category: 'library', action: 'Select Backdrop', @@ -47,7 +43,6 @@ class BackdropLibrary extends React.Component { } BackdropLibrary.propTypes = { - onNewBackdrop: PropTypes.func.isRequired, onRequestClose: PropTypes.func, vm: PropTypes.instanceOf(VM).isRequired }; diff --git a/src/containers/costume-library.jsx b/src/containers/costume-library.jsx index 2e631bd95..afdd56a5d 100644 --- a/src/containers/costume-library.jsx +++ b/src/containers/costume-library.jsx @@ -23,9 +23,7 @@ class CostumeLibrary extends React.PureComponent { bitmapResolution: item.info.length > 2 ? item.info[2] : 1, skinId: null }; - this.props.vm.addCostume(item.md5, vmCostume).then(() => { - this.props.onNewCostume(); - }); + this.props.vm.addCostume(item.md5, vmCostume); analytics.event({ category: 'library', action: 'Select Costume', @@ -45,7 +43,6 @@ class CostumeLibrary extends React.PureComponent { } CostumeLibrary.propTypes = { - onNewCostume: PropTypes.func.isRequired, onRequestClose: PropTypes.func, vm: PropTypes.instanceOf(VM).isRequired }; diff --git a/src/containers/costume-tab.jsx b/src/containers/costume-tab.jsx index 3ce07dd02..f0712949f 100644 --- a/src/containers/costume-tab.jsx +++ b/src/containers/costume-tab.jsx @@ -67,7 +67,6 @@ class CostumeTab extends React.Component { 'handleSelectCostume', 'handleDeleteCostume', 'handleDuplicateCostume', - 'handleNewCostume', 'handleNewBlankCostume', 'handleSurpriseCostume', 'handleSurpriseBackdrop' @@ -97,24 +96,20 @@ class CostumeTab extends React.Component { } if (this.props.editingTarget === editingTarget) { - // Switch to a newly added costume if there is one + // If costumes have been added or removed, change costumes to the editing target's + // current costume. const oldTarget = this.props.sprites[editingTarget] ? this.props.sprites[editingTarget] : this.props.stage; - // @todo: Check that the costume is actually new by making sure it doesn't - // exist in the old costume list. This is blocked by + // @todo: Find and switch to the index of the costume that is new. This is blocked by // https://github.com/LLK/scratch-vm/issues/967 - if (oldTarget.costumeCount < target.costumeCount) { + // Right now, you can land on the wrong costume if a costume changing script is running. + if (oldTarget.costumeCount !== target.costumeCount) { this.setState({selectedCostumeIndex: target.currentCostume}); } } else { // If switching editing targets, update the costume index this.setState({selectedCostumeIndex: target.currentCostume}); } - - // In case of deleted costumes - if (this.state.selectedCostumeIndex > target.costumes.length - 1) { - this.setState({selectedCostumeIndex: target.costumes.length - 1}); - } } handleSelectCostume (costumeIndex) { this.props.vm.editingTarget.setCostume(costumeIndex); @@ -124,14 +119,7 @@ class CostumeTab extends React.Component { this.props.vm.deleteCostume(costumeIndex); } handleDuplicateCostume (costumeIndex) { - this.props.vm.duplicateCostume(costumeIndex).then(() => { - this.setState({selectedCostumeIndex: costumeIndex + 1}); - }); - } - handleNewCostume () { - if (!this.props.vm.editingTarget) return; - const costumes = this.props.vm.editingTarget.getCostumes() || []; - this.setState({selectedCostumeIndex: Math.max(costumes.length - 1, 0)}); + this.props.vm.duplicateCostume(costumeIndex); } handleNewBlankCostume () { const emptyItem = costumeLibraryContent.find(item => ( @@ -146,9 +134,7 @@ class CostumeTab extends React.Component { skinId: null }; - this.props.vm.addCostume(emptyItem.md5, vmCostume).then(() => { - this.handleNewCostume(); - }); + this.props.vm.addCostume(emptyItem.md5, vmCostume); } handleSurpriseCostume () { const item = costumeLibraryContent[Math.floor(Math.random() * costumeLibraryContent.length)]; @@ -159,9 +145,7 @@ class CostumeTab extends React.Component { bitmapResolution: item.info.length > 2 ? item.info[2] : 1, skinId: null }; - this.props.vm.addCostume(item.md5, vmCostume).then(() => { - this.handleNewCostume(); - }); + this.props.vm.addCostume(item.md5, vmCostume); } handleSurpriseBackdrop () { const item = backdropLibraryContent[Math.floor(Math.random() * backdropLibraryContent.length)]; @@ -172,9 +156,7 @@ class CostumeTab extends React.Component { bitmapResolution: item.info.length > 2 ? item.info[2] : 1, skinId: null }; - this.props.vm.addCostume(item.md5, vmCostume).then(() => { - this.handleNewCostume(); - }); + this.props.vm.addCostume(item.md5, vmCostume); } render () { // For paint wrapper @@ -249,14 +231,12 @@ class CostumeTab extends React.Component { {costumeLibraryVisible ? ( ) : null} {backdropLibraryVisible ? ( ) : null} From e4fe143ba6c46e2d5b26aaaeadc9a10268c33a21 Mon Sep 17 00:00:00 2001 From: Karishma Chadha Date: Thu, 22 Mar 2018 15:09:26 -0400 Subject: [PATCH 074/108] Changes to hash should happen through project loader hoc. Changes to the current project id and current project data should happen in a reducer since they are part of global state. That way, the load button can affect the global project data as well. --- src/containers/gui.jsx | 13 +++-- src/containers/import-modal.jsx | 13 ++--- src/containers/load-button.jsx | 32 +++--------- src/containers/paint-editor-wrapper.jsx | 2 +- src/containers/record-modal.jsx | 2 +- src/containers/save-button.jsx | 2 +- src/containers/sound-editor.jsx | 8 +-- src/containers/sprite-selector-item.jsx | 2 +- src/containers/stage-selector.jsx | 4 +- src/examples/blocks-only.jsx | 2 +- src/examples/compatibility-testing.jsx | 2 +- src/examples/player.jsx | 2 +- src/lib/project-loader-hoc.jsx | 65 +++++++++++++++++++------ src/lib/vm-listener-hoc.jsx | 2 +- src/reducers/vm.js | 35 +++++++++++-- 15 files changed, 118 insertions(+), 68 deletions(-) diff --git a/src/containers/gui.jsx b/src/containers/gui.jsx index 85b3a7acd..62ded94da 100644 --- a/src/containers/gui.jsx +++ b/src/containers/gui.jsx @@ -28,12 +28,12 @@ class GUI extends React.Component { componentDidMount () { this.audioEngine = new AudioEngine(); this.props.vm.attachAudioEngine(this.audioEngine); + this.props.vm.setCompatibilityMode(true); + this.props.vm.start(); + if (!this.props.projectData) return; this.props.vm.loadProject(this.props.projectData) .then(() => { - this.setState({loading: false}, () => { - this.props.vm.setCompatibilityMode(true); - this.props.vm.start(); - }); + this.setState({loading: false}); }) .catch(e => { // Need to catch this error and update component state so that @@ -42,6 +42,7 @@ class GUI extends React.Component { }); } componentWillReceiveProps (nextProps) { + if (!nextProps.projectData) return; if (this.props.projectData !== nextProps.projectData) { this.setState({loading: true}, () => { this.props.vm.loadProject(nextProps.projectData) @@ -88,7 +89,8 @@ GUI.propTypes = { importInfoVisible: PropTypes.bool, loadingStateVisible: PropTypes.bool, previewInfoVisible: PropTypes.bool, - projectData: PropTypes.string, + // eslint-disable-line react/forbid-prop-types + projectData: PropTypes.oneOfType([PropTypes.object, PropTypes.string]), vm: PropTypes.instanceOf(VM) }; @@ -102,6 +104,7 @@ const mapStateToProps = state => ({ importInfoVisible: state.modals.importInfo, loadingStateVisible: state.modals.loadingProject, previewInfoVisible: state.modals.previewInfo, + projectData: state.vm.projectData, soundsTabVisible: state.editorTab.activeTabIndex === SOUNDS_TAB_INDEX }); diff --git a/src/containers/import-modal.jsx b/src/containers/import-modal.jsx index 0731098f1..33305f619 100644 --- a/src/containers/import-modal.jsx +++ b/src/containers/import-modal.jsx @@ -9,6 +9,7 @@ import { closeImportInfo, openPreviewInfo } from '../reducers/modals'; +import {setProjectId} from '../reducers/vm'; class ImportModal extends React.Component { constructor (props) { @@ -35,11 +36,7 @@ class ImportModal extends React.Component { const projectId = this.validate(inputValue); if (projectId) { - const projectLink = document.createElement('a'); - document.body.appendChild(projectLink); - projectLink.href = `#${projectId}`; - projectLink.click(); - document.body.removeChild(projectLink); + this.props.setProjectId(projectId); this.props.onViewProject(); } else { this.setState({ @@ -87,7 +84,8 @@ class ImportModal extends React.Component { ImportModal.propTypes = { onBack: PropTypes.func.isRequired, onCancel: PropTypes.func.isRequired, - onViewProject: PropTypes.func + onViewProject: PropTypes.func, + setProjectId: PropTypes.func }; const mapStateToProps = () => ({}); @@ -102,6 +100,9 @@ const mapDispatchToProps = dispatch => ({ }, onViewProject: () => { dispatch(closeImportInfo()); + }, + setProjectId: projectId => { + dispatch(setProjectId(projectId)); } }); diff --git a/src/containers/load-button.jsx b/src/containers/load-button.jsx index e52a6735d..3587bfbdb 100644 --- a/src/containers/load-button.jsx +++ b/src/containers/load-button.jsx @@ -5,10 +5,8 @@ import {connect} from 'react-redux'; import LoadButtonComponent from '../components/load-button/load-button.jsx'; -import { - openLoadingProject, - closeLoadingProject -} from '../reducers/modals'; +import {openLoadingProject} from '../reducers/modals'; +import {setProjectData} from '../reducers/vm'; class LoadButton extends React.Component { constructor (props) { @@ -25,16 +23,8 @@ class LoadButton extends React.Component { } handleChange (e) { this.props.openLoadingState(); - // Remove the hash if any (without triggering a hash change event or a reload) - history.replaceState({}, document.title, '.'); const reader = new FileReader(); - reader.onload = () => this.props.vm.loadProject(reader.result) - .then(() => { - this.props.closeLoadingState(); - }) - .catch(error => { - this.setState({loadingError: true, errorMessage: error}); - }); + reader.onload = () => this.props.setNewProjectData(reader.result, null); reader.readAsArrayBuffer(e.target.files[0]); } handleClick () { @@ -46,9 +36,8 @@ class LoadButton extends React.Component { render () { if (this.state.loadingError) throw new Error(`Failed to load project: ${this.state.errorMessage}`); const { - closeLoadingState, // eslint-disable-line no-unused-vars openLoadingState, // eslint-disable-line no-unused-vars - vm, // eslint-disable-line no-unused-vars + setNewProjectData, // eslint-disable-line no-unused-vars ...props } = this.props; return ( @@ -63,20 +52,15 @@ class LoadButton extends React.Component { } LoadButton.propTypes = { - closeLoadingState: PropTypes.func, openLoadingState: PropTypes.func, - vm: PropTypes.shape({ - loadProject: PropTypes.func - }) + setNewProjectData: PropTypes.func }; -const mapStateToProps = state => ({ - vm: state.vm -}); +const mapStateToProps = () => ({}); const mapDispatchToProps = dispatch => ({ - closeLoadingState: () => dispatch(closeLoadingProject()), - openLoadingState: () => dispatch(openLoadingProject()) + openLoadingState: () => dispatch(openLoadingProject()), + setNewProjectData: (projectData, projectId) => dispatch(setProjectData(projectData, projectId)) }); export default connect( diff --git a/src/containers/paint-editor-wrapper.jsx b/src/containers/paint-editor-wrapper.jsx index 52bb5708f..00787f68e 100644 --- a/src/containers/paint-editor-wrapper.jsx +++ b/src/containers/paint-editor-wrapper.jsx @@ -60,7 +60,7 @@ const mapStateToProps = (state, {selectedCostumeIndex}) => { rotationCenterX: costume && costume.rotationCenterX, rotationCenterY: costume && costume.rotationCenterY, svgId: editingTarget && `${editingTarget}${costume.skinId}`, - vm: state.vm + vm: state.vm.vm }; }; diff --git a/src/containers/record-modal.jsx b/src/containers/record-modal.jsx index 8e4b9d249..ee05f298b 100644 --- a/src/containers/record-modal.jsx +++ b/src/containers/record-modal.jsx @@ -133,7 +133,7 @@ RecordModal.propTypes = { }; const mapStateToProps = state => ({ - vm: state.vm + vm: state.vm.vm }); const mapDispatchToProps = dispatch => ({ diff --git a/src/containers/save-button.jsx b/src/containers/save-button.jsx index fc8bcf40a..bef371708 100644 --- a/src/containers/save-button.jsx +++ b/src/containers/save-button.jsx @@ -63,7 +63,7 @@ SaveButton.propTypes = { }; const mapStateToProps = state => ({ - vm: state.vm + vm: state.vm.vm }); export default connect( diff --git a/src/containers/sound-editor.jsx b/src/containers/sound-editor.jsx index de10ebc2c..acf745131 100644 --- a/src/containers/sound-editor.jsx +++ b/src/containers/sound-editor.jsx @@ -211,17 +211,17 @@ SoundEditor.propTypes = { }; const mapStateToProps = (state, {soundIndex}) => { - const sprite = state.vm.editingTarget.sprite; + const sprite = state.vm.vm.editingTarget.sprite; // Make sure the sound index doesn't go out of range. const index = soundIndex < sprite.sounds.length ? soundIndex : sprite.sounds.length - 1; - const sound = state.vm.editingTarget.sprite.sounds[index]; - const audioBuffer = state.vm.getSoundBuffer(index); + const sound = state.vm.vm.editingTarget.sprite.sounds[index]; + const audioBuffer = state.vm.vm.getSoundBuffer(index); return { soundId: sound.soundId, sampleRate: audioBuffer.sampleRate, samples: audioBuffer.getChannelData(0), name: sound.name, - vm: state.vm + vm: state.vm.vm }; }; diff --git a/src/containers/sprite-selector-item.jsx b/src/containers/sprite-selector-item.jsx index edb124b2c..519e2f99a 100644 --- a/src/containers/sprite-selector-item.jsx +++ b/src/containers/sprite-selector-item.jsx @@ -79,7 +79,7 @@ SpriteSelectorItem.propTypes = { }; const mapStateToProps = (state, {assetId, costumeURL, id}) => ({ - costumeURL: costumeURL || (assetId && state.vm.runtime.storage.get(assetId).encodeDataURI()), + costumeURL: costumeURL || (assetId && state.vm.vm.runtime.storage.get(assetId).encodeDataURI()), receivedBlocks: state.hoveredTarget.receivedBlocks && state.hoveredTarget.sprite === id }); diff --git a/src/containers/stage-selector.jsx b/src/containers/stage-selector.jsx index bf749c12a..6174a31d3 100644 --- a/src/containers/stage-selector.jsx +++ b/src/containers/stage-selector.jsx @@ -78,8 +78,8 @@ StageSelector.propTypes = { }; const mapStateToProps = (state, {assetId}) => ({ - url: assetId && state.vm.runtime.storage.get(assetId).encodeDataURI(), - vm: state.vm + url: assetId && state.vm.vm.runtime.storage.get(assetId).encodeDataURI(), + vm: state.vm.vm }); const mapDispatchToProps = dispatch => ({ diff --git a/src/examples/blocks-only.jsx b/src/examples/blocks-only.jsx index 8d5159e82..0a961129c 100644 --- a/src/examples/blocks-only.jsx +++ b/src/examples/blocks-only.jsx @@ -10,7 +10,7 @@ import ProjectLoaderHOC from '../lib/project-loader-hoc.jsx'; import styles from './blocks-only.css'; -const mapStateToProps = state => ({vm: state.vm}); +const mapStateToProps = state => ({vm: state.vm.vm}); const VMBlocks = connect(mapStateToProps)(Blocks); const VMControls = connect(mapStateToProps)(Controls); diff --git a/src/examples/compatibility-testing.jsx b/src/examples/compatibility-testing.jsx index 3fa8e71d9..0e05ced12 100644 --- a/src/examples/compatibility-testing.jsx +++ b/src/examples/compatibility-testing.jsx @@ -9,7 +9,7 @@ import Box from '../components/box/box.jsx'; import GUI from '../containers/gui.jsx'; import ProjectLoaderHOC from '../lib/project-loader-hoc.jsx'; -const mapStateToProps = state => ({vm: state.vm}); +const mapStateToProps = state => ({vm: state.vm.vm}); const VMStage = connect(mapStateToProps)(Stage); const VMControls = connect(mapStateToProps)(Controls); diff --git a/src/examples/player.jsx b/src/examples/player.jsx index ab50527cd..85ea90f2a 100644 --- a/src/examples/player.jsx +++ b/src/examples/player.jsx @@ -11,7 +11,7 @@ import ProjectLoaderHOC from '../lib/project-loader-hoc.jsx'; import './player.css'; -const mapStateToProps = state => ({vm: state.vm}); +const mapStateToProps = state => ({vm: state.vm.vm}); const VMStage = connect(mapStateToProps)(Stage); const VMControls = connect(mapStateToProps)(Controls); diff --git a/src/lib/project-loader-hoc.jsx b/src/lib/project-loader-hoc.jsx index 2c20b9fed..1f096f660 100644 --- a/src/lib/project-loader-hoc.jsx +++ b/src/lib/project-loader-hoc.jsx @@ -1,9 +1,13 @@ import React from 'react'; +import PropTypes from 'prop-types'; +import {connect} from 'react-redux'; import analytics from './analytics'; import log from './log'; import storage from './storage'; +import {setProjectId, setProjectData} from '../reducers/vm'; + /* Higher Order Component to provide behavior for loading projects by id from * the window's hash (#this part in the url) * @param {React.Component} WrappedComponent component to receive projectData prop @@ -16,8 +20,6 @@ const ProjectLoaderHOC = function (WrappedComponent) { this.fetchProjectId = this.fetchProjectId.bind(this); this.updateProject = this.updateProject.bind(this); this.state = { - projectId: null, - projectData: null, fetchingProject: false }; } @@ -25,15 +27,25 @@ const ProjectLoaderHOC = function (WrappedComponent) { window.addEventListener('hashchange', this.updateProject); this.updateProject(); } - componentWillUpdate (nextProps, nextState) { - if (this.state.projectId !== nextState.projectId) { + componentWillUpdate (nextProps) { + const projectId = nextProps.projectId; + if (this.props.projectId !== projectId) { + // Replace URL hash without triggering a hash change event + history.replaceState({}, document.title, + projectId ? `./#${projectId}` : '.'); + this.setState({fetchingProject: true}, () => { storage - .load(storage.AssetType.Project, this.state.projectId, storage.DataFormat.JSON) - .then(projectAsset => projectAsset && this.setState({ - projectData: projectAsset.data.toString(), - fetchingProject: false - })) + .load(storage.AssetType.Project, projectId, storage.DataFormat.JSON) + .then(projectAsset => { + if (!projectAsset) return; + + this.setState({ + fetchingProject: false + }); + + this.props.setNewProjectData(projectAsset.data, projectId); + }) .catch(err => log.error(err)); }); } @@ -46,9 +58,9 @@ const ProjectLoaderHOC = function (WrappedComponent) { } updateProject () { let projectId = this.fetchProjectId(); - if (projectId !== this.state.projectId) { + if (projectId !== this.props.projectId) { if (projectId.length < 1) projectId = 0; - this.setState({projectId: projectId}); + this.props.setNewProjectId(projectId); if (projectId !== 0) { analytics.event({ @@ -61,20 +73,41 @@ const ProjectLoaderHOC = function (WrappedComponent) { } } render () { - if (!this.state.projectData) return null; + const { + projectId, // eslint-disable-line no-unused-vars + setNewProjectData, // eslint-disable-line no-unused-vars + setNewProjectId, // eslint-disable-line no-unused-vars + ...props + } = this.props; return ( ); } } - return ProjectLoaderComponent; -}; + ProjectLoaderComponent.propTypes = { + projectId: PropTypes.oneOfType([PropTypes.string, PropTypes.number]), + setNewProjectData: PropTypes.func, + setNewProjectId: PropTypes.func + }; + const mapStateToProps = state => ({ + projectId: state.vm.projectId + }); + + const mapDispatchToProps = dispatch => ({ + setNewProjectId: projectId => dispatch(setProjectId(projectId)), + setNewProjectData: (projectData, projectId) => dispatch(setProjectData(projectData, projectId)) + }); + + return connect( + mapStateToProps, + mapDispatchToProps, + )(ProjectLoaderComponent); +}; export { ProjectLoaderHOC as default diff --git a/src/lib/vm-listener-hoc.jsx b/src/lib/vm-listener-hoc.jsx index 8e7a0ca17..dbc520093 100644 --- a/src/lib/vm-listener-hoc.jsx +++ b/src/lib/vm-listener-hoc.jsx @@ -99,7 +99,7 @@ const vmListenerHOC = function (WrappedComponent) { attachKeyboardEvents: true }; const mapStateToProps = state => ({ - vm: state.vm, + vm: state.vm.vm, hoveredSprite: state.hoveredTarget.sprite, editingTarget: state.targets.editingTarget }); diff --git a/src/reducers/vm.js b/src/reducers/vm.js index dd70f3f4f..1f96dc400 100644 --- a/src/reducers/vm.js +++ b/src/reducers/vm.js @@ -2,15 +2,29 @@ import VM from 'scratch-vm'; import storage from '../lib/storage'; const SET_VM = 'scratch-gui/vm/SET_VM'; +const SET_PROJECT_ID = 'scratch-gui/vm/SET_PROJECT_ID'; +const SET_PROJECT_DATA = 'scratch-gui/vm/SET_PROJECT_DATA'; + const defaultVM = new VM(); defaultVM.attachStorage(storage); -const initialState = defaultVM; +const initialState = { + vm: defaultVM, + projectData: null, + projectId: null // 0 means default project, null or undefined means project from local file +}; const reducer = function (state, action) { if (typeof state === 'undefined') state = initialState; switch (action.type) { case SET_VM: - return action.vm; + return Object.assign({}, state, {vm: action.vm}); + case SET_PROJECT_ID: + return Object.assign({}, state, {projectId: action.projectId}); + case SET_PROJECT_DATA: + return Object.assign({}, state, { + projectData: action.projectData, + projectId: action.projectId + }); default: return state; } @@ -21,7 +35,22 @@ const setVM = function (vm) { vm: vm }; }; +const setProjectId = function (projectId) { + return { + type: SET_PROJECT_ID, + projectId: projectId + }; +}; +const setProjectData = function (projectData, projectId) { + return { + type: SET_PROJECT_DATA, + projectData: projectData, + projectId: projectId + }; +}; export { reducer as default, - setVM + setVM, + setProjectId, + setProjectData }; From c4b44ccd054ad10fe21b8d7544f2f041fdbbf256 Mon Sep 17 00:00:00 2001 From: Karishma Chadha Date: Thu, 22 Mar 2018 16:09:47 -0400 Subject: [PATCH 075/108] Make load button work with new changes. --- src/containers/gui.jsx | 5 +---- src/containers/load-button.jsx | 6 ------ src/lib/project-loader-hoc.jsx | 2 +- src/reducers/modals.js | 11 ----------- 4 files changed, 2 insertions(+), 22 deletions(-) diff --git a/src/containers/gui.jsx b/src/containers/gui.jsx index 62ded94da..a5729f901 100644 --- a/src/containers/gui.jsx +++ b/src/containers/gui.jsx @@ -65,14 +65,13 @@ class GUI extends React.Component { const { children, fetchingProject, - loadingStateVisible, projectData, // eslint-disable-line no-unused-vars vm, ...componentProps } = this.props; return ( @@ -87,7 +86,6 @@ GUI.propTypes = { feedbackFormVisible: PropTypes.bool, fetchingProject: PropTypes.bool, importInfoVisible: PropTypes.bool, - loadingStateVisible: PropTypes.bool, previewInfoVisible: PropTypes.bool, // eslint-disable-line react/forbid-prop-types projectData: PropTypes.oneOfType([PropTypes.object, PropTypes.string]), @@ -102,7 +100,6 @@ const mapStateToProps = state => ({ costumesTabVisible: state.editorTab.activeTabIndex === COSTUMES_TAB_INDEX, feedbackFormVisible: state.modals.feedbackForm, importInfoVisible: state.modals.importInfo, - loadingStateVisible: state.modals.loadingProject, previewInfoVisible: state.modals.previewInfo, projectData: state.vm.projectData, soundsTabVisible: state.editorTab.activeTabIndex === SOUNDS_TAB_INDEX diff --git a/src/containers/load-button.jsx b/src/containers/load-button.jsx index 3587bfbdb..a5e90a255 100644 --- a/src/containers/load-button.jsx +++ b/src/containers/load-button.jsx @@ -4,8 +4,6 @@ import React from 'react'; import {connect} from 'react-redux'; import LoadButtonComponent from '../components/load-button/load-button.jsx'; - -import {openLoadingProject} from '../reducers/modals'; import {setProjectData} from '../reducers/vm'; class LoadButton extends React.Component { @@ -22,7 +20,6 @@ class LoadButton extends React.Component { }; } handleChange (e) { - this.props.openLoadingState(); const reader = new FileReader(); reader.onload = () => this.props.setNewProjectData(reader.result, null); reader.readAsArrayBuffer(e.target.files[0]); @@ -36,7 +33,6 @@ class LoadButton extends React.Component { render () { if (this.state.loadingError) throw new Error(`Failed to load project: ${this.state.errorMessage}`); const { - openLoadingState, // eslint-disable-line no-unused-vars setNewProjectData, // eslint-disable-line no-unused-vars ...props } = this.props; @@ -52,14 +48,12 @@ class LoadButton extends React.Component { } LoadButton.propTypes = { - openLoadingState: PropTypes.func, setNewProjectData: PropTypes.func }; const mapStateToProps = () => ({}); const mapDispatchToProps = dispatch => ({ - openLoadingState: () => dispatch(openLoadingProject()), setNewProjectData: (projectData, projectId) => dispatch(setProjectData(projectData, projectId)) }); diff --git a/src/lib/project-loader-hoc.jsx b/src/lib/project-loader-hoc.jsx index 1f096f660..fdf79edcf 100644 --- a/src/lib/project-loader-hoc.jsx +++ b/src/lib/project-loader-hoc.jsx @@ -33,7 +33,7 @@ const ProjectLoaderHOC = function (WrappedComponent) { // Replace URL hash without triggering a hash change event history.replaceState({}, document.title, projectId ? `./#${projectId}` : '.'); - + if (projectId === null) return; // load button triggered this and is already calling setProjectData this.setState({fetchingProject: true}, () => { storage .load(storage.AssetType.Project, projectId, storage.DataFormat.JSON) diff --git a/src/reducers/modals.js b/src/reducers/modals.js index 2a3772e59..ba038ff34 100644 --- a/src/reducers/modals.js +++ b/src/reducers/modals.js @@ -8,7 +8,6 @@ const MODAL_COSTUME_LIBRARY = 'costumeLibrary'; const MODAL_EXTENSION_LIBRARY = 'extensionLibrary'; const MODAL_FEEDBACK_FORM = 'feedbackForm'; const MODAL_IMPORT_INFO = 'importInfo'; -const MODAL_LOADING_PROJECT = 'loadingProject'; const MODAL_PREVIEW_INFO = 'previewInfo'; const MODAL_SOUND_LIBRARY = 'soundLibrary'; const MODAL_SPRITE_LIBRARY = 'spriteLibrary'; @@ -21,7 +20,6 @@ const initialState = { [MODAL_EXTENSION_LIBRARY]: false, [MODAL_FEEDBACK_FORM]: false, [MODAL_IMPORT_INFO]: false, - [MODAL_LOADING_PROJECT]: false, [MODAL_PREVIEW_INFO]: true, [MODAL_SOUND_LIBRARY]: false, [MODAL_SPRITE_LIBRARY]: false, @@ -75,10 +73,6 @@ const openImportInfo = function () { analytics.pageview('modals/import'); return openModal(MODAL_IMPORT_INFO); }; -const openLoadingProject = function () { - analytics.pageview('modals/loading'); - return openModal(MODAL_LOADING_PROJECT); -}; const openPreviewInfo = function () { analytics.pageview('/modals/preview'); return openModal(MODAL_PREVIEW_INFO); @@ -110,9 +104,6 @@ const closeFeedbackForm = function () { const closeImportInfo = function () { return closeModal(MODAL_IMPORT_INFO); }; -const closeLoadingProject = function () { - return closeModal(MODAL_LOADING_PROJECT); -}; const closePreviewInfo = function () { return closeModal(MODAL_PREVIEW_INFO); }; @@ -132,7 +123,6 @@ export { openExtensionLibrary, openFeedbackForm, openImportInfo, - openLoadingProject, openPreviewInfo, openSoundLibrary, openSpriteLibrary, @@ -142,7 +132,6 @@ export { closeExtensionLibrary, closeFeedbackForm, closeImportInfo, - closeLoadingProject, closePreviewInfo, closeSpriteLibrary, closeSoundLibrary, From 7ea295df486f6a7b8f798e782c4f52a7a31c246b Mon Sep 17 00:00:00 2001 From: Karishma Chadha Date: Thu, 22 Mar 2018 16:11:43 -0400 Subject: [PATCH 076/108] Recorded sounds should have actual md5s. --- src/containers/record-modal.jsx | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/src/containers/record-modal.jsx b/src/containers/record-modal.jsx index ee05f298b..45f847807 100644 --- a/src/containers/record-modal.jsx +++ b/src/containers/record-modal.jsx @@ -73,22 +73,24 @@ class RecordModal extends React.Component { sampleRate: this.state.sampleRate, channelData: [clippedSamples] }).then(wavBuffer => { - const md5 = String(Math.floor(100000 * Math.random())); const vmSound = { format: '', - md5: `${md5}.wav`, + dataFormat: 'wav', name: `recording ${this.props.vm.editingTarget.sprite.sounds.length}` }; - // Load the encoded .wav into the storage cache + // Load the encoded .wav into the storage cache and get resulting + // md5 from storage const storage = this.props.vm.runtime.storage; - storage.builtinHelper.cache( + const md5 = storage.builtinHelper.cache( storage.AssetType.Sound, storage.DataFormat.WAV, new Uint8Array(wavBuffer), - md5 ); + // update vmSound object with md5 property + vmSound.md5 = `${md5}.${vmSound.dataFormat}`; + this.props.vm.addSound(vmSound).then(() => { this.props.onClose(); this.props.onNewSound(); From 050d0d8a55c2f5df9476ef72e5fc57fd571cac78 Mon Sep 17 00:00:00 2001 From: "greenkeeper[bot]" Date: Fri, 23 Mar 2018 13:23:34 +0000 Subject: [PATCH 077/108] chore(package): update scratch-blocks to version 0.1.0-prerelease.1521811349 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 2ed5ff0e8..ee0dcb9f8 100644 --- a/package.json +++ b/package.json @@ -89,7 +89,7 @@ "redux-throttle": "0.1.1", "rimraf": "^2.6.1", "scratch-audio": "0.1.0-prerelease.1516198804", - "scratch-blocks": "0.1.0-prerelease.1521560313", + "scratch-blocks": "0.1.0-prerelease.1521811349", "scratch-l10n": "2.0.20180108132626", "scratch-paint": "0.2.0-prerelease.20180316191214", "scratch-render": "0.1.0-prerelease.1516837442", From 630c12bad72adf50b294dcad23fb7bc8c8ca47c7 Mon Sep 17 00:00:00 2001 From: Paul Kaplan Date: Fri, 23 Mar 2018 09:23:47 -0400 Subject: [PATCH 078/108] Fix linting --- src/components/loader/loader.jsx | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/components/loader/loader.jsx b/src/components/loader/loader.jsx index d95e3ba7b..a9b010724 100644 --- a/src/components/loader/loader.jsx +++ b/src/components/loader/loader.jsx @@ -159,8 +159,11 @@ class LoaderComponent extends React.Component { className={styles.messageContainerInner} style={{transform: `translate(0, -${this.state.messageNumber * 25}px)`}} > - {messages.map(m => ( -

+ {messages.map((m, i) => ( +
{m.message}
))} From 69d887cefb4d860e4a2c2a44440f85f11e50da7d Mon Sep 17 00:00:00 2001 From: Paul Kaplan Date: Fri, 23 Mar 2018 09:27:40 -0400 Subject: [PATCH 079/108] Fix typo FWIW the AP style guide recommends "emojis", although many dictionaries also recognize "emoji" as the plural because that is the plural in the original Japanese. --- src/components/loader/loader.jsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/loader/loader.jsx b/src/components/loader/loader.jsx index a9b010724..9da2eb383 100644 --- a/src/components/loader/loader.jsx +++ b/src/components/loader/loader.jsx @@ -89,7 +89,7 @@ const messages = [ { message: ( From 5031340cad64a2877936d1915c761c224176ccbf Mon Sep 17 00:00:00 2001 From: "greenkeeper[bot]" Date: Fri, 23 Mar 2018 13:32:32 +0000 Subject: [PATCH 080/108] chore(package): update scratch-vm to version 0.1.0-prerelease.1521811835-prerelease.1521811852 Closes #1636 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 043bbcd5a..a96feb26d 100644 --- a/package.json +++ b/package.json @@ -94,7 +94,7 @@ "scratch-paint": "0.2.0-prerelease.20180320181154", "scratch-render": "0.1.0-prerelease.1516837442", "scratch-storage": "0.4.0", - "scratch-vm": "0.1.0-prerelease.1521481406-prerelease.1521481427", + "scratch-vm": "0.1.0-prerelease.1521811835-prerelease.1521811852", "selenium-webdriver": "3.6.0", "startaudiocontext": "1.2.1", "style-loader": "^0.20.0", From 004b586cad6b2c4461e3c31dd0875296b4fd2157 Mon Sep 17 00:00:00 2001 From: Karishma Chadha Date: Fri, 23 Mar 2018 10:06:54 -0400 Subject: [PATCH 081/108] Revert "Changes to hash should happen through project loader hoc. Changes to the current project id and current project data should happen in a reducer since they are part of global state. That way, the load button can affect the global project data as well." This reverts commit e4fe143ba6c46e2d5b26aaaeadc9a10268c33a21. --- src/containers/gui.jsx | 18 +++---- src/containers/import-modal.jsx | 13 +++-- src/containers/load-button.jsx | 34 ++++++++++--- src/containers/paint-editor-wrapper.jsx | 2 +- src/containers/record-modal.jsx | 2 +- src/containers/save-button.jsx | 2 +- src/containers/sound-editor.jsx | 8 +-- src/containers/sprite-selector-item.jsx | 2 +- src/containers/stage-selector.jsx | 4 +- src/examples/blocks-only.jsx | 2 +- src/examples/compatibility-testing.jsx | 2 +- src/examples/player.jsx | 2 +- src/lib/project-loader-hoc.jsx | 65 ++++++------------------- src/lib/vm-listener-hoc.jsx | 2 +- src/reducers/modals.js | 11 +++++ src/reducers/vm.js | 35 ++----------- 16 files changed, 87 insertions(+), 117 deletions(-) diff --git a/src/containers/gui.jsx b/src/containers/gui.jsx index a5729f901..85b3a7acd 100644 --- a/src/containers/gui.jsx +++ b/src/containers/gui.jsx @@ -28,12 +28,12 @@ class GUI extends React.Component { componentDidMount () { this.audioEngine = new AudioEngine(); this.props.vm.attachAudioEngine(this.audioEngine); - this.props.vm.setCompatibilityMode(true); - this.props.vm.start(); - if (!this.props.projectData) return; this.props.vm.loadProject(this.props.projectData) .then(() => { - this.setState({loading: false}); + this.setState({loading: false}, () => { + this.props.vm.setCompatibilityMode(true); + this.props.vm.start(); + }); }) .catch(e => { // Need to catch this error and update component state so that @@ -42,7 +42,6 @@ class GUI extends React.Component { }); } componentWillReceiveProps (nextProps) { - if (!nextProps.projectData) return; if (this.props.projectData !== nextProps.projectData) { this.setState({loading: true}, () => { this.props.vm.loadProject(nextProps.projectData) @@ -65,13 +64,14 @@ class GUI extends React.Component { const { children, fetchingProject, + loadingStateVisible, projectData, // eslint-disable-line no-unused-vars vm, ...componentProps } = this.props; return ( @@ -86,9 +86,9 @@ GUI.propTypes = { feedbackFormVisible: PropTypes.bool, fetchingProject: PropTypes.bool, importInfoVisible: PropTypes.bool, + loadingStateVisible: PropTypes.bool, previewInfoVisible: PropTypes.bool, - // eslint-disable-line react/forbid-prop-types - projectData: PropTypes.oneOfType([PropTypes.object, PropTypes.string]), + projectData: PropTypes.string, vm: PropTypes.instanceOf(VM) }; @@ -100,8 +100,8 @@ const mapStateToProps = state => ({ costumesTabVisible: state.editorTab.activeTabIndex === COSTUMES_TAB_INDEX, feedbackFormVisible: state.modals.feedbackForm, importInfoVisible: state.modals.importInfo, + loadingStateVisible: state.modals.loadingProject, previewInfoVisible: state.modals.previewInfo, - projectData: state.vm.projectData, soundsTabVisible: state.editorTab.activeTabIndex === SOUNDS_TAB_INDEX }); diff --git a/src/containers/import-modal.jsx b/src/containers/import-modal.jsx index 33305f619..0731098f1 100644 --- a/src/containers/import-modal.jsx +++ b/src/containers/import-modal.jsx @@ -9,7 +9,6 @@ import { closeImportInfo, openPreviewInfo } from '../reducers/modals'; -import {setProjectId} from '../reducers/vm'; class ImportModal extends React.Component { constructor (props) { @@ -36,7 +35,11 @@ class ImportModal extends React.Component { const projectId = this.validate(inputValue); if (projectId) { - this.props.setProjectId(projectId); + const projectLink = document.createElement('a'); + document.body.appendChild(projectLink); + projectLink.href = `#${projectId}`; + projectLink.click(); + document.body.removeChild(projectLink); this.props.onViewProject(); } else { this.setState({ @@ -84,8 +87,7 @@ class ImportModal extends React.Component { ImportModal.propTypes = { onBack: PropTypes.func.isRequired, onCancel: PropTypes.func.isRequired, - onViewProject: PropTypes.func, - setProjectId: PropTypes.func + onViewProject: PropTypes.func }; const mapStateToProps = () => ({}); @@ -100,9 +102,6 @@ const mapDispatchToProps = dispatch => ({ }, onViewProject: () => { dispatch(closeImportInfo()); - }, - setProjectId: projectId => { - dispatch(setProjectId(projectId)); } }); diff --git a/src/containers/load-button.jsx b/src/containers/load-button.jsx index a5e90a255..e52a6735d 100644 --- a/src/containers/load-button.jsx +++ b/src/containers/load-button.jsx @@ -4,7 +4,11 @@ import React from 'react'; import {connect} from 'react-redux'; import LoadButtonComponent from '../components/load-button/load-button.jsx'; -import {setProjectData} from '../reducers/vm'; + +import { + openLoadingProject, + closeLoadingProject +} from '../reducers/modals'; class LoadButton extends React.Component { constructor (props) { @@ -20,8 +24,17 @@ class LoadButton extends React.Component { }; } handleChange (e) { + this.props.openLoadingState(); + // Remove the hash if any (without triggering a hash change event or a reload) + history.replaceState({}, document.title, '.'); const reader = new FileReader(); - reader.onload = () => this.props.setNewProjectData(reader.result, null); + reader.onload = () => this.props.vm.loadProject(reader.result) + .then(() => { + this.props.closeLoadingState(); + }) + .catch(error => { + this.setState({loadingError: true, errorMessage: error}); + }); reader.readAsArrayBuffer(e.target.files[0]); } handleClick () { @@ -33,7 +46,9 @@ class LoadButton extends React.Component { render () { if (this.state.loadingError) throw new Error(`Failed to load project: ${this.state.errorMessage}`); const { - setNewProjectData, // eslint-disable-line no-unused-vars + closeLoadingState, // eslint-disable-line no-unused-vars + openLoadingState, // eslint-disable-line no-unused-vars + vm, // eslint-disable-line no-unused-vars ...props } = this.props; return ( @@ -48,13 +63,20 @@ class LoadButton extends React.Component { } LoadButton.propTypes = { - setNewProjectData: PropTypes.func + closeLoadingState: PropTypes.func, + openLoadingState: PropTypes.func, + vm: PropTypes.shape({ + loadProject: PropTypes.func + }) }; -const mapStateToProps = () => ({}); +const mapStateToProps = state => ({ + vm: state.vm +}); const mapDispatchToProps = dispatch => ({ - setNewProjectData: (projectData, projectId) => dispatch(setProjectData(projectData, projectId)) + closeLoadingState: () => dispatch(closeLoadingProject()), + openLoadingState: () => dispatch(openLoadingProject()) }); export default connect( diff --git a/src/containers/paint-editor-wrapper.jsx b/src/containers/paint-editor-wrapper.jsx index 00787f68e..52bb5708f 100644 --- a/src/containers/paint-editor-wrapper.jsx +++ b/src/containers/paint-editor-wrapper.jsx @@ -60,7 +60,7 @@ const mapStateToProps = (state, {selectedCostumeIndex}) => { rotationCenterX: costume && costume.rotationCenterX, rotationCenterY: costume && costume.rotationCenterY, svgId: editingTarget && `${editingTarget}${costume.skinId}`, - vm: state.vm.vm + vm: state.vm }; }; diff --git a/src/containers/record-modal.jsx b/src/containers/record-modal.jsx index 45f847807..9c4311539 100644 --- a/src/containers/record-modal.jsx +++ b/src/containers/record-modal.jsx @@ -135,7 +135,7 @@ RecordModal.propTypes = { }; const mapStateToProps = state => ({ - vm: state.vm.vm + vm: state.vm }); const mapDispatchToProps = dispatch => ({ diff --git a/src/containers/save-button.jsx b/src/containers/save-button.jsx index bef371708..fc8bcf40a 100644 --- a/src/containers/save-button.jsx +++ b/src/containers/save-button.jsx @@ -63,7 +63,7 @@ SaveButton.propTypes = { }; const mapStateToProps = state => ({ - vm: state.vm.vm + vm: state.vm }); export default connect( diff --git a/src/containers/sound-editor.jsx b/src/containers/sound-editor.jsx index acf745131..de10ebc2c 100644 --- a/src/containers/sound-editor.jsx +++ b/src/containers/sound-editor.jsx @@ -211,17 +211,17 @@ SoundEditor.propTypes = { }; const mapStateToProps = (state, {soundIndex}) => { - const sprite = state.vm.vm.editingTarget.sprite; + const sprite = state.vm.editingTarget.sprite; // Make sure the sound index doesn't go out of range. const index = soundIndex < sprite.sounds.length ? soundIndex : sprite.sounds.length - 1; - const sound = state.vm.vm.editingTarget.sprite.sounds[index]; - const audioBuffer = state.vm.vm.getSoundBuffer(index); + const sound = state.vm.editingTarget.sprite.sounds[index]; + const audioBuffer = state.vm.getSoundBuffer(index); return { soundId: sound.soundId, sampleRate: audioBuffer.sampleRate, samples: audioBuffer.getChannelData(0), name: sound.name, - vm: state.vm.vm + vm: state.vm }; }; diff --git a/src/containers/sprite-selector-item.jsx b/src/containers/sprite-selector-item.jsx index 519e2f99a..edb124b2c 100644 --- a/src/containers/sprite-selector-item.jsx +++ b/src/containers/sprite-selector-item.jsx @@ -79,7 +79,7 @@ SpriteSelectorItem.propTypes = { }; const mapStateToProps = (state, {assetId, costumeURL, id}) => ({ - costumeURL: costumeURL || (assetId && state.vm.vm.runtime.storage.get(assetId).encodeDataURI()), + costumeURL: costumeURL || (assetId && state.vm.runtime.storage.get(assetId).encodeDataURI()), receivedBlocks: state.hoveredTarget.receivedBlocks && state.hoveredTarget.sprite === id }); diff --git a/src/containers/stage-selector.jsx b/src/containers/stage-selector.jsx index 6174a31d3..bf749c12a 100644 --- a/src/containers/stage-selector.jsx +++ b/src/containers/stage-selector.jsx @@ -78,8 +78,8 @@ StageSelector.propTypes = { }; const mapStateToProps = (state, {assetId}) => ({ - url: assetId && state.vm.vm.runtime.storage.get(assetId).encodeDataURI(), - vm: state.vm.vm + url: assetId && state.vm.runtime.storage.get(assetId).encodeDataURI(), + vm: state.vm }); const mapDispatchToProps = dispatch => ({ diff --git a/src/examples/blocks-only.jsx b/src/examples/blocks-only.jsx index 0a961129c..8d5159e82 100644 --- a/src/examples/blocks-only.jsx +++ b/src/examples/blocks-only.jsx @@ -10,7 +10,7 @@ import ProjectLoaderHOC from '../lib/project-loader-hoc.jsx'; import styles from './blocks-only.css'; -const mapStateToProps = state => ({vm: state.vm.vm}); +const mapStateToProps = state => ({vm: state.vm}); const VMBlocks = connect(mapStateToProps)(Blocks); const VMControls = connect(mapStateToProps)(Controls); diff --git a/src/examples/compatibility-testing.jsx b/src/examples/compatibility-testing.jsx index 0e05ced12..3fa8e71d9 100644 --- a/src/examples/compatibility-testing.jsx +++ b/src/examples/compatibility-testing.jsx @@ -9,7 +9,7 @@ import Box from '../components/box/box.jsx'; import GUI from '../containers/gui.jsx'; import ProjectLoaderHOC from '../lib/project-loader-hoc.jsx'; -const mapStateToProps = state => ({vm: state.vm.vm}); +const mapStateToProps = state => ({vm: state.vm}); const VMStage = connect(mapStateToProps)(Stage); const VMControls = connect(mapStateToProps)(Controls); diff --git a/src/examples/player.jsx b/src/examples/player.jsx index 85ea90f2a..ab50527cd 100644 --- a/src/examples/player.jsx +++ b/src/examples/player.jsx @@ -11,7 +11,7 @@ import ProjectLoaderHOC from '../lib/project-loader-hoc.jsx'; import './player.css'; -const mapStateToProps = state => ({vm: state.vm.vm}); +const mapStateToProps = state => ({vm: state.vm}); const VMStage = connect(mapStateToProps)(Stage); const VMControls = connect(mapStateToProps)(Controls); diff --git a/src/lib/project-loader-hoc.jsx b/src/lib/project-loader-hoc.jsx index fdf79edcf..2c20b9fed 100644 --- a/src/lib/project-loader-hoc.jsx +++ b/src/lib/project-loader-hoc.jsx @@ -1,13 +1,9 @@ import React from 'react'; -import PropTypes from 'prop-types'; -import {connect} from 'react-redux'; import analytics from './analytics'; import log from './log'; import storage from './storage'; -import {setProjectId, setProjectData} from '../reducers/vm'; - /* Higher Order Component to provide behavior for loading projects by id from * the window's hash (#this part in the url) * @param {React.Component} WrappedComponent component to receive projectData prop @@ -20,6 +16,8 @@ const ProjectLoaderHOC = function (WrappedComponent) { this.fetchProjectId = this.fetchProjectId.bind(this); this.updateProject = this.updateProject.bind(this); this.state = { + projectId: null, + projectData: null, fetchingProject: false }; } @@ -27,25 +25,15 @@ const ProjectLoaderHOC = function (WrappedComponent) { window.addEventListener('hashchange', this.updateProject); this.updateProject(); } - componentWillUpdate (nextProps) { - const projectId = nextProps.projectId; - if (this.props.projectId !== projectId) { - // Replace URL hash without triggering a hash change event - history.replaceState({}, document.title, - projectId ? `./#${projectId}` : '.'); - if (projectId === null) return; // load button triggered this and is already calling setProjectData + componentWillUpdate (nextProps, nextState) { + if (this.state.projectId !== nextState.projectId) { this.setState({fetchingProject: true}, () => { storage - .load(storage.AssetType.Project, projectId, storage.DataFormat.JSON) - .then(projectAsset => { - if (!projectAsset) return; - - this.setState({ - fetchingProject: false - }); - - this.props.setNewProjectData(projectAsset.data, projectId); - }) + .load(storage.AssetType.Project, this.state.projectId, storage.DataFormat.JSON) + .then(projectAsset => projectAsset && this.setState({ + projectData: projectAsset.data.toString(), + fetchingProject: false + })) .catch(err => log.error(err)); }); } @@ -58,9 +46,9 @@ const ProjectLoaderHOC = function (WrappedComponent) { } updateProject () { let projectId = this.fetchProjectId(); - if (projectId !== this.props.projectId) { + if (projectId !== this.state.projectId) { if (projectId.length < 1) projectId = 0; - this.props.setNewProjectId(projectId); + this.setState({projectId: projectId}); if (projectId !== 0) { analytics.event({ @@ -73,42 +61,21 @@ const ProjectLoaderHOC = function (WrappedComponent) { } } render () { - const { - projectId, // eslint-disable-line no-unused-vars - setNewProjectData, // eslint-disable-line no-unused-vars - setNewProjectId, // eslint-disable-line no-unused-vars - ...props - } = this.props; + if (!this.state.projectData) return null; return ( ); } } - ProjectLoaderComponent.propTypes = { - projectId: PropTypes.oneOfType([PropTypes.string, PropTypes.number]), - setNewProjectData: PropTypes.func, - setNewProjectId: PropTypes.func - }; - - const mapStateToProps = state => ({ - projectId: state.vm.projectId - }); - - const mapDispatchToProps = dispatch => ({ - setNewProjectId: projectId => dispatch(setProjectId(projectId)), - setNewProjectData: (projectData, projectId) => dispatch(setProjectData(projectData, projectId)) - }); - - return connect( - mapStateToProps, - mapDispatchToProps, - )(ProjectLoaderComponent); + return ProjectLoaderComponent; }; + export { ProjectLoaderHOC as default }; diff --git a/src/lib/vm-listener-hoc.jsx b/src/lib/vm-listener-hoc.jsx index dbc520093..8e7a0ca17 100644 --- a/src/lib/vm-listener-hoc.jsx +++ b/src/lib/vm-listener-hoc.jsx @@ -99,7 +99,7 @@ const vmListenerHOC = function (WrappedComponent) { attachKeyboardEvents: true }; const mapStateToProps = state => ({ - vm: state.vm.vm, + vm: state.vm, hoveredSprite: state.hoveredTarget.sprite, editingTarget: state.targets.editingTarget }); diff --git a/src/reducers/modals.js b/src/reducers/modals.js index ba038ff34..2a3772e59 100644 --- a/src/reducers/modals.js +++ b/src/reducers/modals.js @@ -8,6 +8,7 @@ const MODAL_COSTUME_LIBRARY = 'costumeLibrary'; const MODAL_EXTENSION_LIBRARY = 'extensionLibrary'; const MODAL_FEEDBACK_FORM = 'feedbackForm'; const MODAL_IMPORT_INFO = 'importInfo'; +const MODAL_LOADING_PROJECT = 'loadingProject'; const MODAL_PREVIEW_INFO = 'previewInfo'; const MODAL_SOUND_LIBRARY = 'soundLibrary'; const MODAL_SPRITE_LIBRARY = 'spriteLibrary'; @@ -20,6 +21,7 @@ const initialState = { [MODAL_EXTENSION_LIBRARY]: false, [MODAL_FEEDBACK_FORM]: false, [MODAL_IMPORT_INFO]: false, + [MODAL_LOADING_PROJECT]: false, [MODAL_PREVIEW_INFO]: true, [MODAL_SOUND_LIBRARY]: false, [MODAL_SPRITE_LIBRARY]: false, @@ -73,6 +75,10 @@ const openImportInfo = function () { analytics.pageview('modals/import'); return openModal(MODAL_IMPORT_INFO); }; +const openLoadingProject = function () { + analytics.pageview('modals/loading'); + return openModal(MODAL_LOADING_PROJECT); +}; const openPreviewInfo = function () { analytics.pageview('/modals/preview'); return openModal(MODAL_PREVIEW_INFO); @@ -104,6 +110,9 @@ const closeFeedbackForm = function () { const closeImportInfo = function () { return closeModal(MODAL_IMPORT_INFO); }; +const closeLoadingProject = function () { + return closeModal(MODAL_LOADING_PROJECT); +}; const closePreviewInfo = function () { return closeModal(MODAL_PREVIEW_INFO); }; @@ -123,6 +132,7 @@ export { openExtensionLibrary, openFeedbackForm, openImportInfo, + openLoadingProject, openPreviewInfo, openSoundLibrary, openSpriteLibrary, @@ -132,6 +142,7 @@ export { closeExtensionLibrary, closeFeedbackForm, closeImportInfo, + closeLoadingProject, closePreviewInfo, closeSpriteLibrary, closeSoundLibrary, diff --git a/src/reducers/vm.js b/src/reducers/vm.js index 1f96dc400..dd70f3f4f 100644 --- a/src/reducers/vm.js +++ b/src/reducers/vm.js @@ -2,29 +2,15 @@ import VM from 'scratch-vm'; import storage from '../lib/storage'; const SET_VM = 'scratch-gui/vm/SET_VM'; -const SET_PROJECT_ID = 'scratch-gui/vm/SET_PROJECT_ID'; -const SET_PROJECT_DATA = 'scratch-gui/vm/SET_PROJECT_DATA'; - const defaultVM = new VM(); defaultVM.attachStorage(storage); -const initialState = { - vm: defaultVM, - projectData: null, - projectId: null // 0 means default project, null or undefined means project from local file -}; +const initialState = defaultVM; const reducer = function (state, action) { if (typeof state === 'undefined') state = initialState; switch (action.type) { case SET_VM: - return Object.assign({}, state, {vm: action.vm}); - case SET_PROJECT_ID: - return Object.assign({}, state, {projectId: action.projectId}); - case SET_PROJECT_DATA: - return Object.assign({}, state, { - projectData: action.projectData, - projectId: action.projectId - }); + return action.vm; default: return state; } @@ -35,22 +21,7 @@ const setVM = function (vm) { vm: vm }; }; -const setProjectId = function (projectId) { - return { - type: SET_PROJECT_ID, - projectId: projectId - }; -}; -const setProjectData = function (projectData, projectId) { - return { - type: SET_PROJECT_DATA, - projectData: projectData, - projectId: projectId - }; -}; export { reducer as default, - setVM, - setProjectId, - setProjectData + setVM }; From dac58b6b2c9fb4386682fc4ab0534f0dbad11d01 Mon Sep 17 00:00:00 2001 From: Karishma Chadha Date: Fri, 23 Mar 2018 10:32:33 -0400 Subject: [PATCH 082/108] Updating scratch-vm version in package.json --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 27814ab0c..d8b102fe6 100644 --- a/package.json +++ b/package.json @@ -94,7 +94,7 @@ "scratch-paint": "0.2.0-prerelease.20180309170325", "scratch-render": "0.1.0-prerelease.1516837442", "scratch-storage": "0.4.0", - "scratch-vm": "0.1.0-prerelease.1520606673-prerelease.1520606691", + "scratch-vm": "0.1.0-prerelease.1521814818-prerelease.1521814838", "selenium-webdriver": "3.6.0", "startaudiocontext": "1.2.1", "style-loader": "^0.20.0", From 9095a9e378f5ab86f428da006c38ed20224d5340 Mon Sep 17 00:00:00 2001 From: "greenkeeper[bot]" Date: Fri, 23 Mar 2018 18:39:16 +0000 Subject: [PATCH 083/108] chore(package): update scratch-render to version 0.1.0-prerelease.1521830325 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 38bd01686..a9a2f953a 100644 --- a/package.json +++ b/package.json @@ -92,7 +92,7 @@ "scratch-blocks": "0.1.0-prerelease.1521811349", "scratch-l10n": "2.0.20180108132626", "scratch-paint": "0.2.0-prerelease.20180320181154", - "scratch-render": "0.1.0-prerelease.1516837442", + "scratch-render": "0.1.0-prerelease.1521830325", "scratch-storage": "0.4.0", "scratch-vm": "0.1.0-prerelease.1521814818-prerelease.1521814838", "selenium-webdriver": "3.6.0", From a1f86edb6925cb85a1cac1cb898f5f1407808a8d Mon Sep 17 00:00:00 2001 From: "greenkeeper[bot]" Date: Mon, 26 Mar 2018 15:27:29 +0000 Subject: [PATCH 084/108] chore(package): update react-responsive to version 4.1.0 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 38bd01686..369d822ca 100644 --- a/package.json +++ b/package.json @@ -79,7 +79,7 @@ "react-intl-redux": "0.7.0", "react-modal": "3.3.2", "react-redux": "5.0.7", - "react-responsive": "4.0.5", + "react-responsive": "4.1.0", "react-style-proptype": "3.2.1", "react-tabs": "2.2.1", "react-test-renderer": "16.2.0", From fb93e1431508b5ed09c2d344ab0f4d1302472d76 Mon Sep 17 00:00:00 2001 From: "greenkeeper[bot]" Date: Mon, 26 Mar 2018 15:38:31 +0000 Subject: [PATCH 085/108] chore(package): update scratch-paint to version 0.2.0-prerelease.20180326153721 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 38bd01686..3af92cb92 100644 --- a/package.json +++ b/package.json @@ -91,7 +91,7 @@ "scratch-audio": "0.1.0-prerelease.1516198804", "scratch-blocks": "0.1.0-prerelease.1521811349", "scratch-l10n": "2.0.20180108132626", - "scratch-paint": "0.2.0-prerelease.20180320181154", + "scratch-paint": "0.2.0-prerelease.20180326153721", "scratch-render": "0.1.0-prerelease.1516837442", "scratch-storage": "0.4.0", "scratch-vm": "0.1.0-prerelease.1521814818-prerelease.1521814838", From 4e8af2cd9d3224fc52827892c80267715515860c Mon Sep 17 00:00:00 2001 From: Paul Kaplan Date: Mon, 26 Mar 2018 11:43:33 -0400 Subject: [PATCH 086/108] Include the update for scratch-vm to stay in sync --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index a9a2f953a..15ca6a5df 100644 --- a/package.json +++ b/package.json @@ -94,7 +94,7 @@ "scratch-paint": "0.2.0-prerelease.20180320181154", "scratch-render": "0.1.0-prerelease.1521830325", "scratch-storage": "0.4.0", - "scratch-vm": "0.1.0-prerelease.1521814818-prerelease.1521814838", + "scratch-vm": "0.1.0-prerelease.1522071980-prerelease.1522072000", "selenium-webdriver": "3.6.0", "startaudiocontext": "1.2.1", "style-loader": "^0.20.0", From 3712a72c45315e085177f9255657c9a720b36c65 Mon Sep 17 00:00:00 2001 From: Paul Kaplan Date: Tue, 27 Mar 2018 16:08:20 -0400 Subject: [PATCH 087/108] Do not autofocus filter in libraries. Resolves #1644 --- src/components/filter/filter.jsx | 1 - 1 file changed, 1 deletion(-) diff --git a/src/components/filter/filter.jsx b/src/components/filter/filter.jsx index 5363ef081..6ccf4fdd4 100644 --- a/src/components/filter/filter.jsx +++ b/src/components/filter/filter.jsx @@ -25,7 +25,6 @@ const FilterComponent = props => { src={filterIcon} /> Date: Tue, 27 Mar 2018 19:31:59 -0400 Subject: [PATCH 088/108] WIP: Most of menubar --- src/components/button/button.css | 11 ++ src/components/button/button.jsx | 17 ++- .../language-selector/dropdown-caret.svg | 12 ++ .../language-selector/language-icon.svg | 10 +- .../language-selector/language-selector.css | 7 +- .../language-selector/language-selector.jsx | 33 +++-- src/components/menu-bar/icon--mystuff.png | Bin 0 -> 1464 bytes src/components/menu-bar/icon--profile.png | Bin 0 -> 5213 bytes .../menu-bar/icon--see-community.svg | 12 ++ src/components/menu-bar/menu-bar.css | 71 +++++----- src/components/menu-bar/menu-bar.jsx | 127 +++++++++++++++--- src/css/colors.css | 4 + 12 files changed, 236 insertions(+), 68 deletions(-) create mode 100644 src/components/language-selector/dropdown-caret.svg create mode 100644 src/components/menu-bar/icon--mystuff.png create mode 100644 src/components/menu-bar/icon--profile.png create mode 100644 src/components/menu-bar/icon--see-community.svg diff --git a/src/components/button/button.css b/src/components/button/button.css index 44243650f..1062748fe 100644 --- a/src/components/button/button.css +++ b/src/components/button/button.css @@ -1,3 +1,14 @@ .button { cursor: pointer; + border-radius: 4px; + padding: .75rem; + font-weight: bold; + border: 1px solid rgba(0,0,0,.1); +} + +.icon { + margin-right: .5rem; + width: 1.5rem; + height: 1.5rem; + vertical-align: middle; } diff --git a/src/components/button/button.jsx b/src/components/button/button.jsx index 59b39668f..a85e8e6ab 100644 --- a/src/components/button/button.jsx +++ b/src/components/button/button.jsx @@ -6,14 +6,26 @@ import styles from './button.css'; const ButtonComponent = ({ className, + disabled, + iconClassName, + iconSrc, onClick, children, ...props }) => { - if (props.disabled === true) { + + if (disabled) { onClick = function () {}; } + const icon = iconSrc && ( + + ); + return ( + {icon} {children} ); @@ -33,6 +46,8 @@ ButtonComponent.propTypes = { children: PropTypes.node, className: PropTypes.string, disabled: PropTypes.bool, + iconClassName: PropTypes.string, + iconSrc: PropTypes.string, onClick: PropTypes.func.isRequired }; diff --git a/src/components/language-selector/dropdown-caret.svg b/src/components/language-selector/dropdown-caret.svg new file mode 100644 index 000000000..9ed9f8a54 --- /dev/null +++ b/src/components/language-selector/dropdown-caret.svg @@ -0,0 +1,12 @@ + + + + dropdown-caret + Created with Sketch. + + + + + + + \ No newline at end of file diff --git a/src/components/language-selector/language-icon.svg b/src/components/language-selector/language-icon.svg index 42bd409ab..e3a712ffb 100644 --- a/src/components/language-selector/language-icon.svg +++ b/src/components/language-selector/language-icon.svg @@ -1,12 +1,12 @@ - + - + Language Created with Sketch. - - - + + + diff --git a/src/components/language-selector/language-selector.css b/src/components/language-selector/language-selector.css index 0ae9e0a10..bae30cdd3 100644 --- a/src/components/language-selector/language-selector.css +++ b/src/components/language-selector/language-selector.css @@ -9,8 +9,11 @@ } .language-icon { - height: 2rem; - display: none; + height: 1.5rem; +} + +.disabled { + opacity: .5; } .language-select { diff --git a/src/components/language-selector/language-selector.jsx b/src/components/language-selector/language-selector.jsx index db846fef5..e4779d8c6 100644 --- a/src/components/language-selector/language-selector.jsx +++ b/src/components/language-selector/language-selector.jsx @@ -1,27 +1,22 @@ +import classNames from 'classnames'; import PropTypes from 'prop-types'; import React from 'react'; import Box from '../box/box.jsx'; -import {ComingSoonTooltip} from '../coming-soon/coming-soon.jsx'; import locales from 'scratch-l10n'; import languageIcon from './language-icon.svg'; +import dropdownCaret from './dropdown-caret.svg'; import styles from './language-selector.css'; const LanguageSelector = ({ currentLocale, onChange, + open, ...props }) => ( - -
- +
+ {open ? ( -
- + ) : ( + + + + + )} +
); LanguageSelector.propTypes = { currentLocale: PropTypes.string, - onChange: PropTypes.func + onChange: PropTypes.func, + open: PropTypes.boolean }; export default LanguageSelector; diff --git a/src/components/menu-bar/icon--mystuff.png b/src/components/menu-bar/icon--mystuff.png new file mode 100644 index 0000000000000000000000000000000000000000..79bbcb7f9da39c0a73db5a142082b9c39c2825bc GIT binary patch literal 1464 zcmaJ>eM}Q~7%s)4@-diT0t?$NN2VpAch{D3^wNUZQfX$fmJ01Qm7_iA3B5b62W^2l zU^4~?aT_=%DPlIaj3qK8Q~6NA1qN&bbQ76GB4$g-2!e5cNd$J~%l$ES$=&<=y?LMK z{d#gW#>@j@!LJ1i1cESqhStPegnz|5g7|OeX>T!aVz_h*mqq7uZk#0qX?8k~0Q640 zfG`ob-CI0Ns04yQF=@7N7Q;czMmr(g9|L)u438EFRH+^Yw-pi`kVh1dlp0*<=>-AO zt_E`y2E@Q<2nU%_#u8a&nPyvAp-pKAQ&Rwy2jdBx1cw72XA$MXJZf;27vs-)AKB(Wh$D1a&TMp4|0W4K2l`tZMWikmLA#r&r4);hXSKJ1JmT=iv zlHo|20{o149$mtzLB7(p7M#o`E#+Dt6F)H6gEO!cLi{al1R4zgAL?{&M!Pr@@v`3k zBzBp-3;~-67hS^I_{HVN`BO2Nh9z*0X3aERv@u1agXUUrBl|b7TH03P zBq(kJYk!HAZ;AB_!pZQNwFFC+5_TO+JAu{4F>>o#kS+PvvG%QNk#32F`C?%IdjGZV z4HvH=|8Y~i{AE-A1jTEf<;5K}m3~Gb5bn`y)6Aa9x%0=xn!~Y!XRLMg8Ox20XB(dZ z;kD;(ik~;^JyaOp2);GYQ{XkKh9WPhzWpk`N#zBu?AoQjf8x)oPpwHuAGJ)qJ8@-X z`8_OWCa2}<(&*I9-h~GX?)muzB>k`@D6vZOw9QVt`|}c|v(1;_uB*;w zZigoQ9RA0tT*=tg#=duDI0|`oj8SOyIfP5LHFY-6P)zCR93V$L$G&XY(?p zqj|YI8_Ago$RrYyw>p~!O*x^^ZrhXCd!$fYU;10@!5`+lZ4*!gYUxjDH$Gh&x)cV@ zeDiy0U(Dw#pSioNd!vVnoVOk8|?ectCahG%wJu9HB&a!MHV-QB@~ zMaRIHabzihn>ZR&-#6Odp2LWQzFyynefXZF5P8@6W0i_iE85E+wgbhc=2xn((Q$ez z;$&_lBkB;sZx(e#H62;$tjRA%8uVcgLwwKhu3&wDsWJ)>WvrPO@_<9WF^IWQaa^nu zQpqzP_X&f##?s0zJ+#+MMULpKUzF>n{whclx+`(y_Vf4eWw+ur7v63i{Fkv|a{;fWSA4lt_ldcu@oH|cad2{HQS~oLPws3RFKf3x VEC~l0V8H(`)u(4_+xF*H{{v_a7~TK? literal 0 HcmV?d00001 diff --git a/src/components/menu-bar/icon--profile.png b/src/components/menu-bar/icon--profile.png new file mode 100644 index 0000000000000000000000000000000000000000..41e62b6140efe34784c1c5fa697f1bf73c236b85 GIT binary patch literal 5213 zcmV-j6r$^iP)Px}7fD1xRCodHTM2knRhIr=?MrIQz9%Fk1QG(cLI@B=#I3_DX7BU%i@hUnP~QSe1}SfB5-vzwcGu zdiUIO&pr3td(T$fvYQSEF-VaN(k3>A0dB3V5?@R&ei}MeEf!9hA^w($pY);2z8Js0 zYX#JjAjS$`LQxwUIgG(l_5xOXF$!qif`!ZW!#iq`*f$LD>e|=w=%Y(9^-l$OcirFc z=W2B{fU^EZ`2BwDNGt~=9Hb}bivZkE(;N~YOoNCo#zz?7o|!W-KJ$N(Y1oZl&7K(s z4f7$f=ra7QsE!)yaH?TK7(m1@chX{D>R;e%*^ZOCJCOE^kHY{WhU2=Y(7AORs^-^Y zG&QYSxr#nR!-yD;Y&T$BSt-8$#V@h!si!dOvdhC5hMeY*0AW;dDq%LTcDd9Z2dw{f zLF$M7Kd2UF6MO3q=x}${G$@M}0Gu33l>!_G2tp8Urwe@3dMG&uUfeV{j3f$ygyUhz zDu--3;}Vrk(+QCRwVHV-xa1yK9X?2^`x(SQqNXrs-aC*LEl0!2slN8adS+;jK6m@&Nqk39A`zW8DX?)%mK zkf!Issy2a(70Jy3gffig~w;W*Nt~#!Q@%UP7?6(zB}S0@C79B z+1LK9JEj)B6NMm(iO#7TQS4~Pn{U2G@*coLyB0#BG2*TZ8*u&n z>yc-x!-+p7?qcgKfJR6wYBVM z?JrTHeCZtmCSOvD9Xocw++{{ZWhGr0KKy3sqj>#|*WvZ~@ch5l^!KJ()D-^jH3{53 z2QX=78Fug4gXG(Oi%z=GR_GUkPpJvIsx zb-7@Ht7$t_o)b_g6lm_^k)Q$&ow_mR;Ou2w0$5{9j}}Iy88U*k*qezsp_gOfF5yaCAsmO8^%7i8JF=(V50{0``tJSo>;o*{qBbi8v+~7NaJ!tyu6zIi zj~P;#6pN-`8Xj<9B`yap$Xg9_RO$5C7(n=Uez)U8icxN#r!C(+h zrxO;d4L_fIEq3kR8E$jBT-d#_6`S5U0lhqrfk%~?1Vlp2drXGpv}70!21q0lEWUR! zjvP6PKu~~>mPO7)jEo~CX^~#97hAVgLoSzt4eWHf@%HbU;j+{99;XaRKxDu2nE@16 zXkbb-h!z>&dk#p62)Z`ma=XxU#DTpZ`r)vCZ*?P4h3ms2Al&N=R^o2MGdRYesLnb8 z=a%5CFTptie!Lv082vDqTJ=MUg!ACa@;eCyQ(0n{xaVbN;&F`2Sqg_+hEEQxf!#AI zHikHFFBy9u#$_KwfE+C$eJM6zTmsCF0?4?%$WP;N>$F8^?lF+<{2F;~w8%2ly-ARE09c6U1@-5=A9DTUc-WE93N zamll~XbDK=k{XNPSLDIb)(ACeJ043HWI+d{f&;PuJ?xtv_#IHnCEx@B?ML=OIeH#A z(izP5!nlL8hPWK?@=2u2a*&&d0ILfL1_kVX1(Gx_fcHfqWsG1dhlf|egA^2;cOh&& zU63Z0qW#49DA<8N;u4@$c7ijEg+j2xoKy+@$|2N&9iM<(7fthJVLhf-A}%5|=<0=z)IH5-1gNQ6O!{R6ObQxQbBK5wN^%Z{2a8pSOF&+74Xv{s9xo5QRt2loiWMtf5OHv+6@Zg` z9rhD|qXsUQ7dovH7E<3|c;Uq`j5J^Y6Ir9CKGxXcyO;z7MbQqREBy|1UHCEC1b(bt z`zkhU+$44qJl!M*9&+dU$s_57+}9=^IBV9tjP>g`h%kOmjpmX!NLTb>bZT{60%9s8 zDtQm)Ejj>W*-g-^YL}`oXYO27WTy7RkZG0++M2c&s1zo2kTAz9Q3QB+GyJs2g`f&jPQa-jHHqY zFiR`Q+1Lp;;ZIbSgz>OS6agw(5>yD8O$~Lm*zv{Z%xw=-N*X*KGRukm9J%uKWG!8J z)fE)RcuDl){r2(ShLN5;aT0Qs8cy>3fAsZXq&AZ|)_NY)QawE>VYt3ZOc}8H8gbJj z#V9VzqOBFOYFb)aaR2?k#HK3(ZX+H-a!8jWOxN|BkFi8fl2wJ*Pd1vlP+)U-6Z zE2OksLE54gY}vd8Z~f&hy!XL-eQ1cNZtVD|g&fDSn1eIGm;|tf0MFqcD;se2zXiz{ zC5u+2!n$|=hM!-1o#+d7@jS^snPaqNwKBPApw7QxzQ`SB%J=kGP=B-q2S1BD1REx{ zbu6~@erR+aT>G#Q+5{c68ZGVj0ABjfC-J~>8{`3sp^!|hO7LRZ(j_PvJC+Pmit-R~ zJKt->p)dNEDH3O7J*Esq0`%1rGyJ$k)INA4ULw2{yv1tv98d*a9$w@^bz|J9h*nQYnP8+4zVR+DeW3cZa`2_|EDn)`0 zR*!iX4A$XHx1A&4taISBx8a#y`yUIwv%Ugnn-S+2aJE$6V0!Fq1%o*_GDICW% zqmh+it0Fp8J+7Q^J4{*$oZcWML`=bvmVZHyvvgz>jGz~raF%H+#%28va+B)Feg|qg za+X#&)VB`B1Wqmt}}V6c$f zY@)jbezF|G#zS9)CKP0pFrH8sZ7MyZIpi}2VJrl<8GP3P_*^F_AV)q=FDN=lF>~r8 zmq}o8$!H6XVWbVajEDhd$2eGB5^~zmYS3~>$d9N_DFae30PnEE-h7yH|Ej^!1cHJO zO05Cu#S>}4Lo@E1cbHmwAs(w@14mNeLi_Q3WEPWuQpCYSk)VemXFj=0c&JWohrrUK zNaSV20J9?t4sT`{-Eb-+Vt~_|LmW?sNz;IUDw(|274W$oX!&|Q(#Btk+_H(_cygn% z39)5jD=9e1ofe<8NT#TjKz=!8IxvGT7&_sDG6OnW&9FD^N6OgAkn&ChT0bZ87f2$R zuV+M48CfqOsDRU*1&PKFS;81{V%o@oDT8s+B(!k3XxCp3m7X1fw3_yIsJgZwGq8)y zccyl*sm8lTLu~?Wn-=NCa3@_xctWlmuZ{5dHY3kOy?F=xEI^$$89~cl*j&Ygb7W;i zY@3k#-*YU^AU3Qus7^xOChL=y8>x(;n^h3-=wQ zGHgvSG2tX8k6H_!PAdgPMWhs_;C&vLQ*TC2UcrFLhenoBK45lk9?WUC!B4)`e&4z+ zqHd=)I{i~`L2mA-=*jm^fcfWgsI5EgR`7l=g+|CTB@v)ft57v&8TskRTRqG&YzZjO zUPsp+JJJ2L54+)4=fkR+08Wzu83mPCS^LUbRBzo*2bcsEQ!d8h#rKK?iR#jEe6&etOT~$>x zL_AIhdEF&)=qsOrz2XxzU-UV;vlr9t5JYz3ZV_fUAH#BpBq-W&?aZekRIGuXvUpew zRO)dcNTLh!&Nf<{P#8=|Nv4~DGIv;Ee|s>S%@pbJA}cc;f_Xo>4^T$yscm#C&`m*w zQ>W6sKNrT*g+M|9nw#pyMAlE>-QIs9a#`MW4dK8esZ~hkD>z~Iz z_V@e6MdU+#49WmfYrt}-?13h@g?0obT`;EGAjm0eh^{EgY=o9VlNm-m#^q;W{KQGn z6^wzy9~6T*Y;2aum5@N%4HcG6_5_7Fl9DL`!7c)F>WYONyo^zDxeUvmq`l1KoQi{1 zn+1hf(P*_uP|9GhJ%;c0?Zx4`CbafgX)H>gB3*Po08MPSbJIB6vNJDb-LUrNF1ql6L6B z_P4&n!Cj&7&VXU#{yc342thx(y~p6!)}U;1B1RV%p{Qsyk`fa|ab-zuY!$s8FY4;+ z#J^F@o;@2&?pp#~uLML=!NNU9j~*3+9_8ibVJYc@VNsWwni@Ru`zI&?+>2LVT`S^e zK@!F+#t;^*>!kedlQk!C=$qp>w9^WmqyQ#)37tWqE!c-I-uG$W0t{iYiqu`Y(~Z6W zN=r%9h!B=2+qd7@iZTM(geoegpt`ymm(7}qqT(@PfQ_v*Q*s!yr1TVz3EkV>6y5Ej zP!i2qy#5#tiuq$B1ze9DIf6%)J`62wfylzf;wcKGCFbVk7UJmo4CIq)KHPHJ5-e+byVXMOv&$Ab?&h`DnqF5g=i9=7rhib4fQ3Th6t;`6uZJoU%l=Y4%+eUF#{ zeaKRBotSc+8mYMOzjTU+tx|5}Z0+qTi4r+5-i6)KemR4VkyrmNFO z67e0~2J0#Ge$4Np$h%);(1HawP#|)FC{Zll=cD%?+FtBCNM?A={x)fSASXeO4F)EL}D<9(3XO&H!v?RphWgsD4HnFpv_C43-2kUJR6UrKk9~ zHco?bPK8GXEuwt|bUPn!UTnZnK;lx5IKf2*?%e_s!zW3b<+eFzSQ zBwibfo7&Bk(LztCgjO_EKOINrKX>wsj$x_7A;N!JpXV6x(^}8r&*q#244-E|tsegm X?GceYo~S%s00000NkvXXu0mjfu(-5L literal 0 HcmV?d00001 diff --git a/src/components/menu-bar/icon--see-community.svg b/src/components/menu-bar/icon--see-community.svg new file mode 100644 index 000000000..1f5b6ee6e --- /dev/null +++ b/src/components/menu-bar/icon--see-community.svg @@ -0,0 +1,12 @@ + + + + See Community + Created with Sketch. + + + + + + + \ No newline at end of file diff --git a/src/components/menu-bar/menu-bar.css b/src/components/menu-bar/menu-bar.css index d1f4c3185..937908b64 100644 --- a/src/components/menu-bar/menu-bar.css +++ b/src/components/menu-bar/menu-bar.css @@ -6,24 +6,26 @@ flex-direction: row; justify-content: space-between; flex-wrap: nowrap; - - /* - For most things, we shouldn't explicitly set height, and let the - content push the element to whatever fits. Using a fixed height - instead, will help us subtract the value we assign from the body, - adding up to a perfect 100%. This means we don't need to set - overflow: hidden, which makes it hard to debug. border-box - simplifies by all of this by removing padding from the equation. + + /* + For most things, we shouldn't explicitly set height, and let the + content push the element to whatever fits. Using a fixed height + instead, will help us subtract the value we assign from the body, + adding up to a perfect 100%. This means we don't need to set + overflow: hidden, which makes it hard to debug. border-box + simplifies by all of this by removing padding from the equation. */ box-sizing: border-box; - height: $menu-bar-height; + height: $menu-bar-height; - /* - @todo: This adds ~20px in Chrome, when scrolling to the right, + /* + @todo: This adds ~20px in Chrome, when scrolling to the right, but fixes [FFx + Safari] [resize window down + scroll to the right] bug. - width: 100%; + width: 100%; */ font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; + font-size: .85rem; + font-weight: bold; background-color: $motion-primary; color: white; } @@ -33,18 +35,20 @@ flex-direction: row; justify-content: flex-start; flex-wrap: nowrap; + align-items: center; } -/* - Using a wrapper so when logo is hovered, it transforms via its center point - @todo: not sure if this is needed +/* + Using a wrapper so when logo is hovered, it transforms via its center point + @todo: not sure if this is needed */ .logo-wrapper { } .scratch-logo { - height: $menu-bar-height; + height: $menu-bar-height; padding: 0.8rem 0; + vertical-align: middle; } .scratch-logo:hover { @@ -61,10 +65,10 @@ .menu-item { display: block; padding: 0 1.5rem; - line-height: $menu-bar-height; + line-height: $menu-bar-height; cursor: pointer; text-decoration: none; - color: $motion-tertiary; + color: #fff; user-select: none; } @@ -75,21 +79,28 @@ } .feedback-button { - border-radius: 5px; - padding: .75rem; background-color: #FFF; - cursor: pointer; - font-size: .75rem; - font-weight: bold; color: $motion-primary; } -.feedback-button-icon { - vertical-align: middle; -} - -.feedback-button-icon { - margin-right: .5rem; - width: 1.5rem; +.divider { + border-right: 1px dashed $menubar-gray; + margin: 0 1rem; height: 1.5rem; } + +.title-field { + border: 1px dashed $menubar-gray; + border-radius: 4px; + width: 190px; + height: 1.5rem; + padding: .75rem; +} + +.share-button { + background: #FFAB19; +} + +.coming-soon >:not(.coming-soon-tooltip) { + opacity: 0.5; +} diff --git a/src/components/menu-bar/menu-bar.jsx b/src/components/menu-bar/menu-bar.jsx index 580729454..6a760672f 100644 --- a/src/components/menu-bar/menu-bar.jsx +++ b/src/components/menu-bar/menu-bar.jsx @@ -6,15 +6,18 @@ import React from 'react'; import Box from '../box/box.jsx'; import Button from '../button/button.jsx'; -import LoadButton from '../../containers/load-button.jsx'; -import SaveButton from '../../containers/save-button.jsx'; +import {ComingSoonTooltip} from '../coming-soon/coming-soon.jsx'; import LanguageSelector from '../../containers/language-selector.jsx'; import {openFeedbackForm} from '../../reducers/modals'; import styles from './menu-bar.css'; +import mystuffIcon from './icon--mystuff.png'; +import profileIcon from './icon--profile.png'; import feedbackIcon from './icon--feedback.svg'; +import communityIcon from './icon--see-community.svg'; +import dropdownCaret from '../language-selector/dropdown-caret.svg'; import scratchLogo from './scratch-logo.svg'; const MenuBar = props => ( @@ -32,29 +35,119 @@ const MenuBar = props => ( src={scratchLogo} />
- - - +
+ + + +
+
+ +
File
+
+
+
+ +
Edit
+
+
+
+
+ +
+ +
+
+ + + +
+
+ + + +
-
+
+
+ +
+ +
+
+ + +
+ + scratch-cat + +
+
+
); diff --git a/src/css/colors.css b/src/css/colors.css index be8a9a0db..b46bc50bf 100644 --- a/src/css/colors.css +++ b/src/css/colors.css @@ -4,6 +4,8 @@ $ui-background-blue: #e8edf1; $text-primary: #575e75; +$menubar-gray: rgba(0,0,0,0.25); + $motion-primary: #4C97FF; $motion-tertiary: #3373CC; $motion-transparent: hsla(215, 100%, 65%, 0.20); @@ -11,6 +13,8 @@ $motion-transparent: hsla(215, 100%, 65%, 0.20); $red-primary: #FF661A; $red-tertiary: #E64D00; +$share-orange: #FFAB19; + $sound-primary: #CF63CF; $sound-tertiary: #A63FA6; From b0246494d02342d0578e05192220926d0675ea51 Mon Sep 17 00:00:00 2001 From: "greenkeeper[bot]" Date: Wed, 28 Mar 2018 12:57:06 +0000 Subject: [PATCH 089/108] chore(package): update scratch-paint to version 0.2.0-prerelease.20180328125648 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 85f9b8dbc..87361a625 100644 --- a/package.json +++ b/package.json @@ -91,7 +91,7 @@ "scratch-audio": "0.1.0-prerelease.1516198804", "scratch-blocks": "0.1.0-prerelease.1521811349", "scratch-l10n": "2.0.20180108132626", - "scratch-paint": "0.2.0-prerelease.20180326153721", + "scratch-paint": "0.2.0-prerelease.20180328125648", "scratch-render": "0.1.0-prerelease.1521830325", "scratch-storage": "0.4.0", "scratch-vm": "0.1.0-prerelease.1522071980-prerelease.1522072000", From fdcca30504f96b938118795c112777a145676bd8 Mon Sep 17 00:00:00 2001 From: "greenkeeper[bot]" Date: Wed, 28 Mar 2018 13:03:09 +0000 Subject: [PATCH 090/108] chore(package): update scratch-paint to version 0.2.0-prerelease.20180328130249 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 87361a625..544cade35 100644 --- a/package.json +++ b/package.json @@ -91,7 +91,7 @@ "scratch-audio": "0.1.0-prerelease.1516198804", "scratch-blocks": "0.1.0-prerelease.1521811349", "scratch-l10n": "2.0.20180108132626", - "scratch-paint": "0.2.0-prerelease.20180328125648", + "scratch-paint": "0.2.0-prerelease.20180328130249", "scratch-render": "0.1.0-prerelease.1521830325", "scratch-storage": "0.4.0", "scratch-vm": "0.1.0-prerelease.1522071980-prerelease.1522072000", From 1c4d0de2119dd0a9972a0a1d3eaa04adc57eea91 Mon Sep 17 00:00:00 2001 From: "greenkeeper[bot]" Date: Wed, 28 Mar 2018 15:13:04 +0000 Subject: [PATCH 091/108] chore(package): update scratch-vm to version 0.1.0-prerelease.1522249865-prerelease.1522249883 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 544cade35..a46700619 100644 --- a/package.json +++ b/package.json @@ -94,7 +94,7 @@ "scratch-paint": "0.2.0-prerelease.20180328130249", "scratch-render": "0.1.0-prerelease.1521830325", "scratch-storage": "0.4.0", - "scratch-vm": "0.1.0-prerelease.1522071980-prerelease.1522072000", + "scratch-vm": "0.1.0-prerelease.1522249865-prerelease.1522249883", "selenium-webdriver": "3.6.0", "startaudiocontext": "1.2.1", "style-loader": "^0.20.0", From 093ef5e212ada6858ca87d8da76c26a83d8ca4cc Mon Sep 17 00:00:00 2001 From: Paul Kaplan Date: Wed, 28 Mar 2018 12:52:41 -0400 Subject: [PATCH 092/108] Rename button to avoid collision with scratch-paint --- src/components/button/button.css | 2 +- src/components/button/button.jsx | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/components/button/button.css b/src/components/button/button.css index 1062748fe..1c145975c 100644 --- a/src/components/button/button.css +++ b/src/components/button/button.css @@ -1,4 +1,4 @@ -.button { +.outlined-button { cursor: pointer; border-radius: 4px; padding: .75rem; diff --git a/src/components/button/button.jsx b/src/components/button/button.jsx index a85e8e6ab..5f26763be 100644 --- a/src/components/button/button.jsx +++ b/src/components/button/button.jsx @@ -29,7 +29,7 @@ const ButtonComponent = ({ return ( Date: Wed, 28 Mar 2018 12:53:34 -0400 Subject: [PATCH 093/108] Style menu bar component --- src/components/menu-bar/menu-bar.css | 33 ++++++++++++++++++++++++++++ src/components/menu-bar/menu-bar.jsx | 13 +++++------ 2 files changed, 39 insertions(+), 7 deletions(-) diff --git a/src/components/menu-bar/menu-bar.css b/src/components/menu-bar/menu-bar.css index 937908b64..5111092ad 100644 --- a/src/components/menu-bar/menu-bar.css +++ b/src/components/menu-bar/menu-bar.css @@ -104,3 +104,36 @@ .coming-soon >:not(.coming-soon-tooltip) { opacity: 0.5; } + +.account-info-wrapper { + display: flex; + flex-direction: row; + padding: 0 .5rem; + align-items: center; +} + +.mystuff-icon { + margin-right: .5rem; + width: 1.25rem; + height: 1.25rem; +} + +.account-nav-menu, .mystuff-button { + padding: 0 .25rem; + display: flex; + flex-direction: row; + align-items: center; +} + +.profile-icon { + margin-right: .5rem; + width: 2rem; + height: 2rem; + border-radius: 0.25rem; +} + +.dropdown-caret-icon { + margin-left: .5rem; + width: 0.5rem; + height: 0.5rem; +} diff --git a/src/components/menu-bar/menu-bar.jsx b/src/components/menu-bar/menu-bar.jsx index 6a760672f..19f3c5d3d 100644 --- a/src/components/menu-bar/menu-bar.jsx +++ b/src/components/menu-bar/menu-bar.jsx @@ -131,20 +131,19 @@ const MenuBar = props => ( place="bottom" tooltipId="mystuff" > -
- +
+
- -
- +
+ scratch-cat - +
From f34ad99fe1d1e93701cb2d18cd516c7f35ef051b Mon Sep 17 00:00:00 2001 From: "greenkeeper[bot]" Date: Wed, 28 Mar 2018 19:18:25 +0000 Subject: [PATCH 094/108] chore(package): update scratch-blocks to version 0.1.0-prerelease.1522264400 Closes #1678 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 544cade35..e27b67b8e 100644 --- a/package.json +++ b/package.json @@ -89,7 +89,7 @@ "redux-throttle": "0.1.1", "rimraf": "^2.6.1", "scratch-audio": "0.1.0-prerelease.1516198804", - "scratch-blocks": "0.1.0-prerelease.1521811349", + "scratch-blocks": "0.1.0-prerelease.1522264400", "scratch-l10n": "2.0.20180108132626", "scratch-paint": "0.2.0-prerelease.20180328130249", "scratch-render": "0.1.0-prerelease.1521830325", From 73eeee6c339783bd636e65d62d0f7b4c36b1b31f Mon Sep 17 00:00:00 2001 From: Ray Schamp Date: Wed, 28 Mar 2018 16:03:51 -0400 Subject: [PATCH 095/108] Finish tweaking size/positioning --- src/components/button/button.css | 13 +++++-- src/components/button/button.jsx | 2 +- src/components/menu-bar/menu-bar.css | 53 +++++++++++++--------------- src/components/menu-bar/menu-bar.jsx | 11 ++++-- 4 files changed, 44 insertions(+), 35 deletions(-) diff --git a/src/components/button/button.css b/src/components/button/button.css index 1c145975c..a771be6f4 100644 --- a/src/components/button/button.css +++ b/src/components/button/button.css @@ -1,14 +1,21 @@ .outlined-button { cursor: pointer; - border-radius: 4px; - padding: .75rem; + border-radius: .25rem; font-weight: bold; border: 1px solid rgba(0,0,0,.1); + display: flex; + flex-direction: row; + align-items: center; + padding-left: .75rem; + padding-right: .75rem; } .icon { margin-right: .5rem; width: 1.5rem; height: 1.5rem; - vertical-align: middle; +} + +.content { + white-space: nowrap; } diff --git a/src/components/button/button.jsx b/src/components/button/button.jsx index 5f26763be..1d348ba24 100644 --- a/src/components/button/button.jsx +++ b/src/components/button/button.jsx @@ -37,7 +37,7 @@ const ButtonComponent = ({ {...props} > {icon} - {children} +
{children}
); }; diff --git a/src/components/menu-bar/menu-bar.css b/src/components/menu-bar/menu-bar.css index 5111092ad..9913e80c0 100644 --- a/src/components/menu-bar/menu-bar.css +++ b/src/components/menu-bar/menu-bar.css @@ -24,7 +24,7 @@ width: 100%; */ font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; - font-size: .85rem; + font-size: .75rem; font-weight: bold; background-color: $motion-primary; color: white; @@ -38,13 +38,6 @@ align-items: center; } -/* - Using a wrapper so when logo is hovered, it transforms via its center point - @todo: not sure if this is needed -*/ -.logo-wrapper { -} - .scratch-logo { height: $menu-bar-height; padding: 0.8rem 0; @@ -57,48 +50,51 @@ transition: all .075s ease-in; } -.title { - display: inline-block; - margin: 0 2rem; -} - .menu-item { display: block; - padding: 0 1.5rem; - line-height: $menu-bar-height; + padding: 0 0.5rem; cursor: pointer; text-decoration: none; color: #fff; user-select: none; -} - -.feedback-button-wrapper { align-self: center; - padding: 0 .5rem; - line-height: $menu-bar-height; } .feedback-button { background-color: #FFF; color: $motion-primary; + height: 34px; } .divider { border-right: 1px dashed $menubar-gray; - margin: 0 1rem; - height: 1.5rem; + margin: 0 .5rem; + height: 34px; } .title-field { border: 1px dashed $menubar-gray; - border-radius: 4px; - width: 190px; - height: 1.5rem; - padding: .75rem; + border-radius: .25rem; + width: 12rem; + height: 34px; + background-color: transparent; + padding: .5rem; +} + +.title-field, +.title-field::placeholder { + color: #fff; + font-weight: bold; + font-size: .8rem; } .share-button { background: #FFAB19; + height: 34px; +} + +.community-button { + height: 34px; } .coming-soon >:not(.coming-soon-tooltip) { @@ -114,8 +110,7 @@ .mystuff-icon { margin-right: .5rem; - width: 1.25rem; - height: 1.25rem; + height: 1rem; } .account-nav-menu, .mystuff-button { @@ -128,7 +123,7 @@ .profile-icon { margin-right: .5rem; width: 2rem; - height: 2rem; + height: 34px; border-radius: 0.25rem; } diff --git a/src/components/menu-bar/menu-bar.jsx b/src/components/menu-bar/menu-bar.jsx index 19f3c5d3d..b30f55975 100644 --- a/src/components/menu-bar/menu-bar.jsx +++ b/src/components/menu-bar/menu-bar.jsx @@ -73,7 +73,11 @@ const MenuBar = props => ( tooltipClassName={styles.comingSoonTooltip} tooltipId="title-field" > -
+
@@ -132,7 +136,10 @@ const MenuBar = props => ( tooltipId="mystuff" >
- +
Date: Wed, 28 Mar 2018 16:07:22 -0400 Subject: [PATCH 096/108] Lint --- src/components/menu-bar/menu-bar.jsx | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/components/menu-bar/menu-bar.jsx b/src/components/menu-bar/menu-bar.jsx index b30f55975..fd6d136f8 100644 --- a/src/components/menu-bar/menu-bar.jsx +++ b/src/components/menu-bar/menu-bar.jsx @@ -148,9 +148,15 @@ const MenuBar = props => ( tooltipId="account-nav" >
- + scratch-cat - +
From 6d2a0465aa0156b11d80da992d168ab2a6700db9 Mon Sep 17 00:00:00 2001 From: Ray Schamp Date: Wed, 28 Mar 2018 16:39:31 -0400 Subject: [PATCH 097/108] Final tweaks with @carljbowman --- src/components/button/button.css | 2 - src/components/menu-bar/menu-bar.css | 22 ++++++-- src/components/menu-bar/menu-bar.jsx | 77 +++++++++++++++------------- 3 files changed, 59 insertions(+), 42 deletions(-) diff --git a/src/components/button/button.css b/src/components/button/button.css index a771be6f4..5e69aabd4 100644 --- a/src/components/button/button.css +++ b/src/components/button/button.css @@ -2,7 +2,6 @@ cursor: pointer; border-radius: .25rem; font-weight: bold; - border: 1px solid rgba(0,0,0,.1); display: flex; flex-direction: row; align-items: center; @@ -12,7 +11,6 @@ .icon { margin-right: .5rem; - width: 1.5rem; height: 1.5rem; } diff --git a/src/components/menu-bar/menu-bar.css b/src/components/menu-bar/menu-bar.css index 9913e80c0..7e59dd4ef 100644 --- a/src/components/menu-bar/menu-bar.css +++ b/src/components/menu-bar/menu-bar.css @@ -52,7 +52,7 @@ .menu-item { display: block; - padding: 0 0.5rem; + padding: 0 0.25rem; cursor: pointer; text-decoration: none; color: #fff; @@ -60,6 +60,16 @@ align-self: center; } +.file-group { + display: flex; + flex-direction: row; + align-items: center; +} + +.file-group .menu-item { + padding: 0 0.75rem; +} + .feedback-button { background-color: #FFF; color: $motion-primary; @@ -90,11 +100,17 @@ .share-button { background: #FFAB19; - height: 34px; + height: 32px; + box-shadow: 0 0 0 1px rgba(0,0,0,.1); } .community-button { - height: 34px; + height: 32px; + box-shadow: 0 0 0 1px rgba(0,0,0,.1); +} + +.community-button-icon { + height: 1.25rem; } .coming-soon >:not(.coming-soon-tooltip) { diff --git a/src/components/menu-bar/menu-bar.jsx b/src/components/menu-bar/menu-bar.jsx index fd6d136f8..587b51fc4 100644 --- a/src/components/menu-bar/menu-bar.jsx +++ b/src/components/menu-bar/menu-bar.jsx @@ -27,43 +27,45 @@ const MenuBar = props => ( })} >
-
- Scratch -
-
- - - -
-
- -
File
-
-
-
- -
Edit
-
+
+
+ Scratch +
+
+ + + +
+
+ +
File
+
+
+
+ +
Edit
+
+
@@ -105,6 +107,7 @@ const MenuBar = props => ( >