Compare commits

..
Author SHA1 Message Date
DD Liu 73b53988fc Merge pull request #5283 from LLK/greenkeeper/scratch-paint-0.2.0-prerelease.20191104214909
Update scratch-paint to the latest version 🚀
brings in LLK/scratch-svg-renderer#99 via paint
2019-11-04 20:05:58 -05:00
greenkeeper[bot] 39e1bac823 chore(package): update lockfile package-lock.json 2019-11-04 21:50:54 +00:00
greenkeeper[bot] c5f17db7d1 chore(package): update scratch-paint to version 0.2.0-prerelease.20191104214909 2019-11-04 21:50:50 +00:00
DD Liu 036c627130 Merge pull request #5281 from LLK/greenkeeper/scratch-svg-renderer-0.2.0-prerelease.20191104164753
Update scratch-svg-renderer to the latest version 🚀
brings in https://github.com/LLK/scratch-svg-renderer/pull/99
2019-11-04 16:35:41 -05:00
greenkeeper[bot] dd8fb2024d chore(package): update lockfile package-lock.json 2019-11-04 16:50:01 +00:00
greenkeeper[bot] c4b43dd321 chore(package): update scratch-svg-renderer to version 0.2.0-prerelease.20191104164753 2019-11-04 16:49:57 +00:00
chrisgarrity f4061aedaa Merge pull request #5274 from LLK/greenkeeper/scratch-l10n-3.6.20191029224007
Greenkeeper/scratch l10n 3.6.20191029224007
2019-11-04 07:50:25 -05:00
Paul Kaplan c3d7c086f8 Merge pull request #5277 from paulkaplan/publish-libs
Include library JSON files in package distribution
2019-11-04 05:11:02 -05:00
DD Liu 5ecaa2fb44 Merge pull request #5279 from LLK/greenkeeper/scratch-render-0.1.0-prerelease.20191101193213
Update scratch-render to the latest version 🚀
brings in LLK/scratch-svg-renderer#84 via render
2019-11-01 20:32:13 -04:00
DD Liu 3a35693ce3 Merge branch 'develop' into greenkeeper/scratch-render-0.1.0-prerelease.20191101193213 2019-11-01 20:31:19 -04:00
DD Liu cd23935bc3 Merge pull request #5280 from LLK/greenkeeper/scratch-paint-0.2.0-prerelease.20191101193358
Update scratch-paint to the latest version 🚀
brings in LLK/scratch-svg-renderer#84 via paint
2019-11-01 20:26:57 -04:00
greenkeeper[bot] 055853d746 chore(package): update lockfile package-lock.json 2019-11-01 19:39:25 +00:00
greenkeeper[bot] bae72c0413 chore(package): update scratch-paint to version 0.2.0-prerelease.20191101193358 2019-11-01 19:39:19 +00:00
greenkeeper[bot] ca927f111b chore(package): update lockfile package-lock.json 2019-11-01 19:38:39 +00:00
greenkeeper[bot] 13a0e9098f chore(package): update scratch-render to version 0.1.0-prerelease.20191101193213 2019-11-01 19:38:35 +00:00
DD Liu 3d3eb3d059 Merge pull request #5273 from LLK/greenkeeper/scratch-svg-renderer-0.2.0-prerelease.20191031221353
Update scratch-svg-renderer to the latest version 🚀
brings in https://github.com/LLK/scratch-svg-renderer/pull/84
2019-11-01 15:27:27 -04:00
Paul Kaplan f788870dc2 Merge pull request #5275 from LLK/greenkeeper/chromedriver-78.0.1
Greenkeeper/chromedriver 78.0.1
2019-11-01 11:00:19 -04:00
Paul Kaplan 6eaf6312b9 Include library JSON files in package distribution
Files like src/lib/libraries/sprites.json were being used by
packages like scratch-desktop in order to fetch all the library
assets for offline access. We stopped publishing src in #5263 to
stop bloating the dist with copies of src files. Explicitly
exporting the files that are needed by other repos is a better
long-term plan.

The files are now published to dist/libraries/*.json. Once this is
merged those repos that use the src/ path need to change it to e.g.
`require('scratch-gui/dist/libraries/backdrops.json')`
2019-11-01 10:54:52 -04:00
greenkeeper[bot] d3474992b7 chore(package): update lockfile package-lock.json 2019-10-31 22:16:09 +00:00
greenkeeper[bot] bdfe83e110 chore(package): update scratch-svg-renderer to version 0.2.0-prerelease.20191031221353 2019-10-31 22:16:05 +00:00
Chris Willis-Ford 19c9db0eb1 Merge pull request #5272 from cwillisf/chromedriver-autoplay-policy
tests: set --autoplay-policy=no-user-gesture-required
2019-10-31 10:18:15 -07:00
Karishma Chadha 2b642e9ef0 Merge pull request #5269 from LLK/greenkeeper/scratch-render-0.1.0-prerelease.20191029200037
Update scratch-render to the latest version 🚀
2019-10-30 16:41:06 -04:00
Christopher Willis-Ford a55f9ae9ed tests: set --autoplay-policy=no-user-gesture-required 2019-10-30 10:40:50 -07:00
Karishma Chadha 054d3b1a8f Merge pull request #5271 from kchadha/tag-hotfix-branches
Create git tags for hotfix branches.
2019-10-30 10:56:51 -04:00
Karishma Chadha a27b27fa71 Create git tags for hotfix branches. 2019-10-30 09:28:03 -04:00
greenkeeper[bot] 3f51a86d9f chore(package): update lockfile package-lock.json 2019-10-29 23:46:19 +00:00
greenkeeper[bot] 3fe0fa9b44 chore(package): update scratch-l10n to version 3.6.20191029224007
Closes #5250
2019-10-29 23:46:14 +00:00
chrisgarrity 269ee1dd8e Merge pull request #5270 from LLK/greenkeeper/scratch-blocks-0.1.0-prerelease.1572384380
Update scratch-blocks to the latest version 🚀[Translation update]
2019-10-29 17:59:36 -04:00
greenkeeper[bot] 46cecc0c3a chore(package): update lockfile package-lock.json 2019-10-29 21:29:13 +00:00
greenkeeper[bot] b0945f80cf chore(package): update scratch-blocks to version 0.1.0-prerelease.1572384380 2019-10-29 21:29:08 +00:00
greenkeeper[bot] 89c88fec4c chore(package): update lockfile package-lock.json 2019-10-29 20:07:37 +00:00
greenkeeper[bot] 9a43442cf5 chore(package): update scratch-render to version 0.1.0-prerelease.20191029200037 2019-10-29 20:07:32 +00:00
greenkeeper[bot] 2bf8db0dfa chore(package): update lockfile package-lock.json 2019-10-28 15:48:43 +00:00
greenkeeper[bot] 78c38af7a6 chore(package): update chromedriver to version 78.0.1
Closes #5268
2019-10-28 15:48:38 +00:00
Eric Rosenbaum 19e392d061 Merge pull request #5263 from LLK/hotfix/hoc-2-tutorials-2019
[hotfix] Add 2 HoC tutorials
2019-10-24 15:24:32 -04:00
Eric Rosenbaum f19ac7459a Don’t publish duplicate assets 2019-10-22 14:57:09 -04:00
Eric Rosenbaum 3fe729c025 Remove duplicate 2019-10-22 14:26:29 -04:00
Zoë Bentley 428b5da5b6 Reduced file size of GIFs 2019-10-22 14:26:29 -04:00
Zoë Bentley 78d831d6af Linter
# Conflicts:
#	src/lib/libraries/decks/en-steps.js
#	src/lib/libraries/decks/index.jsx
2019-10-22 14:26:29 -04:00
Zoë Bentley 8f7a9d96f1 Edited one GIF to be slower
# Conflicts:
#	src/lib/libraries/decks/en-steps.js
#	src/lib/libraries/decks/index.jsx
#	src/lib/libraries/decks/translate-video.js
2019-10-22 14:26:29 -04:00
Zoë Bentley c23678ef3d Made Travis happy (shortened length of one GIF name) 2019-10-22 14:26:29 -04:00
Zoë Bentley 6f2a0b057a Code a Cartoon 10/21 2019-10-22 14:26:29 -04:00
Zoë Bentley e73c5ce91c Changed order of tutorials
# Conflicts:
#	package-lock.json
#	package.json
2019-10-22 14:26:29 -04:00
Zoë Bentley be8873a6e0 Changed order of tutorials actually 2019-10-22 14:26:29 -04:00
Zoë Bentley 43f5f0aebc Reverted the tips-library.jsx file to its correct state 2019-10-22 14:26:29 -04:00
Zoë Bentley 84b6c33813 Optimized images and made small tweaks to GIFs 2019-10-22 14:26:29 -04:00
Zoë Bentley deff6dd385 Added first draft of Code a Cartoon video and made some other small changes 2019-10-22 14:26:29 -04:00
Zoë Bentley ca0c47f742 Draft of Code a Cartoon tutorial for Oct 1st 2019-10-22 14:26:29 -04:00
Ray Schamp 5253554fff Merge pull request #4854 from towerofnix/list-whitespace
Always display whitespace in list monitors
2019-10-22 09:46:54 -04:00
Florrie 81c22f369c Always display whitespace in all monitors 2019-10-21 20:57:09 -03:00
Karishma Chadha fde5b56e65 Merge pull request #5259 from LLK/greenkeeper/scratch-render-0.1.0-prerelease.20191021180653
Update scratch-render to the latest version 🚀
2019-10-21 16:28:09 -04:00
greenkeeper[bot] c7b4e1b832 chore(package): update lockfile package-lock.json 2019-10-21 18:53:21 +00:00
greenkeeper[bot] a37868f921 chore(package): update scratch-render to version 0.1.0-prerelease.20191021180653 2019-10-21 18:53:14 +00:00
Benjamin Wheeler 395b55868b Merge pull request #5168 from benjiwheeler/clear-title-on-default-project
Refactor title handling
2019-10-21 10:52:02 -04:00
Ben Wheeler e3fa196ade revised name of updateReduxProjectTitle, updateReduxProjectTitleWithDefault 2019-10-18 17:53:28 -04:00
Ben Wheeler f4a9bfac9f in titledhoc, consolidate function calls 2019-10-18 13:41:20 -04:00
Ben Wheeler b6ff1f40b5 better names for prop functions 2019-10-18 13:40:58 -04:00
Paul Kaplan 758b0ef1ff Merge pull request #5253 from LLK/greenkeeper/scratch-vm-0.2.0-prerelease.20191017151616
Update scratch-vm to the latest version 🚀
2019-10-17 14:24:55 -04:00
Ben Wheeler 68780ae6cf added back missing canEditTitle 2019-10-17 13:26:34 -04:00
Ben Wheeler 22e2c17ff4 don’t pass onUpdateProjectTitle below titledHIC 2019-10-17 13:26:33 -04:00
Ben Wheeler 9c33bbb2ee remove TitledHOC from playground, and explicitly pass canEditTitle 2019-10-17 13:26:33 -04:00
Ben Wheeler b63ac51fb1 move project title management into titled hoc 2019-10-17 13:26:33 -04:00
Ben Wheeler 91e2fc92f3 on showing project without id, tell owner of GUI to set title to default 2019-10-17 13:26:33 -04:00
Paul Kaplan a3f0652e7d Update scratch-vm to pull in video fixes 2019-10-17 11:25:32 -04:00
greenkeeper[bot] 7193c50bbe chore(package): update lockfile package-lock.json 2019-10-17 15:19:16 +00:00
greenkeeper[bot] be0259f543 chore(package): update scratch-vm to version 0.2.0-prerelease.20191017151616 2019-10-17 15:19:12 +00:00
Benjamin Wheeler 5fed732e7e Merge pull request #5241 from benjiwheeler/extension-line-height
Fix extension modal tiles' description line height
2019-10-16 17:42:51 -04:00
Paul Kaplan 33d7181432 Merge pull request #5248 from LLK/greenkeeper/scratch-vm-0.2.0-prerelease.20191015002244
Update scratch-vm to the latest version 🚀
2019-10-14 22:13:23 -04:00
greenkeeper[bot] f6fa9e3e25 chore(package): update lockfile package-lock.json 2019-10-15 00:25:41 +00:00
greenkeeper[bot] dee9323f5c chore(package): update scratch-vm to version 0.2.0-prerelease.20191015002244 2019-10-15 00:25:37 +00:00
Paul Kaplan 3513a680a6 Merge pull request #5197 from paulkaplan/fix-backpack-thumbnailing
Draw backpack thumbnails smaller
2019-10-14 12:04:47 -04:00
Ben Wheeler b8833199e1 Fix extension line height 2019-10-10 22:25:24 -04:00
chrisgarrity 38aa76fae8 Merge pull request #5239 from chrisgarrity/update-blocks
Update blocks for swahili
2019-10-10 14:48:35 -04:00
Chris Garrity 18c7b58a16 Update blocks for swahili 2019-10-10 14:29:56 -04:00
DD Liu d7d38109a8 Merge pull request #5237 from fsih/updatePaint
Update paint to add swahili to overflow languages
2019-10-10 12:58:46 -04:00
DD Liu 2317758df8 update paint to add swahili to overflow languages 2019-10-10 12:15:29 -04:00
DD Liu 25c8253138 Merge pull request #5234 from LLK/greenkeeper/scratch-render-0.1.0-prerelease.20191001200908
Greenkeeper/scratch render 0.1.0 prerelease.20191001200908
2019-10-09 15:32:57 -04:00
chrisgarrity 75f9da9f22 Merge pull request #5233 from chrisgarrity/add-swahili
change l10n version to get swahili
2019-10-09 10:05:19 -04:00
Chris Garrity 8c3ab1df78 change l10n version to get swahili 2019-10-09 09:50:39 -04:00
chrisgarrity e04c290587 Merge pull request #5232 from LLK/greenkeeper/scratch-blocks-0.1.0-prerelease.1570622534
Update scratch-blocks to the latest version 🚀
2019-10-09 08:36:46 -04:00
greenkeeper[bot] 527f8dd3e7 chore(package): update lockfile package-lock.json 2019-10-09 12:17:56 +00:00
greenkeeper[bot] 251db0108d chore(package): update scratch-blocks to version 0.1.0-prerelease.1570622534 2019-10-09 12:17:51 +00:00
chrisgarrity 5100a1bd8a Merge pull request #5231 from LLK/greenkeeper/scratch-l10n-3.6.20191008224547
Greenkeeper/scratch l10n 3.6.20191008224547
2019-10-09 08:17:43 -04:00
greenkeeper[bot] ee5e2324a8 chore(package): update lockfile package-lock.json 2019-10-09 01:00:21 +00:00
greenkeeper[bot] 624bf7c965 chore(package): update scratch-l10n to version 3.6.20191008224547
Closes #5230
2019-10-09 01:00:17 +00:00
zoebentley 3089503ab1 Merge pull request #5228 from zoebentley/imagine-a-world
Changed title of Imagine If tutorial to Imagine a World
2019-10-08 08:44:07 -05:00
Zoë Bentley 8cac1b1bb7 Changed title of Imagine If tutorial to Imagine a World 2019-10-07 09:49:52 -04:00
Eric Rosenbaum 67fe5185fb Merge pull request #5218 from ericrosenbaum/feature/limit-loud-rms-no-waveshaper
Limit louder effect with a max RMS (w/o waveshaper)
2019-10-02 12:13:57 -04:00
greenkeeper[bot] 9122b26d1a chore(package): update lockfile package-lock.json 2019-10-01 20:12:23 +00:00
greenkeeper[bot] efcd2c9ebc chore(package): update scratch-render to version 0.1.0-prerelease.20191001200908
Closes #5217
2019-10-01 20:12:19 +00:00
Karishma Chadha 181c7ea93f Merge pull request #5222 from LLK/greenkeeper/scratch-vm-0.2.0-prerelease.20191001145300
Greenkeeper/scratch vm 0.2.0 prerelease.20191001145300
2019-10-01 10:54:32 -05:00
greenkeeper[bot] a8a0bc437a chore(package): update lockfile package-lock.json 2019-10-01 14:55:57 +00:00
greenkeeper[bot] c6bc1c3450 chore(package): update scratch-vm to version 0.2.0-prerelease.20191001145300
Closes #5191
2019-10-01 14:55:53 +00:00
Ray Schamp 1ad0f43d23 Merge pull request #5220 from rschamp/ci/circle
Add config for CircleCI
2019-09-30 15:04:18 -04:00
rschamp a3400b3b0f Disable publishing
While CircleCI is running in parallel with Travis, let Travis continue to handle the deployments.
2019-09-30 14:22:58 -04:00
Eric Rosenbaum 523667dfaf Remove waveshaper from volume effect
the waveshaper node is implemented incorrectly on Mac Safari (https://bugs.webkit.org/show_bug.cgi?id=129333) and causes extreme distortion of the sound
2019-09-27 14:26:14 -04:00
Eric Rosenbaum 5599626405 Revert "Revert "Limit louder effect with a max RMS""
This reverts commit 45cb96f2d4.
2019-09-27 14:20:34 -04:00
Paul Kaplan d31d42cf3c Merge pull request #5216 from LLK/revert-5212-greenkeeper/scratch-render-0.1.0-prerelease.20190925202615
Revert "Update scratch-render to the latest version 🚀"
2019-09-26 10:05:56 -04:00
Paul Kaplan 11646d4877 Revert "Update scratch-render to the latest version 🚀" 2019-09-26 10:03:54 -04:00
Paul Kaplan e53c8ddd85 Merge pull request #5214 from LLK/revert-5149-feature/limit-louder-rms
Revert "Limit louder effect with a max RMS"
2019-09-26 09:49:33 -04:00
Paul Kaplan 45cb96f2d4 Revert "Limit louder effect with a max RMS" 2019-09-26 09:48:15 -04:00
Chris Willis-Ford ab0d58ed6c Merge pull request #5212 from LLK/greenkeeper/scratch-render-0.1.0-prerelease.20190925202615
Update scratch-render to the latest version 🚀
2019-09-25 13:59:22 -07:00
greenkeeper[bot] bdcddf5655 chore(package): update lockfile package-lock.json 2019-09-25 20:33:27 +00:00
greenkeeper[bot] 0f0219a4b1 chore(package): update scratch-render to version 0.1.0-prerelease.20190925202615 2019-09-25 20:32:57 +00:00
Eric Rosenbaum aa2890a2ca Merge pull request #5211 from LLK/greenkeeper/scratch-audio-0.1.0-prerelease.20190925183642
Update scratch-audio to the latest version 🚀
2019-09-25 15:49:01 -04:00
greenkeeper[bot] 43bddbba14 chore(package): update lockfile package-lock.json 2019-09-25 18:38:19 +00:00
greenkeeper[bot] e4af27cd40 chore(package): update scratch-audio to version 0.1.0-prerelease.20190925183642 2019-09-25 18:38:15 +00:00
chrisgarrity d390e67542 Merge pull request #5210 from LLK/greenkeeper/scratch-blocks-0.1.0-prerelease.1569422127
Update scratch-blocks to the latest version 🚀
2019-09-25 15:54:21 +01:00
greenkeeper[bot] a8b7be6197 chore(package): update lockfile package-lock.json 2019-09-25 14:38:29 +00:00
greenkeeper[bot] 35da6ace36 chore(package): update scratch-blocks to version 0.1.0-prerelease.1569422127 2019-09-25 14:38:25 +00:00
chrisgarrity 8590ceb4ce Merge pull request #5209 from LLK/greenkeeper/scratch-l10n-3.5.20190924223720
Update scratch-l10n to the latest version 🚀
2019-09-25 15:06:51 +01:00
greenkeeper[bot] 96e637cfc0 chore(package): update lockfile package-lock.json 2019-09-25 00:52:57 +00:00
greenkeeper[bot] f1470feb0a chore(package): update scratch-l10n to version 3.5.20190924223720 2019-09-25 00:52:53 +00:00
rschamp 7070b19562 Fix npm cache order in setup 2019-09-24 09:44:19 -04:00
rschamp 931a17462a Add build to build deploy step 2019-09-23 22:19:22 -04:00
rschamp 859e636d1a Moar parallel 2019-09-23 21:55:05 -04:00
rschamp 7ccf9f5bef FIx cache ordering 2019-09-23 21:35:26 -04:00
rschamp 0f589004a1 Use npm install to get better cache benefits 2019-09-23 21:31:42 -04:00
rschamp 2df4df0791 Use granular caching 2019-09-23 21:26:06 -04:00
rschamp 41296a9624 Optimize 2019-09-23 17:31:40 -04:00
rschamp 3dbfebe923 Parallelize 2019-09-23 16:27:30 -04:00
rschamp 5e0fc58f27 De-alias workflow
The requirements for npm publishing and gh-pages are different anyway.
2019-09-23 15:29:33 -04:00
rschamp 5eb8438782 Aliasify
The equivalent config for Travis is only 87 lines long, and easy to read. Can CircleCI be similarly easy to read? Is this easy? Are you still reading this?
2019-09-23 14:43:06 -04:00
rschamp 4f0bf3c5aa Add config for gh-pages deploy 2019-09-23 13:59:22 -04:00
DD Liu abe79b30ff Merge pull request #5203 from LLK/greenkeeper/scratch-paint-0.2.0-prerelease.20190923154429
Greenkeeper/scratch paint 0.2.0 prerelease.20190923154429
2019-09-23 12:38:24 -04:00
greenkeeper[bot] 5d1b1fb4c0 chore(package): update lockfile package-lock.json 2019-09-23 15:57:57 +00:00
greenkeeper[bot] 9265ee6323 chore(package): update scratch-paint to version 0.2.0-prerelease.20190923154429
Closes #5201
2019-09-23 15:57:51 +00:00
Ray Schamp 519256c50c Merge pull request #5194 from rschamp/dont-build-tags
Don’t push tags to gh-pages
2019-09-23 11:14:50 -04:00
Eric Rosenbaum 17324e5340 Merge pull request #5149 from ericrosenbaum/feature/limit-louder-rms
Limit louder effect with a max RMS
2019-09-23 10:52:17 -04:00
Ray Schamp 7d01844371 Merge pull request #5196 from rschamp/max-old-space-size
Allow Node to use more memory for old space
2019-09-20 14:35:40 -04:00
rschamp 745fa360c3 Actually use the tag for npm publish 2019-09-20 14:31:55 -04:00
rschamp 51fbae655e Use circle prefix in default NPM dist channel 2019-09-20 13:59:45 -04:00
rschamp c3119aae2c Set max-old-space-size for NPM publishing 2019-09-20 13:58:54 -04:00
rschamp bc1b787974 Allow Node to use more memory for old space
This flag essentially configures how much memory Node can use. If it’s too low, then Node processes may hang as Node spends time garbage collecting. Increasing it allows more memory to be used before garbage collection is necessary.  Travis VMs have 7.5GB of memory, so set the limit to just below that to avoid running out of memory completely.
2019-09-20 13:41:34 -04:00
Paul Kaplan fb4b492f1c Draw backpack thumbnails smaller 2019-09-20 13:37:02 -04:00
rschamp e3cc730cd7 Make npm publishing do the thing 2019-09-20 13:12:12 -04:00
rschamp 46743c9bf8 Make git tagging do the thing 2019-09-20 13:12:12 -04:00
rschamp d573e34501 Add NPM tagging configuration 2019-09-20 13:12:12 -04:00
rschamp fac69fbcf4 Tag after publishing 2019-09-20 13:12:12 -04:00
rschamp 99f2ac586d Try out yaml inheritance in preparation for parallelization 2019-09-20 13:12:12 -04:00
rschamp 33dc1f7095 Remove circle branch from deploy list 2019-09-20 13:12:12 -04:00
rschamp 0707527800 Cache builds by commit not build number 2019-09-20 13:12:12 -04:00
rschamp f71e117e3a Cache git checkouts 2019-09-20 13:12:12 -04:00
rschamp d011aca301 Add NPM publish step 2019-09-20 13:12:12 -04:00
rschamp 2c3f3349b5 Add coverage report 2019-09-20 13:12:12 -04:00
rschamp 10eef7234f Add build artifact 2019-09-20 13:12:12 -04:00
rschamp 17154cefec Add back jest and build steps with reporting 2019-09-20 13:12:12 -04:00
rschamp e3d4d6e9d7 Circle doesn’t know about eslint warnings
They show up as errors
2019-09-20 13:12:12 -04:00
rschamp 89918a304f Try uploading lint results 2019-09-20 13:12:12 -04:00
rschamp 74b795ada8 Reformat 2019-09-20 13:12:12 -04:00
rschamp 40a3b857da Keep config-dependent environment vars in the config
NODE_ENV isn’t one we’d want to change dynamically, so keep it checked in to the config
2019-09-20 13:12:12 -04:00
rschamp 615927f3f2 Add initial CircleCI config 2019-09-20 13:12:12 -04:00
rschamp 3d1ad740dd Don’t push tags to gh-pages
These builds make our gh-pages branch too large for GitHub to handle.
2019-09-20 10:18:15 -04:00
DD Liu 4c76f654b7 Merge pull request #5189 from fsih/reupdateAssets
Reupdate watermelon a and basketball background with asset exported from sketch
2019-09-19 16:31:57 -04:00
DD Liu bd835adcd4 Reupdate watermelon a and basketball background with asset exported from sketch 2019-09-19 15:21:17 -04:00
Karishma Chadha 78e4cfce68 Merge pull request #5183 from LLK/greenkeeper/scratch-vm-0.2.0-prerelease.20190918022946
Update scratch-vm to the latest version 🚀
2019-09-18 09:34:28 -07:00
Eric Rosenbaum deb5889a2c Merge pull request #5182 from LLK/greenkeeper/scratch-l10n-3.5.20190917223712
Update scratch-l10n to the latest version 🚀
2019-09-18 11:10:26 -04:00
greenkeeper[bot] 2030ad54bc chore(package): update lockfile package-lock.json 2019-09-18 02:32:41 +00:00
greenkeeper[bot] a95604008d chore(package): update scratch-vm to version 0.2.0-prerelease.20190918022946 2019-09-18 02:32:37 +00:00
greenkeeper[bot] bb21288cff chore(package): update lockfile package-lock.json 2019-09-17 22:39:32 +00:00
greenkeeper[bot] f31977489f chore(package): update scratch-l10n to version 3.5.20190917223712 2019-09-17 22:39:28 +00:00
Paul Kaplan f179587c2e Merge pull request #5180 from LLK/greenkeeper/scratch-vm-0.2.0-prerelease.20190917163837
Update scratch-vm to the latest version 🚀
2019-09-17 14:07:04 -04:00
greenkeeper[bot] fa3d9c9e1e chore(package): update lockfile package-lock.json 2019-09-17 16:41:32 +00:00
greenkeeper[bot] 459eb2b767 chore(package): update scratch-vm to version 0.2.0-prerelease.20190917163837 2019-09-17 16:41:29 +00:00
Paul Kaplan 4e1c6afe02 Merge pull request #5178 from paulkaplan/skip-flakey
Skip flakey test
2019-09-17 12:35:56 -04:00
Paul Kaplan dc69ccea64 Skip flakey test 2019-09-17 12:18:03 -04:00
Paul Kaplan 03d9f8f2c6 Merge pull request #5169 from LLK/recording-glitch
Use a larger buffer size for recording to prevent glitching
2019-09-17 11:10:20 -04:00
Paul Kaplan 5d006cf677 Merge pull request #5175 from LLK/greenkeeper/chromedriver-77.0.0
Update chromedriver to the latest version 🚀
2019-09-17 10:54:50 -04:00
DD Liu 6c9657e453 Merge pull request #5172 from fsih/fixAndroidAssets
Fix assets that aren't working correctly in Android libraries
2019-09-17 10:24:24 -04:00
greenkeeper[bot] e82ec50e7b chore(package): update lockfile package-lock.json 2019-09-17 00:00:43 +00:00
greenkeeper[bot] 09ccbb4c01 chore(package): update chromedriver to version 77.0.0 2019-09-17 00:00:38 +00:00
Karishma Chadha e3b2ab22a6 Merge pull request #5170 from LLK/greenkeeper/scratch-vm-0.2.0-prerelease.20190916185023
Update scratch-vm to the latest version 🚀
2019-09-16 18:56:29 -04:00
DD Liu a2bc04e5d4 Fix assets that aren't working correctly in Android libraries 2019-09-16 16:27:55 -04:00
greenkeeper[bot] a4c81e55c0 chore(package): update lockfile package-lock.json 2019-09-16 18:57:52 +00:00
greenkeeper[bot] 2b571d9d83 chore(package): update scratch-vm to version 0.2.0-prerelease.20190916185023 2019-09-16 18:57:47 +00:00
Ray Schamp 6caaaf6f36 Merge pull request #5166 from rschamp/debug-chromedriver
Use not broken Travis VM distribution
2019-09-16 10:53:12 -04:00
Paul Kaplan 2b9550f3d9 Use single setState call instead of two 2019-09-13 14:05:07 -04:00
Paul Kaplan 94bb677fd8 Force meter and waveform to separate paint layer 2019-09-13 14:04:54 -04:00
Paul Kaplan 5b6f33e1a4 Use a larger buffer size for recording to prevent glitching 2019-09-13 12:46:25 -04:00
Paul Kaplan 32723a8876 Merge pull request #5114 from LLK/default-last-asset
Default blocks to last asset instead of first
2019-09-13 09:51:54 -04:00
rschamp a1fc068dd1 Un-hack 2019-09-12 14:50:32 -04:00
rschamp 225fc772f6 Bump travis dist version 2019-09-12 14:42:20 -04:00
Karishma Chadha 2a167ba775 Merge pull request #5165 from LLK/greenkeeper/scratch-render-0.1.0-prerelease.20190912174749
Update scratch-render to the latest version 🚀
2019-09-12 13:59:54 -04:00
greenkeeper[bot] 193717a1a9 chore(package): update lockfile package-lock.json 2019-09-12 17:49:51 +00:00
greenkeeper[bot] 4fc140ec2c chore(package): update scratch-render to version 0.1.0-prerelease.20190912174749 2019-09-12 17:49:47 +00:00
Ray Schamp 2ffac96579 Merge pull request #5163 from rschamp/bump-chromedriver
Ugly hack to keep being able to publish
2019-09-12 11:50:41 -04:00
rschamp bc57adc12c Ugly hack to keep being able to publish 2019-09-12 11:32:02 -04:00
Karishma Chadha dc64aa92fd Merge pull request #5151 from LLK/greenkeeper/scratch-vm-0.2.0-prerelease.20190904154449
Update scratch-vm to the latest version 🚀
2019-09-11 12:41:30 -04:00
chrisgarrity 8b5ff14ac9 Merge pull request #5161 from LLK/greenkeeper/scratch-l10n-3.5.20190910223701
Greenkeeper/scratch l10n 3.5.20190910223701
2019-09-11 11:56:30 -04:00
Karishma Chadha 6641c4696b Merge pull request #5154 from LLK/greenkeeper/scratch-render-0.1.0-prerelease.20190905011937
Update scratch-render to the latest version 🚀
2019-09-11 10:16:16 -04:00
Paul Kaplan a680d30930 Merge pull request #5143 from towerofnix/selector-padding
Use list-area:after to pad scroll area
2019-09-11 09:22:10 -04:00
Paul Kaplan 1dce71e787 Merge pull request #5115 from paulkaplan/fix-bluetooth-keyboards
Fix bluetooth keyboards with iOS keypress blocks
2019-09-11 09:12:40 -04:00
greenkeeper[bot] 1451416e6b chore(package): update lockfile package-lock.json 2019-09-10 22:39:16 +00:00
greenkeeper[bot] f4f20203f4 chore(package): update scratch-l10n to version 3.5.20190910223701
Closes #5150
2019-09-10 22:39:12 +00:00
Eric Rosenbaum 2df0c80b30 Simplify chunk counting logic 2019-09-10 10:35:19 -04:00
picklesrus 7aa036a18c Merge pull request #5157 from LLK/greenkeeper/scratch-blocks-0.1.0-prerelease.1568071968
Update scratch-blocks to the latest version 🚀
2019-09-09 19:57:28 -04:00
greenkeeper[bot] 2f9a2ec305 chore(package): update lockfile package-lock.json 2019-09-09 23:36:02 +00:00
greenkeeper[bot] 75ccdbad51 chore(package): update scratch-blocks to version 0.1.0-prerelease.1568071968 2019-09-09 23:35:58 +00:00
Eric Rosenbaum 6414985461 Calc tooLoud with chunkLevels, disable louder btn 2019-09-05 13:49:22 -04:00
greenkeeper[bot] 230debb911 chore(package): update lockfile package-lock.json 2019-09-05 01:21:30 +00:00
greenkeeper[bot] b42291d10b chore(package): update scratch-render to version 0.1.0-prerelease.20190905011937 2019-09-05 01:21:26 +00:00
DD Liu 79616ba067 Merge pull request #5153 from LLK/greenkeeper/scratch-render-0.1.0-prerelease.20190904212449
Update scratch-render to the latest version 🚀
2019-09-04 18:42:44 -04:00
greenkeeper[bot] 35c1a3e5e2 chore(package): update lockfile package-lock.json 2019-09-04 21:46:08 +00:00
greenkeeper[bot] ac0e81dc00 chore(package): update scratch-render to version 0.1.0-prerelease.20190904212449 2019-09-04 21:46:03 +00:00
greenkeeper[bot] f9ea1088e8 chore(package): update lockfile package-lock.json 2019-09-04 15:56:55 +00:00
greenkeeper[bot] bb837f57e2 chore(package): update scratch-vm to version 0.2.0-prerelease.20190904154449 2019-09-04 15:56:47 +00:00
Eric Rosenbaum 059d3f709b Use a waveshaper to hard limit samples 2019-09-04 11:01:10 -04:00
Eric Rosenbaum 26ca5da725 Limit louder effect with a max RMS 2019-09-03 18:13:45 -04:00
Karishma Chadha ce8b0ff593 Merge pull request #5146 from LLK/greenkeeper/scratch-render-0.1.0-prerelease.20190830194018
Greenkeeper/scratch render 0.1.0 prerelease.20190830194018
2019-09-03 10:46:28 -04:00
Florrie b74f19e6e6 Use list-area:after to pad scroll area 2019-09-02 23:26:46 -03:00
greenkeeper[bot] 3566251676 chore(package): update lockfile package-lock.json 2019-08-30 19:43:11 +00:00
greenkeeper[bot] 4f02dbd807 chore(package): update scratch-render to version 0.1.0-prerelease.20190830194018
Closes #5139
2019-08-30 19:43:07 +00:00
DD Liu eed0aab4e5 Merge pull request #5137 from LLK/greenkeeper/scratch-render-0.1.0-prerelease.20190830153254
Update scratch-render to the latest version 🚀
2019-08-30 12:03:36 -04:00
greenkeeper[bot] 498ab2f547 chore(package): update lockfile package-lock.json 2019-08-30 15:34:51 +00:00
greenkeeper[bot] 9c1c6c6e4c chore(package): update scratch-render to version 0.1.0-prerelease.20190830153254 2019-08-30 15:34:47 +00:00
Paul Kaplan bd29738d52 Merge pull request #5134 from zoebentley/portuguese-brazilian
Fixed Portuguese (Brazilian) locale for tutorial videos
2019-08-29 16:14:22 -04:00
Zoë Bentley 2f08acae45 Fixed Portuguese (Brazilian) locale 2019-08-29 15:41:06 -04:00
Paul Kaplan 7b9aed73f3 Fix multi-word matching in the blocks 2019-08-22 09:44:22 -04:00
Paul Kaplan 280f139ba2 Fix costume test 2019-08-21 16:05:29 -04:00
Paul Kaplan def5cdc450 Send keyCode if the key information is gone 2019-08-21 15:28:04 -04:00
Paul Kaplan 79fe377f19 Update integration tests 2019-08-21 15:17:34 -04:00
Paul Kaplan b2dd3ed421 Default blocks to last asset instead of first 2019-08-21 14:56:46 -04:00
Florrie 639fc6a994 Always display whitespace in list monitors 2019-05-26 11:18:25 -03:00
68 changed files with 1639 additions and 1120 deletions

No files matched your search

+207
View File
@@ -0,0 +1,207 @@
version: 2.1
aliases:
- &save_git_cache
save_cache:
paths:
- .git
key: v1-git-{{ .Revision }}
- &restore_git_cache
restore_cache:
keys:
- v1-git-{{ .Revision }}
- v1-git-
- &save_build_cache
save_cache:
paths:
- build
key: v1-build-{{ .Revision }}
- &restore_build_cache
restore_cache:
keys:
- v1-build-{{ .Revision }}
- &save_dist_cache
save_cache:
paths:
- dist
key: v1-dist-{{ .Revision }}
- &restore_dist_cache
restore_cache:
keys:
- v1-dist-{{ .Revision }}
- &save_npm_cache
save_cache:
paths:
- node_modules
key: v1-npm-{{ checksum "package-lock.json" }}
- &restore_npm_cache
restore_cache:
keys:
- v1-npm-{{ checksum "package-lock.json" }}
- v1-npm-
- &defaults
docker:
- image: circleci/node:8.16-browsers
working_directory: ~/repo
jobs:
setup:
<<: *defaults
steps:
- *restore_git_cache
- checkout
- *restore_npm_cache
- run: npm install
- *save_git_cache
- *save_npm_cache
lint:
<<: *defaults
steps:
- *restore_git_cache
- checkout
- *restore_npm_cache
- run:
name: Lint
command: npm run test:lint -- --quiet --output-file test-results/eslint/results.xml --format junit
- store_test_results:
path: test-results
unit:
<<: *defaults
environment:
JEST_JUNIT_OUTPUT_NAME: results.xml
steps:
- *restore_git_cache
- checkout
- *restore_npm_cache
- run:
name: Unit
environment:
JEST_JUNIT_OUTPUT_DIR: test-results/unit
command: npm run test:unit -- --reporters="default" --reporters="jest-junit" --coverage --coverageReporters=text --coverageReporters=lcov
- store_artifacts:
path: coverage
- store_test_results:
path: test-results
build:
<<: *defaults
environment:
NODE_ENV: production
NODE_OPTIONS: --max-old-space-size=4000
steps:
- *restore_git_cache
- checkout
- *restore_npm_cache
- run:
name: Build
command: npm run build
- *save_build_cache
- *save_dist_cache
store_build:
<<: *defaults
steps:
- *restore_build_cache
- store_artifacts:
path: build
store_dist:
<<: *defaults
steps:
- *restore_dist_cache
- store_artifacts:
path: dist
integration:
<<: *defaults
parallelism: 2
environment:
JEST_JUNIT_OUTPUT_NAME: results.txt
steps:
- *restore_git_cache
- checkout
- *restore_npm_cache
- *restore_build_cache
- run:
name: Integration
environment:
JEST_JUNIT_OUTPUT_DIR: test-results/integration
command: |
export TESTFILES=$(circleci tests glob "test/integration/*.test.js" | circleci tests split --split-by=timings)
$(npm bin)/jest ${TESTFILES} --reporters="default" --reporters="jest-junit"
- store_test_results:
path: test-results
deploy-npm:
<<: *defaults
environment:
NODE_OPTIONS: --max-old-space-size=4000
steps:
- *restore_git_cache
- *restore_dist_cache
- checkout
- run: |
echo export RELEASE_VERSION="0.1.0-prerelease.$(date +'%Y%m%d%H%M%S')" >> $BASH_ENV
echo export NPM_TAG=circlelatest >> $BASH_ENV
if [ "$CIRCLE_BRANCH" == "master" ]
then echo export NPM_TAG=circlestable >> $BASH_ENV
fi
if [[ "$CIRCLE_BRANCH" == hotfix/* ]] # double brackets are important for matching the wildcard
then echo export NPM_TAG=circlehotfix >> $BASH_ENV
fi
- run: npm version --no-git-tag-version $RELEASE_VERSION
- run: |
npm set //registry.npmjs.org/:_authToken=$NPM_TOKEN
npm publish --tag $NPM_TAG
- run: git tag $RELEASE_VERSION
- run: git push $CIRCLE_REPOSITORY_URL $RELEASE_VERSION
deploy-gh-pages:
<<: *defaults
steps:
- *restore_git_cache
- checkout
- *restore_npm_cache
- *restore_build_cache
- run: |
git config --global user.email $(git log --pretty=format:"%ae" -n1)
git config --global user.name $(git log --pretty=format:"%an" -n1)
- run: npm run deploy -- -e $CIRCLE_BRANCH
workflows:
version: 2
build-test-deploy:
jobs:
- setup
- lint:
requires:
- setup
- unit:
requires:
- setup
- build:
requires:
- setup
- integration:
requires:
- build
- store_build:
requires:
- build
- store_dist:
requires:
- build
# Disable deployment while running in parallel with Travis
# - deploy-npm:
# requires:
# - lint
# - unit
# - integration
# - build
# filters:
# branches:
# only:
# - master
# - develop
# - /^hotfix\/.*/
# - deploy-gh-pages:
# requires:
# - lint
# - unit
# - integration
# - build
+3
View File
@@ -5,6 +5,9 @@
/node_modules
npm-*
# Double copies of all the static assets and tutorial gifs
/src
# Testing
/.nyc_output
/coverage
+6 -2
View File
@@ -1,16 +1,18 @@
language: node_js
sudo: required
dist: trusty
dist: xenial
addons:
chrome: stable
node_js:
- 8
env:
global:
- CHROMEDRIVER_VERSION=LATEST
- NODE_ENV=production
- SMOKE_URL=https://llk.github.io/scratch-gui/$TRAVIS_PULL_REQUEST_BRANCH
- NODE_OPTIONS=--max-old-space-size=7250
- NPM_TAG=latest
- RELEASE_VERSION="0.1.0-prerelease.$(date +'%Y%m%d%H%M%S')"
- SMOKE_URL=https://llk.github.io/scratch-gui/$TRAVIS_PULL_REQUEST_BRANCH
cache:
directories:
- node_modules
@@ -55,6 +57,7 @@ deploy:
- master
- develop
- smoke
- hotfix/*
condition: $TRAVIS_EVENT_TYPE != cron
skip_cleanup: true
script: if npm info scratch-gui | grep -q $RELEASE_VERSION; then git tag $RELEASE_VERSION && git push https://${GH_TOKEN}@github.com/${TRAVIS_REPO_SLUG}.git $RELEASE_VERSION; fi
@@ -74,6 +77,7 @@ deploy:
on:
all_branches: true
condition: $TRAVIS_EVENT_TYPE != cron && ! $TRAVIS_BRANCH =~ ^greenkeeper/
tags: false # Don't push tags to gh-pages
skip_cleanup: true
script: npm run deploy -- -x -e $TRAVIS_BRANCH -r https://${GH_TOKEN}@github.com/${TRAVIS_REPO_SLUG}.git
- provider: script
+595 -539
View File
File diff suppressed because it is too large. Load diff
+9 -9
View File
@@ -44,7 +44,7 @@
"babel-loader": "^8.0.4",
"base64-loader": "1.0.0",
"bowser": "1.9.4",
"chromedriver": "76.0.0",
"chromedriver": "78.0.1",
"classnames": "2.2.6",
"computed-style-to-inline-style": "3.0.0",
"copy-webpack-plugin": "^4.5.1",
@@ -67,6 +67,7 @@
"immutable": "3.8.2",
"intl": "1.2.5",
"jest": "^21.0.0",
"jest-junit": "^7.0.0",
"js-base64": "2.4.9",
"keymirror": "0.1.1",
"lodash.bindall": "4.4.0",
@@ -102,19 +103,18 @@
"react-test-renderer": "16.2.0",
"react-tooltip": "3.8.0",
"react-virtualized": "9.20.1",
"react-visibility-sensor": "5.0.2",
"redux": "3.7.2",
"redux-mock-store": "^1.2.3",
"redux-throttle": "0.1.1",
"rimraf": "^2.6.1",
"scratch-audio": "0.1.0-prerelease.20190114210212",
"scratch-l10n": "3.5.20190827223456",
"scratch-blocks": "0.1.0-prerelease.1566984014",
"scratch-paint": "0.2.0-prerelease.20190822205009",
"scratch-render": "0.1.0-prerelease.20190822204747",
"scratch-audio": "0.1.0-prerelease.20190925183642",
"scratch-l10n": "3.6.20191029224007",
"scratch-blocks": "0.1.0-prerelease.1572384380",
"scratch-paint": "0.2.0-prerelease.20191104214909",
"scratch-render": "0.1.0-prerelease.20191101193213",
"scratch-storage": "1.3.2",
"scratch-svg-renderer": "0.2.0-prerelease.20190822202608",
"scratch-vm": "0.2.0-prerelease.20190822194548",
"scratch-svg-renderer": "0.2.0-prerelease.20191104164753",
"scratch-vm": "0.2.0-prerelease.20191017151616",
"selenium-webdriver": "3.6.0",
"startaudiocontext": "1.2.1",
"style-loader": "^0.23.0",
+9 -1
View File
@@ -50,8 +50,16 @@ $fade-out-distance: 100px;
overflow-y: scroll;
display: flex;
flex-direction: column;
}
.list-area:after {
/* Make sure there is room to scroll beyond the last tile */
padding-bottom: 70px;
content: '';
display: block;
height: 70px;
width: 100%;
flex-shrink: 0;
order: 99999999;
}
.list-item {
-4
View File
@@ -94,7 +94,6 @@ const GUIComponent = props => {
onLogOut,
onOpenRegistration,
onToggleLoginOpen,
onUpdateProjectTitle,
onActivateCostumesTab,
onActivateSoundsTab,
onActivateTab,
@@ -228,7 +227,6 @@ const GUIComponent = props => {
onSeeCommunity={onSeeCommunity}
onShare={onShare}
onToggleLoginOpen={onToggleLoginOpen}
onUpdateProjectTitle={onUpdateProjectTitle}
/>
<Box className={styles.bodyWrapper}>
<Box className={styles.flexWrapper}>
@@ -406,7 +404,6 @@ GUIComponent.propTypes = {
onTelemetryModalOptIn: PropTypes.func,
onTelemetryModalOptOut: PropTypes.func,
onToggleLoginOpen: PropTypes.func,
onUpdateProjectTitle: PropTypes.func,
renderLogin: PropTypes.func,
showComingSoon: PropTypes.bool,
soundsTabVisible: PropTypes.bool,
@@ -433,7 +430,6 @@ GUIComponent.defaultProps = {
isCreating: false,
isShared: false,
loading: false,
onUpdateProjectTitle: () => {},
showComingSoon: false,
stageSizeMode: STAGE_SIZE_MODES.large
};
+3 -1
View File
@@ -139,7 +139,9 @@
.featured-description {
display: block;
font-weight: normal;
line-height: 2;
line-height: 1.375rem;
padding-top: .3125rem;
padding-bottom: .25rem;
}
.featured-extension-metadata {
+7 -10
View File
@@ -4,7 +4,6 @@ import React from 'react';
import Box from '../box/box.jsx';
import PlayButton from '../../containers/play-button.jsx';
import ScratchImage from '../scratch-image/scratch-image.jsx';
import styles from './library-item.css';
import classNames from 'classnames';
@@ -37,12 +36,10 @@ class LibraryItemComponent extends React.PureComponent {
/>
</div>
) : null}
{this.props.iconSource ? (
<ScratchImage
className={styles.featuredImage}
imageSource={this.props.iconSource}
/>
) : null}
<img
className={styles.featuredImage}
src={this.props.iconURL}
/>
</div>
{this.props.insetIconURL ? (
<div className={styles.libraryItemInsetImageContainer}>
@@ -130,9 +127,9 @@ class LibraryItemComponent extends React.PureComponent {
onMouseEnter={this.props.showPlayButton ? this.props.onMouseEnter : null}
onMouseLeave={this.props.showPlayButton ? this.props.onMouseLeave : null}
>
<ScratchImage
<img
className={styles.libraryItemImage}
imageSource={this.props.iconSource}
src={this.props.iconURL}
/>
</Box>
</Box>
@@ -162,7 +159,7 @@ LibraryItemComponent.propTypes = {
extensionId: PropTypes.string,
featured: PropTypes.bool,
hidden: PropTypes.bool,
iconSource: ScratchImage.ImageSourcePropType,
iconURL: PropTypes.string,
insetIconURL: PropTypes.string,
internetConnectionRequired: PropTypes.bool,
isPlaying: PropTypes.bool,
+7 -50
View File
@@ -10,7 +10,6 @@ import Divider from '../divider/divider.jsx';
import Filter from '../filter/filter.jsx';
import TagButton from '../../containers/tag-button.jsx';
import Spinner from '../spinner/spinner.jsx';
import storage from '../../lib/storage';
import styles from './library.css';
@@ -30,47 +29,6 @@ const messages = defineMessages({
const ALL_TAG = {tag: 'all', intlLabel: messages.allTag};
const tagListPrefix = [ALL_TAG];
/**
* Find the AssetType which corresponds to a particular file extension. For example, 'png' => AssetType.ImageBitmap.
* @param {string} fileExtension - the file extension to look up.
* @returns {AssetType} - the AssetType corresponding to the extension, if any.
*/
const getAssetTypeForFileExtension = function (fileExtension) {
const compareOptions = {
sensitivity: 'accent',
usage: 'search'
};
for (const assetTypeId in storage.AssetType) {
const assetType = storage.AssetType[assetTypeId];
if (fileExtension.localeCompare(assetType.runtimeFormat, compareOptions) === 0) {
return assetType;
}
}
};
/**
* Figure out an `imageSource` (URI or asset ID & type) for a library item's icon.
* @param {object} item - either a library item or one of a library item's costumes.
* @returns {object} - an `imageSource` ready to be passed to a `ScratchImage`.
*/
const getItemImageSource = function (item) {
if (item.rawURL) {
return {
uri: item.rawURL
};
}
// TODO: adjust libraries to be more storage-friendly; don't use split() here.
const md5 = item.md5 || item.baseLayerMD5;
if (md5) {
const [assetId, fileExtension] = md5.split('.');
return {
assetId: assetId,
assetType: getAssetTypeForFileExtension(fileExtension)
};
}
};
class LibraryComponent extends React.Component {
constructor (props) {
super(props);
@@ -250,10 +208,8 @@ class LibraryComponent extends React.Component {
})}
ref={this.setFilteredDataRef}
>
{this.state.loaded ? this.getFilteredData().map((dataItem, index) => {
const iconSource = getItemImageSource(dataItem);
const icons = dataItem.json && dataItem.json.costumes.map(getItemImageSource);
return (<LibraryItem
{this.state.loaded ? this.getFilteredData().map((dataItem, index) => (
<LibraryItem
bluetoothRequired={dataItem.bluetoothRequired}
collaborator={dataItem.collaborator}
description={dataItem.description}
@@ -261,8 +217,9 @@ class LibraryComponent extends React.Component {
extensionId={dataItem.extensionId}
featured={dataItem.featured}
hidden={dataItem.hidden}
iconSource={iconSource}
icons={icons}
iconMd5={dataItem.md5}
iconRawURL={dataItem.rawURL}
icons={dataItem.json && dataItem.json.costumes}
id={index}
insetIconURL={dataItem.insetIconURL}
internetConnectionRequired={dataItem.internetConnectionRequired}
@@ -273,8 +230,8 @@ class LibraryComponent extends React.Component {
onMouseEnter={this.handleMouseEnter}
onMouseLeave={this.handleMouseLeave}
onSelect={this.handleSelect}
/>);
}) : (
/>
)) : (
<div className={styles.spinnerWrapper}>
<Spinner
large
-3
View File
@@ -395,7 +395,6 @@ class MenuBar extends React.Component {
<SBFileUploader
canSave={this.props.canSave}
userOwnsProject={this.props.userOwnsProject}
onUpdateProjectTitle={this.props.onUpdateProjectTitle}
>
{(className, renderFileInput, handleLoadProject) => (
<MenuItem
@@ -495,7 +494,6 @@ class MenuBar extends React.Component {
>
<ProjectTitleInput
className={classNames(styles.titleFieldGrowable)}
onUpdateProjectTitle={this.props.onUpdateProjectTitle}
/>
</MenuBarItemTooltip>
</div>
@@ -746,7 +744,6 @@ MenuBar.propTypes = {
onSeeCommunity: PropTypes.func,
onShare: PropTypes.func,
onToggleLoginOpen: PropTypes.func,
onUpdateProjectTitle: PropTypes.func,
projectTitle: PropTypes.string,
renderLogin: PropTypes.func,
sessionExists: PropTypes.bool,
+21 -31
View File
@@ -1,9 +1,9 @@
import classNames from 'classnames';
import {connect} from 'react-redux';
import PropTypes from 'prop-types';
import bindAll from 'lodash.bindall';
import React from 'react';
import {defineMessages, intlShape, injectIntl} from 'react-intl';
import {setProjectTitle} from '../../reducers/project-title';
import BufferedInputHOC from '../forms/buffered-input-hoc.jsx';
import Input from '../forms/input.jsx';
@@ -19,39 +19,27 @@ const messages = defineMessages({
}
});
class ProjectTitleInput extends React.Component {
constructor (props) {
super(props);
bindAll(this, [
'handleUpdateProjectTitle'
]);
}
// call onUpdateProjectTitle if it is defined (only defined when gui
// is used within scratch-www)
handleUpdateProjectTitle (newTitle) {
if (this.props.onUpdateProjectTitle) {
this.props.onUpdateProjectTitle(newTitle);
}
}
render () {
return (
<BufferedInput
className={classNames(styles.titleField, this.props.className)}
maxLength="100"
placeholder={this.props.intl.formatMessage(messages.projectTitlePlaceholder)}
tabIndex="0"
type="text"
value={this.props.projectTitle}
onSubmit={this.handleUpdateProjectTitle}
/>
);
}
}
const ProjectTitleInput = ({
className,
intl,
onSubmit,
projectTitle
}) => (
<BufferedInput
className={classNames(styles.titleField, className)}
maxLength="100"
placeholder={intl.formatMessage(messages.projectTitlePlaceholder)}
tabIndex="0"
type="text"
value={projectTitle}
onSubmit={onSubmit}
/>
);
ProjectTitleInput.propTypes = {
className: PropTypes.string,
intl: intlShape.isRequired,
onUpdateProjectTitle: PropTypes.func,
onSubmit: PropTypes.func,
projectTitle: PropTypes.string
};
@@ -59,7 +47,9 @@ const mapStateToProps = state => ({
projectTitle: state.scratchGui.projectTitle
});
const mapDispatchToProps = () => ({});
const mapDispatchToProps = dispatch => ({
onSubmit: title => dispatch(setProjectTitle(title))
});
export default injectIntl(connect(
mapStateToProps,
+3 -1
View File
@@ -43,6 +43,7 @@
margin: 0 5px;
border-radius: calc($space / 2);
padding: 0 2px;
white-space: pre-wrap;
transform: translateZ(0); /* Fixes flickering in Safari */
}
@@ -53,6 +54,7 @@
text-align: center;
color: white;
font-size: 1rem;
white-space: pre-wrap;
transform: translateZ(0); /* Fixes flickering in Safari */
}
@@ -149,7 +151,7 @@
overflow: hidden; /* Don't let long values escape container */
text-overflow: ellipsis;
user-select: text; /* Allow selecting list values for 2.0 compatibility, only relevant in player */
white-space: nowrap;
white-space: pre;
}
.list-input {
+3 -1
View File
@@ -20,8 +20,10 @@
border: 1px solid $ui-black-transparent;
border-radius: 5px;
padding: 3px;
/* Force these to be on their own render layer because they update often */
transform: translateZ(0);
}
.meter-container {
margin-right: 5px;
height: 180px;
@@ -1,139 +0,0 @@
import PropTypes from 'prop-types';
import React from 'react';
import VisibilitySensor from 'react-visibility-sensor';
import storage from '../../lib/storage';
class ScratchImage extends React.PureComponent {
static init () {
this._maxParallelism = 6;
this._currentJobs = 0;
this._pendingImages = new Set();
}
static loadPendingImages () {
if (this._currentJobs >= this._maxParallelism) {
// already busy
return;
}
// Find the first visible image. If there aren't any, find the first non-visible image.
let nextImage;
for (const image of this._pendingImages) {
if (image.isVisible) {
nextImage = image;
break;
} else {
nextImage = nextImage || image;
}
}
// If we found an image to load:
// 1) Remove it from the queue
// 2) Load the image
// 3) Pump the queue again
if (nextImage) {
this._pendingImages.delete(nextImage);
const imageSource = nextImage.props.imageSource;
++this._currentJobs;
storage
.load(imageSource.assetType, imageSource.assetId)
.then(asset => {
if (!nextImage.wasUnmounted) {
const dataURI = asset.encodeDataURI();
nextImage.setState({
imageURI: dataURI
});
}
--this._currentJobs;
this.loadPendingImages();
});
}
}
constructor (props) {
super(props);
this.state = {};
Object.assign(this.state, this._loadImageSource(props.imageSource));
}
componentWillReceiveProps (nextProps) {
const newState = this._loadImageSource(nextProps.imageSource);
this.setState(newState);
}
componentWillUnmount () {
this.wasUnmounted = true;
ScratchImage._pendingImages.delete(this);
}
/**
* Calculate the state changes necessary to load the image specified in the provided source info. If the component
* is mounted, call setState() with the return value of this function. If the component has not yet mounted, use
* the return value of this function as initial state for the component.
*
* @param {object} imageSource - the new source for the image, including either assetId or URI
* @returns {object} - the new state values, if any.
*/
_loadImageSource (imageSource) {
if (imageSource) {
if (imageSource.uri) {
ScratchImage._pendingImages.delete(this);
return {
imageURI: imageSource.uri,
lastRequestedAsset: null
};
}
if (this.state.lastRequestedAsset !== imageSource.assetId) {
ScratchImage._pendingImages.add(this);
return {
lastRequestedAsset: imageSource.assetId
};
}
}
// Nothing to do - don't change any state.
return {};
}
render () {
const {
src: _src,
imageSource: _imageSource,
...imgProps
} = this.props;
return (
<VisibilitySensor
intervalCheck
scrollCheck
>
{
({isVisible}) => {
this.isVisible = isVisible;
ScratchImage.loadPendingImages();
return (
<img
src={this.state.imageURI}
{...imgProps}
/>
);
}
}
</VisibilitySensor>
);
}
}
ScratchImage.ImageSourcePropType = PropTypes.oneOfType([
PropTypes.shape({
assetId: PropTypes.string.isRequired,
assetType: PropTypes.oneOf(Object.values(storage.AssetType)).isRequired
}),
PropTypes.shape({
uri: PropTypes.string.isRequired
})
]);
ScratchImage.propTypes = {
imageSource: ScratchImage.ImageSourcePropType.isRequired
};
ScratchImage.init();
export default ScratchImage;
@@ -265,6 +265,7 @@ const SoundEditor = props => (
onClick={props.onSlower}
/>
<IconButton
disabled={props.tooLoud}
className={classNames(styles.effectButton, styles.flipInRtl)}
img={louderIcon}
title={<FormattedMessage {...messages.louder} />}
@@ -340,6 +341,7 @@ SoundEditor.propTypes = {
onUndo: PropTypes.func.isRequired,
playhead: PropTypes.number,
setRef: PropTypes.func,
tooLoud: PropTypes.bool.isRequired,
trimEnd: PropTypes.number,
trimStart: PropTypes.number
};
+3 -3
View File
@@ -340,9 +340,9 @@ class Blocks extends React.Component {
const targetSounds = target.getSounds();
const dynamicBlocksXML = this.props.vm.runtime.getBlocksXML();
return makeToolboxXML(target.isStage, target.id, dynamicBlocksXML,
targetCostumes[0].name,
stageCostumes[0].name,
targetSounds.length > 0 ? targetSounds[0].name : ''
targetCostumes[targetCostumes.length - 1].name,
stageCostumes[stageCostumes.length - 1].name,
targetSounds.length > 0 ? targetSounds[targetSounds.length - 1].name : ''
);
} catch {
return null;
+4 -30
View File
@@ -4,14 +4,13 @@ import {compose} from 'redux';
import {connect} from 'react-redux';
import ReactModal from 'react-modal';
import VM from 'scratch-vm';
import {defineMessages, injectIntl, intlShape} from 'react-intl';
import {injectIntl, intlShape} from 'react-intl';
import ErrorBoundaryHOC from '../lib/error-boundary-hoc.jsx';
import {
getIsError,
getIsShowingProject
} from '../reducers/project-state';
import {setProjectTitle} from '../reducers/project-title';
import {
activateTab,
BLOCKS_TAB_INDEX,
@@ -29,6 +28,7 @@ import {
import FontLoaderHOC from '../lib/font-loader-hoc.jsx';
import LocalizationHOC from '../lib/localization-hoc.jsx';
import ProjectFetcherHOC from '../lib/project-fetcher-hoc.jsx';
import TitledHOC from '../lib/titled-hoc.jsx';
import ProjectSaverHOC from '../lib/project-saver-hoc.jsx';
import QueryParserHOC from '../lib/query-parser-hoc.jsx';
import storage from '../lib/storage';
@@ -39,18 +39,9 @@ import cloudManagerHOC from '../lib/cloud-manager-hoc.jsx';
import GUIComponent from '../components/gui/gui.jsx';
import {setIsScratchDesktop} from '../lib/isScratchDesktop.js';
const messages = defineMessages({
defaultProjectTitle: {
id: 'gui.gui.defaultProjectTitle',
description: 'Default title for project',
defaultMessage: 'Scratch Project'
}
});
class GUI extends React.Component {
componentDidMount () {
setIsScratchDesktop(this.props.isScratchDesktop);
this.setReduxTitle(this.props.projectTitle);
this.props.onStorageInit(storage);
this.props.onVmInit(this.props.vm);
}
@@ -58,24 +49,12 @@ class GUI extends React.Component {
if (this.props.projectId !== prevProps.projectId && this.props.projectId !== null) {
this.props.onUpdateProjectId(this.props.projectId);
}
if (this.props.projectTitle !== prevProps.projectTitle) {
this.setReduxTitle(this.props.projectTitle);
}
if (this.props.isShowingProject && !prevProps.isShowingProject) {
// this only notifies container when a project changes from not yet loaded to loaded
// At this time the project view in www doesn't need to know when a project is unloaded
this.props.onProjectLoaded();
}
}
setReduxTitle (newTitle) {
if (newTitle === null || typeof newTitle === 'undefined') {
this.props.onUpdateReduxProjectTitle(
this.props.intl.formatMessage(messages.defaultProjectTitle)
);
} else {
this.props.onUpdateReduxProjectTitle(newTitle);
}
}
render () {
if (this.props.isError) {
throw new Error(
@@ -92,11 +71,9 @@ class GUI extends React.Component {
onProjectLoaded,
onStorageInit,
onUpdateProjectId,
onUpdateReduxProjectTitle,
onVmInit,
projectHost,
projectId,
projectTitle,
/* eslint-enable no-unused-vars */
children,
fetchingProject,
@@ -131,12 +108,9 @@ GUI.propTypes = {
onSeeCommunity: PropTypes.func,
onStorageInit: PropTypes.func,
onUpdateProjectId: PropTypes.func,
onUpdateProjectTitle: PropTypes.func,
onUpdateReduxProjectTitle: PropTypes.func,
onVmInit: PropTypes.func,
projectHost: PropTypes.string,
projectId: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
projectTitle: PropTypes.string,
telemetryModalVisible: PropTypes.bool,
vm: PropTypes.instanceOf(VM).isRequired
};
@@ -186,8 +160,7 @@ const mapDispatchToProps = dispatch => ({
onActivateSoundsTab: () => dispatch(activateTab(SOUNDS_TAB_INDEX)),
onRequestCloseBackdropLibrary: () => dispatch(closeBackdropLibrary()),
onRequestCloseCostumeLibrary: () => dispatch(closeCostumeLibrary()),
onRequestCloseTelemetryModal: () => dispatch(closeTelemetryModal()),
onUpdateReduxProjectTitle: title => dispatch(setProjectTitle(title))
onRequestCloseTelemetryModal: () => dispatch(closeTelemetryModal())
});
const ConnectedGUI = injectIntl(connect(
@@ -204,6 +177,7 @@ const WrappedGui = compose(
FontLoaderHOC,
QueryParserHOC,
ProjectFetcherHOC,
TitledHOC,
ProjectSaverHOC,
vmListenerHOC,
vmManagerHOC,
+18 -8
View File
@@ -91,17 +91,21 @@ class LibraryItem extends React.PureComponent {
const nextIconIndex = (this.state.iconIndex + 1) % this.props.icons.length;
this.setState({iconIndex: nextIconIndex});
}
curIconSource () {
curIconMd5 () {
if (this.props.icons &&
this.state.isRotatingIcon &&
this.state.iconIndex < this.props.icons.length &&
this.props.icons[this.state.iconIndex]) {
return this.props.icons[this.state.iconIndex];
this.props.icons[this.state.iconIndex] &&
this.props.icons[this.state.iconIndex].baseLayerMD5) {
return this.props.icons[this.state.iconIndex].baseLayerMD5;
}
return this.props.iconSource;
return this.props.iconMd5;
}
render () {
const iconSource = this.curIconSource();
const iconMd5 = this.curIconMd5();
const iconURL = iconMd5 ?
`https://cdn.assets.scratch.mit.edu/internalapi/asset/${iconMd5}/get/` :
this.props.iconRawURL;
return (
<LibraryItemComponent
bluetoothRequired={this.props.bluetoothRequired}
@@ -111,7 +115,8 @@ class LibraryItem extends React.PureComponent {
extensionId={this.props.extensionId}
featured={this.props.featured}
hidden={this.props.hidden}
iconSource={iconSource}
iconURL={iconURL}
icons={this.props.icons}
id={this.props.id}
insetIconURL={this.props.insetIconURL}
internetConnectionRequired={this.props.internetConnectionRequired}
@@ -142,8 +147,13 @@ LibraryItem.propTypes = {
extensionId: PropTypes.string,
featured: PropTypes.bool,
hidden: PropTypes.bool,
iconSource: LibraryItemComponent.propTypes.iconSource, // single icon
icons: PropTypes.arrayOf(LibraryItemComponent.propTypes.iconSource), // rotating icons
iconMd5: PropTypes.string,
iconRawURL: PropTypes.string,
icons: PropTypes.arrayOf(
PropTypes.shape({
baseLayerMD5: PropTypes.string
})
),
id: PropTypes.number.isRequired,
insetIconURL: PropTypes.string,
internetConnectionRequired: PropTypes.bool,
+4 -4
View File
@@ -44,10 +44,10 @@ class RecordingStep extends React.Component {
alert(this.props.intl.formatMessage(messages.alertMsg)); // eslint-disable-line no-alert
}
handleLevelUpdate (level) {
this.setState({level});
if (this.props.recording) {
this.setState({levels: (this.state.levels || []).concat([level])});
}
this.setState({
level: level,
levels: this.props.recording ? (this.state.levels || []).concat([level]) : this.state.levels
});
}
handleRecord () {
this.audioRecorder.startRecording();
+5 -3
View File
@@ -3,6 +3,7 @@ import PropTypes from 'prop-types';
import React from 'react';
import {connect} from 'react-redux';
import {defineMessages, injectIntl, intlShape} from 'react-intl';
import {setProjectTitle} from '../reducers/project-title';
import log from '../lib/log';
import sharedMessages from '../lib/shared-messages';
@@ -131,7 +132,7 @@ class SBFileUploader extends React.Component {
// This is necessary in case the user wants to reload a project
if (filename) {
const uploadedProjectTitle = this.getProjectTitleFromFilename(filename);
this.props.onUpdateProjectTitle(uploadedProjectTitle);
this.props.onReceivedProjectTitle(uploadedProjectTitle);
}
this.resetFileInput();
})
@@ -179,9 +180,9 @@ SBFileUploader.propTypes = {
loadingState: PropTypes.oneOf(LoadingStates),
onLoadingFinished: PropTypes.func,
onLoadingStarted: PropTypes.func,
onUpdateProjectTitle: PropTypes.func,
projectChanged: PropTypes.bool,
requestProjectUpload: PropTypes.func,
onReceivedProjectTitle: PropTypes.func,
userOwnsProject: PropTypes.bool,
vm: PropTypes.shape({
loadProject: PropTypes.func
@@ -209,7 +210,8 @@ const mapDispatchToProps = (dispatch, ownProps) => ({
dispatch(closeFileMenu());
},
requestProjectUpload: loadingState => dispatch(requestProjectUpload(loadingState)),
onLoadingStarted: () => dispatch(openLoadingProject())
onLoadingStarted: () => dispatch(openLoadingProject()),
onReceivedProjectTitle: title => dispatch(setProjectTitle(title))
});
// Allow incoming props to override redux-provided props. Used to mock in tests.
+12
View File
@@ -14,6 +14,8 @@ import log from '../lib/log.js';
const UNDO_STACK_SIZE = 99;
const MAX_RMS = 1.2;
class SoundEditor extends React.Component {
constructor (props) {
super(props);
@@ -265,6 +267,15 @@ class SoundEditor extends React.Component {
}
});
}
tooLoud () {
const numChunks = this.state.chunkLevels.length;
const startIndex = this.state.trimStart === null ?
0 : Math.floor(this.state.trimStart * numChunks);
const endIndex = this.state.trimEnd === null ?
numChunks - 1 : Math.ceil(this.state.trimEnd * numChunks);
const trimChunks = this.state.chunkLevels.slice(startIndex, endIndex);
return Math.max(...trimChunks) > MAX_RMS;
}
getUndoItem () {
return {
...this.copyCurrentBuffer(),
@@ -399,6 +410,7 @@ class SoundEditor extends React.Component {
name={this.props.name}
playhead={this.state.playhead}
setRef={this.setRef}
tooLoud={this.tooLoud()}
trimEnd={this.state.trimEnd}
trimStart={this.state.trimStart}
onChangeName={this.handleChangeName}
-2
View File
@@ -1,6 +1,5 @@
import GUI from './containers/gui.jsx';
import AppStateHOC from './lib/app-state-hoc.jsx';
import TitledHOC from './lib/titled-hoc.jsx';
import GuiReducer, {guiInitialState, guiMiddleware, initEmbedded, initFullScreen, initPlayer} from './reducers/gui';
import LocalesReducer, {localesInitialState, initLocale} from './reducers/locales';
import {ScratchPaintReducer} from 'scratch-paint';
@@ -17,7 +16,6 @@ const guiReducers = {
export {
GUI as default,
AppStateHOC,
TitledHOC,
setAppElement,
guiReducers,
guiInitialState,
+14 -14
View File
@@ -1,12 +1,12 @@
import 'get-float-time-domain-data';
import getUserMedia from 'get-user-media-promise';
import SharedAudioContext from './shared-audio-context.js';
import {computeRMS} from './audio-util.js';
import {computeRMS, computeChunkedRMS} from './audio-util.js';
class AudioRecorder {
constructor () {
this.audioContext = new SharedAudioContext();
this.bufferLength = 1024;
this.bufferLength = 8192;
this.userMediaStream = null;
this.mediaStreamSource = null;
@@ -51,7 +51,7 @@ class AudioRecorder {
this.userMediaStream = userMediaStream;
this.mediaStreamSource = this.audioContext.createMediaStreamSource(userMediaStream);
this.sourceNode = this.audioContext.createGain();
this.scriptProcessorNode = this.audioContext.createScriptProcessor(this.bufferLength, 2, 2);
this.scriptProcessorNode = this.audioContext.createScriptProcessor(this.bufferLength, 1, 1);
this.scriptProcessorNode.onaudioprocess = processEvent => {
if (this.recording && !this.disposed) {
@@ -68,9 +68,9 @@ class AudioRecorder {
const update = () => {
if (this.disposed) return;
requestAnimationFrame(update);
this.analyserNode.getFloatTimeDomainData(dataArray);
onUpdate(computeRMS(dataArray));
requestAnimationFrame(update);
};
requestAnimationFrame(update);
@@ -83,7 +83,16 @@ class AudioRecorder {
}
stop () {
const chunkLevels = this.buffers.map(buffer => computeRMS(buffer));
const buffer = new Float32Array(this.buffers.length * this.bufferLength);
let offset = 0;
for (let i = 0; i < this.buffers.length; i++) {
const bufferChunk = this.buffers[i];
buffer.set(bufferChunk, offset);
offset += bufferChunk.length;
}
const chunkLevels = computeChunkedRMS(buffer);
const maxRMS = Math.max.apply(null, chunkLevels);
const threshold = maxRMS / 8;
@@ -105,15 +114,6 @@ class AudioRecorder {
trimEnd = 1;
}
const buffer = new Float32Array(this.buffers.length * this.bufferLength);
let offset = 0;
for (let i = 0; i < this.buffers.length; i++) {
const bufferChunk = this.buffers[i];
buffer.set(bufferChunk, offset);
offset += bufferChunk.length;
}
return {
levels: chunkLevels,
samples: buffer,
+11 -6
View File
@@ -3,15 +3,20 @@ const jpegThumbnail = dataUrl => new Promise((resolve, reject) => {
image.onload = () => {
const canvas = document.createElement('canvas');
const ctx = canvas.getContext('2d');
// TODO we may want to draw to a smaller, fixed size to optimize file size
canvas.width = image.width;
canvas.height = image.height;
const maxDimension = 96; // 3x the maximum displayed size of 32px
if (image.height > image.width) {
canvas.height = maxDimension;
canvas.width = (maxDimension / image.height) * image.width;
} else {
canvas.width = maxDimension;
canvas.height = (maxDimension / image.width) * image.height;
}
ctx.fillStyle = 'white'; // Create white background, since jpeg doesn't have transparency
ctx.fillRect(0, 0, canvas.width, canvas.height);
ctx.drawImage(image, 0, 0);
// TODO we can play with the `quality` option here to optimize file size
ctx.drawImage(image, 0, 0, canvas.width, canvas.height);
resolve(canvas.toDataURL('image/jpeg', 0.92 /* quality */)); // Default quality is 0.92
};
image.onerror = err => {
+1 -1
View File
@@ -52,7 +52,7 @@
},
{
"name": "Basketball 1",
"md5": "e494c4f44897d94e0541f7036a302449.svg",
"md5": "ae21eac3d1814aee1d37ae82ea287816.svg",
"type": "backdrop",
"tags": [
"sports",
+4 -4
View File
@@ -2563,7 +2563,7 @@
},
{
"name": "Dinosaur1-c",
"md5": "a2bb28d5ba55ba997bec63772437cecf.svg",
"md5": "78f7e20f0e187fdca81195e4cc134175.svg",
"type": "costume",
"tags": [
"animals",
@@ -10493,7 +10493,7 @@
},
{
"name": "Watermelon-a",
"md5": "26fecef75cf3b6e0d98bff5c06475036.svg",
"md5": "8736ecc2524895733534c888cd91fa1f.svg",
"type": "costume",
"tags": [
"food",
@@ -10511,7 +10511,7 @@
},
{
"name": "Watermelon-b",
"md5": "fbdaf4d1d349edd3ddf3a1c4528aa9ec.svg",
"md5": "1ed1c8b78eae2ee7422074d7f883031d.svg",
"type": "costume",
"tags": [
"food",
@@ -10528,7 +10528,7 @@
},
{
"name": "Watermelon-c",
"md5": "5976c10412306fc093c1d1930fa05119.svg",
"md5": "677738282686d2dcce35d731c3ddc043.svg",
"type": "costume",
"tags": [
"food",
+68 -14
View File
@@ -119,7 +119,7 @@ import pongResetScore from './steps/pong-reset-score.en.png';
import pongAddLineSprite from './steps/pong-add-line.en.gif';
import pongGameOver from './steps/pong-game-over.en.png';
// Imagine If
// Imagine a World
import imagineTypeWhatYouWant from './steps/imagine-type-what-you-want.en.png';
import imagineClickGreenFlag from './steps/imagine-click-green-flag.en.png';
import imagineChooseBackdrop from './steps/imagine-choose-backdrop.en.png';
@@ -170,6 +170,34 @@ import moveArrowKeysUpDown from './steps/move-arrow-keys-up-down.en.png';
import glideAroundBackAndForth from './steps/glide-around-back-and-forth.en.png';
import glideAroundPoint from './steps/glide-around-point.en.png';
// Code a Cartoon
import codeCartoonSaySomething from './steps/code-cartoon-01-say-something.en.png';
import codeCartoonAnimate from './steps/code-cartoon-02-animate.en.gif';
import codeCartoonSelectDifferentCharacter from './steps/code-cartoon-03-select-different-character.en.gif';
import codeCartoonUseMinusSign from './steps/code-cartoon-04-use-minus-sign.en.gif';
import codeCartoonGrowShrink from './steps/code-cartoon-05-grow-shrink.en.gif';
import codeCartoonSelectDifferentCharacter2 from './steps/code-cartoon-06-select-another-different-character.en.gif';
import codeCartoonJump from './steps/code-cartoon-07-jump.en.gif';
import codeCartoonChangeScenes from './steps/code-cartoon-08-change-scenes.en.gif';
import codeCartoonGlideAround from './steps/code-cartoon-09-glide-around.en.gif';
import codeCartoonChangeCostumes from './steps/code-cartoon-10-change-costumes.en.gif';
import codeCartoonChooseMoreCharacters from './steps/code-cartoon-11-choose-more-characters.en.jpg';
// Talking Tales
import talesAddExtension from './steps/talking-1-add-extension.en.gif';
import talesChooseSprite from './steps/talking-2-choose-sprite.en.png';
import talesSaySomething from './steps/talking-3-say-something.en.gif';
import talesChooseBackdrop from './steps/talking-4-choose-backdrop.en.png';
import talesSwitchBackdrop from './steps/talking-5-switch-backdrop.en.gif';
import talesChooseAnotherSprite from './steps/talking-6-choose-another-sprite.en.png';
import talesMoveAround from './steps/talking-7-move-around.en.gif';
import talesChooseAnotherBackdrop from './steps/talking-8-choose-another-backdrop.en.png';
import talesAnimateTalking from './steps/talking-9-animate.en.gif';
import talesChooseThirdBackdrop from './steps/talking-10-choose-third-backdrop.en.png';
import talesChooseSound from './steps/talking-11-choose-sound.en.gif';
import talesDanceMoves from './steps/talking-12-dance-moves.en.gif';
import talesAskAnswer from './steps/talking-13-ask-and-answer.en.gif';
const enImages = {
// Intro
introMove: introMove,
@@ -276,7 +304,7 @@ const enImages = {
flyAddScenery: flyAddScenery,
flyMoveScenery: flyMoveScenery,
flySwitchLooks: flySwitchLooks,
// Pong
pongAddBackdrop: pongAddBackdrop,
pongAddBallSprite: pongAddBallSprite,
@@ -291,8 +319,8 @@ const enImages = {
pongResetScore: pongResetScore,
pongAddLineSprite: pongAddLineSprite,
pongGameOver: pongGameOver,
// Imagine If
// Imagine a World
imagineTypeWhatYouWant: imagineTypeWhatYouWant,
imagineClickGreenFlag: imagineClickGreenFlag,
imagineChooseBackdrop: imagineChooseBackdrop,
@@ -308,26 +336,26 @@ const enImages = {
imagineSwitchBackdrops: imagineSwitchBackdrops,
imagineRecordASound: imagineRecordASound,
imagineChooseSound: imagineChooseSound,
// Add a Backdrop
addBackdrop: addBackdrop,
// Add Effects
addEffects: addEffects,
// Hide and Show
hideAndShow: hideAndShow,
// Switch Costumes
switchCostumes: switchCostumes,
// Change Size
changeSize: changeSize,
// Spin
spinTurn: spinTurn,
spinPointInDirection: spinPointInDirection,
// Record a Sound
recordASoundSoundsTab: recordASoundSoundsTab,
recordASoundClickRecord: recordASoundClickRecord,
@@ -341,9 +369,35 @@ const enImages = {
// Glide Around
glideAroundBackAndForth: glideAroundBackAndForth,
glideAroundPoint: glideAroundPoint
glideAroundPoint: glideAroundPoint,
// Code a Cartoon
codeCartoonSaySomething: codeCartoonSaySomething,
codeCartoonAnimate: codeCartoonAnimate,
codeCartoonSelectDifferentCharacter: codeCartoonSelectDifferentCharacter,
codeCartoonUseMinusSign: codeCartoonUseMinusSign,
codeCartoonGrowShrink: codeCartoonGrowShrink,
codeCartoonSelectDifferentCharacter2: codeCartoonSelectDifferentCharacter2,
codeCartoonJump: codeCartoonJump,
codeCartoonChangeScenes: codeCartoonChangeScenes,
codeCartoonGlideAround: codeCartoonGlideAround,
codeCartoonChangeCostumes: codeCartoonChangeCostumes,
codeCartoonChooseMoreCharacters: codeCartoonChooseMoreCharacters,
// Talking Tales
talesAddExtension: talesAddExtension,
talesChooseSprite: talesChooseSprite,
talesSaySomething: talesSaySomething,
talesAskAnswer: talesAskAnswer,
talesChooseBackdrop: talesChooseBackdrop,
talesSwitchBackdrop: talesSwitchBackdrop,
talesChooseAnotherSprite: talesChooseAnotherSprite,
talesMoveAround: talesMoveAround,
talesChooseAnotherBackdrop: talesChooseAnotherBackdrop,
talesAnimateTalking: talesAnimateTalking,
talesChooseThirdBackdrop: talesChooseThirdBackdrop,
talesChooseSound: talesChooseSound,
talesDanceMoves: talesDanceMoves
};
export {enImages};
+440 -173
View File
@@ -42,8 +42,14 @@ import libraryMakeFly from './thumbnails/make-it-fly.jpg';
// Pong
import libraryPong from './thumbnails/pong.jpg';
// Imagine If
import libraryImagineIf from './thumbnails/imagine-if.jpg';
// Imagine a World
import libraryImagine from './thumbnails/imagine.jpg';
// Code a Cartoon
import libraryCodeCartoon from './thumbnails/code-a-cartoon.jpg';
// Talking Tales
import libraryTalking from './thumbnails/talking.png';
// Videos
import recordASound from './thumbnails/record-a-sound.jpg';
@@ -173,25 +179,25 @@ export default {
],
urlId: 'name'
},
'imagine-if': {
'imagine': {
name: (
<FormattedMessage
defaultMessage="Imagine If"
description="Name for the 'Imagine If' how-to"
id="gui.howtos.imagine-if"
defaultMessage="Imagine a World"
description="Name for the 'Imagine a World' how-to"
id="gui.howtos.imagine"
/>
),
tags: ['imagine-if'],
img: libraryImagineIf,
tags: ['imagine'],
img: libraryImagine,
steps: [{
video: 'imagine-if'
video: 'imagine'
}, {
title: (
<FormattedMessage
defaultMessage="Type What You Want to Say"
description="Step name for 'Type What You Want to Say' step"
id="gui.howtos.imagine-if.step_imagineTypeWhatYouWant"
id="gui.howtos.imagine.step_imagineTypeWhatYouWant"
/>
),
image: 'imagineTypeWhatYouWant'
@@ -200,7 +206,7 @@ export default {
<FormattedMessage
defaultMessage="Click the Green Flag to Start"
description="Step name for 'Click the Green Flag to Start' step"
id="gui.howtos.imagine-if.step_imagineClickGreenFlag"
id="gui.howtos.imagine.step_imagineClickGreenFlag"
/>
),
image: 'imagineClickGreenFlag'
@@ -209,7 +215,7 @@ export default {
<FormattedMessage
defaultMessage="Choose Any Backdrop"
description="Step name for 'Choose Any Backdrop' step"
id="gui.howtos.imagine-if.step_imagineChooseBackdrop"
id="gui.howtos.imagine.step_imagineChooseBackdrop"
/>
),
image: 'imagineChooseBackdrop'
@@ -218,7 +224,7 @@ export default {
<FormattedMessage
defaultMessage="Choose Any Sprite"
description="Step name for 'Choose Any Sprite' step"
id="gui.howtos.imagine-if.step_imagineChooseSprite"
id="gui.howtos.imagine.step_imagineChooseSprite"
/>
),
image: 'imagineChooseSprite'
@@ -227,7 +233,7 @@ export default {
<FormattedMessage
defaultMessage="Press the Space Key to Glide"
description="Step name for 'Press the Space Key to Glide' step"
id="gui.howtos.imagine-if.step_imagineFlyAround"
id="gui.howtos.imagine.step_imagineFlyAround"
/>
),
image: 'imagineFlyAround'
@@ -236,7 +242,7 @@ export default {
<FormattedMessage
defaultMessage="Choose Another Sprite"
description="Step name for 'Choose Another Sprite' step"
id="gui.howtos.imagine-if.step_imagineChooseAnotherSprite"
id="gui.howtos.imagine.step_imagineChooseAnotherSprite"
/>
),
image: 'imagineChooseAnotherSprite'
@@ -245,7 +251,7 @@ export default {
<FormattedMessage
defaultMessage="Move Left-Right"
description="Step name for 'Move Left-Right' step"
id="gui.howtos.imagine-if.step_imagineLeftRight"
id="gui.howtos.imagine.step_imagineLeftRight"
/>
),
image: 'imagineLeftRight'
@@ -254,7 +260,7 @@ export default {
<FormattedMessage
defaultMessage="Move Up-Down"
description="Step name for 'Move Up-Down' step"
id="gui.howtos.imagine-if.step_imagineUpDown"
id="gui.howtos.imagine.step_imagineUpDown"
/>
),
image: 'imagineUpDown'
@@ -263,7 +269,7 @@ export default {
<FormattedMessage
defaultMessage="Change Costumes"
description="Step name for 'Change Costumes' step"
id="gui.howtos.imagine-if.step_imagineChangeCostumes"
id="gui.howtos.imagine.step_imagineChangeCostumes"
/>
),
image: 'imagineChangeCostumes'
@@ -272,7 +278,7 @@ export default {
<FormattedMessage
defaultMessage="Glide to a Point"
description="Step name for 'Glide to a Point' step"
id="gui.howtos.imagine-if.step_imagineGlideToPoint"
id="gui.howtos.imagine.step_imagineGlideToPoint"
/>
),
image: 'imagineGlideToPoint'
@@ -281,7 +287,7 @@ export default {
<FormattedMessage
defaultMessage="Grow and Shrink"
description="Step name for 'Grow and Shrink' step"
id="gui.howtos.imagine-if.step_imagineGrowShrink"
id="gui.howtos.imagine.step_imagineGrowShrink"
/>
),
image: 'imagineGrowShrink'
@@ -290,7 +296,7 @@ export default {
<FormattedMessage
defaultMessage="Choose Another Backdrop"
description="Step name for 'Choose Another Backdrop' step"
id="gui.howtos.imagine-if.step_imagineChooseAnotherBackdrop"
id="gui.howtos.imagine.step_imagineChooseAnotherBackdrop"
/>
),
image: 'imagineChooseAnotherBackdrop'
@@ -299,7 +305,7 @@ export default {
<FormattedMessage
defaultMessage="Switch Backdrops"
description="Step name for 'Switch Backdrops' step"
id="gui.howtos.imagine-if.step_imagineSwitchBackdrops"
id="gui.howtos.imagine.step_imagineSwitchBackdrops"
/>
),
image: 'imagineSwitchBackdrops'
@@ -308,7 +314,7 @@ export default {
<FormattedMessage
defaultMessage="Add a Sound"
description="Step name for 'Add a Sound' step"
id="gui.howtos.imagine-if.step_imagineRecordASound"
id="gui.howtos.imagine.step_imagineRecordASound"
/>
),
image: 'imagineRecordASound'
@@ -317,7 +323,7 @@ export default {
<FormattedMessage
defaultMessage="Choose Your Sound"
description="Step name for 'Choose Your Sound' step"
id="gui.howtos.imagine-if.step_imagineChooseSound"
id="gui.howtos.imagine.step_imagineChooseSound"
/>
),
image: 'imagineChooseSound'
@@ -328,9 +334,9 @@ export default {
]
}
],
urlId: 'imagine-if'
urlId: 'imagine'
},
'Make-Music': {
name: (
<FormattedMessage
@@ -400,7 +406,7 @@ export default {
],
urlId: 'music'
},
'Tell-A-Story': {
name: (
<FormattedMessage
@@ -513,7 +519,7 @@ export default {
],
urlId: 'tell-a-story'
},
'Chase-Game': {
name: (
<FormattedMessage
@@ -711,7 +717,7 @@ export default {
],
urlId: 'animate-a-character'
},
'Make-A-Game': {
name: (
<FormattedMessage
@@ -798,7 +804,7 @@ export default {
],
urlId: 'clicker-game'
},
'make-it-fly': {
name: (
<FormattedMessage
@@ -928,7 +934,7 @@ export default {
],
urlId: 'make-it-fly'
},
'pong': {
name: (
<FormattedMessage
@@ -1069,6 +1075,287 @@ export default {
urlId: 'pong'
},
'code-cartoon': {
name: (
<FormattedMessage
defaultMessage="Code a Cartoon"
description="Name for the 'Code a Cartoon' how-to"
id="gui.howtos.code-cartoon"
/>
),
tags: ['code-cartoon'],
requiredProjectId: '331474033',
img: libraryCodeCartoon,
steps: [{
video: 'code-cartoon'
}, {
title: (
<FormattedMessage
defaultMessage="Say Something When You Click the Green Flag"
description="Step name for 'Say Something When You Click the Green Flag' step"
id="gui.howtos.code-cartoon.step_codeCartoonSaySomething"
/>
),
image: 'codeCartoonSaySomething'
}, {
title: (
<FormattedMessage
defaultMessage="Animate a Character When You Click It"
description="Step name for 'Animate a Character When You Click It' step"
id="gui.howtos.code-cartoon.step_codeCartoonAnimate"
/>
),
image: 'codeCartoonAnimate'
}, {
title: (
<FormattedMessage
defaultMessage="Select a Different Character"
description="Step name for 'Select a Different Character' step"
id="gui.howtos.code-cartoon.step_codeCartoonSelectDifferentCharacter"
/>
),
image: 'codeCartoonSelectDifferentCharacter'
}, {
title: (
<FormattedMessage
defaultMessage="Use a Minus Sign to Get Smaller"
description="Step name for 'Use a Minus Sign to Get Smaller' step"
id="gui.howtos.code-cartoon.step_codeCartoonUseMinusSign"
/>
),
image: 'codeCartoonUseMinusSign'
}, {
title: (
<FormattedMessage
defaultMessage="Make a Character Grow and Shrink"
description="Step name for 'Make a Character Grow and Shrink' step"
id="gui.howtos.code-cartoon.step_codeCartoonGrowShrink"
/>
),
image: 'codeCartoonGrowShrink'
}, {
title: (
<FormattedMessage
defaultMessage="Select a Different Character"
description="Step name for 'Select a Different Character' step"
id="gui.howtos.code-cartoon.step_codeCartoonSelectDifferentCharacter2"
/>
),
image: 'codeCartoonSelectDifferentCharacter2'
}, {
title: (
<FormattedMessage
defaultMessage="Jump Up and Down"
description="Step name for 'Jump Up and Down' step"
id="gui.howtos.code-cartoon.step_codeCartoonJump"
/>
),
image: 'codeCartoonJump'
}, {
title: (
<FormattedMessage
defaultMessage="Click a Character to Change Scenes"
description="Step name for 'Click a Character to Change Scenes' step"
id="gui.howtos.code-cartoon.step_codeCartoonChangeScenes"
/>
),
image: 'codeCartoonChangeScenes'
}, {
title: (
<FormattedMessage
defaultMessage="Glide Around"
description="Step name for 'Glide Around' step"
id="gui.howtos.code-cartoon.step_codeCartoonGlideAround"
/>
),
image: 'codeCartoonGlideAround'
}, {
title: (
<FormattedMessage
defaultMessage="Change Costumes"
description="Step name for 'Change Costumes' step"
id="gui.howtos.code-cartoon.step_codeCartoonChangeCostumes"
/>
),
image: 'codeCartoonChangeCostumes'
}, {
title: (
<FormattedMessage
defaultMessage="Choose More Characters to Add to Your Cartoon"
description="Step name for 'Choose More Characters to Add to Your Cartoon' step"
id="gui.howtos.code-cartoon.step_codeCartoonChooseMoreCharacters"
/>
),
image: 'codeCartoonChooseMoreCharacters'
}, {
deckIds: [
'Chase-Game',
'Tell-A-Story'
]
}
],
urlId: 'code-cartoon'
},
'cartoon-network': {
name: (
<FormattedMessage
defaultMessage="Animate an Adventure Game"
description="Animate an Adventure Game' how-to"
id="gui.howtos.cartoon-network"
/>
),
requiredProjectId: '249143200',
img: libraryCartoonNetwork,
steps: [{
video: 'uz5oz5h9yg',
trackingPixel: (
<img src="https://code.org/api/hour/begin_scratch_adventure.png" />
)
}, {
title: (
<FormattedMessage
defaultMessage="Choose a Character to Show"
description="Step name for 'Choose a Character to Show' step"
id="gui.howtos.cartoon-network.step_CNcharacter"
/>
),
image: 'cnShowCharacter'
}, {
title: (
<FormattedMessage
defaultMessage="Say Something"
description="Step name for 'Say Something' step"
id="gui.howtos.cartoon-network.step_CNsay"
/>
),
image: 'cnSay'
}, {
title: (
<FormattedMessage
defaultMessage="Glide Around"
description="Step name for 'Glide Around' step"
id="gui.howtos.cartoon-network.step_CNglide"
/>
),
image: 'cnGlide'
}, {
title: (
<FormattedMessage
defaultMessage=" Choose an Object to Chase "
description="Step name for 'Choose an Object to Chase' step"
id="gui.howtos.cartoon-network.step_CNpicksprite"
/>
),
image: 'cnPickSprite'
}, {
title: (
<FormattedMessage
defaultMessage="Collect Objects"
description="Step name for 'Collect Objects' step"
id="gui.howtos.cartoon-network.step_CNcollect"
/>
),
image: 'cnCollect'
}, {
title: (
<FormattedMessage
defaultMessage="Make a Score Variable"
description="Step name for 'Make a Score Variable' step"
id="gui.howtos.cartoon-network.step_CNvariable"
/>
),
image: 'cnVariable'
}, {
title: (
<FormattedMessage
defaultMessage="Keep Score"
description="Step name for 'Keep Score' step"
id="gui.howtos.cartoon-network.step_CNscore"
/>
),
image: 'cnScore'
}, {
title: (
<FormattedMessage
defaultMessage="Level Up: Change Backdrop"
description="Step name for 'Level Up: Change Backdrop' step"
id="gui.howtos.cartoon-network.step_CNbackdrop"
/>
),
image: 'cnBackdrop'
},
{
video: '6o76f5ivo1'
},
{
deckIds: [
'switch-costume',
'add-effects'
]
}
],
urlId: 'animate-an-adventure-game'
},
'Video-Sensing': {
name: (
<FormattedMessage
defaultMessage="Video Sensing"
description="Name for the 'Video Sensing' how-to"
id="gui.howtos.videosens.name"
/>
),
img: libraryVideoSens,
steps: [{
video: '3pd1z110d6'
},
{
title: (
<FormattedMessage
defaultMessage="Add Extension"
description="Step name for 'Add Extension' step"
id="gui.howtos.videosens.step_addextension"
/>
),
image: 'videoAddExtension'
}, {
title: (
<FormattedMessage
defaultMessage="Pet the Cat"
description="Step name for 'Pet the Cat' step"
id="gui.howtos.videosens.step_pet"
/>
),
image: 'videoPet'
}, {
title: (
<FormattedMessage
defaultMessage="Animate"
description="Step name for 'Animate' step"
id="gui.howtos.videosens.step_animate"
/>
),
image: 'videoAnimate'
}, {
title: (
<FormattedMessage
defaultMessage="Pop a Balloon"
description="Step name for 'Pop a Balloon' step"
id="gui.howtos.videosens.step_pop"
/>
),
image: 'videoPop'
}, {
deckIds: [
'Make-Music',
'add-effects'
]
}
],
urlId: 'video-sensing'
},
'say-it-out-loud': {
name: (
<FormattedMessage
@@ -1183,163 +1470,143 @@ export default {
urlId: 'animations-that-talk'
},
'Video-Sensing': {
'talking': {
name: (
<FormattedMessage
defaultMessage="Video Sensing"
description="Name for the 'Video Sensing' how-to"
id="gui.howtos.videosens.name"
defaultMessage="Talking Tales"
description="Name for the 'Talking Tales' how-to"
id="gui.howtos.talking"
/>
),
img: libraryVideoSens,
tags: ['talking'],
img: libraryTalking,
steps: [{
video: '3pd1z110d6'
},
{
title: (
<FormattedMessage
defaultMessage="Add Extension"
description="Step name for 'Add Extension' step"
id="gui.howtos.videosens.step_addextension"
/>
),
image: 'videoAddExtension'
video: 'talking'
}, {
title: (
<FormattedMessage
defaultMessage="Pet the Cat"
description="Step name for 'Pet the Cat' step"
id="gui.howtos.videosens.step_pet"
defaultMessage="Click to Add the Text-to-Speech Blocks"
description="Step name for 'Click to Add the Text-to-Speech Blocks' step"
id="gui.howtos.talking.step_talesAddExtension"
/>
),
image: 'videoPet'
image: 'talesAddExtension'
}, {
title: (
<FormattedMessage
defaultMessage="Animate"
description="Step name for 'Animate' step"
id="gui.howtos.videosens.step_animate"
defaultMessage="Choose a Sprite"
description="Step name for 'Choose a Sprite' step"
id="gui.howtos.talking.step_talesChooseSprite"
/>
),
image: 'videoAnimate'
image: 'talesChooseSprite'
}, {
title: (
<FormattedMessage
defaultMessage="Pop a Balloon"
description="Step name for 'Pop a Balloon' step"
id="gui.howtos.videosens.step_pop"
defaultMessage="Make a Character Speak"
description="Step name for 'Make a Character Speak' step"
id="gui.howtos.talking.step_talesSaySomething"
/>
),
image: 'videoPop'
image: 'talesSaySomething'
}, {
title: (
<FormattedMessage
defaultMessage="Choose a Backdrop"
description="Step name for 'Choose a Backdrop' step"
id="gui.howtos.talking.step_talesChooseBackdrop"
/>
),
image: 'talesChooseBackdrop'
}, {
title: (
<FormattedMessage
defaultMessage="Click a Character to Go to the Next Backdrop"
description="Step name for 'Click a Character to Go to the Next Backdrop' step"
id="gui.howtos.talking.step_talesSwitchBackdrop"
/>
),
image: 'talesSwitchBackdrop'
}, {
title: (
<FormattedMessage
defaultMessage="Choose Another Sprite"
description="Step name for 'Choose Another Sprite' step"
id="gui.howtos.talking.step_talesChooseAnotherSprite"
/>
),
image: 'talesChooseAnotherSprite'
}, {
title: (
<FormattedMessage
defaultMessage="Move Around"
description="Step name for 'Move Around' step"
id="gui.howtos.talking.step_talesMoveAround"
/>
),
image: 'talesMoveAround'
}, {
title: (
<FormattedMessage
defaultMessage="Choose Another Backdrop"
description="Step name for 'Choose Another Backdrop' step"
id="gui.howtos.talking.step_talesChooseAnotherBackdrop"
/>
),
image: 'talesChooseAnotherBackdrop'
}, {
title: (
<FormattedMessage
defaultMessage="Animate Talking"
description="Step name for 'Animate Talking' step"
id="gui.howtos.talking.step_talesAnimateTalking"
/>
),
image: 'talesAnimateTalking'
}, {
title: (
<FormattedMessage
defaultMessage="Choose Another Backdrop"
description="Step name for 'Choose Another Backdrop' step"
id="gui.howtos.talking.step_talesChooseThirdBackdrop"
/>
),
image: 'talesChooseThirdBackdrop'
}, {
title: (
<FormattedMessage
defaultMessage="Choose a Song to Dance To"
description="Step name for 'Choose a Song to Dance To' step"
id="gui.howtos.talking.step_talesChooseSound"
/>
),
image: 'talesChooseSound'
}, {
title: (
<FormattedMessage
defaultMessage="Dance Moves"
description="Step name for 'Dance Moves' step"
id="gui.howtos.talking.step_talesDanceMoves"
/>
),
image: 'talesDanceMoves'
}, {
title: (
<FormattedMessage
defaultMessage="Get the Ask and Answer Blocks from the Sensing Category"
description="Step name for 'Get the Ask and Answer Blocks from the Sensing Category' step"
id="gui.howtos.talking.step_talesAskAnswer"
/>
),
image: 'talesAskAnswer'
}, {
deckIds: [
'Make-Music',
'add-effects'
'Tell-A-Story',
'Animate-A-Character'
]
}
],
urlId: 'video-sensing'
},
'cartoon-network': {
name: (
<FormattedMessage
defaultMessage="Animate an Adventure Game"
description="Animate an Adventure Game' how-to"
id="gui.howtos.cartoon-network"
/>
),
requiredProjectId: '249143200',
img: libraryCartoonNetwork,
steps: [{
video: 'uz5oz5h9yg',
trackingPixel: (
<img src="https://code.org/api/hour/begin_scratch_adventure.png" />
)
}, {
title: (
<FormattedMessage
defaultMessage="Choose a Character to Show"
description="Step name for 'Choose a Character to Show' step"
id="gui.howtos.cartoon-network.step_CNcharacter"
/>
),
image: 'cnShowCharacter'
}, {
title: (
<FormattedMessage
defaultMessage="Say Something"
description="Step name for 'Say Something' step"
id="gui.howtos.cartoon-network.step_CNsay"
/>
),
image: 'cnSay'
}, {
title: (
<FormattedMessage
defaultMessage="Glide Around"
description="Step name for 'Glide Around' step"
id="gui.howtos.cartoon-network.step_CNglide"
/>
),
image: 'cnGlide'
}, {
title: (
<FormattedMessage
defaultMessage=" Choose an Object to Chase "
description="Step name for 'Choose an Object to Chase' step"
id="gui.howtos.cartoon-network.step_CNpicksprite"
/>
),
image: 'cnPickSprite'
}, {
title: (
<FormattedMessage
defaultMessage="Collect Objects"
description="Step name for 'Collect Objects' step"
id="gui.howtos.cartoon-network.step_CNcollect"
/>
),
image: 'cnCollect'
}, {
title: (
<FormattedMessage
defaultMessage="Make a Score Variable"
description="Step name for 'Make a Score Variable' step"
id="gui.howtos.cartoon-network.step_CNvariable"
/>
),
image: 'cnVariable'
}, {
title: (
<FormattedMessage
defaultMessage="Keep Score"
description="Step name for 'Keep Score' step"
id="gui.howtos.cartoon-network.step_CNscore"
/>
),
image: 'cnScore'
}, {
title: (
<FormattedMessage
defaultMessage="Level Up: Change Backdrop"
description="Step name for 'Level Up: Change Backdrop' step"
id="gui.howtos.cartoon-network.step_CNbackdrop"
/>
),
image: 'cnBackdrop'
},
{
video: '6o76f5ivo1'
},
{
deckIds: [
'switch-costume',
'add-effects'
]
}
],
urlId: 'animate-an-adventure-game'
urlId: 'talking'
},
'add-sprite': {
@@ -1372,7 +1639,7 @@ export default {
],
urlId: 'add-a-sprite'
},
'add-a-backdrop': {
name: (
<FormattedMessage
@@ -1404,7 +1671,7 @@ export default {
}],
urlId: 'add-a-backdrop'
},
'change-size': {
name: (
<FormattedMessage
@@ -1434,7 +1701,7 @@ export default {
}],
urlId: 'change-size'
},
'glide-around': {
name: (
<FormattedMessage
@@ -1539,7 +1806,7 @@ export default {
}],
urlId: 'record-a-sound'
},
'spin-video': {
name: (
<FormattedMessage
@@ -1578,7 +1845,7 @@ export default {
}],
urlId: 'make-it-spin'
},
'hide-and-show': {
name: (
<FormattedMessage
@@ -1677,7 +1944,7 @@ export default {
}],
urlId: 'arrow-keys'
},
'add-effects': {
name: (
<FormattedMessage
@@ -1708,7 +1975,7 @@ export default {
}],
urlId: 'add-effects'
},
'wedo2-getting-started': {
steps: [{
video: '4im7iizv47'
@@ -1716,7 +1983,7 @@ export default {
urlId: 'wedo',
hidden: true
},
'ev3-getting-started': {
steps: [{
video: 'qgu78c5y7d'
@@ -1724,7 +1991,7 @@ export default {
urlId: 'ev3',
hidden: true
},
'whats-new': {
steps: [{
video: 'mtqymxg0qq'
Binary file not shown.

After

Width:  |  Height:  |  Size: 55 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 291 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 47 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 232 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 415 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 44 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 240 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 409 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 913 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 247 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 28 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 69 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 60 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 260 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 95 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 158 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 46 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 72 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 51 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 56 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 54 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 291 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 54 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 43 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 151 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 92 KiB

+20 -14
View File
@@ -9,7 +9,7 @@ const videos = {
'en': 'rpjvs3v9gj',
'it': '2im6c1f9kn',
'pt': 'ngdfp8xg4x',
'pt-BR': 'ngdfp8xg4x',
'pt-br': 'ngdfp8xg4x',
'ja': 'v2c2f3y2sc',
'ja-Hira': 'v2c2f3y2sc'
},
@@ -17,7 +17,7 @@ const videos = {
'en': 'pyur30ho05',
'it': 'c8zcrk6w09',
'pt': 't49tfrukyf',
'pt-BR': 't49tfrukyf',
'pt-br': 't49tfrukyf',
'ja': 'xrmgno02th',
'ja-Hira': 'xrmgno02th'
},
@@ -25,7 +25,7 @@ const videos = {
'en': 'ir0j8ljsgm',
'it': '8nm1v1m9zx',
'pt': '9v4zl8504z',
'pt-BR': '9v4zl8504z',
'pt-br': '9v4zl8504z',
'ja': 'iybhyobckr',
'ja-Hira': 'iybhyobckr'
},
@@ -33,7 +33,7 @@ const videos = {
'en': '5rp47ys13g',
'it': 'vrs1e38944',
'pt': 'rjst5ng61s',
'pt-BR': 'rjst5ng61s',
'pt-br': 'rjst5ng61s',
'ja': 'h4q2ea3ojw',
'ja-Hira': 'h4q2ea3ojw'
},
@@ -41,7 +41,7 @@ const videos = {
'en': 'kusyx9thl5',
'it': '899b2jmjlu',
'pt': 'rw6kr9e37n',
'pt-BR': 'rw6kr9e37n',
'pt-br': 'rw6kr9e37n',
'ja': 'wr6ysk8s6d',
'ja-Hira': 'wr6ysk8s6d'
},
@@ -49,7 +49,7 @@ const videos = {
'en': 'nict6zdzlx',
'it': 'vrrfpm5grh',
'pt': 'wq7sm038pq',
'pt-BR': 'wq7sm038pq',
'pt-br': 'wq7sm038pq',
'ja': 'j382ohngg7',
'ja-Hira': 'j382ohngg7'
},
@@ -57,7 +57,7 @@ const videos = {
'en': 'p8va85hh61',
'it': '1xb1jztsvr',
'pt': '1ad1ip3ly7',
'pt-BR': '1ad1ip3ly7',
'pt-br': '1ad1ip3ly7',
'ja': 'uzkfi9uai0',
'ja-Hira': 'uzkfi9uai0'
},
@@ -71,7 +71,7 @@ const videos = {
'en': 'ulzl1fbzny',
'it': 'ncr9lqk7bt',
'pt': 'aavagpvh5w',
'pt-BR': 'aavagpvh5w',
'pt-br': 'aavagpvh5w',
'ja': '5zmy6u614k',
'ja-Hira': '5zmy6u614k'
},
@@ -79,7 +79,7 @@ const videos = {
'en': '07fed5hhpv',
'it': 'obmrphhobt',
'pt': 'jxqksu6zcw',
'pt-BR': 'jxqksu6zcw',
'pt-br': 'jxqksu6zcw',
'ja': 'hjhc0a8r7j',
'ja-Hira': 'hjhc0a8r7j'
},
@@ -87,7 +87,7 @@ const videos = {
'en': 'g479ahobo9',
'it': 'v0vbx3l5uk',
'pt': 'ibtmwb58y8',
'pt-BR': 'ibtmwb58y8',
'pt-br': 'ibtmwb58y8',
'ja': 'ruynguvag5',
'ja-Hira': 'ruynguvag5'
},
@@ -95,7 +95,7 @@ const videos = {
'en': '1ocp6a1ejn',
'it': 'nty4xjtqcj',
'pt': 'pnlmmv2hs7',
'pt-BR': 'pnlmmv2hs7',
'pt-br': 'pnlmmv2hs7',
'ja': 'g3vluv0ms8',
'ja-Hira': 'g3vluv0ms8'
},
@@ -103,7 +103,7 @@ const videos = {
'en': 'yetrmk4iuu',
'it': 'jse0g0uddw',
'pt': 'erv6eff78p',
'pt-BR': 'erv6eff78p',
'pt-br': 'erv6eff78p',
'ja': 'fk34dcg5oz',
'ja-Hira': 'fk34dcg5oz'
},
@@ -111,7 +111,7 @@ const videos = {
'en': '3jvl8zgjo2',
'it': 'q3cjjyfju9',
'pt': 'dz6jzpf7hm',
'pt-BR': 'dz6jzpf7hm',
'pt-br': 'dz6jzpf7hm',
'ja': 'q7zq9vu0wb',
'ja-Hira': 'q7zq9vu0wb'
},
@@ -121,8 +121,14 @@ const videos = {
'pong-game': {
en: '8m48dv0ens'
},
'imagine-if': {
'imagine': {
en: '1ndh08yiso'
},
'code-cartoon': {
en: 'fpfuky3x6g'
},
'talking': {
en: 'j0208mq4qi'
}
};
+5 -5
View File
@@ -3845,7 +3845,7 @@
{
"costumeName": "dinosaur1-c",
"baseLayerID": -1,
"baseLayerMD5": "a2bb28d5ba55ba997bec63772437cecf.svg",
"baseLayerMD5": "78f7e20f0e187fdca81195e4cc134175.svg",
"bitmapResolution": 1,
"rotationCenterX": 81,
"rotationCenterY": 91
@@ -15612,7 +15612,7 @@
},
{
"name": "Watermelon",
"md5": "26fecef75cf3b6e0d98bff5c06475036.svg",
"md5": "8736ecc2524895733534c888cd91fa1f.svg",
"type": "sprite",
"tags": [
"food",
@@ -15643,7 +15643,7 @@
{
"costumeName": "watermelon-a",
"baseLayerID": -1,
"baseLayerMD5": "26fecef75cf3b6e0d98bff5c06475036.svg",
"baseLayerMD5": "8736ecc2524895733534c888cd91fa1f.svg",
"bitmapResolution": 1,
"rotationCenterX": 40,
"rotationCenterY": 27
@@ -15651,7 +15651,7 @@
{
"costumeName": "watermelon-b",
"baseLayerID": -1,
"baseLayerMD5": "fbdaf4d1d349edd3ddf3a1c4528aa9ec.svg",
"baseLayerMD5": "1ed1c8b78eae2ee7422074d7f883031d.svg",
"bitmapResolution": 1,
"rotationCenterX": 22,
"rotationCenterY": 27
@@ -15659,7 +15659,7 @@
{
"costumeName": "watermelon-c",
"baseLayerID": -1,
"baseLayerMD5": "5976c10412306fc093c1d1930fa05119.svg",
"baseLayerMD5": "677738282686d2dcce35d731c3ddc043.svg",
"bitmapResolution": 1,
"rotationCenterX": 21,
"rotationCenterY": 15
+77 -16
View File
@@ -1,5 +1,18 @@
import PropTypes from 'prop-types';
import React from 'react';
import bindAll from 'lodash.bindall';
import {connect} from 'react-redux';
import {defineMessages, injectIntl, intlShape} from 'react-intl';
import {getIsShowingWithoutId} from '../reducers/project-state';
import {setProjectTitle} from '../reducers/project-title';
const messages = defineMessages({
defaultProjectTitle: {
id: 'gui.gui.defaultProjectTitle',
description: 'Default title for project',
defaultMessage: 'Scratch Project'
}
});
/* Higher Order Component to get and set the project title
* @param {React.Component} WrappedComponent component to receive project title related props
@@ -7,31 +20,79 @@ import bindAll from 'lodash.bindall';
*/
const TitledHOC = function (WrappedComponent) {
class TitledComponent extends React.Component {
constructor (props) {
super(props);
bindAll(this, [
'handleUpdateProjectTitle'
]);
this.state = {
projectTitle: null
};
componentDidMount () {
this.handleReceivedProjectTitle(this.props.projectTitle);
}
handleUpdateProjectTitle (newTitle) {
this.setState({projectTitle: newTitle});
componentDidUpdate (prevProps) {
if (this.props.projectTitle !== prevProps.projectTitle) {
this.handleReceivedProjectTitle(this.props.projectTitle);
}
// if the projectTitle hasn't changed, but the reduxProjectTitle
// HAS changed, we need to report that change to the projectTitle's owner
if (this.props.reduxProjectTitle !== prevProps.reduxProjectTitle &&
this.props.reduxProjectTitle !== this.props.projectTitle) {
this.props.onUpdateProjectTitle(this.props.reduxProjectTitle);
}
}
handleReceivedProjectTitle (requestedTitle) {
let newTitle = requestedTitle;
if (newTitle === null || typeof newTitle === 'undefined') {
newTitle = this.props.intl.formatMessage(messages.defaultProjectTitle);
}
this.props.onChangedProjectTitle(newTitle);
}
render () {
const {
/* eslint-disable no-unused-vars */
intl,
isShowingWithoutId,
onChangedProjectTitle,
// for children, we replace onUpdateProjectTitle with our own
onUpdateProjectTitle,
// we don't pass projectTitle prop to children -- they must use
// redux value
projectTitle,
reduxProjectTitle,
/* eslint-enable no-unused-vars */
...componentProps
} = this.props;
return (
<WrappedComponent
canEditTitle
projectTitle={this.state.projectTitle}
onUpdateProjectTitle={this.handleUpdateProjectTitle}
{...this.props}
{...componentProps}
/>
);
}
}
return TitledComponent;
TitledComponent.propTypes = {
intl: intlShape,
isShowingWithoutId: PropTypes.bool,
onChangedProjectTitle: PropTypes.func,
onUpdateProjectTitle: PropTypes.func,
projectTitle: PropTypes.string,
reduxProjectTitle: PropTypes.string
};
TitledComponent.defaultProps = {
onUpdateProjectTitle: () => {}
};
const mapStateToProps = state => {
const loadingState = state.scratchGui.projectState.loadingState;
return {
isShowingWithoutId: getIsShowingWithoutId(loadingState),
reduxProjectTitle: state.scratchGui.projectTitle
};
};
const mapDispatchToProps = dispatch => ({
onChangedProjectTitle: title => dispatch(setProjectTitle(title))
});
return injectIntl(connect(
mapStateToProps,
mapDispatchToProps,
)(TitledComponent));
};
export {
+4 -4
View File
@@ -87,9 +87,9 @@ const vmListenerHOC = function (WrappedComponent) {
// Don't capture keys intended for Blockly inputs.
if (e.target !== document && e.target !== document.body) return;
const key = (!e.key || e.key === 'Dead') ? e.keyCode : e.key;
this.props.vm.postIOData('keyboard', {
keyCode: e.keyCode,
key: e.key,
key: key,
isDown: true
});
@@ -102,9 +102,9 @@ const vmListenerHOC = function (WrappedComponent) {
handleKeyUp (e) {
// Always capture up events,
// even those that have switched to other targets.
const key = (!e.key || e.key === 'Dead') ? e.keyCode : e.key;
this.props.vm.postIOData('keyboard', {
keyCode: e.keyCode,
key: e.key,
key: key,
isDown: false
});
+2 -3
View File
@@ -9,7 +9,6 @@ import Box from '../components/box/box.jsx';
import GUI from '../containers/gui.jsx';
import HashParserHOC from '../lib/hash-parser-hoc.jsx';
import AppStateHOC from '../lib/app-state-hoc.jsx';
import TitledHOC from '../lib/titled-hoc.jsx';
import {setPlayer} from '../reducers/mode';
@@ -24,6 +23,7 @@ const Player = ({isPlayerOnly, onSeeInside, projectId}) => (
<Box className={classNames(isPlayerOnly ? styles.stageOnly : styles.editor)}>
{isPlayerOnly && <button onClick={onSeeInside}>{'See inside'}</button>}
<GUI
canEditTitle
enableCommunity
isPlayerOnly={isPlayerOnly}
projectId={projectId}
@@ -55,8 +55,7 @@ const ConnectedPlayer = connect(
// ability to compose reducers.
const WrappedPlayer = compose(
AppStateHOC,
HashParserHOC,
TitledHOC
HashParserHOC
)(ConnectedPlayer);
const appTarget = document.createElement('div');
+3 -3
View File
@@ -5,7 +5,6 @@ import {compose} from 'redux';
import AppStateHOC from '../lib/app-state-hoc.jsx';
import GUI from '../containers/gui.jsx';
import HashParserHOC from '../lib/hash-parser-hoc.jsx';
import TitledHOC from '../lib/titled-hoc.jsx';
import log from '../lib/log.js';
const onClickLogo = () => {
@@ -37,8 +36,7 @@ export default appTarget => {
// ability to compose reducers.
const WrappedGui = compose(
AppStateHOC,
HashParserHOC,
TitledHOC
HashParserHOC
)(GUI);
// TODO a hack for testing the backpack, allow backpack host to be set by url param
@@ -67,6 +65,7 @@ export default appTarget => {
// important: this is checking whether `simulateScratchDesktop` is truthy, not just defined!
simulateScratchDesktop ?
<WrappedGui
canEditTitle
isScratchDesktop
showTelemetryModal
canSave={false}
@@ -75,6 +74,7 @@ export default appTarget => {
onTelemetryModalOptOut={handleTelemetryModalOptOut}
/> :
<WrappedGui
canEditTitle
backpackVisible
showComingSoon
backpackHost={backpackHost}
+4
View File
@@ -57,6 +57,10 @@ class SeleniumHelper {
// Stub getUserMedia to always not allow access
args.push('--use-fake-ui-for-media-stream=deny');
// Suppress complaints about AudioContext starting before a user gesture
// This is especially important on Windows, where Selenium directs JS console messages to stdout
args.push('--autoplay-policy=no-user-gesture-required');
chromeCapabilities.set('chromeOptions', {args});
chromeCapabilities.setLoggingPrefs({
performance: 'ALL'
+13 -14
View File
@@ -182,7 +182,8 @@ describe('Working with the blocks', () => {
// Rename the costume
await clickText('Costumes');
const el = await findByXpath("//input[@value='costume1']");
await clickText('costume2', scope.costumesTab);
const el = await findByXpath("//input[@value='costume2']");
await el.sendKeys('newname');
// Make sure it is updated in the block menu
@@ -197,7 +198,8 @@ describe('Working with the blocks', () => {
// Rename the costume
await clickText('Costumes');
const el = await findByXpath("//input[@value='costume1']");
await clickText('costume2', scope.costumesTab);
const el = await findByXpath("//input[@value='costume2']");
await el.sendKeys('<NewCostume>');
// Make sure it is updated in the block menu
@@ -209,17 +211,15 @@ describe('Working with the blocks', () => {
await clickText('Sound', scope.blocksTab);
});
// NOTE: This test describes the current behavior so that changes are not
// introduced inadvertly, but I know this is not the desired behavior
test('Adding costumes DOES NOT update the default costume name in the toolbox', async () => {
test('Adding costumes DOES update the default costume name in the toolbox', async () => {
await loadUri(uri);
// By default, costume1 is in the costume tab
// By default, costume2 is in the costume tab
await clickText('Looks', scope.blocksTab);
await driver.sleep(500); // Wait for scroll to finish
await clickText('costume1', scope.blocksTab);
await clickText('costume2', scope.blocksTab);
// Also check that adding a new costume does not update the list
// Also check that adding a new costume does update the list
await clickText('Costumes');
const el = await findByXpath('//button[@aria-label="Choose a Costume"]');
await driver.actions().mouseMove(el)
@@ -227,14 +227,13 @@ describe('Working with the blocks', () => {
await driver.sleep(500); // Wait for thermometer menu to come up
await clickXpath('//button[@aria-label="Paint"]');
await clickText('costume3', scope.costumesTab);
// Check that the menu has not been updated
// Check that the menu has been updated
await clickText('Code');
await clickText('costume1', scope.blocksTab);
await clickText('costume3', scope.blocksTab);
});
// NOTE: This test describes the current behavior so that changes are not
// introduced inadvertly, but I know this is not the desired behavior
test('Adding a sound DOES NOT update the default sound name in the toolbox', async () => {
// Skipped because it was flakey on travis, but seems to run locally ok
test.skip('Adding a sound DOES update the default sound name in the toolbox', async () => {
await loadUri(uri);
await clickText('Sounds');
await clickXpath('//button[@aria-label="Choose a Sound"]');
@@ -242,7 +241,7 @@ describe('Working with the blocks', () => {
await clickText('Code');
await clickText('Sound', scope.blocksTab);
await driver.sleep(500); // Wait for scroll to finish
await clickText('Meow', scope.blocksTab); // Meow, not A Bass
await clickText('A\u00A0Bass', scope.blocksTab); // Need &nbsp; for block text
});
// Regression test for switching between editor/player causing toolbox to stop updating
+1 -5
View File
@@ -193,11 +193,7 @@ describe('Working with costumes', () => {
.mouseMove(abbyElement)
.perform();
// wait for one of Abby's alternate costumes to appear
const src1 = await abbyElement.findElement({css: 'img'}).getAttribute('src');
await driver.sleep(300);
const src2 = await abbyElement.findElement({css: 'img'}).getAttribute('src');
const sourcesMatch = (src1 === src2);
await expect(sourcesMatch).toBeFalsy(); // 'src' attribute should have changed by now
await findByXpath('//img[@src="https://cdn.assets.scratch.mit.edu/internalapi/asset/b6e23922f23b49ddc6f62f675e77417c.svg/get/"]');
const logs = await getLogs();
await expect(logs).toEqual([]);
});
@@ -11,7 +11,6 @@ describe('SBFileUploader Container', () => {
const mockStore = configureStore();
let onLoadingFinished;
let onLoadingStarted;
let onUpdateProjectTitle;
let store;
// Wrap this in a function so it gets test specific states and can be reused.
@@ -20,7 +19,6 @@ describe('SBFileUploader Container', () => {
<SBFileUploader
onLoadingFinished={onLoadingFinished}
onLoadingStarted={onLoadingStarted}
onUpdateProjectTitle={onUpdateProjectTitle}
>
{(renderFileInput, loadProject) => (
<div
@@ -40,7 +38,6 @@ describe('SBFileUploader Container', () => {
vm: {}
}
});
onUpdateProjectTitle = jest.fn();
onLoadingFinished = jest.fn();
onLoadingStarted = jest.fn();
});
+45
View File
@@ -133,4 +133,49 @@ describe('VMListenerHOC', () => {
const actions = store.getActions();
expect(actions.length).toEqual(0);
});
test('keypresses go to the vm', () => {
const Component = () => (<div />);
const WrappedComponent = vmListenerHOC(Component);
// Mock document.addEventListener so we can trigger keypresses manually
// Cannot use the enzyme simulate method because that only works on synthetic events
const eventTriggers = {};
document.addEventListener = jest.fn((event, cb) => {
eventTriggers[event] = cb;
});
vm.postIOData = jest.fn();
store = mockStore({
scratchGui: {
mode: {isFullScreen: true},
modals: {soundRecorder: true},
vm: vm
}
});
mount(
<WrappedComponent
attachKeyboardEvents
store={store}
vm={vm}
/>
);
// keyboard events that do not target the document or body are ignored
eventTriggers.keydown({key: 'A', target: null});
expect(vm.postIOData).not.toHaveBeenLastCalledWith('keyboard', {key: 'A', isDown: true});
// keydown/up with target as the document are sent to the vm via postIOData
eventTriggers.keydown({key: 'A', target: document});
expect(vm.postIOData).toHaveBeenLastCalledWith('keyboard', {key: 'A', isDown: true});
eventTriggers.keyup({key: 'A', target: document});
expect(vm.postIOData).toHaveBeenLastCalledWith('keyboard', {key: 'A', isDown: false});
// When key is 'Dead' e.g. bluetooth keyboards on iOS, it sends keyCode instead
// because the VM can process both named keys or keyCodes as the `key` property
eventTriggers.keyup({key: 'Dead', keyCode: 10, target: document});
expect(vm.postIOData).toHaveBeenLastCalledWith('keyboard', {key: 10, isDown: false});
});
});
+6
View File
@@ -219,6 +219,12 @@ module.exports = [
new CopyWebpackPlugin([{
from: 'extension-worker.{js,js.map}',
context: 'node_modules/scratch-vm/dist/web'
}]),
// Include library JSON files for scratch-desktop to use for downloading
new CopyWebpackPlugin([{
from: 'src/lib/libraries/*.json',
to: 'libraries',
flatten: true
}])
])
})) : []