Compare commits

...
Author SHA1 Message Date
Paul Kaplan 1a588880bf Merge pull request #4901 from paulkaplan/no-videos-on-desktop
Use a "title card" instead of video if using Scratch Desktop
2019-06-05 16:10:16 -04:00
Paul Kaplan e2c2392a70 Only show items in the library that would have image steps for offline
Because the video steps get replaced by an image step if offline, we should not show items that would result in having no content
2019-06-05 15:09:28 -04:00
Paul Kaplan 5160b5ae22 Make the cards images all the same size, and shrink to fit centered 2019-06-05 15:08:32 -04:00
Karishma Chadha 8be847b68a Merge pull request #4904 from LLK/kchadha-update-render
Update scratch-render
2019-06-05 14:51:29 -04:00
Karishma Chadha e7ed24f1ef Update scratch-render 2019-06-05 14:50:57 -04:00
Paul Kaplan 13e324b52d Use title card instead of video if using scratchDesktop flag 2019-06-05 12:53:32 -04:00
Karishma Chadha 5c7b221799 Merge pull request #4900 from LLK/kchadha-update-deps
Update scratch-vm and scratch-l10n.
2019-06-05 11:51:25 -04:00
Karishma Chadha 7398a30223 Update scratch-vm and scratch-l10n. 2019-06-05 11:34:33 -04:00
Paul Kaplan 637b9fd225 Merge pull request #4832 from paulkaplan/do-not-select-stage
Make surprise and library backdrop additions NOT select the stage
2019-06-05 10:45:34 -04:00
Benjamin Wheeler 88442708c2 Merge pull request #4883 from benjiwheeler/fix-project-loading-tests
fixed project loading tests
2019-06-05 10:35:26 -04:00
Paul Kaplan d7759317c4 Merge pull request #4896 from LLK/greenkeeper/scratch-vm-0.2.0-prerelease.20190604153446
chore(package): update scratch-vm to version 0.2.0-prerelease.2019060…
2019-06-04 14:10:38 -04:00
Ben Wheeler fd3045eb9d also turn off examples tests that load remote project 2019-06-04 11:40:03 -04:00
greenkeeper[bot] 09ae22f329 chore(package): update scratch-vm to version 0.2.0-prerelease.20190604153446
Closes #4894
2019-06-04 15:37:41 +00:00
Benjamin Wheeler 365e3b3bce Merge pull request #4881 from LLK/revert-4877-revert-4835-bugfix/4766
Revert "Revert "Pause video on tutorial window shrink""
2019-06-03 16:16:01 -04:00
Evelyn Eastmond 550849c93f Reset video if a new one has been chosen. Added some comments. 2019-05-30 22:03:56 -04:00
Ben Wheeler 8128902cd6 fixed project loading test 2019-05-30 18:52:33 -04:00
Evelyn Eastmond b350049ca7 Testing a commit onto upstream branch for revert PR. 2019-05-30 17:17:01 -04:00
Evelyn Eastmond e0e07929e8 Revert "Revert "Pause video on tutorial window shrink"" 2019-05-30 17:10:58 -04:00
Benjamin Wheeler 128b196220 Merge pull request #4878 from LLK/greenkeeper/scratch-render-0.1.0-prerelease.20190530160621
Update scratch-render to the latest version 🚀
2019-05-30 12:23:54 -04:00
greenkeeper[bot] 5b806dff27 chore(package): update scratch-render to version 0.1.0-prerelease.20190530160621 2019-05-30 16:13:40 +00:00
Benjamin Wheeler 9c5d358c3e Merge pull request #4877 from LLK/revert-4835-bugfix/4766
Revert "Pause video on tutorial window shrink"
2019-05-30 12:01:22 -04:00
Benjamin Wheeler ab89ee1a4f Revert "Pause video on tutorial window shrink" 2019-05-30 11:59:45 -04:00
Paul Kaplan dc82e5f653 Merge pull request #4873 from LLK/revert-4800-delay-gui
Revert "Delay loading and rendering gui"
2019-05-30 11:35:57 -04:00
Paul Kaplan 7fb3a81a66 Merge pull request #4874 from LLK/revert-4677-update-toolbox
Revert "render only new toolbox xmls"
2019-05-30 11:31:30 -04:00
Paul Kaplan d958b14b8d Revert "render only new toolbox xmls" 2019-05-30 10:50:41 -04:00
Paul Kaplan 0a6c75eb93 Revert "Delay loading and rendering gui" 2019-05-30 09:41:05 -04:00
Colby Gutierrez-Kraybill 7c5a4fc682 Merge pull request #4870 from LLK/greenkeeper/scratch-vm-0.2.0-prerelease.20190524155459
chore(package): update scratch-vm to version 0.2.0-prerelease.2019052…
2019-05-29 15:46:39 -04:00
Bryce Taylor ca8caa8504 Merge pull request #4871 from BryceLTaylor/Stabilize-Integration-Tests
Stabilize integration tests
2019-05-29 15:40:02 -04:00
Benjamin Wheeler 339dfe0b08 Merge pull request #4846 from paulkaplan/update-builtin-assets
Update the built-in SVG assets for the default project
2019-05-29 15:11:15 -04:00
BryceLTaylor b9cefd325b Remove unused reference to findByText in integration tests 2019-05-29 14:45:57 -04:00
BryceLTaylor fa974c68bd Remove WaitUntilGone function from integration tests
These were causing the tests to fail and should be fixed by the update to FindByXpath function.
2019-05-29 14:23:50 -04:00
BryceLTaylor 3c47e0e040 Make Find by Xpath ensure element is visible in integration tests 2019-05-29 14:23:50 -04:00
Colby Gutierrez-Kraybill 34a9a97201 Merge pull request #4868 from LLK/greenkeeper/scratch-l10n-3.3.20190529144051
Update scratch-l10n to the latest version 🚀
2019-05-29 13:23:10 -04:00
Colby Gutierrez-Kraybill f6847e3aea Merge branch 'develop' into greenkeeper/scratch-l10n-3.3.20190529144051 2019-05-29 13:08:47 -04:00
Evelyn Eastmond e27021cbf4 Merge pull request #4835 from evhan55/bugfix/4766
Pause video on tutorial window shrink
2019-05-29 12:39:50 -04:00
Colby Gutierrez-Kraybill 3dc6413ea4 Merge pull request #4867 from LLK/greenkeeper/scratch-blocks-0.1.0-prerelease.1559136797
Update scratch-blocks to the latest version 🚀
2019-05-29 11:38:53 -04:00
greenkeeper[bot] 53c04a1ad9 chore(package): update scratch-l10n to version 3.3.20190529144051 2019-05-29 14:45:06 +00:00
Evelyn Eastmond b2486380fb Disable dragging on video to allow for scrobbling. 2019-05-29 09:46:08 -04:00
greenkeeper[bot] 9f41ddaaa2 chore(package): update scratch-blocks to version 0.1.0-prerelease.1559136797 2019-05-29 13:35:43 +00:00
Paul Kaplan ef4d8c6e8d Merge pull request #4852 from LLK/greenkeeper/scratch-blocks-0.1.0-prerelease.1558719162
Update scratch-blocks to the latest version 🚀
2019-05-29 08:34:07 -04:00
Paul Kaplan a6245b87f6 Merge pull request #4866 from LLK/greenkeeper/scratch-render-0.1.0-prerelease.20190528231524
chore(package): update scratch-render to version 0.1.0-prerelease.201…
2019-05-29 08:33:43 -04:00
Evelyn Eastmond fa4541e85c Adding dynamic removal of dynamically loaded scripts. 2019-05-29 08:27:20 -04:00
Evelyn Eastmond 376f5626a4 Remove auto-play on expansion. 2019-05-28 20:34:14 -04:00
Evelyn Eastmond e17dc90983 Fix Wistia access to use window. 2019-05-28 20:34:14 -04:00
Evelyn Eastmond a63385343a Remove useless props constructor. 2019-05-28 20:34:14 -04:00
Evelyn Eastmond 3c3206d8e2 Remove bindAll import. 2019-05-28 20:34:14 -04:00
Evelyn Eastmond f6c8feae6e Video play/pause test on video step expand/shrink. 2019-05-28 20:34:14 -04:00
Evelyn Eastmond 98a007a17e Pause video on component update if not expanded. 2019-05-28 20:34:14 -04:00
Evelyn Eastmond 3e0d5b9ede Clean up and get handle on video on load. 2019-05-28 20:34:14 -04:00
Evelyn Eastmond 555082bb1d Change Wistia embed so video API is accessible from current window. 2019-05-28 20:34:14 -04:00
Evelyn Eastmond 5c95c352c3 Trying VideoStep component. 2019-05-28 20:34:14 -04:00
greenkeeper[bot] 3b4758ca5c chore(package): update scratch-render to version 0.1.0-prerelease.20190528231524
Closes #4864
2019-05-28 23:16:58 +00:00
Chris Willis-Ford 699671bde5 Merge pull request #4841 from cwillisf/test-failure-feedback
add timeouts & messages to all driver.wait calls
2019-05-28 09:43:39 -07:00
Paul Kaplan 7facbf35b2 Merge pull request #4851 from LLK/greenkeeper/scratch-paint-0.2.0-prerelease.20190524133325
Update scratch-paint to the latest version 🚀
2019-05-24 13:38:31 -04:00
greenkeeper[bot] b54fe54b4a chore(package): update scratch-blocks to version 0.1.0-prerelease.1558719162 2019-05-24 17:35:05 +00:00
Christopher Willis-Ford 796339dcfe simplify SeleniumHelper timeout options 2019-05-24 09:35:44 -07:00
greenkeeper[bot] 1721a322c2 chore(package): update scratch-vm to version 0.2.0-prerelease.20190524155459
Closes #4840
2019-05-24 15:57:43 +00:00
greenkeeper[bot] 3125097b83 chore(package): update scratch-paint to version 0.2.0-prerelease.20190524133325 2019-05-24 13:34:51 +00:00
Paul Kaplan aa0c40fca1 Merge pull request #4850 from LLK/greenkeeper/scratch-render-0.1.0-prerelease.20190524125950
Update scratch-render to the latest version 🚀
2019-05-24 09:26:53 -04:00
Paul Kaplan 2d61027bbe Merge pull request #4848 from LLK/greenkeeper/scratch-svg-renderer-0.2.0-prerelease.20190523193400
Update scratch-svg-renderer to the latest version 🚀
2019-05-24 09:26:33 -04:00
greenkeeper[bot] 2dac3cae81 chore(package): update scratch-render to version 0.1.0-prerelease.20190524125950 2019-05-24 13:02:23 +00:00
greenkeeper[bot] 43d3df2ffd chore(package): update scratch-svg-renderer to version 0.2.0-prerelease.20190523193400 2019-05-23 19:38:15 +00:00
Paul Kaplan 44ffaeee2c Merge pull request #4847 from LLK/greenkeeper/scratch-paint-0.2.0-prerelease.20190523183140
Update scratch-paint to the latest version 🚀
2019-05-23 15:33:33 -04:00
greenkeeper[bot] 0bf4e2c781 chore(package): update scratch-paint to version 0.2.0-prerelease.20190523183140 2019-05-23 18:56:29 +00:00
Paul Kaplan d342b82219 Merge pull request #4800 from mzgoddard/delay-gui
Delay loading and rendering gui
2019-05-23 14:14:37 -04:00
Paul Kaplan 227581ebcf Merge pull request #4677 from mzgoddard/update-toolbox
render only new toolbox xmls
2019-05-23 14:14:09 -04:00
Paul Kaplan eb74d6c033 Include a unit test to ensure default project assets are included 2019-05-23 11:22:36 -04:00
Paul Kaplan a2035a68e4 Update the built-in SVG assets for the default project 2019-05-23 09:59:41 -04:00
Christopher Willis-Ford 1b055af545 add timeouts & messages to all driver.wait calls 2019-05-22 18:25:45 -07:00
Karishma Chadha 5b79947178 Merge pull request #4842 from LLK/greenkeeper/scratch-paint-0.2.0-prerelease.20190522213620
Update scratch-paint to the latest version 🚀
2019-05-22 17:40:57 -04:00
Karishma Chadha 9e329b999e Merge branch 'develop' into greenkeeper/scratch-paint-0.2.0-prerelease.20190522213620 2019-05-22 17:40:44 -04:00
Karishma Chadha e5e0c3dd28 Merge pull request #4843 from LLK/greenkeeper/scratch-render-0.1.0-prerelease.20190522213558
Update scratch-render to the latest version 🚀
2019-05-22 17:39:51 -04:00
greenkeeper[bot] e810422429 chore(package): update scratch-render to version 0.1.0-prerelease.20190522213558 2019-05-22 21:38:44 +00:00
greenkeeper[bot] 8b2c590309 chore(package): update scratch-paint to version 0.2.0-prerelease.20190522213620 2019-05-22 21:38:30 +00:00
Benjamin Wheeler d92ef0c807 Merge pull request #4833 from LLK/greenkeeper/scratch-storage-1.3.2
Update scratch-storage to the latest version 🚀
2019-05-22 14:42:44 -04:00
Benjamin Wheeler faa14b7add Merge branch 'develop' into greenkeeper/scratch-storage-1.3.2 2019-05-22 14:42:11 -04:00
Benjamin Wheeler abbc8ddad0 Merge pull request #4837 from LLK/greenkeeper/scratch-l10n-3.3.20190522144128
Update scratch-l10n to the latest version 🚀
2019-05-22 14:41:02 -04:00
Benjamin Wheeler 551e03b256 Merge pull request #4822 from LLK/greenkeeper/react-intl-2.9.0
Update react-intl to the latest version 🚀
2019-05-22 14:30:36 -04:00
Paul Kaplan f65f80160f Merge pull request #4834 from LLK/greenkeeper/scratch-svg-renderer-0.2.0-prerelease.20190521170426
Update scratch-svg-renderer to the latest version 🚀
2019-05-22 14:05:17 -04:00
Paul Kaplan 5438c14bdb Merge branch 'develop' into greenkeeper/scratch-svg-renderer-0.2.0-prerelease.20190521170426 2019-05-22 14:04:51 -04:00
Paul Kaplan 8f3d84ec60 Merge pull request #4830 from LLK/greenkeeper/scratch-vm-0.2.0-prerelease.20190520172914
Update scratch-vm to the latest version 🚀
2019-05-22 13:55:03 -04:00
greenkeeper[bot] c3df930bea chore(package): update scratch-l10n to version 3.3.20190522144128 2019-05-22 14:43:31 +00:00
greenkeeper[bot] 4513a45306 chore(package): update scratch-svg-renderer to version 0.2.0-prerelease.20190521170426 2019-05-21 17:06:21 +00:00
greenkeeper[bot] a94a83dc4f chore(package): update scratch-storage to version 1.3.2 2019-05-21 16:06:05 +00:00
Eric Rosenbaum e1e5c8352c Merge pull request #4806 from ericrosenbaum/bugfix/no-surprise-letters
Surprise sprite button does not give you letters
2019-05-21 11:55:00 -04:00
Paul Kaplan 98ceb00bb4 Fix lint 2019-05-21 11:01:48 -04:00
Paul Kaplan 77974839b0 Make surprise and library backdrop additions NOT select the stage 2019-05-21 10:46:05 -04:00
greenkeeper[bot] 706341011a chore(package): update scratch-vm to version 0.2.0-prerelease.20190520172914 2019-05-20 17:32:00 +00:00
chrisgarrity 4a26810956 Merge pull request #4825 from LLK/greenkeeper/scratch-paint-0.2.0-prerelease.20190516171147
Update scratch-paint to the latest version 🚀
2019-05-16 13:14:51 -04:00
greenkeeper[bot] 92fd318aa8 chore(package): update scratch-paint to version 0.2.0-prerelease.20190516171147 2019-05-16 17:13:17 +00:00
chrisgarrity bc2555ddc4 Merge pull request #4824 from LLK/greenkeeper/scratch-l10n-3.3.20190516144548
Update scratch-l10n to the latest version 🚀
2019-05-16 10:56:28 -04:00
greenkeeper[bot] 8ee9794304 chore(package): update scratch-l10n to version 3.3.20190516144548 2019-05-16 14:48:58 +00:00
picklesrus 30388ffa4f Merge pull request #4819 from LLK/greenkeeper/scratch-l10n-3.3.20190515143901
Update scratch-l10n to the latest version 🚀
2019-05-15 15:33:14 -04:00
greenkeeper[bot] fdea0a1620 chore(package): update react-intl to version 2.9.0 2019-05-15 18:01:27 +00:00
picklesrus 41e2909782 Merge pull request #4821 from LLK/greenkeeper/scratch-vm-0.2.0-prerelease.20190515153227
chore(package): update scratch-vm to version 0.2.0-prerelease.2019051…
2019-05-15 13:16:09 -04:00
greenkeeper[bot] 4048ed8c84 chore(package): update scratch-vm to version 0.2.0-prerelease.20190515153227
Closes #4804
2019-05-15 15:36:48 +00:00
greenkeeper[bot] 7a21b17d0c chore(package): update scratch-l10n to version 3.3.20190515143901 2019-05-15 14:41:54 +00:00
chrisgarrity 72bc6f3005 Merge pull request #4816 from chrisgarrity/add-rap-uz
Update dependencies for Rapa Nui and Uzbek
2019-05-15 08:05:33 -04:00
Chris Garrity a8a7e0c92f Update dependencies for Rapa Nui 2019-05-14 18:18:43 -04:00
Eric Rosenbaum a11fcfe373 Fix typo in variable name 2019-05-09 15:12:13 -04:00
Eric Rosenbaum 52a3600819 Surprise sprites do not include letters and numbers 2019-05-09 15:06:26 -04:00
Michael "Z" Goddard bec6223e6e delay loading and rendering gui
- Create the scratch renderer earlier in the GUI container/HOC stack
- Delay loading and rendering GUI component until after project assets
  have been fetched
2019-05-08 16:58:07 -04:00
Paul Kaplan 333b91ccfd Merge pull request #4802 from LLK/greenkeeper/scratch-l10n-3.2.20190508143856
Update scratch-l10n to the latest version 🚀
2019-05-08 14:27:43 -04:00
greenkeeper[bot] a3266fe641 chore(package): update scratch-l10n to version 3.2.20190508143856 2019-05-08 14:53:25 +00:00
Evelyn Eastmond 10449a21b5 Merge pull request #4801 from evhan55/bugfix/4799
Enable pointer events for workspace while tutorial is showing
2019-05-08 08:38:20 -04:00
Evelyn Eastmond 29f5d2a872 Fixing pointer events to not prevent clicks in workspace. 2019-05-07 15:43:35 -04:00
Evelyn Eastmond f8b3e4961c Merge pull request #4731 from evhan55/feature/4670
Add shrink/expand and new fencing feature to tutorial cards
2019-05-07 12:53:02 -04:00
Evelyn Eastmond cca701e954 Add more layout for RTL. 2019-05-07 11:52:27 -04:00
Evelyn Eastmond 89c0807cba Reset position and expanded state of cards on activation. 2019-05-07 11:42:40 -04:00
Evelyn Eastmond 544a4c745d Change drag offset var names. 2019-05-07 11:42:40 -04:00
Evelyn Eastmond f6e9a7dd23 Remove console log from reducer, fix variable and comments in component. 2019-05-07 11:42:40 -04:00
Evelyn Eastmond 69132b6f43 Add variables for calculation of custom dragging bounds. 2019-05-07 11:42:40 -04:00
Evelyn Eastmond aa88e2c6a6 Removing tester top/left positions. 2019-05-07 11:42:40 -04:00
Evelyn Eastmond b89734b0e9 Add preliminary fencing div/overlay, with Paul's help. 2019-05-07 11:42:40 -04:00
Evelyn Eastmond d5eb058d00 Fixing linting and an extra line. 2019-05-07 11:42:40 -04:00
Evelyn Eastmond fe308b6b58 Commenting out div overlay hack for now. 2019-05-07 11:42:40 -04:00
Evelyn Eastmond ab14942c80 Starting to play with Draggable for cards. 2019-05-07 11:42:40 -04:00
Evelyn Eastmond 908cb2e5c6 New close button and some margin for text. 2019-05-07 11:42:40 -04:00
Evelyn Eastmond 6935aa0820 Add formattedmessage to shrink/expand labels. 2019-05-07 11:42:40 -04:00
Evelyn Eastmond 4ec8ac16a8 Reword 'toggle' to 'shrinkExpand' throughout code. 2019-05-07 11:42:40 -04:00
Evelyn Eastmond bfe2877d0b Rename icon, add shrink expand icons to card header. 2019-05-07 11:42:40 -04:00
Evelyn Eastmond 9d50e9a165 Adding initial shrink/expand icons. 2019-05-07 11:42:40 -04:00
Evelyn Eastmond eb496cfe75 Give cards a min-width so shrink/expand doesn't change size. 2019-05-07 11:42:40 -04:00
Evelyn Eastmond dfd01da913 Using a hidden css style, cleaning up left/right button and card hiding. 2019-05-07 11:42:40 -04:00
Evelyn Eastmond c8bdb6ce09 Change remove and toggle buttons flow to column for stacking layout. 2019-05-07 11:42:40 -04:00
Evelyn Eastmond 3169c03e66 Reverse order of close button icon and label. 2019-05-07 11:42:40 -04:00
Evelyn Eastmond 26323cccf2 Hide bottom border on header in shrink mode. 2019-05-07 11:42:40 -04:00
Evelyn Eastmond 2bb9a61539 Fixing right-card and card-preview to use toggle correctly. 2019-05-07 11:42:40 -04:00
Evelyn Eastmond 4efd3fcbad Rename shrinkButton to toggleButton. 2019-05-07 11:42:40 -04:00
Evelyn Eastmond 170705440a Adding toggle state to Cards. Using toggle state to set the CSS state. 2019-05-07 11:42:40 -04:00
Evelyn Eastmond a52fdaa032 Completing propagation of toddleCards. 2019-05-07 11:42:40 -04:00
Evelyn Eastmond 6d972da227 Adding a stub toggleCards reducer. 2019-05-07 11:42:40 -04:00
Evelyn Eastmond 96bd677ef9 Starting to add an onToggleCards prop. 2019-05-07 11:42:40 -04:00
Evelyn Eastmond b77bc7a8b4 Adding a new div to hold the shrink button. 2019-05-07 11:42:40 -04:00
Paul Kaplan 7f06f55f83 Merge pull request #4798 from LLK/greenkeeper/scratch-vm-0.2.0-prerelease.20190506184649
Update scratch-vm to the latest version 🚀
2019-05-07 08:41:22 -04:00
greenkeeper[bot] 04381439c2 chore(package): update scratch-vm to version 0.2.0-prerelease.20190506184649 2019-05-06 18:49:45 +00:00
Paul Kaplan 7b658c60c7 Merge pull request #4786 from paulkaplan/update-eslint-react
Update eslint-plugin-react and fix newly discovered lint errors.
2019-05-06 10:33:59 -04:00
picklesrus 0c68103eb6 Merge pull request #4664 from mzgoddard/is-3d-supported
replace Blocks.utils.is3dSupported with constant value function
2019-05-02 11:53:52 -04:00
Michael "Z" Goddard 65c787d0da replace Blocks.utils.is3dSupported with constant value function 2019-05-01 17:31:39 -04:00
chrisgarrity 0b40daf936 Merge pull request #4793 from LLK/greenkeeper/scratch-l10n-3.2.20190501144004
chore(package): update scratch-l10n to version 3.2.20190501144004
2019-05-01 17:09:25 -04:00
chrisgarrity 75607ebbe3 Merge pull request #4792 from LLK/greenkeeper/scratch-vm-0.2.0-prerelease.20190430163103
chore(package): update scratch-vm to version 0.2.0-prerelease.2019043…
2019-05-01 17:07:50 -04:00
Paul Kaplan 58b178f679 Merge pull request #4775 from LLK/greenkeeper/chromedriver-74.0.0
chore(package): update chromedriver to version 74.0.0
2019-05-01 15:00:07 -04:00
Paul Kaplan ffeebb03bd Update eslint-plugin-react and fix new lint errors.
This includes a small bug where the target pane wouldn't automatically update if changes to the sprite occured while in fullscreen/player mode.

Closes #4221
2019-05-01 11:01:44 -04:00
greenkeeper[bot] 7c1f0d2739 chore(package): update scratch-l10n to version 3.2.20190501144004
Closes #4774
2019-05-01 14:42:15 +00:00
Eric Rosenbaum ac0c6a4305 Merge pull request #4785 from ericrosenbaum/feature/enable-boost
Enable the boost extension
2019-05-01 10:22:09 -04:00
Benjamin Wheeler ff776dc90c Merge pull request #4784 from benjiwheeler/fix-save-on-see-project-page
Fix auto-save when clicking See Project Page
2019-05-01 09:44:24 -04:00
Ben Wheeler 516baedad9 added tests, rewrote menu-bar-hoc to accomodate tests 2019-05-01 07:02:07 -04:00
Michael "Z" Goddard d83ec5a0b5 replace blocks timeout with a promise
The timeout as a promise lets us update the toolbox during the same
render as the workspace so that the screen updates all together. This
also means the toolbox will update before the loading screen is
dismissed after loading, letting us avoid a second flash for the
toolbox to update.
2019-04-30 16:36:52 -04:00
Eric Rosenbaum 1c8ba1d1eb enable boost extension 2019-04-30 16:13:50 -04:00
Ben Wheeler 16024769c8 renamed confirm-replace-hoc to menu-bar-hoc; moved project changed checking there 2019-04-30 15:02:22 -04:00
Paul Kaplan ed9316266e Merge pull request #4782 from LLK/greenkeeper/scratch-paint-0.2.0-prerelease.20190430175441
Update scratch-paint to the latest version 🚀
2019-04-30 14:35:22 -04:00
greenkeeper[bot] 103f55bd6e chore(package): update scratch-paint to version 0.2.0-prerelease.20190430175441 2019-04-30 17:56:07 +00:00
greenkeeper[bot] 009d9db74f chore(package): update scratch-vm to version 0.2.0-prerelease.20190430163103
Closes #4781
2019-04-30 16:33:45 +00:00
Paul Kaplan 416bc85455 Merge pull request #4717 from gunchleoc/add-troubleshooting-documentation
Add troubleshooting documentation
2019-04-29 13:15:59 -04:00
Benjamin Wheeler 88a5ab8052 Cleaned up wording and explanation around npm linking 2019-04-28 12:44:39 -04:00
Paul Kaplan 31454f7ca0 Seriously, update VM to a version that actually exists 2019-04-24 17:15:09 -04:00
Eric Rosenbaum bfd0712c83 update scratch-vm 2019-04-24 16:43:00 -04:00
Eric Rosenbaum 3c9d482a02 Merge pull request #4773 from LLK/ericrosenbaum-update-vm
Update scratch-vm
2019-04-24 13:25:02 -04:00
Eric Rosenbaum 5c3694ec19 Update scratch-vm 2019-04-24 13:24:48 -04:00
Eric Rosenbaum 997abfeb27 Merge pull request #4772 from LLK/greenkeeper/scratch-l10n-3.2.20190424151256
chore(package): update scratch-l10n to version 3.2.20190424151256
2019-04-24 12:56:25 -04:00
Eric Rosenbaum df77245f0d Merge branch 'develop' into greenkeeper/scratch-l10n-3.2.20190424151256 2019-04-24 12:55:55 -04:00
Eric Rosenbaum 5e2ea2ee64 Merge pull request #4771 from LLK/ericrosenbaum-update-blocks
update scratch-blocks version
2019-04-24 12:51:59 -04:00
Eric Rosenbaum 655af4ed31 update scratch-blocks version 2019-04-24 12:51:33 -04:00
greenkeeper[bot] 455808fe26 chore(package): update scratch-l10n to version 3.2.20190424151256
Closes #4770
2019-04-24 15:14:51 +00:00
greenkeeper[bot] c2dbdc6279 chore(package): update chromedriver to version 74.0.0
Closes #4077
2019-04-24 13:33:48 +00:00
GunChleoc 327983fc8c Shift new troubleshooting documentation to README.md 2019-04-10 17:47:52 +01:00
GunChleoc 93477a19d6 Add page title to troubleshooting documentation 2019-04-07 08:27:58 +01:00
GunChleoc a87b08d791 Add troubleshooting page 2019-04-07 08:26:02 +01:00
Michael "Z" Goddard 866af2f766 render toolboxes once the workspace has rendered 2019-03-26 17:33:42 -04:00
Michael "Z" Goddard 656e8c2c77 render only new toolbox xmls 2019-03-21 14:57:22 -04:00
38 changed files with 943 additions and 338 deletions

No files matched your search

+85 -16
View File
@@ -30,29 +30,38 @@ Then go to [http://localhost:8601/](http://localhost:8601/) - the playground out
## Developing alongside other Scratch repositories
### Linking this code to another project's `node_modules/scratch-gui`
### Getting another repo to point to this code
If you wish to develop `scratch-gui` alongside other scratch repositories that depend on it, you may wish
to have the other repositories use your local `scratch-gui` build instead of fetching the current production
version of the scratch-gui that is found by default using `npm install`.
Here's how to link your local `scratch-gui` code to another project's `node_modules/scratch-gui`.
#### Configuration
If you wish to develop scratch-gui alongside other scratch repositories that depend on it, you may wish
to have the other repositories use your local scratch-gui build instead of fetching the current production
version of the scratch-gui that is found by default using `npm install`.
1. In your local `scratch-gui` repository's top level:
1. Make sure you have run `npm install`
2. Build the `dist` directory by running `BUILD_MODE=dist npm run build`
3. Establish a link to this repository by running `npm link`
To do this:
1. Make sure you have run `npm install` from this (scratch-gui) repository's top level
2. Make sure you have run `npm install` from the top level of each repository (such as scratch-www) that depends on scratch-gui
3. From this (scratch-gui) repository's top level, build the `dist` directory by running `BUILD_MODE=dist npm run build`
4. From this (scratch-gui) repository's top level, establish a link to this repository by running `npm link`
5. From the top level of each repository that depends on scratch-gui, run `npm link scratch-gui`
6. Build or run the repositories that depend on scratch-gui
2. From the top level of each repository (such as `scratch-www`) that depends on `scratch-gui`:
1. Make sure you have run `npm install`
2. Run `npm link scratch-gui`
3. Build or run the repositoriy
Instead of `BUILD_MODE=dist npm run build` you can also use `BUILD_MODE=dist npm run watch`, however this may be unreliable.
#### Using `npm run watch`
Instead of `BUILD_MODE=dist npm run build`, you can use `BUILD_MODE=dist npm run watch` instead. This will watch for changes to your `scratch-gui` code, and automatically rebuild when there are changes. Sometimes this has been unreliable; if you are having problems, try going back to `BUILD_MODE=dist npm run build` until you resolve them.
#### Oh no! It didn't work!
* Follow the recipe above step by step and don't change the order. It is especially important to run npm first because installing after the linking will reset the linking.
* Make sure the repositories are siblings on your machine's file tree.
* If you have multiple Terminal tabs or windows open for the different Scratch repositories, make sure to use the same node version in all of them.
* In the worst case unlink the repositories by running `npm unlink` in both, and start over.
If you can't get linking to work right, try:
* Follow the recipe above step by step and don't change the order. It is especially important to run `npm install` _before_ `npm link`, because installing after the linking will reset the linking.
* Make sure the repositories are siblings on your machine's file tree, like `.../.../MY_SCRATCH_DEV_DIRECTORY/scratch-gui/` and `.../.../MY_SCRATCH_DEV_DIRECTORY/scratch-www/`.
* Consistent node.js version: If you have multiple Terminal tabs or windows open for the different Scratch repositories, make sure to use the same node version in all of them.
* If nothing else works, unlink the repositories by running `npm unlink` in both, and start over.
## Testing
### Documentation
@@ -121,6 +130,66 @@ If you want to watch the browser as it runs the test, rather than running headle
USE_HEADLESS=no $(npm bin)/jest --runInBand test/integration/backpack.test.js
```
## Troubleshooting
### Ignoring optional dependencies
When running `npm install`, you can get warnings about optionsl dependencies:
```
npm WARN optional Skipping failed optional dependency /chokidar/fsevents:
npm WARN notsup Not compatible with your operating system or architecture: fsevents@1.2.7
```
You can suppress them by adding the `no-optional` switch:
```
npm install --no-optional
```
Further reading: [Stack Overflow](https://stackoverflow.com/questions/36725181/not-compatible-with-your-operating-system-or-architecture-fsevents1-0-11)
### Resolving dependencies
When installing for the first time, you can get warnings which need to be resolved:
```
npm WARN eslint-config-scratch@5.0.0 requires a peer of babel-eslint@^8.0.1 but none was installed.
npm WARN eslint-config-scratch@5.0.0 requires a peer of eslint@^4.0 but none was installed.
npm WARN scratch-paint@0.2.0-prerelease.20190318170811 requires a peer of react-intl-redux@^0.7 but none was installed.
npm WARN scratch-paint@0.2.0-prerelease.20190318170811 requires a peer of react-responsive@^4 but none was installed.
```
You can check which versions are available:
```
npm view react-intl-redux@0.* version
```
You will neet do install the required version:
```
npm install --no-optional --save-dev react-intl-redux@^0.7
```
The dependency itself might have more missing dependencies, which will show up like this:
```
user@machine:~/sources/scratch/scratch-gui (491-translatable-library-objects)$ npm install --no-optional --save-dev react-intl-redux@^0.7
scratch-gui@0.1.0 /media/cuideigin/Linux/sources/scratch/scratch-gui
├── react-intl-redux@0.7.0
└── UNMET PEER DEPENDENCY react-responsive@5.0.0
```
You will need to install those as well:
```
npm install --no-optional --save-dev react-responsive@^5.0.0
```
Further reading: [Stack Overflow](https://stackoverflow.com/questions/46602286/npm-requires-a-peer-of-but-all-peers-are-in-package-json-and-node-modules)
## Publishing to GitHub Pages
You can publish the GUI to github.io so that others on the Internet can view it.
[Read the wiki for a step-by-step guide.](https://github.com/LLK/scratch-gui/wiki/Publishing-to-GitHub-Pages)
+10 -10
View File
@@ -44,7 +44,7 @@
"babel-loader": "^8.0.4",
"base64-loader": "1.0.0",
"bowser": "1.9.4",
"chromedriver": "2.44.1",
"chromedriver": "74.0.0",
"classnames": "2.2.6",
"computed-style-to-inline-style": "3.0.0",
"copy-webpack-plugin": "^4.5.1",
@@ -56,7 +56,7 @@
"eslint": "^5.0.1",
"eslint-config-scratch": "^5.0.0",
"eslint-plugin-import": "^2.8.0",
"eslint-plugin-react": "7.11.1",
"eslint-plugin-react": "^7.12.4",
"file-loader": "2.0.0",
"get-float-time-domain-data": "0.1.0",
"get-user-media-promise": "1.1.4",
@@ -90,7 +90,7 @@
"react-dom": "16.2.0",
"react-draggable": "3.0.5",
"react-ga": "2.5.3",
"react-intl": "2.8.0",
"react-intl": "2.9.0",
"react-modal": "3.6.1",
"react-popover": "0.5.10",
"react-redux": "5.0.7",
@@ -105,13 +105,13 @@
"redux-throttle": "0.1.1",
"rimraf": "^2.6.1",
"scratch-audio": "0.1.0-prerelease.20190114210212",
"scratch-blocks": "0.1.0-prerelease.1556058260",
"scratch-l10n": "3.2.20190417195644",
"scratch-paint": "0.2.0-prerelease.20190416185326",
"scratch-render": "0.1.0-prerelease.20190419202157",
"scratch-storage": "1.2.2",
"scratch-svg-renderer": "0.2.0-prerelease.20190419183947",
"scratch-vm": "0.2.0-prerelease.20190417203423",
"scratch-l10n": "3.3.20190605143948",
"scratch-blocks": "0.1.0-prerelease.1559136797",
"scratch-paint": "0.2.0-prerelease.20190524133325",
"scratch-render": "0.1.0-prerelease.20190605151415",
"scratch-storage": "1.3.2",
"scratch-svg-renderer": "0.2.0-prerelease.20190523193400",
"scratch-vm": "0.2.0-prerelease.20190604212312",
"selenium-webdriver": "3.6.0",
"startaudiocontext": "1.2.1",
"style-loader": "^0.23.0",
+44 -10
View File
@@ -2,10 +2,18 @@
@import "../../css/colors.css";
@import "../../css/z-index.css";
.card-container-overlay {
position: fixed;
pointer-events: none;
z-index: $z-index-card;
}
.card-container {
position:absolute;
pointer-events: auto;
z-index: $z-index-card;
margin: 0.5rem 2rem;
min-width: 468px;
}
.left-card, .right-card {
@@ -104,11 +112,38 @@
font-weight: bold;
}
.header-buttons-hidden {
border-bottom: 0px;
}
.header-buttons-right {
display: flex;
flex-direction: row;
}
.header-buttons img {
margin-bottom: 2px;
}
.shrink-expand-button {
cursor: pointer;
color: white;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
padding: 0.75rem;
}
.shrink-expand-button:hover, .all-button:hover {
background-color: $ui-black-transparent;
}
.remove-button, .all-button {
cursor: pointer;
color: white;
display: flex;
flex-direction: row;
flex-direction: column;
justify-content: center;
align-items: center;
padding: 0.75rem;
@@ -127,6 +162,7 @@
}
.step-body {
width: 100%;
background: $ui-white;
display: flex;
flex-direction: column;
@@ -142,6 +178,8 @@
.step-image {
max-width: 450px;
max-height: 200px;
object-fit: contain;
background: #F9F9F9;
border: 1px solid #ddd;
border-radius: 0.5rem;
@@ -188,7 +226,7 @@
}
.close-icon {
height: 1rem;
height: 1.25rem;
margin: .125rem 0; /* To offset the .25rem difference in icon size */
}
@@ -240,14 +278,6 @@
margin-right: 0.5rem;
}
.video-cover {
width: 100%;
height: 100%;
position: absolute;
top: 0;
left: 0;
}
.steps-list {
display: flex;
flex-direction: row;
@@ -267,3 +297,7 @@
background: $ui-white;
box-shadow: 0px 0px 0px 2px $ui-black-transparent;
}
.hidden {
display: none;
}
+199 -90
View File
@@ -1,10 +1,14 @@
import PropTypes from 'prop-types';
import React, {Fragment} from 'react';
import classNames from 'classnames';
import {FormattedMessage} from 'react-intl';
import Draggable from 'react-draggable';
import styles from './card.css';
import shrinkIcon from './icon--shrink.svg';
import expandIcon from './icon--expand.svg';
import rightArrow from './icon--next.svg';
import leftArrow from './icon--prev.svg';
@@ -14,8 +18,8 @@ import closeIcon from './icon--close.svg';
import {translateVideo} from '../../lib/libraries/decks/translate-video.js';
import {translateImage} from '../../lib/libraries/decks/translate-image.js';
const CardHeader = ({onCloseCards, onShowAll, totalSteps, step}) => (
<div className={styles.headerButtons}>
const CardHeader = ({onCloseCards, onShrinkExpandCards, onShowAll, totalSteps, step, expanded}) => (
<div className={expanded ? styles.headerButtons : classNames(styles.headerButtons, styles.headerButtonsHidden)}>
<div
className={styles.allButton}
onClick={onShowAll}
@@ -41,49 +45,104 @@ const CardHeader = ({onCloseCards, onShowAll, totalSteps, step}) => (
))}
</div>
) : null}
<div
className={styles.removeButton}
onClick={onCloseCards}
>
<FormattedMessage
defaultMessage="Close"
description="Title for button to close how-to card"
id="gui.cards.close"
/>
<img
className={styles.closeIcon}
src={closeIcon}
/>
<div className={styles.headerButtonsRight}>
<div
className={styles.shrinkExpandButton}
onClick={onShrinkExpandCards}
>
<img
draggable={false}
src={expanded ? shrinkIcon : expandIcon}
/>
{expanded ?
<FormattedMessage
defaultMessage="Shrink"
description="Title for button to shrink how-to card"
id="gui.cards.shrink"
/> :
<FormattedMessage
defaultMessage="Expand"
description="Title for button to expand how-to card"
id="gui.cards.expand"
/>
}
</div>
<div
className={styles.removeButton}
onClick={onCloseCards}
>
<img
className={styles.closeIcon}
src={closeIcon}
/>
<FormattedMessage
defaultMessage="Close"
description="Title for button to close how-to card"
id="gui.cards.close"
/>
</div>
</div>
</div>
);
// Video step needs to know if the card is being dragged to cover the video
// so that the mouseup is not swallowed by the iframe.
const VideoStep = ({video, dragging}) => (
<div className={styles.stepVideo}>
{dragging ? (
<div className={styles.videoCover} />
) : null}
<iframe
allowFullScreen
allowTransparency="true"
frameBorder="0"
height="257"
scrolling="no"
src={`https://fast.wistia.net/embed/iframe/${video}?seo=false&videoFoam=true`}
title="📹"
width="466"
/>
<script
async
src="https://fast.wistia.net/assets/external/E-v1.js"
/>
</div>
);
class VideoStep extends React.Component {
componentDidMount () {
const script = document.createElement('script');
script.src = `https://fast.wistia.com/embed/medias/${this.props.video}.jsonp`;
script.async = true;
script.setAttribute('id', 'wistia-video-content');
document.body.appendChild(script);
const script2 = document.createElement('script');
script2.src = 'https://fast.wistia.com/assets/external/E-v1.js';
script2.async = true;
script2.setAttribute('id', 'wistia-video-api');
document.body.appendChild(script2);
}
// We use the Wistia API here to update or pause the video dynamically:
// https://wistia.com/support/developers/player-api
componentDidUpdate (prevProps) {
// Get a handle on the currently loaded video
const video = window.Wistia.api(prevProps.video);
// Reset the video source if a new video has been chosen from the library
if (prevProps.video !== this.props.video) {
video.replaceWith(this.props.video);
}
// Pause the video if the modal is being shrunken
if (!this.props.expanded) {
video.pause();
}
}
componentWillUnmount () {
const script = document.getElementById('wistia-video-content');
script.parentNode.removeChild(script);
const script2 = document.getElementById('wistia-video-api');
script2.parentNode.removeChild(script2);
}
render () {
return (
<div className={styles.stepVideo}>
<div
className={`wistia_embed wistia_async_${this.props.video}`}
id="video-div"
style={{height: `257px`, width: `466px`}}
>
&nbsp;
</div>
</div>
);
}
}
VideoStep.propTypes = {
dragging: PropTypes.bool.isRequired,
expanded: PropTypes.bool.isRequired,
video: PropTypes.string.isRequired
};
@@ -107,13 +166,13 @@ ImageStep.propTypes = {
title: PropTypes.node.isRequired
};
const NextPrevButtons = ({isRtl, onNextStep, onPrevStep}) => (
const NextPrevButtons = ({isRtl, onNextStep, onPrevStep, expanded}) => (
<Fragment>
{onNextStep ? (
<div>
<div className={isRtl ? styles.leftCard : styles.rightCard} />
<div className={expanded ? (isRtl ? styles.leftCard : styles.rightCard) : styles.hidden} />
<div
className={isRtl ? styles.leftButton : styles.rightButton}
className={expanded ? (isRtl ? styles.leftButton : styles.rightButton) : styles.hidden}
onClick={onNextStep}
>
<img
@@ -125,9 +184,9 @@ const NextPrevButtons = ({isRtl, onNextStep, onPrevStep}) => (
) : null}
{onPrevStep ? (
<div>
<div className={isRtl ? styles.rightCard : styles.leftCard} />
<div className={expanded ? (isRtl ? styles.rightCard : styles.leftCard) : styles.hidden} />
<div
className={isRtl ? styles.rightButton : styles.leftButton}
className={expanded ? (isRtl ? styles.rightButton : styles.leftButton) : styles.hidden}
onClick={onPrevStep}
>
<img
@@ -141,13 +200,16 @@ const NextPrevButtons = ({isRtl, onNextStep, onPrevStep}) => (
);
NextPrevButtons.propTypes = {
expanded: PropTypes.bool.isRequired,
isRtl: PropTypes.bool,
onNextStep: PropTypes.func,
onPrevStep: PropTypes.func
};
CardHeader.propTypes = {
expanded: PropTypes.bool.isRequired,
onCloseCards: PropTypes.func.isRequired,
onShowAll: PropTypes.func.isRequired,
onShrinkExpandCards: PropTypes.func.isRequired,
step: PropTypes.number,
totalSteps: PropTypes.number
};
@@ -219,78 +281,113 @@ const Cards = props => {
locale,
onActivateDeckFactory,
onCloseCards,
onShrinkExpandCards,
onDrag,
onStartDrag,
onEndDrag,
onShowAll,
onNextStep,
onPrevStep,
showVideos,
step,
expanded,
...posProps
} = props;
let {x, y} = posProps;
if (activeDeckId === null) return;
// Tutorial cards need to calculate their own dragging bounds
// to allow for dragging the cards off the left, right and bottom
// edges of the workspace.
const cardHorizontalDragOffset = 400; // ~80% of card width
const cardVerticalDragOffset = expanded ? 257 : 0; // ~80% of card height, if expanded
const menuBarHeight = 48; // TODO: get pre-calculated from elsewhere?
const wideCardWidth = 500;
if (x === 0 && y === 0) {
// initialize positions
x = isRtl ? -292 : 292;
// The tallest cards are about 385px high, and the default position is pinned
x = isRtl ? (-190 - wideCardWidth - cardHorizontalDragOffset) : 292;
x += cardHorizontalDragOffset;
// The tallest cards are about 320px high, and the default position is pinned
// to near the bottom of the blocks palette to allow room to work above.
const tallCardHeight = 385;
const tallCardHeight = 320;
const bottomMargin = 60; // To avoid overlapping the backpack region
y = window.innerHeight - tallCardHeight - bottomMargin;
y = window.innerHeight - tallCardHeight - bottomMargin - menuBarHeight;
}
const steps = content[activeDeckId].steps;
return (
<Draggable
bounds="parent"
position={{x: x, y: y}}
onDrag={onDrag}
onStart={onStartDrag}
onStop={onEndDrag}
// Custom overlay to act as the bounding parent for the draggable, using values from above
<div
className={styles.cardContainerOverlay}
style={{
width: `${window.innerWidth + (2 * cardHorizontalDragOffset)}px`,
height: `${window.innerHeight - menuBarHeight + cardVerticalDragOffset}px`,
top: `${menuBarHeight}px`,
left: `${-cardHorizontalDragOffset}px`
}}
>
<div className={styles.cardContainer}>
<div className={styles.card}>
<CardHeader
step={step}
totalSteps={steps.length}
onCloseCards={onCloseCards}
onShowAll={onShowAll}
/>
<div className={styles.stepBody}>
{steps[step].deckIds ? (
<PreviewsStep
content={content}
deckIds={steps[step].deckIds}
onActivateDeckFactory={onActivateDeckFactory}
onShowAll={onShowAll}
/>
) : (
steps[step].video ? (
<VideoStep
dragging={dragging}
video={translateVideo(steps[step].video, locale)}
<Draggable
bounds="parent"
cancel="#video-div" // disable dragging on video div
position={{x: x, y: y}}
onDrag={onDrag}
onStart={onStartDrag}
onStop={onEndDrag}
>
<div className={styles.cardContainer}>
<div className={styles.card}>
<CardHeader
expanded={expanded}
step={step}
totalSteps={steps.length}
onCloseCards={onCloseCards}
onShowAll={onShowAll}
onShrinkExpandCards={onShrinkExpandCards}
/>
<div className={expanded ? styles.stepBody : styles.hidden}>
{steps[step].deckIds ? (
<PreviewsStep
content={content}
deckIds={steps[step].deckIds}
onActivateDeckFactory={onActivateDeckFactory}
onShowAll={onShowAll}
/>
) : (
<ImageStep
image={translateImage(steps[step].image, locale)}
title={steps[step].title}
/>
)
)}
{steps[step].trackingPixel && steps[step].trackingPixel}
steps[step].video ? (
showVideos ? (
<VideoStep
dragging={dragging}
expanded={expanded}
video={translateVideo(steps[step].video, locale)}
/>
) : ( // Else show the deck image and title
<ImageStep
image={content[activeDeckId].img}
title={content[activeDeckId].name}
/>
)
) : (
<ImageStep
image={translateImage(steps[step].image, locale)}
title={steps[step].title}
/>
)
)}
{steps[step].trackingPixel && steps[step].trackingPixel}
</div>
<NextPrevButtons
expanded={expanded}
isRtl={isRtl}
onNextStep={step < steps.length - 1 ? onNextStep : null}
onPrevStep={step > 0 ? onPrevStep : null}
/>
</div>
<NextPrevButtons
isRtl={isRtl}
onNextStep={step < steps.length - 1 ? onNextStep : null}
onPrevStep={step > 0 ? onPrevStep : null}
/>
</div>
</div>
</Draggable>
</Draggable>
</div>
);
};
@@ -309,6 +406,7 @@ Cards.propTypes = {
})
}),
dragging: PropTypes.bool.isRequired,
expanded: PropTypes.bool.isRequired,
isRtl: PropTypes.bool.isRequired,
locale: PropTypes.string.isRequired,
onActivateDeckFactory: PropTypes.func.isRequired,
@@ -318,10 +416,21 @@ Cards.propTypes = {
onNextStep: PropTypes.func.isRequired,
onPrevStep: PropTypes.func.isRequired,
onShowAll: PropTypes.func,
onShrinkExpandCards: PropTypes.func.isRequired,
onStartDrag: PropTypes.func,
showVideos: PropTypes.bool,
step: PropTypes.number.isRequired,
x: PropTypes.number,
y: PropTypes.number
};
export default Cards;
Cards.defaultProps = {
showVideos: true
};
export {
Cards as default,
// Others exported for testability
ImageStep,
VideoStep
};
+6 -6
View File
@@ -1,17 +1,17 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="20px" height="20px" viewBox="0 0 20 20" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<!-- Generator: Sketch 52.2 (67145) - http://www.bohemiancoding.com/sketch -->
<title>General/Check Copy</title>
<!-- Generator: Sketch 53.2 (72643) - https://sketchapp.com -->
<title>Extensions/Connection/Close</title>
<desc>Created with Sketch.</desc>
<defs>
<path d="M10,7.73577763 L12.2675846,5.46819305 C12.8909754,4.84480221 13.8988379,4.84194841 14.5284447,5.47155526 C15.1536925,6.096803 15.1476685,7.11655392 14.531807,7.73241542 L12.2642224,10 L14.531807,12.2675846 C15.1551978,12.8909754 15.1580516,13.8988379 14.5284447,14.5284447 C13.903197,15.1536925 12.8834461,15.1476685 12.2675846,14.531807 L10,12.2642224 L7.73241542,14.531807 C7.10902458,15.1551978 6.10116212,15.1580516 5.47155526,14.5284447 C4.84630752,13.903197 4.85233155,12.8834461 5.46819305,12.2675846 L7.73577763,10 L5.46819305,7.73241542 C4.84480221,7.10902458 4.84194841,6.10116212 5.47155526,5.47155526 C6.096803,4.84630752 7.11655392,4.85233155 7.73241542,5.46819305 L10,7.73577763 Z" id="path-1"></path>
<path d="M15.464935,15.467297 C14.7644059,16.1777705 13.6185877,16.1777705 12.9081142,15.467297 L9.99881899,12.5580018 L7.08841885,15.467297 C6.38236506,16.1733508 5.23765187,16.1733508 4.53159807,15.467297 C4.17912364,15.1148226 4.00012409,14.6485398 4.00012409,14.1888866 C4.00012409,13.7281285 4.17912364,13.2629506 4.53159807,12.9104762 L7.44089328,10.001181 L4.52717833,7.08636112 C4.17359897,6.73278176 3.99459941,6.26760391 4.00012409,5.80242606 C4.00012409,5.34166795 4.17359897,4.88201477 4.52717833,4.52954034 C5.23212719,3.82348655 6.37684038,3.82348655 7.08399911,4.52954034 L9.99881899,7.44325529 L12.9125339,4.52954034 C13.6185877,3.82348655 14.7644059,3.82348655 15.4704597,4.52954034 C16.1765134,5.2344892 16.1765134,6.38030733 15.4704597,7.08636112 L12.5545348,10.001181 L15.4704597,12.914896 C16.1765134,13.6209497 16.1765134,14.7557185 15.464935,15.467297" id="path-1"></path>
</defs>
<g id="General/Check-Copy" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g id="Extensions/Connection/Close" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<mask id="mask-2" fill="white">
<use xlink:href="#path-1"></use>
</mask>
<use id="close-icon" fill="#FFFFFF" xlink:href="#path-1"></use>
<g id="Color/White" mask="url(#mask-2)" fill="#FFFFFF">
<use id="close" fill="#FFFFFF" xlink:href="#path-1"></use>
<g id="White" mask="url(#mask-2)" fill="#FFFFFF">
<rect id="Color" x="0" y="0" width="20" height="20"></rect>
</g>
</g>

Before

Width:  |  Height:  |  Size: 1.5 KiB

After

Width:  |  Height:  |  Size: 1.7 KiB

+18
View File
@@ -0,0 +1,18 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="20px" height="20px" viewBox="0 0 20 20" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<!-- Generator: Sketch 53.2 (72643) - https://sketchapp.com -->
<title>Tutorials/Expand</title>
<desc>Created with Sketch.</desc>
<defs>
<path d="M4.5,2 L15.5,2 C16.8807119,2 18,3.11928813 18,4.5 L18,5.5 C18,5.77614237 17.7761424,6 17.5,6 L2.5,6 C2.22385763,6 2,5.77614237 2,5.5 L2,4.5 C2,3.11928813 3.11928813,2 4.5,2 Z M2.5,7 L17.5,7 C17.7761424,7 18,7.22385763 18,7.5 L18,15.5 C18,16.8807119 16.8807119,18 15.5,18 L4.5,18 C3.11928813,18 2,16.8807119 2,15.5 L2,7.5 C2,7.22385763 2.22385763,7 2.5,7 Z M9.65509466,15.1636146 C9.745416,15.2533569 9.86700241,15.3031495 9.99727357,15.3031495 C10.1275447,15.3031495 10.2491311,15.2533569 10.3394525,15.1636146 L12.1574588,13.3456082 C12.3004676,13.2025994 12.3415754,12.9993764 12.2657286,12.8158388 C12.1898819,12.6334592 12.0109762,12.5153467 11.8100691,12.5153467 L11.1506075,12.5153467 L10.7899012,9.98808625 C10.7464775,9.64474938 10.4703026,9.36567961 10.1124912,9.30951827 C10.0783312,9.30546539 10.0435922,9.30314946 10.0094322,9.30314946 C9.61282891,9.30314946 9.27586085,9.59785176 9.22548933,9.98519134 L8.8740467,12.5153467 L8.18447804,12.5153467 C7.9858869,12.5153467 7.81450796,12.6265114 7.73692425,12.8065751 C7.65876155,12.9866388 7.69639544,13.1962306 7.83708829,13.3456082 L9.65509466,15.1636146 Z" id="path-1"></path>
</defs>
<g id="Tutorials/Expand" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<mask id="mask-2" fill="white">
<use xlink:href="#path-1"></use>
</mask>
<g id="Combined-Shape" fill-rule="nonzero"></g>
<g id="White" mask="url(#mask-2)" fill="#FFFFFF">
<rect id="Color" x="0" y="0" width="20" height="20"></rect>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.9 KiB

+18
View File
@@ -0,0 +1,18 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="20px" height="20px" viewBox="0 0 20 20" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<!-- Generator: Sketch 53.2 (72643) - https://sketchapp.com -->
<title>Tutorials/Shink</title>
<desc>Created with Sketch.</desc>
<defs>
<path d="M2.5,8 C2.22385763,8 2,7.77614237 2,7.5 C2,7.22385763 2.22385763,7 2.5,7 L3.5,7 C3.77614237,7 4,7.22385763 4,7.5 C4,7.77614237 3.77614237,8 3.5,8 L2.5,8 Z M5.5,8 C5.22385763,8 5,7.77614237 5,7.5 C5,7.22385763 5.22385763,7 5.5,7 L6.5,7 C6.77614237,7 7,7.22385763 7,7.5 C7,7.77614237 6.77614237,8 6.5,8 L5.5,8 Z M8.5,8 C8.22385763,8 8,7.77614237 8,7.5 C8,7.22385763 8.22385763,7 8.5,7 L9.5,7 C9.77614237,7 10,7.22385763 10,7.5 C10,7.77614237 9.77614237,8 9.5,8 L8.5,8 Z M11.5,8 C11.2238576,8 11,7.77614237 11,7.5 C11,7.22385763 11.2238576,7 11.5,7 L12.5,7 C12.7761424,7 13,7.22385763 13,7.5 C13,7.77614237 12.7761424,8 12.5,8 L11.5,8 Z M14.5,8 C14.2238576,8 14,7.77614237 14,7.5 C14,7.22385763 14.2238576,7 14.5,7 L15.5,7 C15.7761424,7 16,7.22385763 16,7.5 C16,7.77614237 15.7761424,8 15.5,8 L14.5,8 Z M17,7.5 C17,7.22385763 17.2238576,7 17.5,7 C17.7761424,7 18,7.22385763 18,7.5 L18,8.5 C18,8.77614237 17.7761424,9 17.5,9 C17.2238576,9 17,8.77614237 17,8.5 L17,7.5 Z M17,10.5 C17,10.2238576 17.2238576,10 17.5,10 C17.7761424,10 18,10.2238576 18,10.5 L18,11.5 C18,11.7761424 17.7761424,12 17.5,12 C17.2238576,12 17,11.7761424 17,11.5 L17,10.5 Z M17,13.5 C17,13.2238576 17.2238576,13 17.5,13 C17.7761424,13 18,13.2238576 18,13.5 L18,14.5 C18,14.7761424 17.7761424,15 17.5,15 C17.2238576,15 17,14.7761424 17,14.5 L17,13.5 Z M16.8130884,16.2258789 C16.9469778,15.9843665 17.2513011,15.8971208 17.4928135,16.0310102 C17.7343259,16.1648996 17.8215716,16.4692229 17.6876822,16.7107353 C17.4827416,17.0804113 17.1867239,17.3929429 16.8289716,17.6178178 C16.59518,17.7647739 16.286523,17.6943798 16.1395669,17.4605882 C15.9926108,17.2267966 16.0630049,16.9181396 16.2967965,16.7711835 C16.5118233,16.6360225 16.6900031,16.4479027 16.8130884,16.2258789 Z M14.5614675,17 C14.8376098,17 15.0614675,17.2238576 15.0614675,17.5 C15.0614675,17.7761424 14.8376098,18 14.5614675,18 L13.5614675,18 C13.2853251,18 13.0614675,17.7761424 13.0614675,17.5 C13.0614675,17.2238576 13.2853251,17 13.5614675,17 L14.5614675,17 Z M11.5614675,17 C11.8376098,17 12.0614675,17.2238576 12.0614675,17.5 C12.0614675,17.7761424 11.8376098,18 11.5614675,18 L10.5614675,18 C10.2853251,18 10.0614675,17.7761424 10.0614675,17.5 C10.0614675,17.2238576 10.2853251,17 10.5614675,17 L11.5614675,17 Z M8.56146746,17 C8.83760983,17 9.06146746,17.2238576 9.06146746,17.5 C9.06146746,17.7761424 8.83760983,18 8.56146746,18 L7.56146746,18 C7.28532508,18 7.06146746,17.7761424 7.06146746,17.5 C7.06146746,17.2238576 7.28532508,17 7.56146746,17 L8.56146746,17 Z M5.56146746,17 C5.83760983,17 6.06146746,17.2238576 6.06146746,17.5 C6.06146746,17.7761424 5.83760983,18 5.56146746,18 L4.56146746,18 C4.28532508,18 4.06146746,17.7761424 4.06146746,17.5 C4.06146746,17.2238576 4.28532508,17 4.56146746,17 L5.56146746,17 Z M3.22779886,16.2951753 C3.37445671,16.5291541 3.30366909,16.8377211 3.06969027,16.9843789 C2.83571145,17.1310368 2.52714447,17.0602491 2.38048662,16.8262703 C2.15682122,16.4694332 2.02609629,16.0609535 2.00352115,15.6335963 C1.98895424,15.3578384 2.20069137,15.1224836 2.47644927,15.1079167 C2.75220716,15.0933498 2.98756192,15.3050869 3.00212882,15.5808448 C3.01567642,15.8373067 3.0937811,16.0813625 3.22779886,16.2951753 Z M3,13.6229349 C3,13.8990773 2.77614237,14.1229349 2.5,14.1229349 C2.22385763,14.1229349 2,13.8990773 2,13.6229349 L2,12.6229349 C2,12.3467925 2.22385763,12.1229349 2.5,12.1229349 C2.77614237,12.1229349 3,12.3467925 3,12.6229349 L3,13.6229349 Z M3,10.6229349 C3,10.8990773 2.77614237,11.1229349 2.5,11.1229349 C2.22385763,11.1229349 2,10.8990773 2,10.6229349 L2,9.62293492 C2,9.34679254 2.22385763,9.12293492 2.5,9.12293492 C2.77614237,9.12293492 3,9.34679254 3,9.62293492 L3,10.6229349 Z M3,7.62293492 C3,7.89907729 2.77614237,8.12293492 2.5,8.12293492 C2.22385763,8.12293492 2,7.89907729 2,7.62293492 L2,7.5 C2,7.22385763 2.22385763,7 2.5,7 C2.77614237,7 3,7.22385763 3,7.5 L3,7.62293492 Z M4.5,2 L15.5,2 C16.8807119,2 18,3.11928813 18,4.5 L18,5.5 C18,5.77614237 17.7761424,6 17.5,6 L2.5,6 C2.22385763,6 2,5.77614237 2,5.5 L2,4.5 C2,3.11928813 3.11928813,2 4.5,2 Z M10.3449053,9.44268434 L12.1629117,11.2606907 C12.3036046,11.4100683 12.3412384,11.6196601 12.2630758,11.7997238 C12.185492,11.9797875 12.0141131,12.0909522 11.815522,12.0909522 L11.1259533,12.0909522 L10.7745107,14.6211076 C10.7241392,15.0084472 10.3871711,15.3031495 9.99056779,15.3031495 C9.9564078,15.3031495 9.92166882,15.3008335 9.88750883,15.2967806 C9.52969739,15.2406193 9.25352253,14.9615495 9.21009882,14.6182127 L8.84939246,12.0909522 L8.18993091,12.0909522 C7.98902384,12.0909522 7.81011812,11.9728397 7.73427135,11.7904601 C7.65842459,11.6069225 7.69953238,11.4036995 7.84254116,11.2606907 L9.66054753,9.44268434 C9.75086886,9.35294199 9.87245528,9.30314946 10.0027264,9.30314946 C10.1329976,9.30314946 10.254584,9.35294199 10.3449053,9.44268434 Z" id="path-1"></path>
</defs>
<g id="Tutorials/Shink" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<mask id="mask-2" fill="white">
<use xlink:href="#path-1"></use>
</mask>
<g id="Rectangle" fill-rule="nonzero"></g>
<g id="White" mask="url(#mask-2)" fill="#FFFFFF">
<rect id="Color" x="0" y="0" width="20" height="20"></rect>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 5.5 KiB

@@ -1,50 +0,0 @@
import {connect} from 'react-redux';
import PropTypes from 'prop-types';
import bindAll from 'lodash.bindall';
import React from 'react';
const ConfirmReplaceHOC = function (WrappedComponent) {
class ConfirmReplaceProject extends React.PureComponent {
constructor (props) {
super(props);
bindAll(this, [
'confirmReadyToReplaceProject'
]);
}
confirmReadyToReplaceProject (message) {
let readyToReplaceProject = true;
if (this.props.projectChanged && !this.props.canCreateNew) {
readyToReplaceProject = confirm(message); // eslint-disable-line no-alert
}
return readyToReplaceProject;
}
render () {
const {
/* eslint-disable no-unused-vars */
projectChanged,
/* eslint-enable no-unused-vars */
...props
} = this.props;
return (<WrappedComponent
confirmReadyToReplaceProject={this.confirmReadyToReplaceProject}
{...props}
/>);
}
}
ConfirmReplaceProject.propTypes = {
canCreateNew: PropTypes.bool,
projectChanged: PropTypes.bool
};
const _mapStateToProps = state => ({
projectChanged: state.scratchGui.projectChanged
});
return connect(_mapStateToProps)(ConfirmReplaceProject);
};
export default ConfirmReplaceHOC;
+8 -4
View File
@@ -28,7 +28,7 @@ import LoginDropdown from './login-dropdown.jsx';
import SB3Downloader from '../../containers/sb3-downloader.jsx';
import DeletionRestorer from '../../containers/deletion-restorer.jsx';
import TurboMode from '../../containers/turbo-mode.jsx';
import ConfirmReplaceHOC from './confirm-replace-hoc.jsx';
import MenuBarHOC from '../../containers/menu-bar-hoc.jsx';
import {openTipsLibrary} from '../../reducers/modals';
import {setPlayer} from '../../reducers/mode';
@@ -192,8 +192,8 @@ class MenuBar extends React.Component {
this.props.onRequestCloseFile();
}
handleClickSeeCommunity (waitForUpdate) {
if (this.props.canSave && this.props.projectChanged) { // save before transitioning to project page
this.props.autoUpdateProject();
if (this.props.shouldSaveBeforeTransition()) {
this.props.autoUpdateProject(); // save before transitioning to project page
waitForUpdate(true); // queue the transition to project page
} else {
waitForUpdate(false); // immediately transition to project page
@@ -705,6 +705,7 @@ MenuBar.propTypes = {
canSave: PropTypes.bool,
canShare: PropTypes.bool,
className: PropTypes.string,
confirmReadyToReplaceProject: PropTypes.func,
editMenuOpen: PropTypes.bool,
enableCommunity: PropTypes.bool,
fileMenuOpen: PropTypes.bool,
@@ -714,6 +715,7 @@ MenuBar.propTypes = {
isShowingProject: PropTypes.bool,
isUpdating: PropTypes.bool,
languageMenuOpen: PropTypes.bool,
locale: PropTypes.string.isRequired,
loginMenuOpen: PropTypes.bool,
onClickAccount: PropTypes.func,
onClickEdit: PropTypes.func,
@@ -741,7 +743,9 @@ MenuBar.propTypes = {
projectTitle: PropTypes.string,
renderLogin: PropTypes.func,
sessionExists: PropTypes.bool,
shouldSaveBeforeTransition: PropTypes.func,
showComingSoon: PropTypes.bool,
userOwnsProject: PropTypes.bool,
username: PropTypes.string,
vm: PropTypes.instanceOf(VM).isRequired
};
@@ -794,7 +798,7 @@ const mapDispatchToProps = dispatch => ({
export default compose(
injectIntl,
ConfirmReplaceHOC,
MenuBarHOC,
connect(
mapStateToProps,
mapDispatchToProps
+2 -13
View File
@@ -2,7 +2,6 @@ import bindAll from 'lodash.bindall';
import PropTypes from 'prop-types';
import React from 'react';
import {defineMessages, injectIntl, intlShape} from 'react-intl';
import {connect} from 'react-redux';
import VM from 'scratch-vm';
import backdropLibraryContent from '../lib/libraries/backdrops.json';
@@ -33,7 +32,7 @@ class BackdropLibrary extends React.Component {
bitmapResolution: item.info.length > 2 ? item.info[2] : 1,
skinId: null
};
this.props.vm.setEditingTarget(this.props.stageID);
// Do not switch to stage, just add the backdrop
this.props.vm.addBackdrop(item.md5, vmBackdrop);
}
render () {
@@ -53,17 +52,7 @@ class BackdropLibrary extends React.Component {
BackdropLibrary.propTypes = {
intl: intlShape.isRequired,
onRequestClose: PropTypes.func,
stageID: PropTypes.string.isRequired,
vm: PropTypes.instanceOf(VM).isRequired
};
const mapStateToProps = state => ({
stageID: state.scratchGui.targets.stage.id
});
const mapDispatchToProps = () => ({});
export default injectIntl(connect(
mapStateToProps,
mapDispatchToProps
)(BackdropLibrary));
export default injectIntl(BackdropLibrary);
+6 -1
View File
@@ -5,6 +5,7 @@ import React from 'react';
import {
activateDeck,
closeCards,
shrinkExpandCards,
nextStep,
prevStep,
dragCard,
@@ -18,6 +19,7 @@ import {
import CardsComponent from '../components/cards/cards.jsx';
import {loadImageData} from '../lib/libraries/decks/translate-image.js';
import {notScratchDesktop} from '../lib/isScratchDesktop';
class Cards extends React.Component {
componentDidMount () {
@@ -46,11 +48,13 @@ const mapStateToProps = state => ({
content: state.scratchGui.cards.content,
activeDeckId: state.scratchGui.cards.activeDeckId,
step: state.scratchGui.cards.step,
expanded: state.scratchGui.cards.expanded,
x: state.scratchGui.cards.x,
y: state.scratchGui.cards.y,
isRtl: state.locales.isRtl,
locale: state.locales.locale,
dragging: state.scratchGui.cards.dragging
dragging: state.scratchGui.cards.dragging,
showVideos: notScratchDesktop()
});
const mapDispatchToProps = dispatch => ({
@@ -60,6 +64,7 @@ const mapDispatchToProps = dispatch => ({
dispatch(closeCards());
},
onCloseCards: () => dispatch(closeCards()),
onShrinkExpandCards: () => dispatch(shrinkExpandCards()),
onNextStep: () => dispatch(nextStep()),
onPrevStep: () => dispatch(prevStep()),
onDrag: (e_, data) => dispatch(dragCard(data.x, data.y)),
+66
View File
@@ -0,0 +1,66 @@
import {connect} from 'react-redux';
import PropTypes from 'prop-types';
import bindAll from 'lodash.bindall';
import React from 'react';
const MenuBarHOC = function (WrappedComponent) {
class MenuBarContainer extends React.PureComponent {
constructor (props) {
super(props);
bindAll(this, [
'confirmReadyToReplaceProject',
'shouldSaveBeforeTransition'
]);
}
confirmReadyToReplaceProject (message) {
let readyToReplaceProject = true;
if (this.props.projectChanged && !this.props.canCreateNew) {
readyToReplaceProject = this.props.confirmWithMessage(message);
}
return readyToReplaceProject;
}
shouldSaveBeforeTransition () {
return (this.props.canSave && this.props.projectChanged);
}
render () {
const {
/* eslint-disable no-unused-vars */
projectChanged,
/* eslint-enable no-unused-vars */
...props
} = this.props;
return (<WrappedComponent
confirmReadyToReplaceProject={this.confirmReadyToReplaceProject}
shouldSaveBeforeTransition={this.shouldSaveBeforeTransition}
{...props}
/>);
}
}
MenuBarContainer.propTypes = {
canCreateNew: PropTypes.bool,
canSave: PropTypes.bool,
confirmWithMessage: PropTypes.func,
projectChanged: PropTypes.bool
};
MenuBarContainer.defaultProps = {
// default to using standard js confirm
confirmWithMessage: message => (confirm(message)) // eslint-disable-line no-alert
};
const mapStateToProps = state => ({
projectChanged: state.scratchGui.projectChanged
});
const mapDispatchToProps = () => ({});
// Allow incoming props to override redux-provided props. Used to mock in tests.
const mergeProps = (stateProps, dispatchProps, ownProps) => Object.assign(
{}, stateProps, dispatchProps, ownProps
);
return connect(
mapStateToProps,
mapDispatchToProps,
mergeProps
)(MenuBarContainer);
};
export default MenuBarHOC;
+17 -10
View File
@@ -50,7 +50,7 @@ class StageSelector extends React.Component {
'setFileInput'
]);
}
addBackdropFromLibraryItem (item) {
addBackdropFromLibraryItem (item, shouldActivateTab = true) {
const vmBackdrop = {
name: item.name,
md5: item.md5,
@@ -59,25 +59,30 @@ class StageSelector extends React.Component {
bitmapResolution: item.info.length > 2 ? item.info[2] : 1,
skinId: null
};
this.handleNewBackdrop(vmBackdrop);
this.handleNewBackdrop(vmBackdrop, shouldActivateTab);
}
handleClick () {
this.props.onSelect(this.props.id);
}
handleNewBackdrop (backdrops_) {
handleNewBackdrop (backdrops_, shouldActivateTab = true) {
const backdrops = Array.isArray(backdrops_) ? backdrops_ : [backdrops_];
return Promise.all(backdrops.map(backdrop =>
this.props.vm.addBackdrop(backdrop.md5, backdrop)
)).then(() =>
this.props.onActivateTab(COSTUMES_TAB_INDEX)
);
)).then(() => {
if (shouldActivateTab) {
return this.props.onActivateTab(COSTUMES_TAB_INDEX);
}
});
}
handleSurpriseBackdrop () {
handleSurpriseBackdrop (e) {
e.stopPropagation(); // Prevent click from falling through to selecting stage.
// @todo should this not add a backdrop you already have?
const item = backdropLibraryContent[Math.floor(Math.random() * backdropLibraryContent.length)];
this.addBackdropFromLibraryItem(item);
this.addBackdropFromLibraryItem(item, false);
}
handleEmptyBackdrop () {
handleEmptyBackdrop (e) {
e.stopPropagation(); // Prevent click from falling through to stage selector, select it manually below
this.props.vm.setEditingTarget(this.props.id);
this.handleNewBackdrop(emptyCostume(this.props.intl.formatMessage(sharedMessages.backdrop, {index: 1})));
}
handleBackdropUpload (e) {
@@ -85,6 +90,7 @@ class StageSelector extends React.Component {
this.props.onShowImporting();
handleFileUpload(e.target, (buffer, fileType, fileName, fileIndex, fileCount) => {
costumeUpload(buffer, fileType, storage, vmCostumes => {
this.props.vm.setEditingTarget(this.props.id);
vmCostumes.forEach((costume, i) => {
costume.name = `${fileName}${i ? i + 1 : ''}`;
});
@@ -96,7 +102,8 @@ class StageSelector extends React.Component {
}, this.props.onCloseImporting);
}, this.props.onCloseImporting);
}
handleFileUploadClick () {
handleFileUploadClick (e) {
e.stopPropagation(); // Prevent click from selecting the stage, that is handled manually in backdrop upload
this.fileInput.click();
}
handleMouseEnter () {
+1
View File
@@ -423,6 +423,7 @@ class Stage extends React.Component {
Stage.propTypes = {
isColorPicking: PropTypes.bool,
isFullScreen: PropTypes.bool.isRequired,
isStarted: PropTypes.bool,
micIndicator: PropTypes.bool,
onActivateColorPicker: PropTypes.func,
onDeactivateColorPicker: PropTypes.func,
+4 -1
View File
@@ -105,7 +105,10 @@ class TargetPane extends React.Component {
}
}
handleSurpriseSpriteClick () {
const item = spriteLibraryContent[Math.floor(Math.random() * spriteLibraryContent.length)];
const surpriseSprites = spriteLibraryContent.filter(sprite =>
(sprite.tags.indexOf('letters') === -1) && (sprite.tags.indexOf('numbers') === -1)
);
const item = surpriseSprites[Math.floor(Math.random() * surpriseSprites.length)];
randomizeSpritePosition(item);
this.props.vm.addSprite(JSON.stringify(item.json))
.then(this.handleActivateBlocksTab);
+9 -3
View File
@@ -62,10 +62,16 @@ class TipsLibrary extends React.PureComponent {
}
render () {
const decksLibraryThumbnailData = Object.keys(decksLibraryContent)
.filter(id =>
.filter(id => {
if (notScratchDesktop()) return true; // Do not filter anything in online editor
const deck = decksLibraryContent[id];
// Scratch Desktop doesn't want tutorials with `requiredProjectId`
notScratchDesktop() || !decksLibraryContent[id].hasOwnProperty('requiredProjectId')
)
if (deck.hasOwnProperty('requiredProjectId')) return false;
// Scratch Desktop should not load tutorials that are _only_ videos
if (deck.steps.filter(s => s.title).length === 0) return false;
// Allow any other tutorials
return true;
})
.map(id => ({
rawURL: decksLibraryContent[id].img,
id: id,
+2 -1
View File
@@ -113,7 +113,8 @@ const AppStateHOC = function (WrappedComponent, localesOnly) {
}
AppStateWrapper.propTypes = {
isFullScreen: PropTypes.bool,
isPlayerOnly: PropTypes.bool
isPlayerOnly: PropTypes.bool,
showTelemetryModal: PropTypes.bool
};
return AppStateWrapper;
};
+10
View File
@@ -331,5 +331,15 @@ export default function (vm) {
return collator.compare(str1, str2);
};
// Blocks wants to know if 3D CSS transforms are supported. The cross
// section of browsers Scratch supports and browsers that support 3D CSS
// transforms will make the return always true.
//
// Shortcutting to true lets us skip an expensive style recalculation when
// first loading the Scratch editor.
ScratchBlocks.utils.is3dSupported = function () {
return true;
};
return ScratchBlocks;
}
@@ -1,42 +0,0 @@
<svg version="1.1" id="cat" x="0px" y="0px" width="95px" height="111px" viewBox="0 0 95 111" enable-background="new 0 0 95 111" xml:space="preserve" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<g>
<g id="Layer_3">
<path fill="#FAA51D" stroke="#000000" d="M22.462,79.039c-2.415-0.451-5.304-1.309-7.742-3.503&#xD;&#xA;&#x9;&#x9;C9.268,70.629,7.526,62.535,3.672,64.622c-3.856,2.088-3.782,15.165,8.353,19.194c4.182,1.391,7.998,1.396,11.091,1.312&#xD;&#xA;&#x9;&#x9;c0.811-0.025,7.717-0.654,10.079-4.074c2.361-3.42,0.719-4.272-0.09-4.744C32.295,75.838,25.878,79.677,22.462,79.039z"/>
<path fill="#FFFFFF" d="M4.236,64.877c-1.989,0.613-3.075,4.998-2.076,8.484c0.998,3.49,2.634,5.022,3.863,6.398&#xD;&#xA;&#x9;&#x9;c1.528,1.038-0.72-2.402,1.361-4.15c2.075-1.744,5.733-0.914,5.733-0.914s-2.909-3.987-4.57-6.396&#xD;&#xA;&#x9;&#x9;C6.975,65.988,6.359,64.375,4.236,64.877z"/>
</g>
<g>
<path fill="#FAA51D" d="M38.217,86.756c0,0-8.832,6.2-17.071,8.412l0.086,0.215c1.247,1.824,5.87,7.497-0.334,9.496&#xD;&#xA;&#x9;&#x9;c-5.333,1.717-15.12-13.104-10.821-15.902c2.626-1.713,4.892-0.252,4.892-0.252s3.474-1.07,6.001-2.345&#xD;&#xA;&#x9;&#x9;c4.303-2.161,5.784-3.453,5.784-3.453s4.184-4.306,6.856-4.137C36.281,78.96,41.669,83.504,38.217,86.756z"/>
<path fill="none" stroke="#231F20" stroke-width="1.2" d="M21.232,95.383c1.247,1.824,5.87,7.497-0.334,9.496&#xD;&#xA;&#x9;&#x9;c-5.333,1.717-15.329-13.344-11.03-16.145c2.626-1.713,5.101-0.01,5.101-0.01s3.474-1.072,6.001-2.348&#xD;&#xA;&#x9;&#x9;c4.303-2.161,5.784-3.453,5.784-3.453"/>
<path fill="none" stroke="#231F20" stroke-width="1.2" d="M38.217,86.756c0,0-10.123,7.107-18.804,8.819"/>
</g>
<path fill="#FAA51D" stroke="#231F20" stroke-width="1.2" d="M52.169,74.885c0,0,1.235,0.165,4.744,3.676&#xD;&#xA;&#x9;c3.509,3.508,6.026,2.16,8.911,0.724c2.877-1.443,10.537-6.126,6.49-9.817c-4.049-3.688-6.207,1.146-9.715,2.405&#xD;&#xA;&#x9;c-3.512,1.26-5.061-2.487-6.858-4.287c-0.589-0.593-1.188-1.099-1.729-1.505c0,0-0.971-0.76-1.906,2.79&#xD;&#xA;&#x9;C51.172,72.412,50.162,73.415,52.169,74.885z"/>
<g id="Layer_2_1_">
<path fill="#FAA51D" stroke="#231F20" stroke-width="1.2" d="M46.753,82.012c1.188-0.912,2.397-2.402,3.951-4.713&#xD;&#xA;&#x9;&#x9;c1.296-1.927,2.7-5.578,2.7-5.578c0.875-2.521,1.934-6.576-1.902-7.296c-1.553-0.291-4.079-0.098-7.67-0.776&#xD;&#xA;&#x9;&#x9;c-3.593-0.681-6.798-2.522-9.517,2.233c-2.718,4.757-9.59,8.271-1.056,16.563c0,0,4.901,3.842,10.764,9.639&#xD;&#xA;&#x9;&#x9;c4.831,4.775,12.045,10.602,12.045,10.602s18.972,2.188,19.535-0.693c1.922-9.79-14.777-6.911-14.777-6.911&#xD;&#xA;&#x9;&#x9;s-4.605-3.933-6.725-5.794c-3.478-3.059-11.125-10.771-11.125-10.771"/>
<path fill="#FFFFFF" d="M51.253,75.434c0,0,2.47-2.66-2.469-5.317c-4.939-2.657-7.213-0.017-8.739,1.521&#xD;&#xA;&#x9;&#x9;c-2.644,2.655,3.443,6.611,3.443,6.611l3.176,3.204c0,0,1.738-1.647,2.499-2.979C50.036,77.26,51.253,75.434,51.253,75.434"/>
</g>
<g id="Layer_8"/>
<path fill="#FAA51D" stroke="#231F20" stroke-width="1.2" d="M29.926,73.218c0.749-0.571,2.889-2.202,4.854-3.657&#xD;&#xA;&#x9;c2.428-1.799,6.117-5.849,1.077-7.646c-5.04-1.801-7.507,1.604-11.519,4.946c-2.159,1.801-5.308,2.699-4.319,6.209&#xD;&#xA;&#x9;c0.993,3.511,4.862,13.408,11.789,10.17c6.929-3.239-1.799-9.18-3.06-11.157"/>
<g id="Layer_2">
<path fill="#FAA51D" stroke="#231F20" stroke-width="1.2" d="M52.709,14.156c-1.54-0.143-4.75-0.316-6.518-0.231&#xD;&#xA;&#x9;&#x9;c-4.728,0.225-9.224,1.928-9.224,1.928L23.949,7.357l2.235,18.906c0.646-0.782-10.555,12.804-3.479,24.224&#xD;&#xA;&#x9;&#x9;c7.08,11.426,22.233,16.518,40.988,12.792c18.755-3.729,23.229-14.531,21.986-20.246c-1.242-5.714-8.322-7.823-8.322-7.823&#xD;&#xA;&#x9;&#x9;s-0.09-4.48-3.328-9.97c-1.926-3.268-8.348-8.041-8.348-8.041L62.822,5.647l-7.452,7.204L52.709,14.156z"/>
<path fill="#FFFFFF" d="M76.42,35.066l-2.482-2.064l-9.115,2.661c0,0,0,3.419-4.367,4.367c-4.37,0.951-11.211-2.277-11.211-2.277&#xD;&#xA;&#x9;&#x9;L41.46,41.17c0,0-8.437,0.928-8.739,6.081C32.048,58.704,46.1,63.479,51.425,63.783c2.905,0.167,8.235-0.338,12.277-1.141&#xD;&#xA;&#x9;&#x9;c17.752-3.234,22.551-13.919,21.31-19.635c-1.242-5.714-7.978-7.196-7.978-7.196L76.42,35.066z"/>
<path fill="none" stroke="#231F20" stroke-width="1.2" d="M10.673,46.155c0,0,4.107,0.374,5.974,0.268&#xD;&#xA;&#x9;&#x9;c1.865-0.107,5.492-0.587,5.492-0.587"/>
<path fill="none" stroke="#231F20" stroke-width="1.2" d="M81.656,40.671c0,0,4.549-0.743,6.859-1.549&#xD;&#xA;&#x9;&#x9;c2.715-0.942,4.543-2.545,4.543-2.545"/>
<path fill="none" stroke="#231F20" stroke-width="1.2" d="M22.337,41.909c0,0-2.384-1.777-6.117-3.43&#xD;&#xA;&#x9;&#x9;c-4.134-1.831-6.405-2.303-6.405-2.303"/>
<path fill="none" stroke="#231F20" stroke-width="1.2" d="M82.117,46.622c0,0,2.726,1.104,5.533,1.385&#xD;&#xA;&#x9;&#x9;c2.77,0.276,4.646,0.11,4.646,0.11"/>
<path fill="none" stroke="#000000" stroke-linecap="round" stroke-miterlimit="10" d="M52.35,14.212&#xD;&#xA;&#x9;&#x9;c2.84,0.7,3.887,1.469,3.887,1.469"/>
<line fill="none" stroke="#000000" x1="33.898" y1="13.684" x2="39.956" y2="18.042"/>
</g>
<g id="Layer_5">
<path fill="#FFFFFF" stroke="#231F20" d="M71.84,25.366c2.924,4.479,3.033,9.591,0.242,11.415&#xD;&#xA;&#x9;&#x9;c-2.793,1.825-7.426-0.332-10.354-4.813c-2.933-4.48-3.037-9.589-0.244-11.415C64.275,18.73,68.913,20.884,71.84,25.366z"/>
<path fill="#231F20" d="M71.089,32.522c0,1.08-0.802,1.956-1.8,1.956c-0.993,0-1.803-0.877-1.803-1.956&#xD;&#xA;&#x9;&#x9;c0-1.08,0.81-1.958,1.803-1.958C70.287,30.564,71.089,31.442,71.089,32.522"/>
</g>
<g id="Layer_7">
<path fill="#FFFFFF" stroke="#231F20" d="M47.867,28.619c2.926,4.48,2.619,9.862-0.681,12.015&#xD;&#xA;&#x9;&#x9;c-3.302,2.159-8.351,0.272-11.276-4.208c-2.928-4.48-2.624-9.86,0.678-12.017C39.891,22.253,44.938,24.137,47.867,28.619z"/>
<path fill="#231F20" d="M46.079,34.507c0,1.081-0.803,1.957-1.801,1.957c-0.992,0-1.803-0.878-1.803-1.957&#xD;&#xA;&#x9;&#x9;c0-1.08,0.811-1.957,1.803-1.957C45.274,32.55,46.079,33.427,46.079,34.507"/>
</g>
<path fill="#5E4A42" stroke="#000000" d="M59.766,37.926c1.854,0,4.555-0.284,4.697,0.569c0.143,0.855-1.709,4.203-2.988,4.345&#xD;&#xA;&#x9;c-1.283,0.142-6.125-2.353-6.195-3.919C55.206,37.355,58.055,37.926,59.766,37.926z"/>
<g id="Layer_4">
<path fill="none" stroke="#231F20" stroke-width="1.2" d="M46.774,45.235c0,0,10.347,3.054,14.217,3.897&#xD;&#xA;&#x9;&#x9;c3.868,0.842,10.851,1.684,10.851,1.684s-7.99,10.245-17.328,7.644C45.176,55.863,45.345,49.975,46.774,45.235z"/>
</g>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 6.5 KiB

@@ -1,37 +0,0 @@
<svg version="1.1" id="cat" x="0px" y="0px" width="95px" height="111px" viewBox="0 0 95 111" enable-background="new 0 0 95 111" xml:space="preserve" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<g>
<g id="Layer_8">
<path fill="#FAA51D" stroke="#231F20" stroke-width="1.2" d="M23.754,82.506c-2.871-1.402-10.511-2.518-14.771-6.695&#xD;&#xA;&#x9;&#x9;c-9.431-9.246-3.824-21.732,0.704-21.797c3.611-0.061,3.363,5.482,4.622,11.145c0.875,3.939,1.673,6.988,6.407,9.674&#xD;&#xA;&#x9;&#x9;c4.735,2.688,6.918,2.916,6.918,2.916s3.258,0.791,1.596,2.562C27.568,82.076,23.754,82.506,23.754,82.506z"/>
<path fill="#FFFFFF" d="M14.291,66.369c-0.115-0.459-0.222-0.928-0.33-1.413c-1.172-5.271-0.941-10.432-4.303-10.377&#xD;&#xA;&#x9;&#x9;c-3.433,0.05-7.53,7.771-4.19,15.285c0.193-0.143,0.399-0.336,0.569-0.588c0.451-0.664,0.821-2.969,2.654-3.688&#xD;&#xA;&#x9;&#x9;C9.989,65.082,12.778,65.869,14.291,66.369z"/>
</g>
<path fill="#FAA51D" stroke="#231F20" stroke-width="1.2" d="M52.543,61.473c0,0,1.455,2.342,1.519,4.969&#xD;&#xA;&#x9;c0.065,2.723-0.351,6.984,1.804,8.158c3.381,1.842,9.959-0.463,10.174,5.191c0.211,5.652-10.152,3.623-13.299,2.547&#xD;&#xA;&#x9;c-2.695-0.926-4.559-1.758-5.18-5.182c0,0-3.764-13.969-0.196-15.59C50.933,59.945,52.543,61.473,52.543,61.473z"/>
<path fill="#FAA51D" stroke="#231F20" stroke-width="1.2" d="M14.61,89.584c0,0,1.504,10.391-5.922,8.387&#xD;&#xA;&#x9;c-5.586-1.51-5.705-20.68-0.406-20.691c3.237-0.006,4.425,2.859,4.425,2.859s4.385,4.812,6.95,4.312&#xD;&#xA;&#x9;c2.565-0.502,7.978-6.703,7.978-6.703s2.875-2.539,6.146,0.023c3.271,2.561,1.521,6.178,1.521,6.178s-6.07,7.072-11.014,8.072&#xD;&#xA;&#x9;c-4.945,1.002-9.375-2.568-11.58-3.451"/>
<g id="Layer_6">
<path fill="#FAA51D" stroke="#231F20" stroke-width="1.2" d="M42.435,76.238c0,0,4.866,4.062,8.166,7.52&#xD;&#xA;&#x9;&#x9;c4.384,4.592-3.339,15.039-3.339,15.039s11.234,6.467,2.998,11c-2.657,1.467-15.661-13.225-15.661-13.225s7.979-7.475,4.972-10.172&#xD;&#xA;&#x9;&#x9;c-4.964-4.449-10.771-4.959-11.6-9.824c-0.502-2.957,0.613-4.502,2.658-7.053c1.354-1.689,2.084-3.182,2.084-3.182&#xD;&#xA;&#x9;&#x9;s1.135-7.238,4.289-8.254c3.153-1.014,8.842,0.057,10.758,0.395c1.914,0.338,6.645,1.877,4.617,9.922c0,0-1.451,3.771-2.789,5.762&#xD;&#xA;&#x9;&#x9;c-1.604,2.389-2.854,3.924-4.08,4.867"/>
<path fill="#FFFFFF" d="M50.182,72.631c0,0,2.55-2.748-2.551-5.494c-5.102-2.746-7.449-0.016-9.024,1.572&#xD;&#xA;&#x9;&#x9;c-2.731,2.742,3.334,7.453,3.334,7.453l3.383,2.564c0,0,1.916-1.582,2.701-2.957C48.807,74.396,50.182,72.631,50.182,72.631"/>
</g>
<path fill="#FAA51D" stroke="#231F20" stroke-width="1.2" d="M24.428,65.395c0.939,0.057,3.625,0.213,6.064,0.391&#xD;&#xA;&#x9;c3.014,0.217,8.451-0.451,5.801-5.098c-2.649-4.65-6.74-3.674-11.961-3.754c-2.812-0.043-5.785-1.412-7.322,1.895&#xD;&#xA;&#x9;c-1.534,3.312-5.051,13.338,2.313,15.396c7.366,2.057,4.618-8.137,4.95-10.457"/>
<g id="Layer_2">
<path fill="#FAA51D" stroke="#231F20" stroke-width="1.2" d="M51.709,10.156c-1.54-0.143-4.75-0.316-6.518-0.231&#xD;&#xA;&#x9;&#x9;c-4.728,0.225-9.224,1.928-9.224,1.928L22.949,3.357l2.235,18.906c0.646-0.782-10.555,12.804-3.479,24.224&#xD;&#xA;&#x9;&#x9;c7.08,11.426,22.233,16.518,40.988,12.792c18.755-3.728,23.229-14.531,21.986-20.246c-1.242-5.714-8.322-7.823-8.322-7.823&#xD;&#xA;&#x9;&#x9;s-0.09-4.48-3.328-9.97c-1.926-3.268-8.348-8.041-8.348-8.041L61.822,1.647L54.37,8.851L51.709,10.156z"/>
<path fill="#FFFFFF" d="M75.42,31.066l-2.483-2.064l-9.115,2.661c0,0,0,3.419-4.367,4.367c-4.37,0.951-11.211-2.277-11.211-2.277&#xD;&#xA;&#x9;&#x9;l-7.784,3.417c0,0-8.437,0.928-8.739,6.081C31.048,54.704,45.1,59.478,50.425,59.783c2.905,0.167,8.235-0.337,12.277-1.14&#xD;&#xA;&#x9;&#x9;c17.752-3.235,22.551-13.92,21.309-19.635c-1.242-5.714-7.977-7.196-7.977-7.196L75.42,31.066z"/>
<path fill="none" stroke="#231F20" stroke-width="1.2" d="M9.673,42.155c0,0,4.107,0.374,5.974,0.268&#xD;&#xA;&#x9;&#x9;c1.865-0.107,5.492-0.587,5.492-0.587"/>
<path fill="none" stroke="#231F20" stroke-width="1.2" d="M80.656,36.671c0,0,4.549-0.743,6.859-1.549&#xD;&#xA;&#x9;&#x9;c2.715-0.942,4.543-2.545,4.543-2.545"/>
<path fill="none" stroke="#231F20" stroke-width="1.2" d="M21.337,37.909c0,0-2.384-1.777-6.117-3.43&#xD;&#xA;&#x9;&#x9;c-4.134-1.831-6.405-2.303-6.405-2.303"/>
<path fill="none" stroke="#231F20" stroke-width="1.2" d="M81.117,42.622c0,0,2.726,1.104,5.533,1.385&#xD;&#xA;&#x9;&#x9;c2.77,0.276,4.647,0.11,4.647,0.11"/>
<path fill="none" stroke="#000000" stroke-linecap="round" stroke-miterlimit="10" d="M51.349,10.212&#xD;&#xA;&#x9;&#x9;c2.84,0.7,3.888,1.469,3.888,1.469"/>
<line fill="none" stroke="#000000" x1="32.898" y1="9.684" x2="38.956" y2="14.042"/>
</g>
<g id="Layer_5">
<path fill="#FFFFFF" stroke="#231F20" d="M70.84,21.366c2.924,4.479,3.033,9.591,0.242,11.415&#xD;&#xA;&#x9;&#x9;c-2.793,1.825-7.426-0.332-10.354-4.813c-2.932-4.48-3.037-9.589-0.244-11.415C63.275,14.73,67.913,16.884,70.84,21.366z"/>
<path fill="#231F20" d="M70.089,28.522c0,1.08-0.802,1.956-1.8,1.956c-0.993,0-1.803-0.877-1.803-1.956&#xD;&#xA;&#x9;&#x9;c0-1.08,0.81-1.958,1.803-1.958C69.287,26.564,70.089,27.442,70.089,28.522"/>
</g>
<g id="Layer_7">
<path fill="#FFFFFF" stroke="#231F20" d="M46.867,24.619c2.926,4.48,2.619,9.862-0.681,12.015&#xD;&#xA;&#x9;&#x9;c-3.302,2.159-8.351,0.272-11.276-4.208c-2.928-4.48-2.624-9.86,0.678-12.017C38.891,18.253,43.938,20.137,46.867,24.619z"/>
<path fill="#231F20" d="M45.079,30.507c0,1.081-0.803,1.957-1.801,1.957c-0.992,0-1.803-0.878-1.803-1.957&#xD;&#xA;&#x9;&#x9;c0-1.08,0.811-1.957,1.803-1.957C44.274,28.55,45.079,29.427,45.079,30.507"/>
</g>
<path fill="#5E4A42" stroke="#000000" d="M58.766,33.926c1.854,0,4.555-0.284,4.697,0.569c0.143,0.855-1.709,4.203-2.988,4.345&#xD;&#xA;&#x9;c-1.283,0.142-6.125-2.353-6.195-3.919C54.206,33.355,57.055,33.926,58.766,33.926z"/>
<g id="Layer_4">
<path fill="none" stroke="#231F20" stroke-width="1.2" d="M45.774,41.235c0,0,10.347,3.054,14.217,3.897&#xD;&#xA;&#x9;&#x9;c3.868,0.842,10.851,1.684,10.851,1.684s-7.99,10.245-17.328,7.644C44.176,51.863,44.345,45.975,45.774,41.235z"/>
</g>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 6.1 KiB

@@ -0,0 +1,42 @@
<svg width="96px" height="101px" viewBox="0 0 96 101" version="1.1" xml:space="preserve" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<!-- Generator: Sketch 52.5 (67469) - http://www.bohemiancoding.com/sketch -->
<g>
<title>costume1.1</title>
<desc>Created with Sketch.</desc>
<g id="Page-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g id="costume1" transform="translate(-13.000000, -10.000000)">
<g id="costume1.1" transform="translate(13.000000, 10.000000)">
<g id="tail" transform="translate(0.000000, 59.000000)">
<path d="M21.9,14.8 C19.5,14.3 16.6,13.5 14.2,11.3 C8.7,6.4 7,-1.7 3.2,0.4 C-0.7,2.5 -0.6,15.6 11.6,19.6 C15.8,21 19.6,21 22.7,20.9 C23.5,20.9 30.4,20.2 32.8,16.8 C35.2,13.4 33.5,12.5 32.7,12.1 C31.8,11.6 25.3,15.4 21.9,14.8 Z" stroke="#001026" stroke-width="1.2" fill="#FFAB19" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M3.8,0.6 C1.8,1.2 0.8,5.4 1.8,8.9 C2.8,12.4 4.4,14.2 5.7,15.5 C5.5,14.8 5.1,12.6 6.8,11.3 C8.9,9.6 12.6,10.5 12.6,10.5 C12.6,10.5 9.5,6.7 7.9,4 C6.3,1.7 5.8,0.2 3.8,0.6 Z" id="detail" fill="#FFFFFF"/>
</g>
<path d="M37.7,81.5 C35.9,82.7 29.7,87.1 21.8,89.6 L21.4,89.7 C21,89.8 20.8,90.3 21,90.7 C22.7,93.1 25.8,97.9 20.3,99.6 C15,101.3 5.1,87.2 9.3,83.5 C11.2,82.1 12.9,82.8 13.8,83.2 C14.3,83.4 14.8,83.4 15.3,83.3 C16.5,82.9 18.7,82.1 20.4,81.2 C24.7,79 25.7,78.1 27.7,76.6 C29.7,75.1 34.3,71.4 38,74.6 C41.2,77.3 39.4,80.3 37.7,81.5 Z" id="leg" stroke="#001026" stroke-width="1.2" fill="#FFAB19" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M53.6,60.7 C54.1,61.1 60.2,68.3 62.2,66.5 C64.6,64.4 67.9,60.3 71.5,63.6 C75.1,66.9 68.3,72.5 65.4,74 C58.5,77.1 52.9,71.2 51.7,69.6 C50.5,68 48.4,65.3 48.4,62.7 C48.5,59.9 51.9,59.2 53.6,60.7 Z" id="arm" stroke="#001026" stroke-width="1.2" fill="#FFAB19" stroke-linecap="round" stroke-linejoin="round"/>
<g id="body-and-leg" transform="translate(28.000000, 57.000000)">
<path d="M18.2,19.7 C19.4,18.8 20.6,17.3 22.2,15 C23.5,13.1 24.9,9.4 24.9,9.4 C25.8,6.9 26.4,2.1 23.1,2.2 C20.9,2.3 18.9,2 15.5,1.5 C9.5,0.3 8.4,-0.5 5.9,3.6 C3.2,8.4 -3.7,11.9 4.8,20.2 C4.8,20.2 9.7,24 15.6,29.8 C19.6,33.7 25.9,39.3 28.1,41.2 C28.6,41.6 29.2,41.8 29.8,41.9 C39.5,42.8 46.7,41.8 46.7,37.5 C46.7,30.3 32.4,32.8 32.4,32.8 C32.4,32.8 27.8,28.9 25.7,27 L18.2,19.7 Z" id="body" stroke="#001026" stroke-width="1.2" fill="#FFAB19" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M22.6,13 C22.6,13 24.5,10.5 20.2,7.8 C15.7,4.9 14,8.1 12.2,10.5 C10.2,13.6 12.2,15.1 14.2,16.9 C15.8,18.4 17.3,19.6 17.3,19.6 C17.3,19.6 20.4,17.5 22.6,13 Z" id="tummy" fill="#FFFFFF"/>
</g>
<path d="M30.2,68.4 C32.4,71.2 35.8,74.7 31.5,77.6 C25.6,80.9 20.7,70.9 19.7,67.4 C18.8,64.3 21.4,62.3 23.6,60.6 C27.9,57.5 31.5,54.7 35.5,56.2 C40.5,58 36.9,62 34.4,63.8 C32.9,64.9 31.4,66.1 30.3,66.8 C30,67.3 29.9,67.9 30.2,68.4 Z" id="arm" stroke="#001026" stroke-width="1.2" fill="#FFAB19" stroke-linecap="round" stroke-linejoin="round"/>
<g id="head" transform="translate(14.000000, 0.000000)">
<path d="M39.1,9 C36.8,8.6 34.4,8.4 31.6,8.6 C26.9,8.8 22.4,10.5 22.4,10.5 L10.3,2.6 C9.9,2.4 9.4,2.7 9.5,3.1 L11.6,21 C12.2,20.2 1,33.8 8.1,45.2 C15.2,56.6 30.3,61.7 49.1,58 C67.9,54.3 72.3,43.5 71.1,37.8 C69.9,32.1 62.8,30 62.8,30 C62.8,30 62.7,25.5 59.5,20 C57.6,16.7 51.2,12 51.2,12 L48.6,1.3 C48.5,0.9 48,0.8 47.7,1 L39.1,9 Z" stroke="#001026" stroke-width="1.2" fill="#FFAB19"/>
<path d="M62.5,30.4 C62.5,30.4 69.4,32.2 70.6,37.9 C71.8,43.6 67,53.9 48.4,57.5 C24.2,62.5 12.7,48.1 19.4,37.5 C26.1,26.8 37.6,35.9 46,35.3 C53.2,34.8 54,28.5 62.5,30.4 Z" id="face" fill="#FFFFFF"/>
<path d="M31,41.1 C31,40.7 31.4,40.4 31.8,40.5 C33.7,41.2 39.1,42.8 45.1,43.2 C50.5,43.5 53.7,43.2 55.2,42.9 C55.7,42.8 56.1,43.3 55.9,43.8 C55,46.5 51.2,54 40.7,53.4 C31.6,52.4 30.7,46 31,41.1 Z" id="mouth" stroke="#001026" stroke-width="1.2" fill="#FFFFFF" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M69,35.4 C69,35.4 76.2,35.3 80.9,31.5" id="whisker" stroke="#001026" stroke-width="1.2" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M69.4,41.3 C69.4,41.3 73.3,43.2 79.6,42.7" id="whisker" stroke="#001026" stroke-width="1.2" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M45.6,32.7 C47.7,32.7 49.9,32.9 50,33.6 C50.1,35 48.6,37.8 47,37.9 C45.2,38.1 41,35.6 41,34 C40.9,32.8 43.6,32.7 45.6,32.7 Z" id="nose" stroke="#001026" stroke-width="1.2" fill="#001026" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M0.6,31.2 C0.6,31.2 9.2,34 12.7,37.1" id="whisker" stroke="#001026" stroke-width="1.2" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M1.3,41.2 C1.3,41.2 8.7,42.3 13,40.6" id="whisker" stroke="#001026" stroke-width="1.2" stroke-linecap="round" stroke-linejoin="round"/>
<g id="eye" transform="translate(44.000000, 15.000000)">
<path d="M13.4,6 C16.3,10.5 16.4,15.6 13.6,17.4 C10.8,19.2 6.2,17.1 3.2,12.6 C0.3,8.1 0.2,3 3,1.2 C5.8,-0.7 10.5,1.5 13.4,6 Z" id="pupil" stroke="#001026" stroke-width="1.2" fill="#FFFFFF" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M13,11.7 C13,12.8 12.2,13.7 11.2,13.7 C10.2,13.7 9.4,12.8 9.4,11.7 C9.4,10.6 10.2,9.7 11.2,9.7 C12.2,9.7 13,10.6 13,11.7" id="pupil" fill="#001026"/>
</g>
<g id="eye" transform="translate(19.000000, 18.000000)">
<path d="M13.6,5.8 C16.6,10.2 16.4,15.6 13.7,17.5 C10.4,19.4 6,18 3,13.6 C-0.1,9.2 -0.3,3.5 2.8,1.3 C5.9,-1 10.6,1.4 13.6,5.8 Z" stroke="#001026" stroke-width="1.2" fill="#FFFFFF" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M13,11.6 C13,12.7 12.2,13.6 11.2,13.6 C10.2,13.6 9.4,12.7 9.4,11.6 C9.4,10.5 10.2,9.6 11.2,9.6 C12.2,9.7 13,10.5 13,11.6" id="pupil" fill="#001026"/>
</g>
</g>
</g>
</g>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 5.9 KiB

@@ -0,0 +1,42 @@
<svg width="93px" height="106px" viewBox="0 0 93 106" version="1.1" xml:space="preserve" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<!-- Generator: Sketch 52.5 (67469) - http://www.bohemiancoding.com/sketch -->
<g>
<title>costume2.1</title>
<desc>Created with Sketch.</desc>
<g id="Page-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g id="cotsume2" transform="translate(-16.000000, -10.000000)">
<g id="costume2.1" transform="translate(16.250000, 9.500000)">
<g id="tail" transform="translate(0.000000, 53.000000)">
<path d="M12,14.8 C8.9,7 10.6,0 6.3,0.4 C1.9,0.8 -3.2,12.5 6.4,21.1 C15.3,29 24.4,26.1 28,24 C31.5,21.8 28.8,20.6 28.2,19.8 C27.6,19 16.4,26.1 12,14.8 Z" stroke="#001026" stroke-width="1.2" fill="#FFAB19" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M6.8,0.9 C4.3,0.5 2.1,4.1 1.6,7.6 C1.4,11.2 2,13.3 2.7,15 C2.8,14.3 3.7,11.9 6.6,11.4 C9,11 10.6,13 10.6,13 C10.6,13 9.6,10 9.1,5.6 C8.7,2.9 8.8,1.3 6.8,0.9 Z" id="detail" fill="#FFFFFF"/>
</g>
<path d="M32.9,83.2 C32.2,84.1 30.2,87.6 25.4,90.6 C22.1,92.7 13.6,89.2 13.6,89.2 C14.5,98.4 7,98.2 5.6,95.2 C4.5,92.8 4.7,82.5 6.9,81.7 C10.3,80.5 14.9,82.5 19,82.5 C20.2,82.5 21.5,79.9 24.3,77.1 C26.3,75.1 28.9,71.4 33.1,74 C36.7,76.3 34.8,80.5 32.9,83.2 Z" id="leg" stroke="#001026" stroke-width="1.2" fill="#FFAB19" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M50.1,62 C50.4,64.2 50.6,72.6 53,73.9 C55.3,75.1 62.3,73.1 62.7,78 C63.1,82.8 56.6,82.9 51.2,81.4 C44.2,79.5 41,68.8 45,62.2 C46.5,59.9 49.8,59.7 50.1,62 Z" id="arm" stroke="#001026" stroke-width="1.2" fill="#FFAB19" stroke-linecap="round" stroke-linejoin="round"/>
<g id="body-and-leg" transform="translate(24.000000, 57.000000)">
<path d="M18.2,21.3 C19.4,20.4 21.2,18 22.8,15.6 C24.1,13.7 25.5,10 25.5,10 C26.4,7.5 27,2.7 23.7,2.8 C21.5,2.9 19.5,2.6 16.1,2.1 C10.1,0.9 8.9,-0.3 6.5,4.2 C2,12.5 -4,18.4 4.2,23.2 C6.2,24.4 9.4,26.4 12.2,28.4 C14.2,30.3 11.2,34.4 9.1,36.8 C8.2,37.9 8.2,39.5 9.3,40.6 C16.6,47.7 18.8,50.2 21.6,47.1 C25.4,42.9 19.4,38.8 19.4,38.8 C19.4,38.8 24.2,31.3 23.6,28 C22.9,24.8 18.2,21.3 18.2,21.3 Z" id="body" stroke="#001026" stroke-width="1.2" fill="#FFAB19" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M22.7284271,14.6028611 C22.7284271,14.6028611 24.6284271,12.1028611 20.3284271,9.40286109 C15.8284271,6.50286109 14.1284271,9.70286109 12.3284271,12.1028611 C10.3284271,15.2028611 12.3284271,16.7028611 14.3284271,18.5028611 C15.9284271,20.0028611 17.4284271,21.2028611 17.4284271,21.2028611 C17.4284271,21.2028611 20.5284271,19.1028611 22.7284271,14.6028611 Z" id="tummy" fill="#FFFFFF"/>
</g>
<path d="M32.3,65.2 C30.1,66.2 26,64.4 24.9,64.6 C24.6,64.7 22.8,69.9 21.7,73 C20.2,77.4 13.4,76.1 13,71.5 C12.7,67.2 16.6,58.9 17.9,57.4 C20.8,53.9 30.6591797,56.7082962 37.2463379,58.456543" id="arm" stroke="#001026" stroke-width="1.2" fill="#FFAB19" stroke-linecap="round" stroke-linejoin="round"/>
<g id="head" transform="translate(10.750000, 0.500000)">
<path d="M39.1,9 C36.8,8.6 34.4,8.4 31.6,8.6 C26.9,8.8 22.4,10.5 22.4,10.5 L10.3,2.6 C9.9,2.4 9.4,2.7 9.5,3.1 L11.6,21 C12.2,20.2 1,33.8 8.1,45.2 C15.2,56.6 30.3,61.7 49.1,58 C67.9,54.3 72.3,43.5 71.1,37.8 C69.9,32.1 62.8,30 62.8,30 C62.8,30 62.7,25.5 59.5,20 C57.6,16.7 51.2,12 51.2,12 L48.6,1.3 C48.5,0.9 48,0.8 47.7,1 L39.1,9 Z" stroke="#001026" stroke-width="1.2" fill="#FFAB19"/>
<path d="M62.5,30.4 C62.5,30.4 69.4,32.2 70.6,37.9 C71.8,43.6 67,53.9 48.4,57.5 C24.2,62.5 12.7,48.1 19.4,37.5 C26.1,26.8 37.6,35.9 46,35.3 C53.2,34.8 54,28.5 62.5,30.4 Z" id="face" fill="#FFFFFF"/>
<path d="M31,41.1 C31,40.7 31.4,40.4 31.8,40.5 C33.7,41.2 39.1,42.8 45.1,43.2 C50.5,43.5 53.7,43.2 55.2,42.9 C55.7,42.8 56.1,43.3 55.9,43.8 C55,46.5 51.2,54 40.7,53.4 C31.6,52.4 30.7,46 31,41.1 Z" id="mouth" stroke="#001026" stroke-width="1.2" fill="#FFFFFF" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M69,35.4 C69,35.4 76.2,35.3 80.9,31.5" id="whisker" stroke="#001026" stroke-width="1.2" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M69.4,41.3 C69.4,41.3 73.3,43.2 79.6,42.7" id="whisker" stroke="#001026" stroke-width="1.2" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M45.6,32.7 C47.7,32.7 49.9,32.9 50,33.6 C50.1,35 48.6,37.8 47,37.9 C45.2,38.1 41,35.6 41,34 C40.9,32.8 43.6,32.7 45.6,32.7 Z" id="nose" stroke="#001026" stroke-width="1.2" fill="#001026" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M0.6,31.2 C0.6,31.2 9.2,34 12.7,37.1" id="whisker" stroke="#001026" stroke-width="1.2" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M1.3,41.2 C1.3,41.2 8.7,42.3 13,40.6" id="whisker" stroke="#001026" stroke-width="1.2" stroke-linecap="round" stroke-linejoin="round"/>
<g id="eye" transform="translate(44.000000, 15.000000)">
<path d="M13.4,6 C16.3,10.5 16.4,15.6 13.6,17.4 C10.8,19.2 6.2,17.1 3.2,12.6 C0.3,8.1 0.2,3 3,1.2 C5.8,-0.7 10.5,1.5 13.4,6 Z" id="pupil" stroke="#001026" stroke-width="1.2" fill="#FFFFFF" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M13,11.7 C13,12.8 12.2,13.7 11.2,13.7 C10.2,13.7 9.4,12.8 9.4,11.7 C9.4,10.6 10.2,9.7 11.2,9.7 C12.2,9.7 13,10.6 13,11.7" id="pupil" fill="#001026"/>
</g>
<g id="eye" transform="translate(19.000000, 18.000000)">
<path d="M13.6,5.8 C16.6,10.2 16.4,15.6 13.7,17.5 C10.4,19.4 6,18 3,13.6 C-0.1,9.2 -0.3,3.5 2.8,1.3 C5.9,-1 10.6,1.4 13.6,5.8 Z" stroke="#001026" stroke-width="1.2" fill="#FFFFFF" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M13,11.6 C13,12.7 12.2,13.6 11.2,13.6 C10.2,13.6 9.4,12.7 9.4,11.6 C9.4,10.5 10.2,9.6 11.2,9.6 C12.2,9.7 13,10.5 13,11.6" id="pupil" fill="#001026"/>
</g>
</g>
</g>
</g>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 5.9 KiB

+4 -4
View File
@@ -4,8 +4,8 @@ import projectData from './project-data';
import popWav from '!arraybuffer-loader!./83a9787d4cb6f3b7632b4ddfebf74367.wav';
import meowWav from '!arraybuffer-loader!./83c36d806dc92327b9e7049a565c6bff.wav';
import backdrop from '!raw-loader!./cd21514d0531fdffb22204e0ec5ed84a.svg';
import costume1 from '!raw-loader!./09dc888b0b7df19f70d81588ae73420e.svg';
import costume2 from '!raw-loader!./3696356a03a8d938318876a593572843.svg';
import costume1 from '!raw-loader!./b7853f557e4426412e64bb3da6531a99.svg';
import costume2 from '!raw-loader!./e6ddc55a6ddd9cc9d84fe0b4c21e016f.svg';
/* eslint-enable import/no-unresolved */
const defaultProject = translator => {
@@ -40,12 +40,12 @@ const defaultProject = translator => {
dataFormat: 'SVG',
data: encoder.encode(backdrop)
}, {
id: '09dc888b0b7df19f70d81588ae73420e',
id: 'b7853f557e4426412e64bb3da6531a99',
assetType: 'ImageVector',
dataFormat: 'SVG',
data: encoder.encode(costume1)
}, {
id: '3696356a03a8d938318876a593572843',
id: 'e6ddc55a6ddd9cc9d84fe0b4c21e016f',
assetType: 'ImageVector',
dataFormat: 'SVG',
data: encoder.encode(costume2)
+1 -1
View File
@@ -240,7 +240,7 @@ export default [
/>
),
featured: true,
disabled: true,
disabled: false,
bluetoothRequired: true,
internetConnectionRequired: true,
launchPeripheralConnectionFlow: true,
+2
View File
@@ -115,8 +115,10 @@ const ProjectFetcherHOC = function (WrappedComponent) {
assetHost: PropTypes.string,
canSave: PropTypes.bool,
intl: intlShape.isRequired,
isCreatingNew: PropTypes.bool,
isFetchingWithId: PropTypes.bool,
isLoadingProject: PropTypes.bool,
isShowingProject: PropTypes.bool,
loadingState: PropTypes.oneOf(LoadingStates),
onActivateTab: PropTypes.func,
onError: PropTypes.func,
+6
View File
@@ -343,6 +343,7 @@ const ProjectSaverHOC = function (WrappedComponent) {
}
ProjectSaverComponent.propTypes = {
autoSaveIntervalSecs: PropTypes.number.isRequired,
autoSaveTimeoutId: PropTypes.number,
canCreateNew: PropTypes.bool,
canSave: PropTypes.bool,
@@ -358,12 +359,16 @@ const ProjectSaverHOC = function (WrappedComponent) {
isShowingWithoutId: PropTypes.bool,
isUpdating: PropTypes.bool,
loadingState: PropTypes.oneOf(LoadingStates),
locale: PropTypes.string.isRequired,
onAutoUpdateProject: PropTypes.func,
onCreateProject: PropTypes.func,
onCreatedProject: PropTypes.func,
onProjectError: PropTypes.func,
onProjectTelemetryEvent: PropTypes.func,
onRemixing: PropTypes.func,
onSetProjectSaver: PropTypes.func.isRequired,
onSetProjectThumbnailer: PropTypes.func.isRequired,
onSetProjectUnchanged: PropTypes.func.isRequired,
onShowAlert: PropTypes.func,
onShowCopySuccessAlert: PropTypes.func,
onShowCreatingCopyAlert: PropTypes.func,
@@ -377,6 +382,7 @@ const ProjectSaverHOC = function (WrappedComponent) {
projectChanged: PropTypes.bool,
reduxProjectId: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
reduxProjectTitle: PropTypes.string,
setAutoSaveTimeoutId: PropTypes.func.isRequired,
vm: PropTypes.instanceOf(VM).isRequired
};
ProjectSaverComponent.defaultProps = {
+4 -2
View File
@@ -60,9 +60,9 @@ const vmListenerHOC = function (WrappedComponent) {
this.props.vm.postIOData('userData', {username: this.props.username});
}
// Re-request a targets update when the shouldEmitTargetsUpdate state changes to true
// Re-request a targets update when the shouldEmitUpdate state changes to true
// i.e. when the editor transitions out of fullscreen/player only modes
if (this.props.shouldEmitTargetsUpdate && !prevProps.shouldEmitTargetsUpdate) {
if (this.props.shouldEmitUpdates && !prevProps.shouldEmitUpdates) {
this.props.vm.emitTargetsUpdate(false /* Emit the event, but do not trigger project change */);
}
}
@@ -148,8 +148,10 @@ const vmListenerHOC = function (WrappedComponent) {
onKeyUp: PropTypes.func,
onMicListeningUpdate: PropTypes.func.isRequired,
onMonitorsUpdate: PropTypes.func.isRequired,
onProjectChanged: PropTypes.func.isRequired,
onProjectRunStart: PropTypes.func.isRequired,
onProjectRunStop: PropTypes.func.isRequired,
onProjectSaved: PropTypes.func.isRequired,
onRuntimeStarted: PropTypes.func.isRequired,
onShowExtensionAlert: PropTypes.func.isRequired,
onTargetsUpdate: PropTypes.func.isRequired,
+1
View File
@@ -107,6 +107,7 @@ const vmManagerHOC = function (WrappedComponent) {
fontsLoaded: PropTypes.bool,
isLoadingWithId: PropTypes.bool,
isPlayerOnly: PropTypes.bool,
isStarted: PropTypes.bool,
loadingState: PropTypes.oneOf(LoadingStates),
locale: PropTypes.string,
messages: PropTypes.objectOf(PropTypes.string),
+14
View File
@@ -3,6 +3,7 @@ import analytics from '../lib/analytics';
import decks from '../lib/libraries/decks/index.jsx';
const CLOSE_CARDS = 'scratch-gui/cards/CLOSE_CARDS';
const SHRINK_EXPAND_CARDS = 'scratch-gui/cards/SHRINK_EXPAND_CARDS';
const VIEW_CARDS = 'scratch-gui/cards/VIEW_CARDS';
const ACTIVATE_DECK = 'scratch-gui/cards/ACTIVATE_DECK';
const NEXT_STEP = 'scratch-gui/cards/NEXT_STEP';
@@ -18,6 +19,7 @@ const initialState = {
step: 0,
x: 0,
y: 0,
expanded: true,
dragging: false
};
@@ -28,6 +30,10 @@ const reducer = function (state, action) {
return Object.assign({}, state, {
visible: false
});
case SHRINK_EXPAND_CARDS:
return Object.assign({}, state, {
expanded: !state.expanded
});
case VIEW_CARDS:
return Object.assign({}, state, {
visible: true
@@ -36,6 +42,9 @@ const reducer = function (state, action) {
return Object.assign({}, state, {
activeDeckId: action.activeDeckId,
step: 0,
x: 0,
y: 0,
expanded: true,
visible: true
});
case NEXT_STEP:
@@ -92,6 +101,10 @@ const closeCards = function () {
return {type: CLOSE_CARDS};
};
const shrinkExpandCards = function () {
return {type: SHRINK_EXPAND_CARDS};
};
const nextStep = function () {
return {type: NEXT_STEP};
};
@@ -118,6 +131,7 @@ export {
activateDeck,
viewCards,
closeCards,
shrinkExpandCards,
nextStep,
prevStep,
dragCard,
+1
View File
@@ -107,6 +107,7 @@ const initTutorialCard = function (currentState, deckId) {
visible: true,
content: decks,
activeDeckId: deckId,
expanded: true,
step: 0,
x: 0,
y: 0,
+14 -10
View File
@@ -8,6 +8,11 @@ const {By, until, Button} = webdriver;
const USE_HEADLESS = process.env.USE_HEADLESS !== 'no';
// The main reason for this timeout is so that we can control the timeout message and report details;
// if we hit the Jasmine default timeout then we get a terse message that we can't control.
// The Jasmine default timeout is 30 seconds so make sure this is lower.
const DEFAULT_TIMEOUT_MILLISECONDS = 20 * 1000;
class SeleniumHelper {
constructor () {
bindAll(this, [
@@ -21,13 +26,12 @@ class SeleniumHelper {
'getSauceDriver',
'getLogs',
'loadUri',
'rightClickText',
'waitUntilGone'
'rightClickText'
]);
}
elementIsVisible (element) {
return this.driver.wait(until.elementIsVisible(element));
elementIsVisible (element, timeoutMessage = 'elementIsVisible timed out') {
return this.driver.wait(until.elementIsVisible(element), DEFAULT_TIMEOUT_MILLISECONDS, timeoutMessage);
}
get scope () {
@@ -79,8 +83,12 @@ class SeleniumHelper {
return this.driver;
}
findByXpath (xpath) {
return this.driver.wait(until.elementLocated(By.xpath(xpath), 5 * 1000));
findByXpath (xpath, timeoutMessage = `findByXpath timed out for path: ${xpath}`) {
return this.driver.wait(until.elementLocated(By.xpath(xpath)), DEFAULT_TIMEOUT_MILLISECONDS, timeoutMessage)
.then(el => (
this.driver.wait(el.isDisplayed(), DEFAULT_TIMEOUT_MILLISECONDS, `${xpath} is not visible`)
.then(() => el)
));
}
findByText (text, scope) {
@@ -120,10 +128,6 @@ class SeleniumHelper {
return this.clickXpath(`//button//*[contains(text(), '${text}')]`);
}
waitUntilGone (element) {
return this.driver.wait(until.stalenessOf(element));
}
getLogs (whitelist) {
if (!whitelist) {
// Default whitelist
+47 -7
View File
@@ -25,7 +25,7 @@ describe('Working with backdrops', () => {
await driver.quit();
});
test('Adding a backdrop from the library', async () => {
test('Adding a backdrop from the library should not switch to stage', async () => {
await loadUri(uri);
// Start on the sounds tab of sprite1 to test switching behavior
@@ -37,12 +37,11 @@ describe('Working with backdrops', () => {
await el.sendKeys('blue');
await clickText('Blue Sky'); // Adds the backdrop
// Make sure the stage is selected and the sound tab remains selected.
// This is different from Scratch2 which selected backdrop tab automatically
// See issue #3500
await clickText('pop', scope.soundsTab);
// Make sure the sprite is still selected, and that the tab has not changed
await clickText('Meow', scope.soundsTab);
// Make sure the backdrop was actually added by going to the backdrops tab
await clickXpath('//span[text()="Stage"]');
await clickText('Backdrops');
await clickText('Blue Sky', scope.costumesTab);
@@ -50,7 +49,48 @@ describe('Working with backdrops', () => {
await expect(logs).toEqual([]);
});
test('Adding multiple backdrops at the same time', async () => {
test('Adding backdrop via paint should switch to stage', async () => {
await loadUri(uri);
const buttonXpath = '//button[@aria-label="Choose a Backdrop"]';
const paintXpath = `${buttonXpath}/following-sibling::div//button[@aria-label="Paint"]`;
const el = await findByXpath(buttonXpath);
await driver.actions().mouseMove(el)
.perform();
await driver.sleep(500); // Wait for thermometer menu to come up
await clickXpath(paintXpath);
// Stage should become selected and costume tab activated
await findByText('backdrop2', scope.costumesTab);
const logs = await getLogs();
await expect(logs).toEqual([]);
});
test('Adding backdrop via surprise should not switch to stage', async () => {
await loadUri(uri);
// Start on the sounds tab of sprite1 to test switching behavior
await clickText('Sounds');
const buttonXpath = '//button[@aria-label="Choose a Backdrop"]';
const surpriseXpath = `${buttonXpath}/following-sibling::div//button[@aria-label="Surprise"]`;
const el = await findByXpath(buttonXpath);
await driver.actions().mouseMove(el)
.perform();
await driver.sleep(500); // Wait for thermometer menu to come up
await clickXpath(surpriseXpath);
// Make sure the sprite is still selected, and that the tab has not changed
await clickText('Meow', scope.soundsTab);
const logs = await getLogs();
await expect(logs).toEqual([]);
});
test('Adding multiple backdrops from file should switch to stage', async () => {
const files = [
path.resolve(__dirname, '../fixtures/gh-3582-png.png'),
path.resolve(__dirname, '../fixtures/100-100.svg')
@@ -67,7 +107,7 @@ describe('Working with backdrops', () => {
const input = await findByXpath(fileXpath);
await input.sendKeys(files.join('\n'));
await clickXpath('//span[text()="Stage"]');
// Should have been switched to stage/costume tab already
await findByText('gh-3582-png', scope.costumesTab);
await findByText('100-100', scope.costumesTab);
+3 -6
View File
@@ -4,15 +4,13 @@ import path from 'path';
import SeleniumHelper from '../helpers/selenium-helper';
const {
findByText,
clickButton,
clickText,
clickXpath,
findByXpath,
getDriver,
getLogs,
loadUri,
waitUntilGone
loadUri
} = new SeleniumHelper();
let driver;
@@ -28,10 +26,9 @@ describe('player example', () => {
await driver.quit();
});
test('Load a project by ID', async () => {
test.skip('Player: load a project by ID', async () => {
const projectId = '96708228';
await loadUri(`${uri}#${projectId}`);
await waitUntilGone(findByText('Loading'));
await clickXpath('//img[@title="Go"]');
await new Promise(resolve => setTimeout(resolve, 2000));
await clickXpath('//img[@title="Stop"]');
@@ -59,7 +56,7 @@ describe('blocks example', () => {
await driver.quit();
});
test('Load a project by ID', async () => {
test.skip('Blocks: load a project by ID', async () => {
const projectId = '96708228';
await loadUri(`${uri}#${projectId}`);
await new Promise(resolve => setTimeout(resolve, 2000));
+1 -4
View File
@@ -9,8 +9,7 @@ const {
getDriver,
loadUri,
rightClickText,
scope,
waitUntilGone
scope
} = new SeleniumHelper();
const uri = path.resolve(__dirname, '../../build/index.html');
@@ -78,7 +77,6 @@ describe('Menu bar settings', () => {
await clickText('File');
const input = await findByXpath('//input[@accept=".sb,.sb2,.sb3"]');
await input.sendKeys(path.resolve(__dirname, '../fixtures/project1.sb3'));
await waitUntilGone(findByText('Loading'));
// No replace alert since no changes were made
await findByText('project1-sprite');
});
@@ -95,7 +93,6 @@ describe('Menu bar settings', () => {
await input.sendKeys(path.resolve(__dirname, '../fixtures/project1.sb3'));
await driver.switchTo().alert()
.accept();
await waitUntilGone(findByText('Loading'));
await findByText('project1-sprite');
});
});
+9 -10
View File
@@ -9,8 +9,7 @@ const {
getDriver,
getLogs,
loadUri,
scope,
waitUntilGone
scope
} = new SeleniumHelper();
const uri = path.resolve(__dirname, '../../build/index.html');
@@ -33,13 +32,14 @@ describe('Loading scratch gui', () => {
await clickText('Oops! Something went wrong.');
});
test('Load a project by ID directly through url', async () => {
// skipping because it relies on network speed, and tests a method
// of loading projects that we are not actively using anymore
test.skip('Load a project by ID directly through url', async () => {
await driver.quit(); // Reset driver to test hitting # url directly
driver = getDriver();
const projectId = '96708228';
await loadUri(`${uri}#${projectId}`);
await waitUntilGone(findByText('Loading'));
await clickXpath('//img[@title="Go"]');
await new Promise(resolve => setTimeout(resolve, 2000));
await clickXpath('//img[@title="Stop"]');
@@ -47,7 +47,9 @@ describe('Loading scratch gui', () => {
await expect(logs).toEqual([]);
});
test('Load a project by ID (fullscreen)', async () => {
// skipping because it relies on network speed, and tests a method
// of loading projects that we are not actively using anymore
test.skip('Load a project by ID (fullscreen)', async () => {
await driver.quit(); // Reset driver to test hitting # url directly
driver = getDriver();
@@ -60,7 +62,6 @@ describe('Loading scratch gui', () => {
.setSize(1920, 1080);
const projectId = '96708228';
await loadUri(`${uri}#${projectId}`);
await waitUntilGone(findByText('Loading'));
await clickXpath('//img[@title="Full Screen Control"]');
await new Promise(resolve => setTimeout(resolve, 500));
await clickXpath('//img[@title="Go"]');
@@ -77,7 +78,6 @@ describe('Loading scratch gui', () => {
test('Creating new project resets active tab to Code tab', async () => {
await loadUri(uri);
await new Promise(resolve => setTimeout(resolve, 2000));
await findByXpath('//*[span[text()="Costumes"]]');
await clickText('Costumes');
await clickXpath(
@@ -85,13 +85,12 @@ describe('Loading scratch gui', () => {
'contains(@class, "menu-bar_hoverable")][span[text()="File"]]'
);
await clickXpath('//li[span[text()="New"]]');
await findByXpath('//*[div[@class="scratchCategoryMenu"]]');
await findByXpath('//div[@class="scratchCategoryMenu"]');
await clickText('Operators', scope.blocksTab);
});
test('Not logged in->made no changes to project->create new project should not show alert', async () => {
await loadUri(uri);
await new Promise(resolve => setTimeout(resolve, 2000));
await clickXpath(
'//div[contains(@class, "menu-bar_menu-bar-item") and ' +
'contains(@class, "menu-bar_hoverable")][span[text()="File"]]'
@@ -103,10 +102,10 @@ describe('Loading scratch gui', () => {
test('Not logged in->made a change to project->create new project should show alert', async () => {
await loadUri(uri);
await new Promise(resolve => setTimeout(resolve, 2000));
await clickText('Sounds');
await clickXpath('//button[@aria-label="Choose a Sound"]');
await clickText('A Bass', scope.modal); // Should close the modal
await findByText('1.28'); // length of A Bass sound
await clickXpath(
'//div[contains(@class, "menu-bar_menu-bar-item") and ' +
'contains(@class, "menu-bar_hoverable")][span[text()="File"]]'
+62
View File
@@ -0,0 +1,62 @@
import React from 'react';
import {mountWithIntl} from '../../helpers/intl-helpers.jsx';
// Mock this utility because it uses dynamic imports that do not work with jest
jest.mock('../../../src/lib/libraries/decks/translate-image.js', () => {});
import Cards, {ImageStep, VideoStep} from '../../../src/components/cards/cards.jsx';
describe('Cards component', () => {
const defaultProps = () => ({
activeDeckId: 'id1',
content: {
id1: {
name: 'id1 - name',
img: 'id1 - img',
steps: [{video: 'videoUrl'}]
}
},
dragging: false,
expanded: true,
isRtl: false,
locale: 'en',
onActivateDeckFactory: jest.fn(),
onCloseCards: jest.fn(),
onDrag: jest.fn(),
onEndDrag: jest.fn(),
onNextStep: jest.fn(),
onPrevStep: jest.fn(),
onShowAll: jest.fn(),
onShrinkExpandCards: jest.fn(),
onStartDrag: jest.fn(),
showVideos: true,
step: 0,
x: 0,
y: 0
});
test('showVideos=true shows the video step', () => {
const component = mountWithIntl(
<Cards
{...defaultProps()}
showVideos
/>
);
expect(component.find(ImageStep).exists()).toEqual(false);
expect(component.find(VideoStep).exists()).toEqual(true);
});
test('showVideos=false shows the title image/name instead of video step', () => {
const component = mountWithIntl(
<Cards
{...defaultProps()}
showVideos={false}
/>
);
expect(component.find(VideoStep).exists()).toEqual(false);
const imageStep = component.find(ImageStep);
expect(imageStep.props().image).toEqual('id1 - img');
expect(imageStep.props().title).toEqual('id1 - name');
});
});
+164
View File
@@ -0,0 +1,164 @@
import React from 'react';
import {mount} from 'enzyme';
import configureStore from 'redux-mock-store';
import MenuBarHOC from '../../../src/containers/menu-bar-hoc.jsx';
describe('Menu Bar HOC', () => {
const mockStore = configureStore();
let store;
beforeEach(() => {
store = mockStore({
scratchGui: {
projectChanged: true
}
});
});
test('Logged in user who IS owner and HAS changed project will NOT be prompted to save', () => {
const Component = () => (<div />);
const WrappedComponent = MenuBarHOC(Component);
const wrapper = mount(
<WrappedComponent
canCreateNew
canSave
projectChanged
// assume the user will click "cancel" on the confirm dialog
confirmWithMessage={() => (false)} // eslint-disable-line react/jsx-no-bind
store={store}
/>
);
const child = wrapper.find(Component);
expect(child.props().projectChanged).toBeUndefined();
expect(child.props().confirmReadyToReplaceProject('message')).toBe(true);
});
test('Logged in user who IS owner and has NOT changed project will NOT be prompted to save', () => {
const Component = () => (<div />);
const WrappedComponent = MenuBarHOC(Component);
const wrapper = mount(
<WrappedComponent
canCreateNew
canSave
confirmWithMessage={() => (false)} // eslint-disable-line react/jsx-no-bind
projectChanged={false}
store={store}
/>
);
const child = wrapper.find(Component);
expect(child.props().projectChanged).toBeUndefined();
expect(child.props().confirmReadyToReplaceProject('message')).toBe(true);
});
test('Logged in user who is NOT owner and HAS changed project will NOT be prompted to save', () => {
const Component = () => (<div />);
const WrappedComponent = MenuBarHOC(Component);
const wrapper = mount(
<WrappedComponent
canCreateNew
projectChanged
canSave={false}
confirmWithMessage={() => (false)} // eslint-disable-line react/jsx-no-bind
store={store}
/>
);
const child = wrapper.find(Component);
expect(child.props().projectChanged).toBeUndefined();
expect(child.props().confirmReadyToReplaceProject('message')).toBe(true);
});
test('Logged OUT user who HAS changed project WILL be prompted to save', () => {
const Component = () => (<div />);
const WrappedComponent = MenuBarHOC(Component);
const wrapper = mount(
<WrappedComponent
projectChanged
canCreateNew={false}
canSave={false}
confirmWithMessage={() => (false)} // eslint-disable-line react/jsx-no-bind
store={store}
/>
);
const child = wrapper.find(Component);
expect(child.props().projectChanged).toBeUndefined();
expect(child.props().confirmReadyToReplaceProject('message')).toBe(false);
});
test('Logged OUT user who has NOT changed project WILL NOT be prompted to save', () => {
const Component = () => (<div />);
const WrappedComponent = MenuBarHOC(Component);
const wrapper = mount(
<WrappedComponent
canCreateNew={false}
canSave={false}
confirmWithMessage={() => (false)} // eslint-disable-line react/jsx-no-bind
projectChanged={false}
store={store}
/>
);
const child = wrapper.find(Component);
expect(child.props().projectChanged).toBeUndefined();
expect(child.props().confirmReadyToReplaceProject('message')).toBe(true);
});
test('Logged in user who IS owner and HAS changed project SHOULD save before transition to project page', () => {
const Component = () => (<div />);
const WrappedComponent = MenuBarHOC(Component);
const wrapper = mount(
<WrappedComponent
canSave
projectChanged
store={store}
/>
);
const child = wrapper.find(Component);
expect(child.props().projectChanged).toBeUndefined();
expect(child.props().shouldSaveBeforeTransition()).toBe(true);
});
test('Logged in user who IS owner and has NOT changed project should NOT save before transition', () => {
const Component = () => (<div />);
const WrappedComponent = MenuBarHOC(Component);
const wrapper = mount(
<WrappedComponent
canSave
projectChanged={false}
store={store}
/>
);
const child = wrapper.find(Component);
expect(child.props().projectChanged).toBeUndefined();
expect(child.props().shouldSaveBeforeTransition()).toBe(false);
});
test('Logged in user who is NOT owner and HAS changed project should NOT save before transition', () => {
const Component = () => (<div />);
const WrappedComponent = MenuBarHOC(Component);
const wrapper = mount(
<WrappedComponent
projectChanged
canSave={false}
store={store}
/>
);
const child = wrapper.find(Component);
expect(child.props().projectChanged).toBeUndefined();
expect(child.props().shouldSaveBeforeTransition()).toBe(false);
});
test('Logged in user who is NOT owner and has NOT changed project should NOT save before transition', () => {
const Component = () => (<div />);
const WrappedComponent = MenuBarHOC(Component);
const wrapper = mount(
<WrappedComponent
canSave={false}
projectChanged={false}
store={store}
/>
);
const child = wrapper.find(Component);
expect(child.props().projectChanged).toBeUndefined();
expect(child.props().shouldSaveBeforeTransition()).toBe(false);
});
});
+21
View File
@@ -0,0 +1,21 @@
import defaultProjectGenerator from '../../../src/lib/default-project/index.js';
describe('defaultProject', () => {
// This test ensures that the assets referenced in the default project JSON
// do not get out of sync with the raw assets that are included alongside.
// see https://github.com/LLK/scratch-gui/issues/4844
test('assets referenced by the project are included', () => {
const translatorFn = () => '';
const defaultProject = defaultProjectGenerator(translatorFn);
const includedAssetIds = defaultProject.map(obj => obj.id);
const projectData = JSON.parse(defaultProject[0].data);
projectData.targets.forEach(target => {
target.costumes.forEach(costume => {
expect(includedAssetIds.includes(costume.assetId)).toBe(true);
});
target.sounds.forEach(sound => {
expect(includedAssetIds.includes(sound.assetId)).toBe(true);
});
});
});
});