2023-05-21 22:06:04 -04:00

2410 lines
126 KiB
JavaScript

(window["webpackJsonpGUI"] = window["webpackJsonpGUI"] || []).push([["addons"],{
/***/ "./node_modules/css-loader/index.js!./src/addons/addons/drag-drop/dragged-over.css":
/*!********************************************************************************!*\
!*** ./node_modules/css-loader!./src/addons/addons/drag-drop/dragged-over.css ***!
\********************************************************************************/
/*! no static exports found */
/***/ (function(module, exports, __webpack_require__) {
exports = module.exports = __webpack_require__(/*! ../../../../node_modules/css-loader/lib/css-base.js */ "./node_modules/css-loader/lib/css-base.js")(false);
// imports
// module
exports.push([module.i, "/* Based on the `stage-selector_raised` class */\ndiv[class*=\"stage-selector_header_\"],\ndiv[class*=\"sprite-selector_sprite-selector\"],\ndiv[class*=\"sprite-info_sprite-info\"],\ndiv[class*=\"monitor_list-body\"] {\n transition: background-color 0.25s ease;\n}\n.sa-dragged-over,\n.sa-dragged-over div[class*=\"stage-selector_header_\"],\n.sa-dragged-over div[class*=\"sprite-info_sprite-info\"],\n.sa-dragged-over div[class*=\"monitor_list-body\"] {\n background-color: hsla(0, 100%, 77%, 1) !important;\n}\n", ""]);
// exports
/***/ }),
/***/ "./node_modules/css-loader/index.js!./src/addons/addons/pause/style.css":
/*!*********************************************************************!*\
!*** ./node_modules/css-loader!./src/addons/addons/pause/style.css ***!
\*********************************************************************/
/*! no static exports found */
/***/ (function(module, exports, __webpack_require__) {
exports = module.exports = __webpack_require__(/*! ../../../../node_modules/css-loader/lib/css-base.js */ "./node_modules/css-loader/lib/css-base.js")(false);
// imports
// module
exports.push([module.i, ".pause-btn {\n width: 2rem;\n height: 2rem;\n padding: 0.375rem;\n border-radius: 0.25rem;\n user-select: none;\n user-drag: none;\n cursor: pointer;\n}\n\n.pause-btn:hover {\n background-color: hsla(0, 100%, 65%, 0.15);\n}\n", ""]);
// exports
/***/ }),
/***/ "./node_modules/css-loader/index.js?!./node_modules/postcss-loader/src/index.js?!./src/addons/modal.css":
/*!*************************************************************************************************************!*\
!*** ./node_modules/css-loader??ref--5-1!./node_modules/postcss-loader/src??postcss!./src/addons/modal.css ***!
\*************************************************************************************************************/
/*! no static exports found */
/***/ (function(module, exports, __webpack_require__) {
exports = module.exports = __webpack_require__(/*! ../../node_modules/css-loader/lib/css-base.js */ "./node_modules/css-loader/lib/css-base.js")(false);
// imports
// module
exports.push([module.i, ".modal_modal-content_fN1pD {\n background-color: white;\n color: #575e75;\n}\n[theme=\"dark\"] .modal_modal-content_fN1pD {\n background-color: var(--ui-primary);\n color: var(--text-primary);\n}\n", ""]);
// exports
exports.locals = {
"modal-content": "modal_modal-content_fN1pD",
"modalContent": "modal_modal-content_fN1pD"
};
/***/ }),
/***/ "./node_modules/url-loader/dist/cjs.js!./src/addons/addons/mute-project/icon--mute.svg":
/*!*********************************************************************************************!*\
!*** ./node_modules/url-loader/dist/cjs.js!./src/addons/addons/mute-project/icon--mute.svg ***!
\*********************************************************************************************/
/*! exports provided: default */
/***/ (function(module, __webpack_exports__, __webpack_require__) {
"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony default export */ __webpack_exports__["default"] = ("data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiPz4KPHN2ZyB3aWR0aD0iMjBweCIgaGVpZ2h0PSIyMHB4IiB2aWV3Qm94PSIwIDAgMjAgMjAiIHZlcnNpb249IjEuMSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB4bWxuczp4bGluaz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94bGluayI+CiAgICA8IS0tIEZyb20gaHR0cHM6Ly9naXRodWIuY29tL0xMSy9zY3JhdGNoLWd1aS8gLS0+CiAgICA8IS0tIEdlbmVyYXRvcjogU2tldGNoIDU1LjIgKDc4MTgxKSAtIGh0dHBzOi8vc2tldGNoYXBwLmNvbSAtLT4KICAgIDx0aXRsZT5Tb3VuZC9FZmZlY3RzL011dGU8L3RpdGxlPgogICAgPGRlc2M+Q3JlYXRlZCB3aXRoIFNrZXRjaC48L2Rlc2M+CiAgICA8ZyBpZD0iU291bmQvRWZmZWN0cy9NdXRlIiBzdHJva2U9Im5vbmUiIHN0cm9rZS13aWR0aD0iMSIgZmlsbD0ibm9uZSIgZmlsbC1ydWxlPSJldmVub2RkIj4KICAgICAgICA8cGF0aCBmaWxsPSIjQ0Y2M0NGIiBkPSJNMTMuNDU0MTc0OSw1LjA0ODE1MjQzIEwxNS42MjgxMTY4LDIuODc0MjEwNTQgQzE1LjkyMTAxLDIuNTgxMzE3MzIgMTYuMzk1ODgzNywyLjU4MTMxNzMyIDE2LjY4ODc3NywyLjg3NDIxMDU0IEMxNi45ODE2NzAyLDMuMTY3MTAzNzYgMTYuOTgxNjcwMiwzLjY0MTk3NzQ5IDE2LjY4ODc3NywzLjkzNDg3MDcxIEw0LjUzMDMzMDA5LDE2LjA5MzMxNzYgQzQuMjM3NDM2ODcsMTYuMzg2MjEwOCAzLjc2MjU2MzEzLDE2LjM4NjIxMDggMy40Njk2Njk5MSwxNi4wOTMzMTc2IEMzLjE3Njc3NjcsMTUuODAwNDI0NCAzLjE3Njc3NjcsMTUuMzI1NTUwNiAzLjQ2OTY2OTkxLDE1LjAzMjY1NzQgTDYuMzEyMTQ5MzIsMTIuMTkwMTc4IEM2LjEyNDExOTEsMTIuMDYyMTM3OSA2LDExLjg0NjMzMzEgNiwxMS42MDI5ODc1IEw2LDguNjM3NDg3NSBDNiw4LjI0NzExMjUgNi4zMTk0MTUyNyw3LjkyNzYxMjUgNi43MDk2ODY3NSw3LjkyNzYxMjUgTDcuMDI0NjAzMjIsNy45Mjc2MTI1IEM4Ljc1Nzc2ODQ4LDcuOTI3NjEyNSAxMC4yOTQxMTEsNi44MTM4NjI1IDEwLjgzMzk2NzgsNS4xNjY4NjI1IEMxMC45Mjk1Njc0LDQuODc0MzYyNSAxMS4yMDE3NDUyLDQuNjc3NDg3NSAxMS41MDc2NjQxLDQuNjc3NDg3NSBMMTIuODMxNDM3OSw0LjY3NzQ4NzUgQzEzLjEwMDI4NDQsNC42Nzc0ODc1IDEzLjMzNDEwNzUsNC44MjcxNzIwOCAxMy40NTQxNzQ5LDUuMDQ4MTUyNDMgWiBNMTMuNTQsOS4wODM2NDc3MSBMMTMuNTQsMTQuODUzMTEyNSBDMTMuNTQsMTUuMjQ1NzM3NSAxMy4yMjI4MzQxLDE1LjU2Mjk4NzUgMTIuODMxNDM3OSwxNS41NjI5ODc1IEwxMS41MDc2NjQxLDE1LjU2Mjk4NzUgQzExLjIwMTc0NTIsMTUuNTYyOTg3NSAxMC45Mjk1Njc0LDE1LjM2NjExMjUgMTAuODMzOTY3OCwxNS4wNzM2MTI1IEMxMC41NzczNzg1LDE0LjI5MDgwNzcgMTAuMDk1NjgxMywxMy42Mjg0NjUgOS40NzQ3MzUzMSwxMy4xNDg5MTI0IEwxMy41NCw5LjA4MzY0NzcxIFoiIGlkPSJwYXRoLTEiPjwvcGF0aD4KICAgIDwvZz4KPC9zdmc+Cg==");
/***/ }),
/***/ "./node_modules/url-loader/dist/cjs.js!./src/addons/addons/pause/pause.svg":
/*!*********************************************************************************!*\
!*** ./node_modules/url-loader/dist/cjs.js!./src/addons/addons/pause/pause.svg ***!
\*********************************************************************************/
/*! exports provided: default */
/***/ (function(module, __webpack_exports__, __webpack_require__) {
"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony default export */ __webpack_exports__["default"] = ("data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIGhlaWdodD0iMTgiIHdpZHRoPSIxOCI+PHBhdGggZD0iTTIzMS40MjkgMTg4LjkyOVYxNzEuMDdoNC4yODV2MTcuODU4em0xMi4xNDIgMFYxNzEuMDdoNC4yODZ2MTcuODU4eiIgdHJhbnNmb3JtPSJtYXRyaXgoMS4wMzMwOSAwIDAgLjk1NDI3IC0yMzguNTczIC0xNjIuNzY5KSIgZGF0YS1wYXBlci1kYXRhPSJ7JnF1b3Q7aXNQYWludGluZ0xheWVyJnF1b3Q7OnRydWV9IiBmaWxsPSIjZmZhZTAwIiBzdHJva2U9IiNkODk0MDAiIHN0cm9rZS1taXRlcmxpbWl0PSIxMCIgc3R5bGU9Im1peC1ibGVuZC1tb2RlOm5vcm1hbCIvPjwvc3ZnPg==");
/***/ }),
/***/ "./node_modules/url-loader/dist/cjs.js!./src/addons/addons/pause/play.svg":
/*!********************************************************************************!*\
!*** ./node_modules/url-loader/dist/cjs.js!./src/addons/addons/pause/play.svg ***!
\********************************************************************************/
/*! exports provided: default */
/***/ (function(module, __webpack_exports__, __webpack_require__) {
"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony default export */ __webpack_exports__["default"] = ("data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIGhlaWdodD0iMTgiIHdpZHRoPSIxOCI+PHBhdGggZD0ibTI0Ni4wNTUgMTgwLTEyLjExIDEyLjExdi0yNC4yMnoiIHRyYW5zZm9ybT0ibWF0cml4KDEuMTM5NDkgMCAwIC42Nzk0MyAtMjY0LjU5NSAtMTEzLjI5OCkiIHN0cm9rZS1taXRlcmxpbWl0PSIxMCIgc3Ryb2tlPSIjZDg5NDAwIiBmaWxsPSIjZmZhZTAwIiBkYXRhLXBhcGVyLWRhdGE9InsmcXVvdDtpc1BhaW50aW5nTGF5ZXImcXVvdDs6dHJ1ZX0iLz48L3N2Zz4=");
/***/ }),
/***/ "./src/addons/addons-l10n/en.json":
/*!****************************************!*\
!*** ./src/addons/addons-l10n/en.json ***!
\****************************************/
/*! exports provided: editor-devtools/bottom, editor-devtools/clean-plus, editor-devtools/code-tab-features, editor-devtools/copy-all, editor-devtools/copy-block, editor-devtools/copy-to-clipboard, editor-devtools/copy-to-clipboard-desc, editor-devtools/costume-tab-features, editor-devtools/ctrl-lr, editor-devtools/ctrl-lr-costume-desc, editor-devtools/ctrl-lr-desc, editor-devtools/ctrl-space, editor-devtools/ctrl-space-desc, editor-devtools/cut-block, editor-devtools/deep, editor-devtools/find, editor-devtools/find-bar, editor-devtools/find-bar-costume-desc, editor-devtools/find-placeholder, editor-devtools/help, editor-devtools/help-make-space, editor-devtools/help-make-space-desc, editor-devtools/help-new, editor-devtools/help-title, editor-devtools/improved-tidy-up, editor-devtools/improved-tidy-up-desc, editor-devtools/insert, editor-devtools/interactive-find-bar, editor-devtools/interactive-find-bar-desc, editor-devtools/lists, editor-devtools/make-space, editor-devtools/middleclick, editor-devtools/middleclick-desc, editor-devtools/orphaned, editor-devtools/paste, editor-devtools/paste-from-clipboard, editor-devtools/paste-from-clipboard-desc, editor-devtools/replace, editor-devtools/start-typing, editor-devtools/swap, editor-devtools/swap-variable, editor-devtools/swap-variable-desc, editor-devtools/top, editor-devtools/tutorials, editor-devtools/unused-list, editor-devtools/unused-var, editor-devtools/var-not-exist, editor-devtools/variables, editor-devtools/youtube, editor-searchable-dropdowns/createBroadcast, editor-searchable-dropdowns/createGlobalList, editor-searchable-dropdowns/createGlobalVariable, editor-searchable-dropdowns/createLocalList, editor-searchable-dropdowns/createLocalVariable, data-category-tweaks-v2/for-all-sprites, data-category-tweaks-v2/for-this-sprite-only, data-category-tweaks-v2/list-category, hide-flyout/lock, hide-flyout/unlock, mediarecorder/cancel, mediarecorder/click-flag, mediarecorder/click-flag-description, mediarecorder/option-title, mediarecorder/record, mediarecorder/record-after-flag, mediarecorder/record-audio, mediarecorder/record-audio-description, mediarecorder/record-description, mediarecorder/record-duration, mediarecorder/record-mic, mediarecorder/record-until-stop, mediarecorder/record-until-stop-disabled, mediarecorder/start, mediarecorder/start-delay, mediarecorder/starting-in, mediarecorder/stop, debugger/block-breakpoint, debugger/block-error, debugger/block-log, debugger/block-warn, debugger/cannot-pause-player, debugger/clear, debugger/clone-of, debugger/close, debugger/console, debugger/debug, debugger/empty-string, debugger/enter-format, debugger/export, debugger/export-desc, debugger/icon-error, debugger/icon-warn, debugger/log-msg-broadcasted, debugger/log-msg-clone-cap, debugger/log-msg-clone-created, debugger/log-msg-flag-clicked, debugger/no-logs, debugger/no-threads-running, debugger/step, debugger/step-desc, debugger/tab-logs, debugger/tab-threads, debugger/thread, debugger/unknown-sprite, debugger/unpause, pause/pause, clones/clones, color-picker/hex, remove-sprite-confirm/confirm, block-count/blocks, onion-skinning/behind, onion-skinning/front, onion-skinning/layering, onion-skinning/merge, onion-skinning/mode, onion-skinning/next, onion-skinning/opacity, onion-skinning/opacityStep, onion-skinning/previous, onion-skinning/settings, onion-skinning/tint, onion-skinning/toggle, 2d-color-picker/shade, better-img-uploads/upload, variable-manager/for-all-sprites, variable-manager/for-this-sprite, variable-manager/search, variable-manager/variables, search-sprites/placeholder, gamepad/axes-a-b, gamepad/axis-arrows, gamepad/axis-cursor, gamepad/axis-custom, gamepad/axis-none, gamepad/browser-support, gamepad/button-n, gamepad/clear, gamepad/config-header, gamepad/key-click, gamepad/key-down, gamepad/key-enter, gamepad/key-left, gamepad/key-none, gamepad/key-right, gamepad/key-space, gamepad/key-up, gamepad/keyinput-title, gamepad/no-controllers, gamepad/reset, gamepad/settings, gamepad/store-in-project, folders/add-to-folder, folders/closed-folder, folders/confirm-backpack-folder, folders/create-folder, folders/name-not-allowed, folders/name-prompt, folders/name-prompt-title, folders/open-folder, folders/remove-folder, folders/remove-from-folder, folders/rename-folder, folders/rename-folder-prompt, folders/rename-folder-prompt-title, block-switching/control_forever, block-switching/control_if, block-switching/control_if_else, block-switching/control_repeat_until, block-switching/control_wait_until, block-switching/data_changevariableby, block-switching/data_hidelist, block-switching/data_hidevariable, block-switching/data_insertatlist, block-switching/data_replaceitemoflist, block-switching/data_setvariableto, block-switching/data_showlist, block-switching/data_showvariable, block-switching/debugger_error, block-switching/debugger_log, block-switching/debugger_warn, block-switching/event_broadcast, block-switching/event_broadcastandwait, block-switching/looks_backdropnumbername, block-switching/looks_changeeffectby, block-switching/looks_changesizeby, block-switching/looks_costumenumbername, block-switching/looks_hide, block-switching/looks_nextbackdrop, block-switching/looks_nextcostume, block-switching/looks_say, block-switching/looks_sayforsecs, block-switching/looks_seteffectto, block-switching/looks_setsizeto, block-switching/looks_show, block-switching/looks_switchbackdropto, block-switching/looks_switchbackdroptoandwait, block-switching/looks_think, block-switching/looks_thinkforsecs, block-switching/motion_changexby, block-switching/motion_changeyby, block-switching/motion_setx, block-switching/motion_sety, block-switching/motion_turnleft, block-switching/motion_turnright, block-switching/motion_xposition, block-switching/motion_yposition, block-switching/music_changeTempo, block-switching/music_setTempo, block-switching/operator_add, block-switching/operator_and, block-switching/operator_divide, block-switching/operator_equals, block-switching/operator_gt, block-switching/operator_lt, block-switching/operator_mod, block-switching/operator_multiply, block-switching/operator_or, block-switching/operator_subtract, block-switching/pen_changePenColorParamBy, block-switching/pen_changePenHueBy, block-switching/pen_changePenShadeBy, block-switching/pen_changePenSizeBy, block-switching/pen_penDown, block-switching/pen_penUp, block-switching/pen_setPenColorParamTo, block-switching/pen_setPenHueToNumber, block-switching/pen_setPenShadeToNumber, block-switching/pen_setPenSizeTo, block-switching/sensing_mousex, block-switching/sensing_mousey, block-switching/sound_changeeffectby, block-switching/sound_changevolumeby, block-switching/sound_play, block-switching/sound_playuntildone, block-switching/sound_seteffectto, block-switching/sound_setvolumeto, blocks2image/error_blocks_not_added, blocks2image/export_all_to_PNG, blocks2image/export_all_to_SVG, blocks2image/export_selected_to_PNG, blocks2image/export_selected_to_SVG, editor-extra-keys/enter-key, move-to-top-bottom/bottom, move-to-top-bottom/top, rename-broadcasts/RENAME_BROADCAST, rename-broadcasts/RENAME_BROADCAST_MODAL_TITLE, rename-broadcasts/RENAME_BROADCAST_TITLE, swap-local-global/cant-convert-cloud, swap-local-global/cant-convert-conflict, swap-local-global/cant-convert-stage, swap-local-global/cant-convert-to-local, swap-local-global/cant-convert-used-elsewhere, swap-local-global/edit, swap-local-global/edit-list-header, swap-local-global/edit-list-option, swap-local-global/edit-variable-header, swap-local-global/edit-variable-option, swap-local-global/to-global, swap-local-global/to-local, hide-stage/hide-stage, default */
/***/ (function(module) {
module.exports = JSON.parse("{\"editor-devtools/bottom\":\"send to bottom\",\"editor-devtools/clean-plus\":\"Clean up Blocks +\",\"editor-devtools/code-tab-features\":\"Code Tab Features\",\"editor-devtools/copy-all\":\"Copy All\",\"editor-devtools/copy-block\":\"Copy Block\",\"editor-devtools/copy-to-clipboard\":\"Copy to Clipboard\",\"editor-devtools/copy-to-clipboard-desc\":\"Right click a block and 3 new options are available to Copy All, Copy Block, and Cut Block. The Copy All will copy to the clipboard everything including and below the block you clicked on. Copy block will only copy the current block and its contents, but nothing below. And cut block will copy it and remove it from the code area.\",\"editor-devtools/costume-tab-features\":\"Costumes Tab Features\",\"editor-devtools/ctrl-lr\":\"Ctrl + Left, Ctrl + Right\",\"editor-devtools/ctrl-lr-costume-desc\":\"These keys navigate you to the previous / next costume in the sprite.\",\"editor-devtools/ctrl-lr-desc\":\"Navigate to previous / next visited position in the code area (after using the navigate to block or find bar). This allows you to middle click a custom block to go to its definition, then press ctrl + Left to go back to where you were before.\",\"editor-devtools/ctrl-space\":\"Ctrl + Space, Middle Click, or Shift + Click\",\"editor-devtools/ctrl-space-desc\":\"Pops up a floating input box where you can type the name of a block (or parts of it) and drag the block into the code to make use of it right there. Hold Shift while dragging to avoid closing the box when adding multiple blocks at once.\",\"editor-devtools/cut-block\":\"Cut Block\",\"editor-devtools/deep\":\"Deep\",\"editor-devtools/find\":\"Find\",\"editor-devtools/find-bar\":\"Find Bar\",\"editor-devtools/find-bar-costume-desc\":\"Click to list all costumes by name, and type to locate one. Use the arrow keys or mouse to click a name to jump straight to that costume.\",\"editor-devtools/find-placeholder\":\"Find (Ctrl+F)\",\"editor-devtools/help\":\"Help\",\"editor-devtools/help-make-space\":\"Make Space\",\"editor-devtools/help-make-space-desc\":\"Make extra space around a script by right clicking on the script and choosing \\\"Make Space\\\".\",\"editor-devtools/help-new\":\"★New★\",\"editor-devtools/help-title\":\"Scratch 3 Developer Tools\",\"editor-devtools/improved-tidy-up\":\"Improved Code Clean Up\",\"editor-devtools/improved-tidy-up-desc\":\"Right click on the code area to pop up the menu and the Clean up Blocks option will have been replaced by a Clean up Blocks + option. Use this to tidy your scripts and it will preserve your scripts columns as well as attempt to align the comments and remove all those orphaned variables, etc.\",\"editor-devtools/insert\":\"Insert\",\"editor-devtools/interactive-find-bar\":\"Interactive Find Bar (Ctrl + F)\",\"editor-devtools/interactive-find-bar-desc\":\"Quickly find and jump to any Custom Block, Variable, Event, or Hat block defined in a sprite by clicking on the new find bar located to the right of the Code, Costumes and Sounds tabs. Begin typing to filter down the list. Use the up and down arrow keys to switch between the possible entries, and the left and right arrows to cycle between all found instances of that block.\",\"editor-devtools/lists\":\"lists\",\"editor-devtools/make-space\":\"Make Space\",\"editor-devtools/middleclick\":\"Jump To\",\"editor-devtools/middleclick-desc\":\"Using the middle mouse button or Shift + Click on a variable or custom block allows you to jump to its definition or open it in the interactive find bar.\",\"editor-devtools/orphaned\":\"{count, plural, one {Developer tools: Delete 1 orphaned reporter block?} other {Developer tools: Delete # orphaned reporter blocks?} }\",\"editor-devtools/paste\":\"Paste\",\"editor-devtools/paste-from-clipboard\":\"Paste from Clipboard\",\"editor-devtools/paste-from-clipboard-desc\":\"Pastes from the clipboard, but importantly pastes it where your mouse cursor is so you can then place it (rather than placing it where you copied it from like the current scratch implementation).\",\"editor-devtools/replace\":\"Developer tools: Switch all {name} in this sprite for the variable named:\",\"editor-devtools/start-typing\":\"Start Typing...\",\"editor-devtools/swap\":\"Swap {var} in Sprite\",\"editor-devtools/swap-variable\":\"Swap Variable in Sprite\",\"editor-devtools/swap-variable-desc\":\"Right click a variable in your scripts for this new option. It allows you to switch all references to this variable in the current sprite all in one go to another variable. This is great for when you made a mistake and want to switch from one variable to another or need to change from a 'for all sprites' to a 'for this sprite only'. This option will not remove the old variable and will not affect any other sprites variables.\",\"editor-devtools/top\":\"send to top\",\"editor-devtools/tutorials\":\"Tutorials\",\"editor-devtools/unused-list\":\"{count, plural, one {Developer tools: Delete 1 unused local list? Here it is:\\n} other {Developer tools: Delete # unused local lists? Here they are:\\n} }\",\"editor-devtools/unused-var\":\"{count, plural, one {Developer tools: Delete 1 unused local variable? Here it is:\\n} other {Developer tools: Delete # unused local variables? Here they are:\\n} }\",\"editor-devtools/var-not-exist\":\"That variable does not exist...\",\"editor-devtools/variables\":\"variables\",\"editor-devtools/youtube\":\"YouTube tutorials\",\"editor-searchable-dropdowns/createBroadcast\":\"Create message \\\"{name}\\\"\",\"editor-searchable-dropdowns/createGlobalList\":\"Create list \\\"{name}\\\" for all sprites\",\"editor-searchable-dropdowns/createGlobalVariable\":\"Create variable \\\"{name}\\\" for all sprites\",\"editor-searchable-dropdowns/createLocalList\":\"Create list \\\"{name}\\\" for this sprite only\",\"editor-searchable-dropdowns/createLocalVariable\":\"Create variable \\\"{name}\\\" for this sprite only\",\"data-category-tweaks-v2/for-all-sprites\":\"For all sprites:\",\"data-category-tweaks-v2/for-this-sprite-only\":\"For this sprite only:\",\"data-category-tweaks-v2/list-category\":\"Lists\",\"hide-flyout/lock\":\"Lock Palette\",\"hide-flyout/unlock\":\"Unlock Palette\",\"mediarecorder/cancel\":\"Cancel\",\"mediarecorder/click-flag\":\"Waiting...\",\"mediarecorder/click-flag-description\":\"Click the green flag to start recording. Click this button to stop.\",\"mediarecorder/option-title\":\"Record Options\",\"mediarecorder/record\":\"Start Recording\",\"mediarecorder/record-after-flag\":\"Do not start recording until the Green Flag is clicked\",\"mediarecorder/record-audio\":\"Include project sounds\",\"mediarecorder/record-audio-description\":\"This does not include Text-to-Speech.\",\"mediarecorder/record-description\":\"Record the stage as a WebM file. You can save it to your computer after the recording is finished.\",\"mediarecorder/record-duration\":\"Record Duration (in seconds)\",\"mediarecorder/record-mic\":\"Include sounds from microphone\",\"mediarecorder/record-until-stop\":\"Stop recording after the project has stopped\",\"mediarecorder/record-until-stop-disabled\":\"You need to enable \\\"{afterFlagOption}\\\" to use this option.\",\"mediarecorder/start\":\"Start\",\"mediarecorder/start-delay\":\"Start Delay (in seconds)\",\"mediarecorder/starting-in\":\"Starting in {secs}...\",\"mediarecorder/stop\":\"Stop Recording\",\"debugger/block-breakpoint\":\"breakpoint\",\"debugger/block-error\":\"error %s\",\"debugger/block-log\":\"log %s\",\"debugger/block-warn\":\"warn %s\",\"debugger/cannot-pause-player\":\"Breakpoint block can only be used while on the editor.\",\"debugger/clear\":\"Clear\",\"debugger/clone-of\":\"Clone of {sprite}\",\"debugger/close\":\"Close\",\"debugger/console\":\"Logs\",\"debugger/debug\":\"Debug\",\"debugger/empty-string\":\"(empty string)\",\"debugger/enter-format\":\"Enter export format:\",\"debugger/export\":\"Export\",\"debugger/export-desc\":\"Click while holding Shift to customize export format.\",\"debugger/icon-error\":\"Error\",\"debugger/icon-warn\":\"Warning\",\"debugger/log-msg-broadcasted\":\"Broadcasted '{broadcast}'.\",\"debugger/log-msg-clone-cap\":\"Failed to create clone of '{sprite}', cannot create over 300 clones.\",\"debugger/log-msg-clone-created\":\"Created clone of '{sprite}'.\",\"debugger/log-msg-flag-clicked\":\"Green flag clicked.\",\"debugger/no-logs\":\"There are no logs to display.\",\"debugger/no-threads-running\":\"No threads running.\",\"debugger/step\":\"Step\",\"debugger/step-desc\":\"Executes one block.\",\"debugger/tab-logs\":\"Logs\",\"debugger/tab-threads\":\"Threads\",\"debugger/thread\":\"Thread {id}\",\"debugger/unknown-sprite\":\"(unknown sprite)\",\"debugger/unpause\":\"Resume\",\"pause/pause\":\"Pause\",\"clones/clones\":\"clones: {cloneCount}\",\"color-picker/hex\":\"hex color\",\"remove-sprite-confirm/confirm\":\"Do you want to delete the sprite?\",\"block-count/blocks\":\"{num, plural, one {1 block} other {# blocks}}\",\"onion-skinning/behind\":\"Behind\",\"onion-skinning/front\":\"Front\",\"onion-skinning/layering\":\"Layering\",\"onion-skinning/merge\":\"Merge\",\"onion-skinning/mode\":\"Mode\",\"onion-skinning/next\":\"Next costumes\",\"onion-skinning/opacity\":\"Opacity (%)\",\"onion-skinning/opacityStep\":\"Opacity step (%)\",\"onion-skinning/previous\":\"Previous costumes\",\"onion-skinning/settings\":\"Onion Skinning Settings\",\"onion-skinning/tint\":\"Tint\",\"onion-skinning/toggle\":\"Toggle Onion Skinning\",\"2d-color-picker/shade\":\"Shade\",\"better-img-uploads/upload\":\"HD Upload\",\"variable-manager/for-all-sprites\":\"Variables for all sprites\",\"variable-manager/for-this-sprite\":\"Variables for this sprite\",\"variable-manager/search\":\"Search\",\"variable-manager/variables\":\"Variables\",\"search-sprites/placeholder\":\"Search sprites...\",\"gamepad/axes-a-b\":\"Axes {a} & {b}\",\"gamepad/axis-arrows\":\"Arrow Keys\",\"gamepad/axis-cursor\":\"Cursor\",\"gamepad/axis-custom\":\"Custom\",\"gamepad/axis-none\":\"None\",\"gamepad/browser-support\":\"This browser and operating system have known bugs that may make this addon difficult to use. Try another browser if you encounter problems.\",\"gamepad/button-n\":\"Button {n}\",\"gamepad/clear\":\"Clear all controls\",\"gamepad/config-header\":\"This comment contains configuration for gamepad support in third-party tools or websites such as https://turbowarp.org/\\nDo not edit by hand\",\"gamepad/key-click\":\"Click\",\"gamepad/key-down\":\"Down\",\"gamepad/key-enter\":\"Enter\",\"gamepad/key-left\":\"Left\",\"gamepad/key-none\":\"(none)\",\"gamepad/key-right\":\"Right\",\"gamepad/key-space\":\"Space\",\"gamepad/key-up\":\"Up\",\"gamepad/keyinput-title\":\"Click and press a key or click to change button. Escape to cancel. Backspace or delete to clear.\",\"gamepad/no-controllers\":\"No controllers detected. Try plugging one in and pressing a button on it.\",\"gamepad/reset\":\"Reset all controls to project defaults\",\"gamepad/settings\":\"Gamepad Settings\",\"gamepad/store-in-project\":\"Store these settings in the project to override the default configuration (Experimental tool for project creators)\",\"folders/add-to-folder\":\"add to folder: {folder}\",\"folders/closed-folder\":\"Folder\",\"folders/confirm-backpack-folder\":\"Save entire folder to backpack?\",\"folders/create-folder\":\"create folder\",\"folders/name-not-allowed\":\"Invalid folder name\",\"folders/name-prompt\":\"Name of folder:\",\"folders/name-prompt-title\":\"Create Folder\",\"folders/open-folder\":\"Opened\",\"folders/remove-folder\":\"remove folder\",\"folders/remove-from-folder\":\"remove from folder\",\"folders/rename-folder\":\"rename folder\",\"folders/rename-folder-prompt\":\"Rename folder to:\",\"folders/rename-folder-prompt-title\":\"Rename Folder\",\"block-switching/control_forever\":\"forever\",\"block-switching/control_if\":\"if\",\"block-switching/control_if_else\":\"if... else\",\"block-switching/control_repeat_until\":\"repeat until\",\"block-switching/control_wait_until\":\"wait until\",\"block-switching/data_changevariableby\":\"change variable\",\"block-switching/data_hidelist\":\"hide list\",\"block-switching/data_hidevariable\":\"hide variable\",\"block-switching/data_insertatlist\":\"insert item\",\"block-switching/data_replaceitemoflist\":\"replace item\",\"block-switching/data_setvariableto\":\"set variable\",\"block-switching/data_showlist\":\"show list\",\"block-switching/data_showvariable\":\"show variable\",\"block-switching/debugger_error\":\"error\",\"block-switching/debugger_log\":\"log\",\"block-switching/debugger_warn\":\"warn\",\"block-switching/event_broadcast\":\"broadcast\",\"block-switching/event_broadcastandwait\":\"broadcast and wait\",\"block-switching/looks_backdropnumbername\":\"backdrop number or name\",\"block-switching/looks_changeeffectby\":\"change effect\",\"block-switching/looks_changesizeby\":\"change size\",\"block-switching/looks_costumenumbername\":\"costume number or name\",\"block-switching/looks_hide\":\"hide\",\"block-switching/looks_nextbackdrop\":\"next backdrop\",\"block-switching/looks_nextcostume\":\"next costume\",\"block-switching/looks_say\":\"say\",\"block-switching/looks_sayforsecs\":\"say for seconds\",\"block-switching/looks_seteffectto\":\"set effect\",\"block-switching/looks_setsizeto\":\"set size\",\"block-switching/looks_show\":\"show\",\"block-switching/looks_switchbackdropto\":\"switch backdrop\",\"block-switching/looks_switchbackdroptoandwait\":\"switch backdrop and wait\",\"block-switching/looks_think\":\"think\",\"block-switching/looks_thinkforsecs\":\"think for seconds\",\"block-switching/motion_changexby\":\"change x\",\"block-switching/motion_changeyby\":\"change y\",\"block-switching/motion_setx\":\"set x\",\"block-switching/motion_sety\":\"set y\",\"block-switching/motion_turnleft\":\"turn left\",\"block-switching/motion_turnright\":\"turn right\",\"block-switching/motion_xposition\":\"x position\",\"block-switching/motion_yposition\":\"y position\",\"block-switching/music_changeTempo\":\"change tempo\",\"block-switching/music_setTempo\":\"set tempo\",\"block-switching/operator_add\":\"+\",\"block-switching/operator_and\":\"and\",\"block-switching/operator_divide\":\"/\",\"block-switching/operator_equals\":\"=\",\"block-switching/operator_gt\":\">\",\"block-switching/operator_lt\":\"<\",\"block-switching/operator_mod\":\"mod\",\"block-switching/operator_multiply\":\"*\",\"block-switching/operator_or\":\"or\",\"block-switching/operator_subtract\":\"-\",\"block-switching/pen_changePenColorParamBy\":\"change parameter\",\"block-switching/pen_changePenHueBy\":\"change hue\",\"block-switching/pen_changePenShadeBy\":\"change shade\",\"block-switching/pen_changePenSizeBy\":\"change size\",\"block-switching/pen_penDown\":\"pen down\",\"block-switching/pen_penUp\":\"pen up\",\"block-switching/pen_setPenColorParamTo\":\"set parameter\",\"block-switching/pen_setPenHueToNumber\":\"set hue\",\"block-switching/pen_setPenShadeToNumber\":\"set shade\",\"block-switching/pen_setPenSizeTo\":\"set size\",\"block-switching/sensing_mousex\":\"mouse x\",\"block-switching/sensing_mousey\":\"mouse y\",\"block-switching/sound_changeeffectby\":\"change effect\",\"block-switching/sound_changevolumeby\":\"change volume\",\"block-switching/sound_play\":\"start\",\"block-switching/sound_playuntildone\":\"play until done\",\"block-switching/sound_seteffectto\":\"set effect\",\"block-switching/sound_setvolumeto\":\"set volume\",\"blocks2image/error_blocks_not_added\":\"Add blocks to workspace!\",\"blocks2image/export_all_to_PNG\":\"Export all as PNG\",\"blocks2image/export_all_to_SVG\":\"Export all as SVG\",\"blocks2image/export_selected_to_PNG\":\"Export block as PNG\",\"blocks2image/export_selected_to_SVG\":\"Export block as SVG\",\"editor-extra-keys/enter-key\":\"enter\",\"move-to-top-bottom/bottom\":\"move to bottom\",\"move-to-top-bottom/top\":\"move to top\",\"rename-broadcasts/RENAME_BROADCAST\":\"Rename message\",\"rename-broadcasts/RENAME_BROADCAST_MODAL_TITLE\":\"Rename Message\",\"rename-broadcasts/RENAME_BROADCAST_TITLE\":\"Rename all \\\"{name}\\\" messages to:\",\"swap-local-global/cant-convert-cloud\":\"Cloud variables can't be converted to this sprite only.\",\"swap-local-global/cant-convert-conflict\":\"Can't convert because it would conflict with variables in another sprite: {sprites}\",\"swap-local-global/cant-convert-stage\":\"The stage can't have variables for this sprite only.\",\"swap-local-global/cant-convert-to-local\":\"Can't convert because it's used by multiple sprites: {sprites}\",\"swap-local-global/cant-convert-used-elsewhere\":\"Can't convert because it's used by another sprite: {sprite}\",\"swap-local-global/edit\":\"Edit properties:\",\"swap-local-global/edit-list-header\":\"Edit List\",\"swap-local-global/edit-list-option\":\"Rename or edit list\",\"swap-local-global/edit-variable-header\":\"Edit Variable\",\"swap-local-global/edit-variable-option\":\"Rename or edit variable\",\"swap-local-global/to-global\":\"Convert to \\\"For all sprites\\\"\",\"swap-local-global/to-local\":\"Convert to \\\"For this sprite only\\\"\",\"hide-stage/hide-stage\":\"Hide stage\"}");
/***/ }),
/***/ "./src/addons/addons/debugger/module.js":
/*!**********************************************!*\
!*** ./src/addons/addons/debugger/module.js ***!
\**********************************************/
/*! exports provided: isPaused, setPaused, onPauseChanged, onSingleStep, getRunningThread, singleStep, setup */
/***/ (function(module, __webpack_exports__, __webpack_require__) {
"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "isPaused", function() { return isPaused; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "setPaused", function() { return setPaused; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "onPauseChanged", function() { return onPauseChanged; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "onSingleStep", function() { return onSingleStep; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "getRunningThread", function() { return getRunningThread; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "singleStep", function() { return singleStep; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "setup", function() { return setup; });
/* harmony import */ var _event_target_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../../event-target.js */ "./src/addons/event-target.js");
/* inserted by pull.js */
// https://github.com/LLK/scratch-vm/blob/bb352913b57991713a5ccf0b611fda91056e14ec/src/engine/thread.js#L198
const STATUS_RUNNING = 0;
const STATUS_PROMISE_WAIT = 1;
const STATUS_YIELD = 2;
const STATUS_YIELD_TICK = 3;
const STATUS_DONE = 4;
let vm;
let paused = false;
let pausedThreadState = new WeakMap();
let pauseNewThreads = false;
let steppingThread = null;
const eventTarget = new _event_target_js__WEBPACK_IMPORTED_MODULE_0__["default"]();
const isPaused = () => paused;
const pauseThread = thread => {
if (thread.updateMonitor || pausedThreadState.has(thread)) {
// Thread is already paused or shouldn't be paused.
return;
}
const pauseState = {
time: vm.runtime.currentMSecs,
status: thread.status
};
pausedThreadState.set(thread, pauseState); // Pausing a thread now works by just setting its status to STATUS_PROMISE_WAIT.
// At the start of each frame, we make sure each paused thread is still paused.
// This is really the best way to implement this.
// Converting thread.status into a getter/setter causes Scratch's sequencer to permanently
// perform significantly slower in some projects. I think this is because it causes some
// very hot functions to be deoptimized.
// Trapping sequencer.stepThread to no-op for a paused thread causes Scratch's sequencer
// to waste 24ms of CPU time every frame because it thinks a thread is running.
thread.status = STATUS_PROMISE_WAIT;
};
const ensurePausedThreadIsStillPaused = thread => {
if (thread.status === STATUS_DONE) {
// If a paused thread is finished by single stepping, let it keep being done.
return;
}
const pauseState = pausedThreadState.get(thread);
if (pauseState) {
if (thread.status !== STATUS_PROMISE_WAIT) {
// We'll record the change so we can properly resume the thread, but the thread must still be paused for now.
pauseState.status = thread.status;
thread.status = STATUS_PROMISE_WAIT;
}
}
};
const setSteppingThread = thread => {
steppingThread = thread;
};
const compensateForTimePassedWhilePaused = (thread, pauseState) => {
// TW: Compiled threads store their timer in a different place.
if (thread.timer) {
thread.timer.startTime += vm.runtime.currentMSecs - pauseState.time;
}
const stackFrame = thread.peekStackFrame();
if (stackFrame && stackFrame.executionContext && stackFrame.executionContext.timer) {
stackFrame.executionContext.timer.startTime += vm.runtime.currentMSecs - pauseState.time;
}
};
const stepUnsteppedThreads = lastSteppedThread => {
// If we paused in the middle of a tick, we need to make sure to step the scripts that didn't get
// stepped in that tick to avoid affecting project behavior.
const threads = vm.runtime.threads;
const startingIndex = getThreadIndex(lastSteppedThread);
if (startingIndex !== -1) {
for (let i = startingIndex; i < threads.length; i++) {
const thread = threads[i];
const status = thread.status;
if (status === STATUS_RUNNING || status === STATUS_YIELD || status === STATUS_YIELD_TICK) {
vm.runtime.sequencer.activeThread = thread;
vm.runtime.sequencer.stepThread(thread);
}
}
}
};
const setPaused = _paused => {
if (paused !== _paused) {
paused = _paused;
eventTarget.dispatchEvent(new CustomEvent("change"));
}
if (_paused) {
vm.runtime.audioEngine.audioContext.suspend();
if (!vm.runtime.ioDevices.clock._paused) {
vm.runtime.ioDevices.clock.pause();
}
vm.runtime.threads.forEach(pauseThread);
const activeThread = vm.runtime.sequencer.activeThread;
if (activeThread) {
setSteppingThread(activeThread);
eventTarget.dispatchEvent(new CustomEvent("step"));
}
} else {
vm.runtime.audioEngine.audioContext.resume();
vm.runtime.ioDevices.clock.resume();
for (const thread of vm.runtime.threads) {
const pauseState = pausedThreadState.get(thread);
if (pauseState) {
compensateForTimePassedWhilePaused(thread, pauseState);
thread.status = pauseState.status;
}
}
pausedThreadState = new WeakMap();
const lastSteppedThread = steppingThread; // This must happen after the "change" event is fired to fix https://github.com/ScratchAddons/ScratchAddons/issues/4281
stepUnsteppedThreads(lastSteppedThread);
steppingThread = null;
}
};
const onPauseChanged = listener => {
eventTarget.addEventListener("change", () => listener(paused));
};
const onSingleStep = listener => {
eventTarget.addEventListener("step", listener);
};
const getRunningThread = () => steppingThread; // A modified version of this function
// https://github.com/LLK/scratch-vm/blob/0e86a78a00db41af114df64255e2cd7dd881329f/src/engine/sequencer.js#L179
// Returns if we should continue executing this thread.
const singleStepThread = thread => {
if (thread.status === STATUS_DONE) {
return false;
} // TW: Can't single-step compiled threads
if (thread.isCompiled) {
return false;
}
const currentBlockId = thread.peekStack();
if (!currentBlockId) {
thread.popStack();
if (thread.stack.length === 0) {
thread.status = STATUS_DONE;
return false;
}
}
pauseNewThreads = true;
vm.runtime.sequencer.activeThread = thread;
/*
We need to call execute(this, thread) like the original sequencer. We don't
have access to that method, so we need to force the original stepThread to run
execute for us then exit before it tries to run more blocks.
So, we make `thread.blockGlowInFrame = ...` throw an exception, so this line:
https://github.com/LLK/scratch-vm/blob/bb352913b57991713a5ccf0b611fda91056e14ec/src/engine/sequencer.js#L214
will end the function early. We then have to set it back to normal afterward.
Why are we here just to suffer?
*/
const specialError = ["special error used by Scratch Addons for implementing single-stepping"];
Object.defineProperty(thread, "blockGlowInFrame", {
set(_block) {
throw specialError;
}
});
try {
thread.status = STATUS_RUNNING; // Restart the warp timer on each step.
// If we don't do this, Scratch will think a lot of time has passed and may yield this thread.
if (thread.warpTimer) {
thread.warpTimer.start();
}
try {
vm.runtime.sequencer.stepThread(thread);
} catch (err) {
if (err !== specialError) throw err;
}
if (thread.status !== STATUS_RUNNING) {
return false;
}
if (thread.peekStack() === currentBlockId) {
thread.goToNextBlock();
}
while (!thread.peekStack()) {
thread.popStack();
if (thread.stack.length === 0) {
thread.status = STATUS_DONE;
return false;
}
const stackFrame = thread.peekStackFrame();
if (stackFrame.isLoop) {
if (thread.peekStackFrame().warpMode) {
continue;
} else {
return false;
}
} else if (stackFrame.waitingReporter) {
return false;
}
thread.goToNextBlock();
}
return true;
} finally {
pauseNewThreads = false;
vm.runtime.sequencer.activeThread = null;
Object.defineProperty(thread, "blockGlowInFrame", {
value: currentBlockId,
configurable: true,
enumerable: true,
writable: true
}); // Strictly this doesn't seem to be necessary, but let's make sure the thread is still paused after we step it.
if (thread.status !== STATUS_DONE) {
thread.status = STATUS_PROMISE_WAIT;
}
}
};
const getRealStatus = thread => {
const pauseState = pausedThreadState.get(thread);
if (pauseState) {
return pauseState.status;
}
return thread.status;
};
const getThreadIndex = thread => {
// We can't use vm.runtime.threads.indexOf(thread) because threads can be restarted.
// This can happens when, for example, a "when I receive message1" script broadcasts message1.
// The object in runtime.threads is replaced when this happens.
if (!thread) return -1;
return vm.runtime.threads.findIndex(otherThread => otherThread.target === thread.target && otherThread.topBlock === thread.topBlock && otherThread.stackClick === thread.stackClick && otherThread.updateMonitor === thread.updateMonitor);
};
const findNewSteppingThread = startingIndex => {
const threads = vm.runtime.threads;
for (let i = startingIndex; i < threads.length; i++) {
const possibleNewThread = threads[i];
if (possibleNewThread.updateMonitor) {
// Never single-step monitor update threads.
continue;
} // TW: Can't single-step compiled threads
if (possibleNewThread.isCompiled) {
continue;
}
const status = getRealStatus(possibleNewThread);
if (status === STATUS_RUNNING || status === STATUS_YIELD || status === STATUS_YIELD_TICK) {
// Thread must not be running for single stepping to work.
pauseThread(possibleNewThread);
return possibleNewThread;
}
}
return null;
};
const singleStep = () => {
if (steppingThread) {
const pauseState = pausedThreadState.get(steppingThread); // We can assume pauseState is defined as any single stepping threads must already be paused.
// Make it look like no time has passed
compensateForTimePassedWhilePaused(steppingThread, pauseState);
pauseState.time = vm.runtime.currentMSecs; // Execute the block
const continueExecuting = singleStepThread(steppingThread);
if (!continueExecuting) {
// Try to move onto the next thread
steppingThread = findNewSteppingThread(getThreadIndex(steppingThread) + 1);
}
} // If we don't have a thread, than we are between VM steps and should search for a new thread
if (!steppingThread) {
setSteppingThread(findNewSteppingThread(0)); // End of VM step, emulate one frame of time passing.
vm.runtime.ioDevices.clock._pausedTime += vm.runtime.currentStepTime; // Skip all sounds forward by vm.runtime.currentStepTime milliseconds so it's as
// if they where playing for one frame.
const audioContext = vm.runtime.audioEngine.audioContext;
for (const target of vm.runtime.targets) {
for (const soundId of Object.keys(target.sprite.soundBank.soundPlayers)) {
const soundPlayer = target.sprite.soundBank.soundPlayers[soundId];
if (soundPlayer.outputNode) {
soundPlayer.outputNode.stop(audioContext.currentTime);
soundPlayer._createSource();
soundPlayer.outputNode.start(audioContext.currentTime, audioContext.currentTime - soundPlayer.startingUntil + vm.runtime.currentStepTime / 1000);
soundPlayer.startingUntil -= vm.runtime.currentStepTime / 1000;
}
}
} // Move all threads forward one frame in time. For blocks like `wait () seconds`
for (const thread of vm.runtime.threads) {
if (pausedThreadState.has(thread)) {
pausedThreadState.get(thread).time += vm.runtime.currentStepTime;
}
} // Try to run edge activated hats
pauseNewThreads = true;
const hats = vm.runtime._hats;
for (const hatType in hats) {
if (!Object.prototype.hasOwnProperty.call(hats, hatType)) continue;
const hat = hats[hatType];
if (hat.edgeActivated) {
vm.runtime.startHats(hatType);
}
}
pauseNewThreads = false;
}
eventTarget.dispatchEvent(new CustomEvent("step"));
};
const setup = _vm => {
if (vm) {
return;
}
vm = _vm;
const originalStepThreads = vm.runtime.sequencer.stepThreads;
vm.runtime.sequencer.stepThreads = function () {
if (isPaused()) {
for (const thread of this.runtime.threads) {
ensurePausedThreadIsStillPaused(thread);
}
}
return originalStepThreads.call(this);
}; // Unpause when green flag
const originalGreenFlag = vm.runtime.greenFlag;
vm.runtime.greenFlag = function () {
setPaused(false);
return originalGreenFlag.call(this);
}; // Disable edge-activated hats and hats like "when key pressed" while paused.
const originalStartHats = vm.runtime.startHats;
vm.runtime.startHats = function (...args) {
const hat = args[0]; // These hats can be manually started by the user when paused or while single stepping.
const isUserInitiated = hat === "event_whenbroadcastreceived" || hat === "control_start_as_clone";
if (pauseNewThreads) {
if (!isUserInitiated && !this.getIsEdgeActivatedHat(hat)) {
return [];
}
const newThreads = originalStartHats.apply(this, args);
for (const thread of newThreads) {
pauseThread(thread);
}
return newThreads;
} else if (paused && !isUserInitiated) {
return [];
}
return originalStartHats.apply(this, args);
}; // Paused threads should not be counted as running when updating GUI state.
const originalGetMonitorThreadCount = vm.runtime._getMonitorThreadCount;
vm.runtime._getMonitorThreadCount = function (threads) {
let count = originalGetMonitorThreadCount.call(this, threads);
if (paused) {
for (const thread of threads) {
if (pausedThreadState.has(thread)) {
count++;
}
}
}
return count;
};
};
/***/ }),
/***/ "./src/addons/addons/drag-drop/_runtime_entry.js":
/*!*******************************************************!*\
!*** ./src/addons/addons/drag-drop/_runtime_entry.js ***!
\*******************************************************/
/*! exports provided: resources */
/***/ (function(module, __webpack_exports__, __webpack_require__) {
"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "resources", function() { return resources; });
/* harmony import */ var _userscript_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./userscript.js */ "./src/addons/addons/drag-drop/userscript.js");
/* harmony import */ var _css_loader_dragged_over_css__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! css-loader!./dragged-over.css */ "./node_modules/css-loader/index.js!./src/addons/addons/drag-drop/dragged-over.css");
/* harmony import */ var _css_loader_dragged_over_css__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(_css_loader_dragged_over_css__WEBPACK_IMPORTED_MODULE_1__);
/* generated by pull.js */
const resources = {
"userscript.js": _userscript_js__WEBPACK_IMPORTED_MODULE_0__["default"],
"dragged-over.css": _css_loader_dragged_over_css__WEBPACK_IMPORTED_MODULE_1___default.a
};
/***/ }),
/***/ "./src/addons/addons/drag-drop/userscript.js":
/*!***************************************************!*\
!*** ./src/addons/addons/drag-drop/userscript.js ***!
\***************************************************/
/*! exports provided: default */
/***/ (function(module, __webpack_exports__, __webpack_require__) {
"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony default export */ __webpack_exports__["default"] = (async function ({
addon,
global,
console
}) {
const DRAG_OVER_CLASS = "sa-dragged-over";
const nativeInputValueSetter = Object.getOwnPropertyDescriptor(window.HTMLInputElement.prototype, "value").set;
const reactAwareSetValue = (el, value) => {
nativeInputValueSetter.call(el, value);
el.dispatchEvent(new Event("change", {
bubbles: true
}));
};
const globalHandleDragOver = e => {
if (addon.self.disabled) return;
if (!e.dataTransfer.types.includes("Files")) {
return;
}
let el;
let callback;
if ((el = e.target.closest('div[class*="sprite-selector_sprite-selector"]')) || (el = e.target.closest('div[class*="stage-selector_stage-selector"]')) || (el = e.target.closest('div[class*="selector_wrapper"]'))) {
callback = files => {
const hdFilter = addon.settings.get("use-hd-upload") ? "" : ":not(.sa-better-img-uploads-input)";
const fileInput = el.querySelector('input[class*="action-menu_file-input"]' + hdFilter);
fileInput.files = files;
fileInput.dispatchEvent(new Event("change", {
bubbles: true
}));
};
} else if (el = e.target.closest('div[class*="monitor_list-monitor"]')) {
callback = files => {
const contextMenuBefore = document.querySelector("body > .react-contextmenu.react-contextmenu--visible"); // Simulate a right click on the list monitor
el.dispatchEvent(new MouseEvent("contextmenu", {
bubbles: true
})); // Get the right click menu that opened (monitor context menus are
// children of <body>)
const contextMenuAfter = document.querySelector("body > .react-contextmenu.react-contextmenu--visible"); // `contextMenuAfter` is only null if the context menu was already open
// for the list monitor, in which case we can use the context menu from
// before the simulated right click
const contextMenu = contextMenuAfter === null ? contextMenuBefore : contextMenuAfter; // Sometimes the menu flashes open, so force hide it.
contextMenu.style.display = "none"; // Override DOM methods to import the text file directly
// See: https://github.com/LLK/scratch-gui/blob/develop/src/lib/import-csv.js#L21-L22
const appendChild = document.body.appendChild;
document.body.appendChild = fileInput => {
// Restore appendChild to <body>
document.body.appendChild = appendChild;
if (fileInput instanceof HTMLInputElement) {
document.body.appendChild(fileInput); // Prevent Scratch from opening the file input dialog
fileInput.click = () => {}; // Insert files from the drop event into the file input
fileInput.files = files;
fileInput.dispatchEvent(new Event("change"));
window.requestAnimationFrame(() => {
window.requestAnimationFrame(() => {
contextMenu.style.display = null;
contextMenu.style.opacity = 0;
contextMenu.style.pointerEvents = "none";
});
});
} else {
// The next call for `appendChild` SHOULD be the file input, but if
// it's not, then make `appendChild` behave as normal.
console.error('File input was not immediately given to appendChild upon clicking "Import"!');
return appendChild(fileInput);
}
}; // Simulate clicking on the "Import" option
contextMenu.children[0].click();
};
} else if (el = e.target.closest('div[class*="question_question-input"] > input[class*="input_input-form_l9eYg"]')) {
callback = async files => {
const text = (await Promise.all(Array.from(files, file => file.text()))).join("") // Match pasting behaviour: remove all newline characters at the end
.replace(/[\r\n]+$/, "").replace(/\r?\n|\r/g, " ");
const selectionStart = el.selectionStart;
reactAwareSetValue(el, el.value.slice(0, selectionStart) + text + el.value.slice(el.selectionEnd));
el.setSelectionRange(selectionStart, selectionStart + text.length);
};
}
if (!el) {
return;
}
e.preventDefault();
if (el.classList.contains(DRAG_OVER_CLASS)) {
return;
}
el.classList.add(DRAG_OVER_CLASS);
const handleDrop = e => {
e.preventDefault();
cleanup();
if (e.dataTransfer.types.includes("Files") && e.dataTransfer.files.length > 0) {
callback(e.dataTransfer.files);
}
};
const handleDragOver = e => {
e.preventDefault();
e.dataTransfer.dropEffect = "copy";
};
e.dataTransfer.dropEffect = "copy";
const handleDragLeave = e => {
e.preventDefault();
cleanup();
};
const cleanup = () => {
el.classList.remove(DRAG_OVER_CLASS);
el.removeEventListener("dragover", handleDragOver);
el.removeEventListener("dragleave", handleDragLeave);
el.removeEventListener("drop", handleDrop);
};
el.addEventListener("dragover", handleDragOver);
el.addEventListener("dragleave", handleDragLeave);
el.addEventListener("drop", handleDrop);
};
document.addEventListener("dragover", globalHandleDragOver, {
useCapture: true
});
});
/***/ }),
/***/ "./src/addons/addons/mute-project/_runtime_entry.js":
/*!**********************************************************!*\
!*** ./src/addons/addons/mute-project/_runtime_entry.js ***!
\**********************************************************/
/*! exports provided: resources */
/***/ (function(module, __webpack_exports__, __webpack_require__) {
"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "resources", function() { return resources; });
/* harmony import */ var _userscript_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./userscript.js */ "./src/addons/addons/mute-project/userscript.js");
/* generated by pull.js */
const resources = {
"userscript.js": _userscript_js__WEBPACK_IMPORTED_MODULE_0__["default"]
};
/***/ }),
/***/ "./src/addons/addons/mute-project/userscript.js":
/*!******************************************************!*\
!*** ./src/addons/addons/mute-project/userscript.js ***!
\******************************************************/
/*! exports provided: default */
/***/ (function(module, __webpack_exports__, __webpack_require__) {
"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony import */ var _url_loader_icon_mute_svg__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! url-loader!./icon--mute.svg */ "./node_modules/url-loader/dist/cjs.js!./src/addons/addons/mute-project/icon--mute.svg");
/* inserted by pull.js */
const _twGetAsset = path => {
if (path === "/icon--mute.svg") return _url_loader_icon_mute_svg__WEBPACK_IMPORTED_MODULE_0__["default"];
throw new Error("Unknown asset: ".concat(path));
};
/* harmony default export */ __webpack_exports__["default"] = (async function ({
addon,
global,
console
}) {
const vm = addon.tab.traps.vm;
let muted = false;
let icon = document.createElement("img");
icon.loading = "lazy";
icon.src = _twGetAsset("/icon--mute.svg");
icon.style.display = "none";
const toggleMute = e => {
if (!addon.self.disabled && (e.ctrlKey || e.metaKey)) {
e.cancelBubble = true;
e.preventDefault();
muted = !muted;
if (muted) {
vm.runtime.audioEngine.inputNode.gain.value = 0;
icon.style.display = "block";
} else {
vm.runtime.audioEngine.inputNode.gain.value = 1;
icon.style.display = "none";
}
}
};
addon.self.addEventListener("disabled", () => {
muted = false;
vm.runtime.audioEngine.inputNode.gain.value = 1;
icon.style.display = "none";
});
while (true) {
let button = await addon.tab.waitForElement("[class^='green-flag_green-flag']", {
markAsSeen: true,
reduxEvents: ["scratch-gui/mode/SET_PLAYER", "fontsLoaded/SET_FONTS_LOADED", "scratch-gui/locales/SELECT_LOCALE"]
});
addon.tab.appendToSharedSpace({
space: "afterStopButton",
element: icon,
order: 0
});
button.addEventListener("click", toggleMute);
button.addEventListener("contextmenu", toggleMute);
}
});
/***/ }),
/***/ "./src/addons/addons/pause/_runtime_entry.js":
/*!***************************************************!*\
!*** ./src/addons/addons/pause/_runtime_entry.js ***!
\***************************************************/
/*! exports provided: resources */
/***/ (function(module, __webpack_exports__, __webpack_require__) {
"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "resources", function() { return resources; });
/* harmony import */ var _userscript_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./userscript.js */ "./src/addons/addons/pause/userscript.js");
/* harmony import */ var _css_loader_style_css__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! css-loader!./style.css */ "./node_modules/css-loader/index.js!./src/addons/addons/pause/style.css");
/* harmony import */ var _css_loader_style_css__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(_css_loader_style_css__WEBPACK_IMPORTED_MODULE_1__);
/* generated by pull.js */
const resources = {
"userscript.js": _userscript_js__WEBPACK_IMPORTED_MODULE_0__["default"],
"style.css": _css_loader_style_css__WEBPACK_IMPORTED_MODULE_1___default.a
};
/***/ }),
/***/ "./src/addons/addons/pause/userscript.js":
/*!***********************************************!*\
!*** ./src/addons/addons/pause/userscript.js ***!
\***********************************************/
/*! exports provided: default */
/***/ (function(module, __webpack_exports__, __webpack_require__) {
"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony import */ var _url_loader_pause_svg__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! url-loader!./pause.svg */ "./node_modules/url-loader/dist/cjs.js!./src/addons/addons/pause/pause.svg");
/* harmony import */ var _url_loader_play_svg__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! url-loader!./play.svg */ "./node_modules/url-loader/dist/cjs.js!./src/addons/addons/pause/play.svg");
/* harmony import */ var _debugger_module_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../debugger/module.js */ "./src/addons/addons/debugger/module.js");
/* inserted by pull.js */
const _twGetAsset = path => {
if (path === "/pause.svg") return _url_loader_pause_svg__WEBPACK_IMPORTED_MODULE_0__["default"];
if (path === "/play.svg") return _url_loader_play_svg__WEBPACK_IMPORTED_MODULE_1__["default"];
throw new Error("Unknown asset: ".concat(path));
};
/* harmony default export */ __webpack_exports__["default"] = (async function ({
addon,
global,
console,
msg
}) {
Object(_debugger_module_js__WEBPACK_IMPORTED_MODULE_2__["setup"])(addon.tab.traps.vm);
const img = document.createElement("img");
img.className = "pause-btn";
img.draggable = false;
img.title = msg("pause");
const setSrc = () => img.src = _twGetAsset(Object(_debugger_module_js__WEBPACK_IMPORTED_MODULE_2__["isPaused"])() ? "/play.svg" : "/pause.svg");
img.addEventListener("click", () => Object(_debugger_module_js__WEBPACK_IMPORTED_MODULE_2__["setPaused"])(!Object(_debugger_module_js__WEBPACK_IMPORTED_MODULE_2__["isPaused"])()));
addon.tab.displayNoneWhileDisabled(img);
addon.self.addEventListener("disabled", () => Object(_debugger_module_js__WEBPACK_IMPORTED_MODULE_2__["setPaused"])(false));
setSrc();
Object(_debugger_module_js__WEBPACK_IMPORTED_MODULE_2__["onPauseChanged"])(setSrc);
while (true) {
await addon.tab.waitForElement("[class^='green-flag']", {
markAsSeen: true,
reduxEvents: ["scratch-gui/mode/SET_PLAYER", "fontsLoaded/SET_FONTS_LOADED", "scratch-gui/locales/SELECT_LOCALE"]
});
addon.tab.appendToSharedSpace({
space: "afterGreenFlag",
element: img,
order: 0
});
}
});
/***/ }),
/***/ "./src/addons/api.js":
/*!***************************!*\
!*** ./src/addons/api.js ***!
\***************************/
/*! no exports provided */
/***/ (function(module, __webpack_exports__, __webpack_require__) {
"use strict";
__webpack_require__.r(__webpack_exports__);
/* WEBPACK VAR INJECTION */(function(global) {/* harmony import */ var intl_messageformat__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! intl-messageformat */ "./node_modules/intl-messageformat/index.js");
/* harmony import */ var intl_messageformat__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(intl_messageformat__WEBPACK_IMPORTED_MODULE_0__);
/* harmony import */ var _settings_store_singleton__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./settings-store-singleton */ "./src/addons/settings-store-singleton.js");
/* harmony import */ var _lib_data_uri_to_blob__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../lib/data-uri-to-blob */ "./src/lib/data-uri-to-blob.js");
/* harmony import */ var _event_target__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./event-target */ "./src/addons/event-target.js");
/* harmony import */ var _hooks__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ./hooks */ "./src/addons/hooks.js");
/* harmony import */ var _generated_addon_manifests__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ./generated/addon-manifests */ "./src/addons/generated/addon-manifests.js");
/* harmony import */ var _addons_l10n_en_json__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! ./addons-l10n/en.json */ "./src/addons/addons-l10n/en.json");
var _addons_l10n_en_json__WEBPACK_IMPORTED_MODULE_6___namespace = /*#__PURE__*/__webpack_require__.t(/*! ./addons-l10n/en.json */ "./src/addons/addons-l10n/en.json", 1);
/* harmony import */ var _generated_l10n_entries__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! ./generated/l10n-entries */ "./src/addons/generated/l10n-entries.js");
/* harmony import */ var _generated_addon_entries__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(/*! ./generated/addon-entries */ "./src/addons/generated/addon-entries.js");
/* harmony import */ var _contextmenu__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(/*! ./contextmenu */ "./src/addons/contextmenu.js");
/* harmony import */ var _modal__WEBPACK_IMPORTED_MODULE_10__ = __webpack_require__(/*! ./modal */ "./src/addons/modal.js");
/* harmony import */ var _polyfill__WEBPACK_IMPORTED_MODULE_11__ = __webpack_require__(/*! ./polyfill */ "./src/addons/polyfill.js");
/* harmony import */ var _polyfill__WEBPACK_IMPORTED_MODULE_11___default = /*#__PURE__*/__webpack_require__.n(_polyfill__WEBPACK_IMPORTED_MODULE_11__);
/**
* Copyright (C) 2021 Thomas Weber
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 3 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
/* eslint-disable no-console */
const escapeHTML = str => str.replace(/([<>'"&])/g, (_, l) => "&#".concat(l.charCodeAt(0), ";"));
const kebabCaseToCamelCase = str => str.replace(/-([a-z])/g, g => g[1].toUpperCase());
const createStylesheet = css => {
const style = document.createElement('style');
style.textContent = css;
return style;
};
let _scratchClassNames = null;
const getScratchClassNames = () => {
if (_scratchClassNames) {
return _scratchClassNames;
}
const cssRules = Array.from(document.styleSheets) // Ignore some scratch-paint stylesheets
.filter(styleSheet => !(styleSheet.ownerNode.textContent.startsWith('/* DO NOT EDIT\n@todo This file is copied from GUI and should be pulled out into a shared library.') && (styleSheet.ownerNode.textContent.includes('input_input-form') || styleSheet.ownerNode.textContent.includes('label_input-group_')))).map(e => {
try {
return [...e.cssRules];
} catch (_e) {
return [];
}
}).flat();
const classes = cssRules.map(e => e.selectorText).filter(e => e).map(e => e.match(/(([\w-]+?)_([\w-]+)_([\w\d-]+))/g)).filter(e => e).flat();
_scratchClassNames = [...new Set(classes)];
const observer = new MutationObserver(mutationList => {
for (const mutation of mutationList) {
for (const node of mutation.addedNodes) {
if (node.tagName === 'STYLE') {
_scratchClassNames = null;
observer.disconnect();
return;
}
}
}
});
observer.observe(document.head, {
childList: true
});
return _scratchClassNames;
};
let _mutationObserver;
let _mutationObserverCallbacks = [];
const addMutationObserverCallback = newCallback => {
if (!_mutationObserver) {
_mutationObserver = new MutationObserver(() => {
for (const cb of _mutationObserverCallbacks) {
cb();
}
});
_mutationObserver.observe(document.documentElement, {
attributes: false,
childList: true,
subtree: true
});
}
_mutationObserverCallbacks.push(newCallback);
};
const removeMutationObserverCallback = callback => {
_mutationObserverCallbacks = _mutationObserverCallbacks.filter(i => i !== callback);
};
class Redux extends _event_target__WEBPACK_IMPORTED_MODULE_3__["default"] {
constructor() {
super();
this._isInReducer = false;
this._initialized = false;
this._nextState = null;
}
initialize() {
if (!this._initialized) {
_hooks__WEBPACK_IMPORTED_MODULE_4__["default"].appStateReducer = (action, prev, next) => {
this._isInReducer = true;
this._nextState = next;
this.dispatchEvent(new CustomEvent('statechanged', {
detail: {
action,
prev,
next
}
}));
this._nextState = null;
this._isInReducer = false;
};
this._initialized = true;
}
}
dispatch(m) {
if (this._isInReducer) {
queueMicrotask(() => _hooks__WEBPACK_IMPORTED_MODULE_4__["default"].appStateStore.dispatch(m));
} else {
_hooks__WEBPACK_IMPORTED_MODULE_4__["default"].appStateStore.dispatch(m);
}
}
get state() {
if (this._nextState) return this._nextState;
return _hooks__WEBPACK_IMPORTED_MODULE_4__["default"].appStateStore.getState();
}
}
const getEditorMode = () => {
// eslint-disable-next-line no-use-before-define
const mode = tabReduxInstance.state.scratchGui.mode;
if (mode.isEmbedded) return 'embed';
if (mode.isFullScreen) return 'fullscreen';
if (mode.isPlayerOnly) return 'projectpage';
return 'editor';
};
const tabReduxInstance = new Redux();
const language = tabReduxInstance.state.locales.locale.split('-')[0];
const getTranslations = async () => {
if (_generated_l10n_entries__WEBPACK_IMPORTED_MODULE_7__["default"][language]) {
const localeMessages = await _generated_l10n_entries__WEBPACK_IMPORTED_MODULE_7__["default"][language]();
Object.assign(_addons_l10n_en_json__WEBPACK_IMPORTED_MODULE_6__, localeMessages);
}
};
const addonMessagesPromise = getTranslations();
const untilInEditor = () => {
if (!tabReduxInstance.state.scratchGui.mode.isPlayerOnly) {
return;
}
return new Promise(resolve => {
const handler = () => {
if (!tabReduxInstance.state.scratchGui.mode.isPlayerOnly) {
resolve();
tabReduxInstance.removeEventListener('statechanged', handler);
}
};
tabReduxInstance.initialize();
tabReduxInstance.addEventListener('statechanged', handler);
});
};
const getDisplayNoneWhileDisabledClass = id => "addons-display-none-".concat(id);
const parseArguments = code => code.split(/(?=[^\\]%[nbs])/g).map(i => i.trim()).filter(i => i.charAt(0) === '%').map(i => i.substring(0, 2));
const fixDisplayName = displayName => displayName.replace(/([^\s])(%[nbs])/g, (_, before, arg) => "".concat(before, " ").concat(arg));
const compareArrays = (a, b) => JSON.stringify(a) === JSON.stringify(b);
let _firstAddBlockRan = false;
const contextMenuCallbacks = [];
const CONTEXT_MENU_ORDER = ['editor-devtools', 'block-switching', 'blocks2image', 'swap-local-global'];
let createdAnyBlockContextMenus = false;
const getInternalKey = element => Object.keys(element).find(key => key.startsWith('__reactInternalInstance$')); // Stylesheets are added at the start of <body> so that they have higher precedence
// than those in <head>
const stylesheetContainer = document.createElement('div');
document.body.insertBefore(stylesheetContainer, document.body.firstChild);
const getStylesheetPrecedence = styleElement => {
const addonId = styleElement.dataset.addonId; // columns must have higher precedence than hide-flyout
if (addonId === 'columns') return 1; // editor-stage-left must have higher precedence than hide-stage
if (addonId === 'editor-stage-left') return 1;
return 0;
};
const addStylesheet = styleElement => {
const priority = getStylesheetPrecedence(styleElement);
for (const child of stylesheetContainer.children) {
if (getStylesheetPrecedence(child) >= priority) {
stylesheetContainer.insertBefore(styleElement, child);
return;
}
}
stylesheetContainer.appendChild(styleElement);
};
class Tab extends _event_target__WEBPACK_IMPORTED_MODULE_3__["default"] {
constructor(id) {
super();
this._id = id;
this._seenElements = new WeakSet(); // traps is public API
this.traps = {
get vm() {
return tabReduxInstance.state.scratchGui.vm;
},
getBlockly: () => {
if (_hooks__WEBPACK_IMPORTED_MODULE_4__["default"].blockly) {
return Promise.resolve(_hooks__WEBPACK_IMPORTED_MODULE_4__["default"].blockly);
}
return new Promise(resolve => {
_hooks__WEBPACK_IMPORTED_MODULE_4__["default"].blocklyCallbacks.push(() => resolve(_hooks__WEBPACK_IMPORTED_MODULE_4__["default"].blockly));
});
},
getPaper: async () => {
const modeSelector = await this.waitForElement("[class*='paint-editor_mode-selector']", {
reduxCondition: state => state.scratchGui.editorTab.activeTabIndex === 1 && !state.scratchGui.mode.isPlayerOnly
});
const reactInternalKey = Object.keys(modeSelector).find(key => key.startsWith('__reactInternalInstance$'));
const internalState = modeSelector[reactInternalKey].child; // .tool or .blob.tool only exists on the selected tool
let toolState = internalState;
let tool;
while (toolState) {
const toolInstance = toolState.child.stateNode;
if (toolInstance.tool) {
tool = toolInstance.tool;
break;
}
if (toolInstance.blob && toolInstance.blob.tool) {
tool = toolInstance.blob.tool;
break;
}
toolState = toolState.sibling;
}
if (tool) {
const paperScope = tool._scope;
return paperScope;
}
throw new Error('cannot find paper :(');
},
getInternalKey
};
}
get redux() {
return tabReduxInstance;
}
waitForElement(selector, {
markAsSeen = false,
condition,
reduxCondition,
reduxEvents
} = {}) {
let externalEventSatisfied = true;
const evaluateCondition = () => {
if (!externalEventSatisfied) return false;
if (condition && !condition()) return false;
if (reduxCondition && !reduxCondition(tabReduxInstance.state)) return false;
return true;
};
if (evaluateCondition()) {
const firstQuery = document.querySelectorAll(selector);
for (const element of firstQuery) {
if (this._seenElements.has(element)) continue;
if (markAsSeen) this._seenElements.add(element);
return Promise.resolve(element);
}
}
let reduxListener;
if (reduxEvents) {
externalEventSatisfied = false;
reduxListener = ({
detail
}) => {
const type = detail.action.type; // As addons can't run before DOM exists here, ignore fontsLoaded/SET_FONTS_LOADED
// Otherwise, as our font loading is very async, we could activate more often than required.
if (reduxEvents.includes(type) && type !== 'fontsLoaded/SET_FONTS_LOADED') {
externalEventSatisfied = true;
}
};
this.redux.initialize();
this.redux.addEventListener('statechanged', reduxListener);
}
return new Promise(resolve => {
const callback = () => {
if (!evaluateCondition()) {
return;
}
const elements = document.querySelectorAll(selector);
for (const element of elements) {
if (this._seenElements.has(element)) continue;
resolve(element);
removeMutationObserverCallback(callback);
if (markAsSeen) this._seenElements.add(element);
if (reduxListener) {
this.redux.removeEventListener('statechanged', reduxListener);
}
break;
}
};
addMutationObserverCallback(callback);
});
}
appendToSharedSpace({
space,
element,
order,
scope
}) {
const SHARED_SPACES = {
stageHeader: {
element: () => document.querySelector("[class^='stage-header_stage-size-row']"),
from: () => [],
until: () => [document.querySelector("[class^='stage-header_stage-size-toggle-group']"), document.querySelector("[class^='stage-header_stage-size-row']").lastChild]
},
fullscreenStageHeader: {
element: () => document.querySelector("[class^='stage-header_stage-menu-wrapper']"),
from: function from() {
let emptyDiv = this.element().querySelector('.addon-spacer');
if (!emptyDiv) {
emptyDiv = document.createElement('div');
emptyDiv.style.marginLeft = 'auto';
emptyDiv.className = 'addon-spacer';
this.element().insertBefore(emptyDiv, this.element().lastChild);
}
return [emptyDiv];
},
until: () => [document.querySelector("[class^='stage-header_stage-menu-wrapper']").lastChild]
},
afterGreenFlag: {
element: () => document.querySelector("[class^='controls_controls-container']"),
from: () => [],
until: () => [document.querySelector("[class^='stop-all_stop-all']")]
},
afterStopButton: {
element: () => document.querySelector("[class^='controls_controls-container']"),
from: () => [document.querySelector("[class^='stop-all_stop-all']")],
until: () => []
},
afterSoundTab: {
element: () => document.querySelector("[class^='react-tabs_react-tabs__tab-list']"),
from: () => [document.querySelector("[class^='react-tabs_react-tabs__tab-list']").children[2]],
until: () => [document.querySelector('#s3devToolBar')]
},
assetContextMenuAfterExport: {
element: () => scope,
from: () => Array.prototype.filter.call(scope.children, c => c.textContent === this.scratchMessage('gui.spriteSelectorItem.contextMenuExport')),
until: () => Array.prototype.filter.call(scope.children, c => c.textContent === this.scratchMessage('gui.spriteSelectorItem.contextMenuDelete'))
},
assetContextMenuAfterDelete: {
element: () => scope,
from: () => Array.prototype.filter.call(scope.children, c => c.textContent === this.scratchMessage('gui.spriteSelectorItem.contextMenuDelete')),
until: () => []
}
};
const spaceInfo = SHARED_SPACES[space];
const spaceElement = spaceInfo.element();
if (!spaceElement) return false;
const from = spaceInfo.from();
const until = spaceInfo.until();
element.dataset.saSharedSpaceOrder = order;
let foundFrom = false;
if (from.length === 0) foundFrom = true; // insertAfter = element whose nextSibling will be the new element
// -1 means append at beginning of space (prepend)
// This will stay null if we need to append at the end of space
let insertAfter = null;
const children = Array.from(spaceElement.children);
for (const indexString of children.keys()) {
const child = children[indexString];
const i = Number(indexString); // Find either element from "from" before doing anything
if (!foundFrom) {
if (from.includes(child)) {
foundFrom = true; // If this is the last child, insertAfter will stay null
// and the element will be appended at the end of space
}
continue;
}
if (until.includes(child)) {
// This is the first SA element appended to this space
// If from = [] then prepend, otherwise append after
// previous child (likely a "from" element)
if (i === 0) insertAfter = -1;else insertAfter = children[i - 1];
break;
}
if (child.dataset.saSharedSpaceOrder) {
if (Number(child.dataset.saSharedSpaceOrder) > order) {
// We found another SA element with higher order number
// If from = [] and this is the first child, prepend.
// Otherwise, append before this child.
if (i === 0) insertAfter = -1;else insertAfter = children[i - 1];
break;
}
}
}
if (!foundFrom) return false; // It doesn't matter if we didn't find an "until"
if (insertAfter === null) {
// This might happen with until = []
spaceElement.appendChild(element);
} else if (insertAfter === -1) {
// This might happen with from = []
spaceElement.prepend(element);
} else {
// Works like insertAfter but using insertBefore API.
// nextSibling cannot be null because insertAfter
// is always set to children[i-1], so it must exist
spaceElement.insertBefore(element, insertAfter.nextSibling);
}
return true;
}
addBlock(procedureCode, {
args,
displayName,
callback
}) {
const procCodeArguments = parseArguments(procedureCode);
if (args.length !== procCodeArguments.length) {
throw new Error('Procedure code and argument list do not match');
}
if (displayName) {
displayName = fixDisplayName(displayName);
const displayNameArguments = parseArguments(displayName);
if (!compareArrays(procCodeArguments, displayNameArguments)) {
console.warn("displayName ".concat(displayName, " for ").concat(procedureCode, " has invalid arguments, ignoring it."));
displayName = procedureCode;
}
} else {
displayName = procedureCode;
}
const vm = this.traps.vm;
vm.addAddonBlock({
procedureCode,
arguments: args,
callback,
color: '#29beb8',
secondaryColor: '#3aa8a4',
displayName
});
if (!_firstAddBlockRan) {
_firstAddBlockRan = true;
this.traps.getBlockly().then(ScratchBlocks => {
const BlockSvg = ScratchBlocks.BlockSvg;
const oldUpdateColour = BlockSvg.prototype.updateColour;
BlockSvg.prototype.updateColour = function (...args2) {
// procedures_prototype also has a procedure code but we do not want to color them.
if (this.type === 'procedures_call') {
const block = this.procCode_ && vm.runtime.getAddonBlock(this.procCode_);
if (block) {
this.colour_ = '#29beb8';
this.colourSecondary_ = '#3aa8a4';
this.colourTertiary_ = '#3aa8a4';
this.customContextMenu = null;
}
}
return oldUpdateColour.call(this, ...args2);
};
const originalCreateAllInputs = ScratchBlocks.Blocks.procedures_call.createAllInputs_;
ScratchBlocks.Blocks.procedures_call.createAllInputs_ = function (...args2) {
const block = this.procCode_ && vm.runtime.getAddonBlock(this.procCode_);
if (block && block.displayName) {
const originalProcCode = this.procCode_;
this.procCode_ = block.displayName;
const ret = originalCreateAllInputs.call(this, ...args2);
this.procCode_ = originalProcCode;
return ret;
}
return originalCreateAllInputs.call(this, ...args2);
};
if (vm.editingTarget) {
vm.emitWorkspaceUpdate();
}
});
}
}
getCustomBlock(procedureCode) {
const vm = this.traps.vm;
return vm.getAddonBlock(procedureCode);
}
createBlockContextMenu(callback, {
workspace = false,
blocks = false,
flyout = false,
comments = false
} = {}) {
contextMenuCallbacks.push({
addonId: this._id,
callback,
workspace,
blocks,
flyout,
comments
});
contextMenuCallbacks.sort((b, a) => CONTEXT_MENU_ORDER.indexOf(b.addonId) - CONTEXT_MENU_ORDER.indexOf(a.addonId));
if (createdAnyBlockContextMenus) return;
createdAnyBlockContextMenus = true;
this.traps.getBlockly().then(ScratchBlocks => {
const oldShow = ScratchBlocks.ContextMenu.show;
ScratchBlocks.ContextMenu.show = function (event, items, rtl) {
const gesture = ScratchBlocks.mainWorkspace.currentGesture_;
const block = gesture.targetBlock_; // eslint-disable-next-line no-shadow
for (const {
callback,
workspace,
blocks,
flyout,
comments
} of contextMenuCallbacks) {
const injectMenu = // Workspace
workspace && !block && !gesture.flyout_ && !gesture.startBubble_ || blocks && block && !gesture.flyout_ || flyout && gesture.flyout_ || comments && gesture.startBubble_;
if (injectMenu) {
try {
items = callback(items, block);
} catch (e) {
console.error('Error while calling context menu callback: ', e);
}
}
}
oldShow.call(this, event, items, rtl);
const blocklyContextMenu = ScratchBlocks.WidgetDiv.DIV.firstChild;
items.forEach((item, i) => {
if (i !== 0 && item.separator) {
const itemElt = blocklyContextMenu.children[i];
itemElt.style.paddingTop = '2px';
itemElt.classList.add('sa-blockly-menu-item-border');
itemElt.style.borderTop = '1px solid hsla(0, 0%, 0%, 0.15)';
}
});
};
});
}
createEditorContextMenu(callback, options) {
Object(_contextmenu__WEBPACK_IMPORTED_MODULE_9__["addContextMenu"])(this, callback, options);
}
copyImage(dataURL) {
if (!navigator.clipboard.write) {
return Promise.reject(new Error('Clipboard API not supported'));
}
const items = [// eslint-disable-next-line no-undef
new ClipboardItem({
'image/png': Object(_lib_data_uri_to_blob__WEBPACK_IMPORTED_MODULE_2__["default"])(dataURL)
})];
return navigator.clipboard.write(items);
}
scratchMessage(id) {
return tabReduxInstance.state.locales.messages[id];
}
scratchClass(...args) {
const scratchClasses = getScratchClassNames();
const classes = [];
for (const arg of args) {
if (typeof arg === 'string') {
for (const scratchClass of scratchClasses) {
if (scratchClass.startsWith("".concat(arg, "_")) && scratchClass.length === arg.length + 6) {
classes.push(scratchClass);
break;
}
}
}
}
const options = args[args.length - 1];
if (typeof options === 'object') {
const others = Array.isArray(options.others) ? options.others : [options.others];
for (const className of others) {
classes.push(className);
}
}
return classes.join(' ');
}
get editorMode() {
return getEditorMode();
}
displayNoneWhileDisabled(el) {
el.classList.add(getDisplayNoneWhileDisabledClass(this._id));
}
get direction() {
return this.redux.state.locales.isRtl ? 'rtl' : 'ltr';
}
createModal(title, {
isOpen = false
} = {}) {
return _modal__WEBPACK_IMPORTED_MODULE_10__["createEditorModal"](this, title, {
isOpen
});
}
confirm(...args) {
return _modal__WEBPACK_IMPORTED_MODULE_10__["confirm"](this, ...args);
}
prompt(...args) {
return _modal__WEBPACK_IMPORTED_MODULE_10__["prompt"](this, ...args);
}
}
class Settings extends _event_target__WEBPACK_IMPORTED_MODULE_3__["default"] {
constructor(addonId, manifest) {
super();
this._addonId = addonId;
this._manifest = manifest;
}
get(id) {
return _settings_store_singleton__WEBPACK_IMPORTED_MODULE_1__["default"].getAddonSetting(this._addonId, id);
}
}
class Self extends _event_target__WEBPACK_IMPORTED_MODULE_3__["default"] {
constructor(id) {
super();
this.id = id;
this.disabled = false;
} // These are removed at build-time by pull.js. Throw if attempting to access them at runtime.
get dir() {
throw new Error("Addon tried to access addon.self.dir");
}
get lib() {
throw new Error("Addon tried to access addon.self.lib");
}
}
class AddonRunner {
constructor(id) {
AddonRunner.instances.push(this);
const manifest = _generated_addon_manifests__WEBPACK_IMPORTED_MODULE_5__["default"][id];
this.id = id;
this.manifest = manifest;
this.messageCache = {};
this.stylesheets = [];
this.disabledStylesheet = null;
this.loading = true;
this.publicAPI = {
global,
console,
addon: {
tab: new Tab(id),
settings: new Settings(id, manifest),
self: new Self(id)
},
msg: this.msg.bind(this),
safeMsg: this.safeMsg.bind(this)
};
}
_msg(key, vars, handler) {
const namespacedKey = "".concat(this.id, "/").concat(key);
if (this.messageCache[namespacedKey]) {
return this.messageCache[namespacedKey].format(vars);
}
let translation = _addons_l10n_en_json__WEBPACK_IMPORTED_MODULE_6__[namespacedKey];
if (!translation) {
return namespacedKey;
}
if (handler) {
translation = handler(translation);
}
const messageFormat = new intl_messageformat__WEBPACK_IMPORTED_MODULE_0___default.a(translation, language);
this.messageCache[namespacedKey] = messageFormat;
return messageFormat.format(vars);
}
msg(key, vars) {
return this._msg(key, vars, null);
}
safeMsg(key, vars) {
return this._msg(key, vars, escapeHTML);
}
settingsChanged() {
this.publicAPI.addon.settings.dispatchEvent(new CustomEvent('change'));
this.updateCSSVariables();
}
updateCSSVariables() {
if (this.manifest.settings) {
const kebabCaseId = kebabCaseToCamelCase(this.id);
for (const setting of this.manifest.settings) {
const settingId = setting.id;
const variable = "--".concat(kebabCaseId, "-").concat(kebabCaseToCamelCase(settingId));
const value = this.publicAPI.addon.settings.get(settingId);
document.documentElement.style.setProperty(variable, value);
}
}
}
meetsCondition(condition) {
if (!condition) {
// No condition, so always active.
return true;
}
if (condition.settings) {
for (const [settingId, expectedValue] of Object.entries(condition.settings)) {
if (this.publicAPI.addon.settings.get(settingId) !== expectedValue) {
return false;
}
}
}
return true;
}
dynamicEnable() {
if (this.loading) {
return;
}
this.appendStylesheets();
if (this.disabledStylesheet) {
this.disabledStylesheet.remove();
this.disabledStylesheet = null;
}
this.publicAPI.addon.self.disabled = false;
this.publicAPI.addon.self.dispatchEvent(new CustomEvent('reenabled'));
}
dynamicDisable() {
if (this.loading) {
return;
}
this.removeStylesheets();
const disabledCSS = ".".concat(getDisplayNoneWhileDisabledClass(this.id), "{display:none !important;}");
this.disabledStylesheet = createStylesheet(disabledCSS);
addStylesheet(this.disabledStylesheet);
this.publicAPI.addon.self.disabled = true;
this.publicAPI.addon.self.dispatchEvent(new CustomEvent('disabled'));
}
removeStylesheets() {
for (const style of this.stylesheets) {
style.remove();
}
}
appendStylesheets() {
for (const style of this.stylesheets) {
addStylesheet(style);
}
}
async run() {
if (this.manifest.editorOnly) {
await untilInEditor();
}
const {
resources
} = await _generated_addon_entries__WEBPACK_IMPORTED_MODULE_8__["default"][this.id]();
if (!this.manifest.noTranslations) {
await addonMessagesPromise;
}
this.updateCSSVariables();
if (this.manifest.userstyles) {
for (const userstyle of this.manifest.userstyles) {
if (!this.meetsCondition(userstyle.if)) {
continue;
}
const m = resources[userstyle.url];
const source = m[0][1];
const style = createStylesheet(source);
style.className = 'scratch-addons-theme';
style.dataset.addonId = this.id;
this.stylesheets.push(style);
}
}
this.appendStylesheets();
if (this.manifest.userscripts) {
for (const userscript of this.manifest.userscripts) {
if (!this.meetsCondition(userscript.if)) {
continue;
}
const fn = resources[userscript.url];
fn(this.publicAPI);
}
}
this.loading = false;
}
}
AddonRunner.instances = [];
const runAddon = addonId => {
const runner = new AddonRunner(addonId);
runner.run();
};
let oldMode = getEditorMode();
const emitUrlChange = () => {
// In Scratch, URL changes usually mean someone went from editor to fullscreen or something like that.
// This is not the case in TW -- the URL can change for many other reasons that addons probably aren't prepared
// to handle.
const newMode = getEditorMode();
if (newMode !== oldMode) {
oldMode = newMode;
setTimeout(() => {
for (const addon of AddonRunner.instances) {
addon.publicAPI.addon.tab.dispatchEvent(new CustomEvent('urlChange'));
}
});
}
};
const originalReplaceState = history.replaceState;
history.replaceState = function (...args) {
originalReplaceState.apply(this, args);
emitUrlChange();
};
const originalPushState = history.pushState;
history.pushState = function (...args) {
originalPushState.apply(this, args);
emitUrlChange();
};
_settings_store_singleton__WEBPACK_IMPORTED_MODULE_1__["default"].addEventListener('addon-changed', e => {
const addonId = e.detail.addonId;
const runner = AddonRunner.instances.find(i => i.id === addonId);
if (runner) {
runner.settingsChanged();
}
if (e.detail.dynamicEnable) {
if (runner) {
runner.dynamicEnable();
} else {
runAddon(addonId);
}
} else if (e.detail.dynamicDisable) {
if (runner) {
runner.dynamicDisable();
}
}
});
for (const id of Object.keys(_generated_addon_manifests__WEBPACK_IMPORTED_MODULE_5__["default"])) {
if (!_settings_store_singleton__WEBPACK_IMPORTED_MODULE_1__["default"].getAddonEnabled(id)) {
continue;
}
runAddon(id);
}
/* WEBPACK VAR INJECTION */}.call(this, __webpack_require__(/*! ./../../node_modules/webpack/buildin/global.js */ "./node_modules/webpack/buildin/global.js")))
/***/ }),
/***/ "./src/addons/contextmenu.js":
/*!***********************************!*\
!*** ./src/addons/contextmenu.js ***!
\***********************************/
/*! exports provided: addContextMenu */
/***/ (function(module, __webpack_exports__, __webpack_require__) {
"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "addContextMenu", function() { return addContextMenu; });
function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); if (enumerableOnly) { symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; }); } keys.push.apply(keys, symbols); } return keys; }
function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; if (i % 2) { ownKeys(Object(source), true).forEach(function (key) { _defineProperty(target, key, source[key]); }); } else if (Object.getOwnPropertyDescriptors) { Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); } else { ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } } return target; }
function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
// This file is imported from
// https://github.com/ScratchAddons/ScratchAddons/blob/master/addon-api/content-script/contextmenu.js
/* eslint-disable */
let initialized = false;
let hasDynamicContextMenu = false;
let contextMenus = [];
const onReactContextMenu = function onReactContextMenu(e) {
var _ctxTarget$this$traps10, _ctxTarget$this$traps11, _ctxTarget$this$traps12, _ctxTarget$this$traps13, _ctxTarget$this$traps14, _ctxTarget$this$traps15;
if (!e.target) return;
const ctxTarget = e.target.closest(".react-contextmenu-wrapper");
if (!ctxTarget) return;
let ctxMenu = ctxTarget.querySelector("nav.react-contextmenu");
let type;
const extra = {};
if (false) { var _ctxTarget$this$traps, _ctxTarget$this$traps2, _ctxTarget$this$traps3, _ctxTarget$this$traps4, _ctxTarget$this$traps5, _ctxTarget$this$traps6, _ctxTarget$this$traps7, _ctxTarget$this$traps8, _ctxTarget$this$traps9; } else if ((_ctxTarget$this$traps10 = ctxTarget[this.traps.getInternalKey(ctxTarget)]) !== null && _ctxTarget$this$traps10 !== void 0 && (_ctxTarget$this$traps11 = _ctxTarget$this$traps10.return) !== null && _ctxTarget$this$traps11 !== void 0 && (_ctxTarget$this$traps12 = _ctxTarget$this$traps11.return) !== null && _ctxTarget$this$traps12 !== void 0 && (_ctxTarget$this$traps13 = _ctxTarget$this$traps12.return) !== null && _ctxTarget$this$traps13 !== void 0 && (_ctxTarget$this$traps14 = _ctxTarget$this$traps13.stateNode) !== null && _ctxTarget$this$traps14 !== void 0 && (_ctxTarget$this$traps15 = _ctxTarget$this$traps14.props) !== null && _ctxTarget$this$traps15 !== void 0 && _ctxTarget$this$traps15.dragType) {
// SpriteSelectorItem which despite its name is used for costumes, sounds, backpacked script etc
const props = ctxTarget[this.traps.getInternalKey(ctxTarget)].return.return.return.stateNode.props;
type = props.dragType.toLowerCase();
extra.name = props.name;
extra.itemId = props.id;
extra.index = props.index;
} else {
return;
}
const ctx = _objectSpread({
menuItem: ctxMenu,
target: ctxTarget,
type
}, extra);
Array.from(ctxMenu.children).forEach(existing => {
if (existing.classList.contains("sa-ctx-menu")) existing.remove();
});
for (const item of hasDynamicContextMenu ? contextMenus.flatMap(menu => typeof menu === "function" ? menu(type, ctx) : menu) : contextMenus) {
if (!item) continue;
if (item.types && !item.types.some(itemType => type === itemType)) continue;
if (item.condition && !item.condition(ctx)) continue;
const itemElem = document.createElement("div");
const classes = ["context-menu_menu-item"];
if (item.border) classes.push("context-menu_menu-item-bordered");
if (item.dangerous) classes.push("context-menu_menu-item-danger");
itemElem.className = this.scratchClass(...classes, {
others: ["react-contextmenu-item", "sa-ctx-menu", item.className || ""]
});
const label = document.createElement("span");
label.textContent = item.label;
itemElem.append(label);
this.displayNoneWhileDisabled(itemElem, {
display: "block"
});
itemElem.addEventListener("click", e => {
e.stopPropagation();
window.dispatchEvent(new CustomEvent("REACT_CONTEXTMENU_HIDE", {
detail: {
action: "REACT_CONTEXTMENU_HIDE"
}
}));
item.callback(ctx);
});
this.appendToSharedSpace({
space: item.position,
order: item.order,
scope: ctxMenu,
element: itemElem
});
}
return;
};
const initialize = tab => {
if (initialized) return;
initialized = true;
document.body.addEventListener("contextmenu", e => onReactContextMenu.call(tab, e), {
capture: true
});
};
const addContextMenu = (tab, callback, opts) => {
if (typeof opts === "undefined") {
contextMenus.push(callback);
hasDynamicContextMenu = true;
} else {
contextMenus.push(_objectSpread(_objectSpread({}, opts), {}, {
callback
}));
}
initialize(tab);
};
/***/ }),
/***/ "./src/addons/generated/addon-entries.js":
/*!***********************************************!*\
!*** ./src/addons/generated/addon-entries.js ***!
\***********************************************/
/*! exports provided: default */
/***/ (function(module, __webpack_exports__, __webpack_require__) {
"use strict";
__webpack_require__.r(__webpack_exports__);
/* generated by pull.js */
/* harmony default export */ __webpack_exports__["default"] = ({
"cat-blocks": () => __webpack_require__.e(/*! import() | addon-entry-cat-blocks */ "addon-entry-cat-blocks").then(__webpack_require__.bind(null, /*! ../addons/cat-blocks/_runtime_entry.js */ "./src/addons/addons/cat-blocks/_runtime_entry.js")),
"editor-devtools": () => __webpack_require__.e(/*! import() | addon-default-entry */ "addon-default-entry").then(__webpack_require__.bind(null, /*! ../addons/editor-devtools/_runtime_entry.js */ "./src/addons/addons/editor-devtools/_runtime_entry.js")),
"editor-searchable-dropdowns": () => __webpack_require__.e(/*! import() | addon-default-entry */ "addon-default-entry").then(__webpack_require__.bind(null, /*! ../addons/editor-searchable-dropdowns/_runtime_entry.js */ "./src/addons/addons/editor-searchable-dropdowns/_runtime_entry.js")),
"data-category-tweaks-v2": () => __webpack_require__.e(/*! import() | addon-entry-data-category-tweaks-v2 */ "addon-entry-data-category-tweaks-v2").then(__webpack_require__.bind(null, /*! ../addons/data-category-tweaks-v2/_runtime_entry.js */ "./src/addons/addons/data-category-tweaks-v2/_runtime_entry.js")),
"block-palette-icons": () => __webpack_require__.e(/*! import() | addon-entry-block-palette-icons */ "addon-entry-block-palette-icons").then(__webpack_require__.bind(null, /*! ../addons/block-palette-icons/_runtime_entry.js */ "./src/addons/addons/block-palette-icons/_runtime_entry.js")),
"hide-flyout": () => __webpack_require__.e(/*! import() | addon-entry-hide-flyout */ "addon-entry-hide-flyout").then(__webpack_require__.bind(null, /*! ../addons/hide-flyout/_runtime_entry.js */ "./src/addons/addons/hide-flyout/_runtime_entry.js")),
"mediarecorder": () => __webpack_require__.e(/*! import() | addon-entry-mediarecorder */ "addon-entry-mediarecorder").then(__webpack_require__.bind(null, /*! ../addons/mediarecorder/_runtime_entry.js */ "./src/addons/addons/mediarecorder/_runtime_entry.js")),
"drag-drop": () => __webpack_require__(/*! ../addons/drag-drop/_runtime_entry.js */ "./src/addons/addons/drag-drop/_runtime_entry.js"),
"debugger": () => __webpack_require__.e(/*! import() | addon-entry-debugger */ "addon-entry-debugger").then(__webpack_require__.bind(null, /*! ../addons/debugger/_runtime_entry.js */ "./src/addons/addons/debugger/_runtime_entry.js")),
"pause": () => __webpack_require__(/*! ../addons/pause/_runtime_entry.js */ "./src/addons/addons/pause/_runtime_entry.js"),
"mute-project": () => __webpack_require__(/*! ../addons/mute-project/_runtime_entry.js */ "./src/addons/addons/mute-project/_runtime_entry.js"),
"clones": () => __webpack_require__.e(/*! import() | addon-entry-clones */ "addon-entry-clones").then(__webpack_require__.bind(null, /*! ../addons/clones/_runtime_entry.js */ "./src/addons/addons/clones/_runtime_entry.js")),
"mouse-pos": () => __webpack_require__.e(/*! import() | addon-entry-mouse-pos */ "addon-entry-mouse-pos").then(__webpack_require__.bind(null, /*! ../addons/mouse-pos/_runtime_entry.js */ "./src/addons/addons/mouse-pos/_runtime_entry.js")),
"color-picker": () => __webpack_require__.e(/*! import() | addon-default-entry */ "addon-default-entry").then(__webpack_require__.bind(null, /*! ../addons/color-picker/_runtime_entry.js */ "./src/addons/addons/color-picker/_runtime_entry.js")),
"remove-sprite-confirm": () => __webpack_require__.e(/*! import() | addon-entry-remove-sprite-confirm */ "addon-entry-remove-sprite-confirm").then(__webpack_require__.bind(null, /*! ../addons/remove-sprite-confirm/_runtime_entry.js */ "./src/addons/addons/remove-sprite-confirm/_runtime_entry.js")),
"block-count": () => __webpack_require__.e(/*! import() | addon-entry-block-count */ "addon-entry-block-count").then(__webpack_require__.bind(null, /*! ../addons/block-count/_runtime_entry.js */ "./src/addons/addons/block-count/_runtime_entry.js")),
"onion-skinning": () => __webpack_require__.e(/*! import() | addon-default-entry */ "addon-default-entry").then(__webpack_require__.bind(null, /*! ../addons/onion-skinning/_runtime_entry.js */ "./src/addons/addons/onion-skinning/_runtime_entry.js")),
"default-costume-editor-color": () => __webpack_require__.e(/*! import() | addon-entry-default-costume-editor-color */ "addon-entry-default-costume-editor-color").then(__webpack_require__.bind(null, /*! ../addons/default-costume-editor-color/_runtime_entry.js */ "./src/addons/addons/default-costume-editor-color/_runtime_entry.js")),
"bitmap-copy": () => __webpack_require__.e(/*! import() | addon-default-entry */ "addon-default-entry").then(__webpack_require__.bind(null, /*! ../addons/bitmap-copy/_runtime_entry.js */ "./src/addons/addons/bitmap-copy/_runtime_entry.js")),
"2d-color-picker": () => __webpack_require__.e(/*! import() | addon-entry-2d-color-picker */ "addon-entry-2d-color-picker").then(__webpack_require__.bind(null, /*! ../addons/2d-color-picker/_runtime_entry.js */ "./src/addons/addons/2d-color-picker/_runtime_entry.js")),
"better-img-uploads": () => __webpack_require__.e(/*! import() | addon-entry-better-img-uploads */ "addon-entry-better-img-uploads").then(__webpack_require__.bind(null, /*! ../addons/better-img-uploads/_runtime_entry.js */ "./src/addons/addons/better-img-uploads/_runtime_entry.js")),
"pick-colors-from-stage": () => __webpack_require__.e(/*! import() | addon-default-entry */ "addon-default-entry").then(__webpack_require__.bind(null, /*! ../addons/pick-colors-from-stage/_runtime_entry.js */ "./src/addons/addons/pick-colors-from-stage/_runtime_entry.js")),
"custom-block-shape": () => __webpack_require__.e(/*! import() | addon-entry-custom-block-shape */ "addon-entry-custom-block-shape").then(__webpack_require__.bind(null, /*! ../addons/custom-block-shape/_runtime_entry.js */ "./src/addons/addons/custom-block-shape/_runtime_entry.js")),
"zebra-striping": () => __webpack_require__.e(/*! import() | addon-entry-zebra-striping */ "addon-entry-zebra-striping").then(__webpack_require__.bind(null, /*! ../addons/zebra-striping/_runtime_entry.js */ "./src/addons/addons/zebra-striping/_runtime_entry.js")),
"editor-theme3": () => __webpack_require__.e(/*! import() | addon-entry-editor-theme3 */ "addon-entry-editor-theme3").then(__webpack_require__.bind(null, /*! ../addons/editor-theme3/_runtime_entry.js */ "./src/addons/addons/editor-theme3/_runtime_entry.js")),
"custom-block-text": () => __webpack_require__.e(/*! import() | addon-entry-custom-block-text */ "addon-entry-custom-block-text").then(__webpack_require__.bind(null, /*! ../addons/custom-block-text/_runtime_entry.js */ "./src/addons/addons/custom-block-text/_runtime_entry.js")),
"editor-colored-context-menus": () => __webpack_require__.e(/*! import() | addon-entry-editor-colored-context-menus */ "addon-entry-editor-colored-context-menus").then(__webpack_require__.bind(null, /*! ../addons/editor-colored-context-menus/_runtime_entry.js */ "./src/addons/addons/editor-colored-context-menus/_runtime_entry.js")),
"editor-stage-left": () => __webpack_require__.e(/*! import() | addon-entry-editor-stage-left */ "addon-entry-editor-stage-left").then(__webpack_require__.bind(null, /*! ../addons/editor-stage-left/_runtime_entry.js */ "./src/addons/addons/editor-stage-left/_runtime_entry.js")),
"editor-buttons-reverse-order": () => __webpack_require__.e(/*! import() | addon-entry-editor-buttons-reverse-order */ "addon-entry-editor-buttons-reverse-order").then(__webpack_require__.bind(null, /*! ../addons/editor-buttons-reverse-order/_runtime_entry.js */ "./src/addons/addons/editor-buttons-reverse-order/_runtime_entry.js")),
"variable-manager": () => __webpack_require__.e(/*! import() | addon-entry-variable-manager */ "addon-entry-variable-manager").then(__webpack_require__.bind(null, /*! ../addons/variable-manager/_runtime_entry.js */ "./src/addons/addons/variable-manager/_runtime_entry.js")),
"search-sprites": () => __webpack_require__.e(/*! import() | addon-entry-search-sprites */ "addon-entry-search-sprites").then(__webpack_require__.bind(null, /*! ../addons/search-sprites/_runtime_entry.js */ "./src/addons/addons/search-sprites/_runtime_entry.js")),
"gamepad": () => __webpack_require__.e(/*! import() | addon-entry-gamepad */ "addon-entry-gamepad").then(__webpack_require__.bind(null, /*! ../addons/gamepad/_runtime_entry.js */ "./src/addons/addons/gamepad/_runtime_entry.js")),
"editor-sounds": () => __webpack_require__.e(/*! import() | addon-entry-editor-sounds */ "addon-entry-editor-sounds").then(__webpack_require__.bind(null, /*! ../addons/editor-sounds/_runtime_entry.js */ "./src/addons/addons/editor-sounds/_runtime_entry.js")),
"folders": () => __webpack_require__.e(/*! import() | addon-default-entry */ "addon-default-entry").then(__webpack_require__.bind(null, /*! ../addons/folders/_runtime_entry.js */ "./src/addons/addons/folders/_runtime_entry.js")),
"block-switching": () => __webpack_require__.e(/*! import() | addon-default-entry */ "addon-default-entry").then(__webpack_require__.bind(null, /*! ../addons/block-switching/_runtime_entry.js */ "./src/addons/addons/block-switching/_runtime_entry.js")),
"load-extensions": () => __webpack_require__.e(/*! import() | addon-entry-load-extensions */ "addon-entry-load-extensions").then(__webpack_require__.bind(null, /*! ../addons/load-extensions/_runtime_entry.js */ "./src/addons/addons/load-extensions/_runtime_entry.js")),
"custom-zoom": () => __webpack_require__.e(/*! import() | addon-entry-custom-zoom */ "addon-entry-custom-zoom").then(__webpack_require__.bind(null, /*! ../addons/custom-zoom/_runtime_entry.js */ "./src/addons/addons/custom-zoom/_runtime_entry.js")),
"initialise-sprite-position": () => __webpack_require__.e(/*! import() | addon-entry-initialise-sprite-position */ "addon-entry-initialise-sprite-position").then(__webpack_require__.bind(null, /*! ../addons/initialise-sprite-position/_runtime_entry.js */ "./src/addons/addons/initialise-sprite-position/_runtime_entry.js")),
"blocks2image": () => __webpack_require__.e(/*! import() | addon-entry-blocks2image */ "addon-entry-blocks2image").then(__webpack_require__.bind(null, /*! ../addons/blocks2image/_runtime_entry.js */ "./src/addons/addons/blocks2image/_runtime_entry.js")),
"remove-curved-stage-border": () => __webpack_require__.e(/*! import() | addon-entry-remove-curved-stage-border */ "addon-entry-remove-curved-stage-border").then(__webpack_require__.bind(null, /*! ../addons/remove-curved-stage-border/_runtime_entry.js */ "./src/addons/addons/remove-curved-stage-border/_runtime_entry.js")),
"transparent-orphans": () => __webpack_require__.e(/*! import() | addon-entry-transparent-orphans */ "addon-entry-transparent-orphans").then(__webpack_require__.bind(null, /*! ../addons/transparent-orphans/_runtime_entry.js */ "./src/addons/addons/transparent-orphans/_runtime_entry.js")),
"paint-by-default": () => __webpack_require__.e(/*! import() | addon-entry-paint-by-default */ "addon-entry-paint-by-default").then(__webpack_require__.bind(null, /*! ../addons/paint-by-default/_runtime_entry.js */ "./src/addons/addons/paint-by-default/_runtime_entry.js")),
"block-cherry-picking": () => __webpack_require__.e(/*! import() | addon-default-entry */ "addon-default-entry").then(__webpack_require__.bind(null, /*! ../addons/block-cherry-picking/_runtime_entry.js */ "./src/addons/addons/block-cherry-picking/_runtime_entry.js")),
"hide-new-variables": () => __webpack_require__.e(/*! import() | addon-entry-hide-new-variables */ "addon-entry-hide-new-variables").then(__webpack_require__.bind(null, /*! ../addons/hide-new-variables/_runtime_entry.js */ "./src/addons/addons/hide-new-variables/_runtime_entry.js")),
"editor-extra-keys": () => __webpack_require__.e(/*! import() | addon-entry-editor-extra-keys */ "addon-entry-editor-extra-keys").then(__webpack_require__.bind(null, /*! ../addons/editor-extra-keys/_runtime_entry.js */ "./src/addons/addons/editor-extra-keys/_runtime_entry.js")),
"hide-delete-button": () => __webpack_require__.e(/*! import() | addon-entry-hide-delete-button */ "addon-entry-hide-delete-button").then(__webpack_require__.bind(null, /*! ../addons/hide-delete-button/_runtime_entry.js */ "./src/addons/addons/hide-delete-button/_runtime_entry.js")),
"no-script-bumping": () => __webpack_require__.e(/*! import() | addon-entry-no-script-bumping */ "addon-entry-no-script-bumping").then(__webpack_require__.bind(null, /*! ../addons/no-script-bumping/_runtime_entry.js */ "./src/addons/addons/no-script-bumping/_runtime_entry.js")),
"disable-stage-drag-select": () => __webpack_require__.e(/*! import() | addon-entry-disable-stage-drag-select */ "addon-entry-disable-stage-drag-select").then(__webpack_require__.bind(null, /*! ../addons/disable-stage-drag-select/_runtime_entry.js */ "./src/addons/addons/disable-stage-drag-select/_runtime_entry.js")),
"move-to-top-bottom": () => __webpack_require__.e(/*! import() | addon-default-entry */ "addon-default-entry").then(__webpack_require__.bind(null, /*! ../addons/move-to-top-bottom/_runtime_entry.js */ "./src/addons/addons/move-to-top-bottom/_runtime_entry.js")),
"disable-paste-offset": () => __webpack_require__.e(/*! import() | addon-entry-disable-paste-offset */ "addon-entry-disable-paste-offset").then(__webpack_require__.bind(null, /*! ../addons/disable-paste-offset/_runtime_entry.js */ "./src/addons/addons/disable-paste-offset/_runtime_entry.js")),
"block-duplicate": () => __webpack_require__.e(/*! import() | addon-default-entry */ "addon-default-entry").then(__webpack_require__.bind(null, /*! ../addons/block-duplicate/_runtime_entry.js */ "./src/addons/addons/block-duplicate/_runtime_entry.js")),
"rename-broadcasts": () => __webpack_require__.e(/*! import() | addon-default-entry */ "addon-default-entry").then(__webpack_require__.bind(null, /*! ../addons/rename-broadcasts/_runtime_entry.js */ "./src/addons/addons/rename-broadcasts/_runtime_entry.js")),
"swap-local-global": () => __webpack_require__.e(/*! import() | addon-entry-swap-local-global */ "addon-entry-swap-local-global").then(__webpack_require__.bind(null, /*! ../addons/swap-local-global/_runtime_entry.js */ "./src/addons/addons/swap-local-global/_runtime_entry.js")),
"editor-comment-previews": () => __webpack_require__.e(/*! import() | addon-default-entry */ "addon-default-entry").then(__webpack_require__.bind(null, /*! ../addons/editor-comment-previews/_runtime_entry.js */ "./src/addons/addons/editor-comment-previews/_runtime_entry.js")),
"columns": () => __webpack_require__.e(/*! import() | addon-entry-columns */ "addon-entry-columns").then(__webpack_require__.bind(null, /*! ../addons/columns/_runtime_entry.js */ "./src/addons/addons/columns/_runtime_entry.js")),
"script-snap": () => __webpack_require__.e(/*! import() | addon-entry-script-snap */ "addon-entry-script-snap").then(__webpack_require__.bind(null, /*! ../addons/script-snap/_runtime_entry.js */ "./src/addons/addons/script-snap/_runtime_entry.js")),
"fullscreen": () => __webpack_require__.e(/*! import() | addon-entry-fullscreen */ "addon-entry-fullscreen").then(__webpack_require__.bind(null, /*! ../addons/fullscreen/_runtime_entry.js */ "./src/addons/addons/fullscreen/_runtime_entry.js")),
"hide-stage": () => __webpack_require__.e(/*! import() | addon-entry-hide-stage */ "addon-entry-hide-stage").then(__webpack_require__.bind(null, /*! ../addons/hide-stage/_runtime_entry.js */ "./src/addons/addons/hide-stage/_runtime_entry.js")),
"tw-straighten-comments": () => __webpack_require__.e(/*! import() | addon-entry-tw-straighten-comments */ "addon-entry-tw-straighten-comments").then(__webpack_require__.bind(null, /*! ../addons/tw-straighten-comments/_runtime_entry.js */ "./src/addons/addons/tw-straighten-comments/_runtime_entry.js")),
"tw-remove-backpack": () => __webpack_require__.e(/*! import() | addon-entry-tw-remove-backpack */ "addon-entry-tw-remove-backpack").then(__webpack_require__.bind(null, /*! ../addons/tw-remove-backpack/_runtime_entry.js */ "./src/addons/addons/tw-remove-backpack/_runtime_entry.js")),
"tw-remove-feedback": () => __webpack_require__.e(/*! import() | addon-entry-tw-remove-feedback */ "addon-entry-tw-remove-feedback").then(__webpack_require__.bind(null, /*! ../addons/tw-remove-feedback/_runtime_entry.js */ "./src/addons/addons/tw-remove-feedback/_runtime_entry.js")),
"tw-disable-compiler": () => __webpack_require__.e(/*! import() | addon-entry-tw-disable-compiler */ "addon-entry-tw-disable-compiler").then(__webpack_require__.bind(null, /*! ../addons/tw-disable-compiler/_runtime_entry.js */ "./src/addons/addons/tw-disable-compiler/_runtime_entry.js")),
"editor-stepping": () => __webpack_require__.e(/*! import() | addon-entry-editor-stepping */ "addon-entry-editor-stepping").then(__webpack_require__.bind(null, /*! ../addons/editor-stepping/_runtime_entry.js */ "./src/addons/addons/editor-stepping/_runtime_entry.js"))
});
/***/ }),
/***/ "./src/addons/generated/l10n-entries.js":
/*!**********************************************!*\
!*** ./src/addons/generated/l10n-entries.js ***!
\**********************************************/
/*! exports provided: default */
/***/ (function(module, __webpack_exports__, __webpack_require__) {
"use strict";
__webpack_require__.r(__webpack_exports__);
/* generated by pull.js */
/* harmony default export */ __webpack_exports__["default"] = ({
"de": () => __webpack_require__.e(/*! import() | addon-l10n-de */ "addon-l10n-de").then(__webpack_require__.t.bind(null, /*! ../addons-l10n/de.json */ "./src/addons/addons-l10n/de.json", 3)),
"es": () => __webpack_require__.e(/*! import() | addon-l10n-es */ "addon-l10n-es").then(__webpack_require__.t.bind(null, /*! ../addons-l10n/es.json */ "./src/addons/addons-l10n/es.json", 3)),
"fr": () => __webpack_require__.e(/*! import() | addon-l10n-fr */ "addon-l10n-fr").then(__webpack_require__.t.bind(null, /*! ../addons-l10n/fr.json */ "./src/addons/addons-l10n/fr.json", 3)),
"hu": () => __webpack_require__.e(/*! import() | addon-l10n-hu */ "addon-l10n-hu").then(__webpack_require__.t.bind(null, /*! ../addons-l10n/hu.json */ "./src/addons/addons-l10n/hu.json", 3)),
"it": () => __webpack_require__.e(/*! import() | addon-l10n-it */ "addon-l10n-it").then(__webpack_require__.t.bind(null, /*! ../addons-l10n/it.json */ "./src/addons/addons-l10n/it.json", 3)),
"ja": () => __webpack_require__.e(/*! import() | addon-l10n-ja */ "addon-l10n-ja").then(__webpack_require__.t.bind(null, /*! ../addons-l10n/ja.json */ "./src/addons/addons-l10n/ja.json", 3)),
"ko": () => __webpack_require__.e(/*! import() | addon-l10n-ko */ "addon-l10n-ko").then(__webpack_require__.t.bind(null, /*! ../addons-l10n/ko.json */ "./src/addons/addons-l10n/ko.json", 3)),
"nl": () => __webpack_require__.e(/*! import() | addon-l10n-nl */ "addon-l10n-nl").then(__webpack_require__.t.bind(null, /*! ../addons-l10n/nl.json */ "./src/addons/addons-l10n/nl.json", 3)),
"pl": () => __webpack_require__.e(/*! import() | addon-l10n-pl */ "addon-l10n-pl").then(__webpack_require__.t.bind(null, /*! ../addons-l10n/pl.json */ "./src/addons/addons-l10n/pl.json", 3)),
"pt": () => __webpack_require__.e(/*! import() | addon-l10n-pt */ "addon-l10n-pt").then(__webpack_require__.t.bind(null, /*! ../addons-l10n/pt.json */ "./src/addons/addons-l10n/pt.json", 3)),
"ro": () => __webpack_require__.e(/*! import() | addon-l10n-ro */ "addon-l10n-ro").then(__webpack_require__.t.bind(null, /*! ../addons-l10n/ro.json */ "./src/addons/addons-l10n/ro.json", 3)),
"ru": () => __webpack_require__.e(/*! import() | addon-l10n-ru */ "addon-l10n-ru").then(__webpack_require__.t.bind(null, /*! ../addons-l10n/ru.json */ "./src/addons/addons-l10n/ru.json", 3)),
"sl": () => __webpack_require__.e(/*! import() | addon-l10n-sl */ "addon-l10n-sl").then(__webpack_require__.t.bind(null, /*! ../addons-l10n/sl.json */ "./src/addons/addons-l10n/sl.json", 3)),
"tr": () => __webpack_require__.e(/*! import() | addon-l10n-tr */ "addon-l10n-tr").then(__webpack_require__.t.bind(null, /*! ../addons-l10n/tr.json */ "./src/addons/addons-l10n/tr.json", 3)),
"zh-tw": () => __webpack_require__.e(/*! import() | addon-l10n-zh-tw */ "addon-l10n-zh-tw").then(__webpack_require__.t.bind(null, /*! ../addons-l10n/zh-tw.json */ "./src/addons/addons-l10n/zh-tw.json", 3))
});
/***/ }),
/***/ "./src/addons/modal.css":
/*!******************************!*\
!*** ./src/addons/modal.css ***!
\******************************/
/*! no static exports found */
/***/ (function(module, exports, __webpack_require__) {
var content = __webpack_require__(/*! !../../node_modules/css-loader??ref--5-1!../../node_modules/postcss-loader/src??postcss!./modal.css */ "./node_modules/css-loader/index.js?!./node_modules/postcss-loader/src/index.js?!./src/addons/modal.css");
if(typeof content === 'string') content = [[module.i, content, '']];
var transform;
var insertInto;
var options = {"hmr":true}
options.transform = transform
options.insertInto = undefined;
var update = __webpack_require__(/*! ../../node_modules/style-loader/lib/addStyles.js */ "./node_modules/style-loader/lib/addStyles.js")(content, options);
if(content.locals) module.exports = content.locals;
if(false) {}
/***/ }),
/***/ "./src/addons/modal.js":
/*!*****************************!*\
!*** ./src/addons/modal.js ***!
\*****************************/
/*! exports provided: createEditorModal, confirm, prompt */
/***/ (function(module, __webpack_exports__, __webpack_require__) {
"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "createEditorModal", function() { return createEditorModal; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "confirm", function() { return confirm; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "prompt", function() { return prompt; });
/* harmony import */ var _components_close_button_icon_close_svg__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../components/close-button/icon--close.svg */ "./src/components/close-button/icon--close.svg");
/* harmony import */ var _components_close_button_icon_close_svg__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(_components_close_button_icon_close_svg__WEBPACK_IMPORTED_MODULE_0__);
/* harmony import */ var _modal_css__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./modal.css */ "./src/addons/modal.css");
/* harmony import */ var _modal_css__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(_modal_css__WEBPACK_IMPORTED_MODULE_1__);
// Based on
// https://github.com/ScratchAddons/ScratchAddons/blob/master/addon-api/content-script/modal.js
const createEditorModal = (tab, title, {
isOpen = false
} = {}) => {
const container = Object.assign(document.createElement('div'), {
className: tab.scratchClass('modal_modal-overlay'),
dir: tab.direction
});
container.style.display = isOpen ? '' : 'none';
document.body.appendChild(container);
const modal = Object.assign(document.createElement('div'), {
className: tab.scratchClass('modal_modal-content')
});
modal.addEventListener('click', e => e.stopPropagation());
container.appendChild(modal);
const header = Object.assign(document.createElement('div'), {
className: tab.scratchClass('modal_header')
});
modal.appendChild(header);
header.appendChild(Object.assign(document.createElement('div'), {
className: tab.scratchClass('modal_header-item', 'modal_header-item-title'),
innerText: title
}));
const closeContainer = Object.assign(document.createElement('div'), {
className: tab.scratchClass('modal_header-item', 'modal_header-item-close')
});
header.appendChild(closeContainer);
const closeButton = Object.assign(document.createElement('div'), {
className: tab.scratchClass('close-button_close-button', 'close-button_large')
});
closeContainer.appendChild(closeButton);
closeButton.appendChild(Object.assign(document.createElement('img'), {
className: tab.scratchClass('close-button_close-icon'),
src: _components_close_button_icon_close_svg__WEBPACK_IMPORTED_MODULE_0___default.a
}));
const content = Object.assign(document.createElement('div'), {
className: _modal_css__WEBPACK_IMPORTED_MODULE_1___default.a.modalContent
});
modal.appendChild(content);
return {
container: modal,
content,
backdrop: container,
closeButton,
open: () => {
container.style.display = '';
},
close: () => {
container.style.display = 'none';
},
remove: container.remove.bind(container)
};
};
const createButtonRow = tab => {
const buttonRow = Object.assign(document.createElement('div'), {
className: tab.scratchClass('prompt_button-row')
});
const cancelButton = Object.assign(document.createElement('button'), {
className: tab.scratchClass('prompt_cancel-button'),
innerText: tab.scratchMessage('gui.prompt.cancel')
});
buttonRow.appendChild(cancelButton);
const okButton = Object.assign(document.createElement('button'), {
className: tab.scratchClass('prompt_ok-button'),
innerText: tab.scratchMessage('gui.prompt.ok')
});
buttonRow.appendChild(okButton);
return {
buttonRow,
cancelButton,
okButton
};
};
const confirm = (tab, title, message, {
useEditorClasses = false
} = {}) => {
const {
remove,
container,
content,
backdrop,
closeButton
} = tab.createModal(title, {
isOpen: true,
useEditorClasses: useEditorClasses,
useSizesClass: true
});
const mode = tab.editorMode !== null && useEditorClasses ? 'editor' : tab.clientVersion;
if (mode === 'editor') {
container.classList.add(tab.scratchClass('prompt_modal-content'));
content.classList.add(tab.scratchClass('prompt_body'));
}
content.appendChild(Object.assign(document.createElement('div'), {
className: tab.scratchClass('prompt_label'),
innerText: message
}));
const {
buttonRow,
cancelButton,
okButton
} = createButtonRow(tab, mode);
content.appendChild(buttonRow);
okButton.focus();
return new Promise(resolve => {
const cancel = () => {
remove();
resolve(false);
};
const ok = () => {
remove();
resolve(true);
};
backdrop.addEventListener('click', cancel);
closeButton.addEventListener('click', cancel);
cancelButton.addEventListener('click', cancel);
okButton.addEventListener('click', ok);
container.addEventListener('keydown', e => {
if (e.key === 'Enter') ok();
if (e.key === 'Escape') cancel();
});
});
};
const prompt = (tab, title, message, defaultValue = '', {
useEditorClasses = false
} = {}) => {
const {
remove,
container,
content,
backdrop,
closeButton
} = tab.createModal(title, {
isOpen: true,
useEditorClasses: useEditorClasses,
useSizesClass: true
});
container.classList.add(tab.scratchClass('prompt_modal-content'));
content.classList.add(tab.scratchClass('prompt_body'));
content.appendChild(Object.assign(document.createElement('div'), {
className: tab.scratchClass('prompt_label'),
innerText: message
}));
const input = Object.assign(document.createElement('input'), {
className: tab.scratchClass('prompt_variable-name-text-input'),
value: defaultValue
});
content.appendChild(input);
input.focus();
input.select();
const {
buttonRow,
cancelButton,
okButton
} = createButtonRow(tab);
content.appendChild(buttonRow);
return new Promise(resolve => {
const cancel = () => {
remove();
resolve(null);
};
const ok = () => {
remove();
resolve(input.value);
};
backdrop.addEventListener('click', cancel);
closeButton.addEventListener('click', cancel);
cancelButton.addEventListener('click', cancel);
okButton.addEventListener('click', ok);
container.addEventListener('keydown', e => {
if (e.key === 'Enter') ok();
if (e.key === 'Escape') cancel();
});
});
};
/***/ }),
/***/ "./src/addons/polyfill.js":
/*!********************************!*\
!*** ./src/addons/polyfill.js ***!
\********************************/
/*! no static exports found */
/***/ (function(module, exports) {
/* eslint-disable no-extend-native */
if (!Blob.prototype.text) {
Blob.prototype.text = function () {
return new Promise((resolve, reject) => {
const fr = new FileReader();
fr.onload = () => resolve(fr.result);
fr.onerror = () => reject(new Error('Cannot read blob as text'));
fr.readAsText(this);
});
};
}
if (!Array.prototype.flat) {
Array.prototype.flat = function (depth = 1) {
const result = [];
for (const i of this) {
if (Array.isArray(i)) {
if (depth < 1) {
result.push(i);
} else {
for (const j of i.flat(depth - 1)) {
result.push(j);
}
}
} else {
result.push(i);
}
}
return result;
};
}
if (typeof queueMicrotask !== 'function') {
window.queueMicrotask = callback => {
Promise.resolve().then(callback);
};
}
/***/ })
}]);
//# sourceMappingURL=addons.js.map