From 91426fe0bc5b5d57cb44d6e5da89cbee2edc992a Mon Sep 17 00:00:00 2001 From: GarboMuffin Date: Wed, 17 Aug 2022 16:39:59 -0500 Subject: [PATCH] Update addons: add zebra-striping --- src/addons/addons.js | 4 +- .../_manifest_entry.js | 3 +- .../addons/hide-stage/_manifest_entry.js | 4 +- .../addons/zebra-striping/_manifest_entry.js | 63 ++++++++++++++++ .../addons/zebra-striping/_runtime_entry.js | 7 ++ .../addons/zebra-striping/userscript.js | 75 +++++++++++++++++++ .../addons/zebra-striping/userstyle.css | 26 +++++++ src/addons/generated/addon-entries.js | 1 + src/addons/generated/addon-manifests.js | 2 + src/addons/generated/upstream-meta.json | 2 +- 10 files changed, 179 insertions(+), 8 deletions(-) create mode 100644 src/addons/addons/zebra-striping/_manifest_entry.js create mode 100644 src/addons/addons/zebra-striping/_runtime_entry.js create mode 100644 src/addons/addons/zebra-striping/userscript.js create mode 100644 src/addons/addons/zebra-striping/userstyle.css diff --git a/src/addons/addons.js b/src/addons/addons.js index edb082d51..6a8640186 100644 --- a/src/addons/addons.js +++ b/src/addons/addons.js @@ -23,6 +23,7 @@ const addons = [ '2d-color-picker', 'better-img-uploads', 'custom-block-shape', + 'zebra-striping', 'editor-theme3', 'custom-block-text', 'editor-colored-context-menus', @@ -64,8 +65,7 @@ const addons = [ ]; const newAddons = [ - 'hide-stage', - 'editor-buttons-reverse-order' + 'zebra-striping' ]; // eslint-disable-next-line import/no-commonjs diff --git a/src/addons/addons/editor-buttons-reverse-order/_manifest_entry.js b/src/addons/addons/editor-buttons-reverse-order/_manifest_entry.js index af8f627b3..fd13a38ef 100644 --- a/src/addons/addons/editor-buttons-reverse-order/_manifest_entry.js +++ b/src/addons/addons/editor-buttons-reverse-order/_manifest_entry.js @@ -3,8 +3,7 @@ const manifest = { "name": "Reverse order of project controls", "description": "Moves the green flag and stop buttons to the right and the full screen button to the left, like in Scratch 2.0.", "tags": [ - "theme", - "new" + "theme" ], "dynamicDisable": true, "userstyles": [ diff --git a/src/addons/addons/hide-stage/_manifest_entry.js b/src/addons/addons/hide-stage/_manifest_entry.js index b3835162f..b6b832c9b 100644 --- a/src/addons/addons/hide-stage/_manifest_entry.js +++ b/src/addons/addons/hide-stage/_manifest_entry.js @@ -20,8 +20,6 @@ const manifest = { "url": "style.css" } ], - "tags": [ - "new" - ] + "tags": [] }; export default manifest; diff --git a/src/addons/addons/zebra-striping/_manifest_entry.js b/src/addons/addons/zebra-striping/_manifest_entry.js new file mode 100644 index 000000000..5fb7e92bb --- /dev/null +++ b/src/addons/addons/zebra-striping/_manifest_entry.js @@ -0,0 +1,63 @@ +/* generated by pull.js */ +const manifest = { + "editorOnly": true, + "noTranslations": true, + "name": "Alternating nested block colors", + "description": "Makes blocks of the same category alternate between lighter and darker shades when nested inside each other. This is also known as zebra striping.", + "credits": [ + { + "name": "CST1229", + "link": "https://scratch.mit.edu/users/CST1229/" + }, + { + "name": "GarboMuffin" + }, + { + "name": "TheColaber", + "link": "https://scratch.mit.edu/users/thecolaber" + } + ], + "tags": [ + "new" + ], + "userscripts": [ + { + "url": "userscript.js" + } + ], + "userstyles": [ + { + "url": "userstyle.css" + } + ], + "settings": [ + { + "dynamic": true, + "name": "Shade", + "id": "shade", + "type": "select", + "potentialValues": [ + { + "name": "Lighter", + "id": "lighter" + }, + { + "name": "Darker", + "id": "darker" + } + ], + "default": "lighter" + }, + { + "dynamic": true, + "name": "Intensity (0-100%)", + "id": "intensity", + "type": "integer", + "min": 0, + "default": 20, + "max": 100 + } + ], + "dynamicDisable": true +}; +export default manifest; diff --git a/src/addons/addons/zebra-striping/_runtime_entry.js b/src/addons/addons/zebra-striping/_runtime_entry.js new file mode 100644 index 000000000..e8d1f9d05 --- /dev/null +++ b/src/addons/addons/zebra-striping/_runtime_entry.js @@ -0,0 +1,7 @@ +/* generated by pull.js */ +import _js from "./userscript.js"; +import _css from "!css-loader!./userstyle.css"; +export const resources = { + "userscript.js": _js, + "userstyle.css": _css, +}; diff --git a/src/addons/addons/zebra-striping/userscript.js b/src/addons/addons/zebra-striping/userscript.js new file mode 100644 index 000000000..a5187e04d --- /dev/null +++ b/src/addons/addons/zebra-striping/userscript.js @@ -0,0 +1,75 @@ +export default async function ({ addon, msg, global, console }) { + const vm = addon.tab.traps.vm; + const ScratchBlocks = await addon.tab.traps.getBlockly(); + + const updateCssVariables = () => { + const map = { + lighter: 1, + darker: -1 + }; + document.documentElement.style.setProperty('--zebraStriping-shadeNumber', map[addon.settings.get("shade")]); + }; + addon.settings.addEventListener("change", updateCssVariables); + updateCssVariables(); + + const originalRender = ScratchBlocks.BlockSvg.prototype.render; + ScratchBlocks.BlockSvg.prototype.render = function (opt_bubble) { + // Any changes that affect block striping should bubble to the top block of the script. + // The top block of the script is responsible for striping all of its children. + // This way stripes are computed exactly once. + if (!this.isInFlyout && !this.isShadow() && this.getParent() === null) { + const stripeState = new Map(); + // Conveniently getDescendants() returns blocks in an order such that each block's + // parent will always come before that block (except the first block which has no + // parent). + for (const block of this.getDescendants()) { + const parent = block.getSurroundParent(); + + let isStriped = false; + if (parent) { + if (block.isShadow()) { + isStriped = !!stripeState.get(parent); + } else if (parent.getCategory() === block.getCategory()) { + isStriped = !stripeState.get(parent); + } + } + stripeState.set(block, isStriped); + + const elements = [block.svgPath_]; + for (const input of block.inputList) { + if (input.outlinePath) { + elements.push(input.outlinePath); + } + for (const field of input.fieldRow) { + if (field.fieldGroup_) { + elements.push(field.fieldGroup_); + } + } + } + for (const el of elements) { + el.classList.toggle("sa-zebra-stripe", isStriped); + } + } + } + return originalRender.call(this, opt_bubble); + }; + + if (vm.editingTarget) { + vm.emitWorkspaceUpdate(); + } + + // The replacement glow filter's ID is randomly generated and changes + // when the workspace is reloaded (which includes loading the page and + // seeing the project page then seeing inside). + // As we need to stack the filter with the striping filter in the + // userstyle, we need to use the usersciript to get the filter's ID + // and set a CSS variable on the document's root. + while (true) { + const replacementGlowEl = await addon.tab.waitForElement('filter[id*="blocklyReplacementGlowFilter"]', { + markAsSeen: true, + reduxEvents: ["scratch-gui/mode/SET_PLAYER", "fontsLoaded/SET_FONTS_LOADED", "scratch-gui/locales/SELECT_LOCALE"], + reduxCondition: (state) => !state.scratchGui.mode.isPlayerOnly, + }); + document.documentElement.style.setProperty("--zebraStriping-replacementGlow", `url(#${replacementGlowEl.id})`); + } +} diff --git a/src/addons/addons/zebra-striping/userstyle.css b/src/addons/addons/zebra-striping/userstyle.css new file mode 100644 index 000000000..78290b5c1 --- /dev/null +++ b/src/addons/addons/zebra-striping/userstyle.css @@ -0,0 +1,26 @@ +:root { + --zebraStriping-percent: calc(var(--zebraStriping-shadeNumber) * var(--zebraStriping-intensity) / 100); + --zebraStriping-bright: calc(1 + var(--zebraStriping-percent)); + --zebraStriping-saturate: calc(1 - var(--zebraStriping-percent)); + --zebraStriping-filter: brightness(var(--zebraStriping-bright)) saturate(var(--zebraStriping-saturate)); + /* "Temporary" value, gets replaced by userscript */ + --zebraStriping-replacementGlow: url(#blocklyReplacementGlowFilter); +} + +.sa-zebra-stripe { + filter: var(--zebraStriping-filter); +} + +.sa-zebra-stripe[filter*="#blocklyReplacementGlowFilter"] { + filter: var(--zebraStriping-filter) var(--zebraStriping-replacementGlow); +} + +/* editor-stepping and debugger compatibility */ +/* this is pretty horrible */ +.sa-zebra-stripe[style*="#sa_glower_filter0"] { + /* !important because editor-stepping Highlighter uses inline styles */ + filter: var(--zebraStriping-filter) url("#sa_glower_filter0") !important; +} +.sa-zebra-stripe[style*="#sa_glower_filter1"] { + filter: var(--zebraStriping-filter) url("#sa_glower_filter1") !important; +} diff --git a/src/addons/generated/addon-entries.js b/src/addons/generated/addon-entries.js index df12c7f5a..ad14386eb 100644 --- a/src/addons/generated/addon-entries.js +++ b/src/addons/generated/addon-entries.js @@ -22,6 +22,7 @@ export default { "2d-color-picker": () => import(/* webpackChunkName: "addon-entry-2d-color-picker" */ "../addons/2d-color-picker/_runtime_entry.js"), "better-img-uploads": () => import(/* webpackChunkName: "addon-entry-better-img-uploads" */ "../addons/better-img-uploads/_runtime_entry.js"), "custom-block-shape": () => import(/* webpackChunkName: "addon-entry-custom-block-shape" */ "../addons/custom-block-shape/_runtime_entry.js"), + "zebra-striping": () => import(/* webpackChunkName: "addon-entry-zebra-striping" */ "../addons/zebra-striping/_runtime_entry.js"), "editor-theme3": () => import(/* webpackChunkName: "addon-entry-editor-theme3" */ "../addons/editor-theme3/_runtime_entry.js"), "custom-block-text": () => import(/* webpackChunkName: "addon-entry-custom-block-text" */ "../addons/custom-block-text/_runtime_entry.js"), "editor-colored-context-menus": () => import(/* webpackChunkName: "addon-entry-editor-colored-context-menus" */ "../addons/editor-colored-context-menus/_runtime_entry.js"), diff --git a/src/addons/generated/addon-manifests.js b/src/addons/generated/addon-manifests.js index 95dbc524e..1e039e5d0 100644 --- a/src/addons/generated/addon-manifests.js +++ b/src/addons/generated/addon-manifests.js @@ -21,6 +21,7 @@ import _bitmap_copy from "../addons/bitmap-copy/_manifest_entry.js"; import _2d_color_picker from "../addons/2d-color-picker/_manifest_entry.js"; import _better_img_uploads from "../addons/better-img-uploads/_manifest_entry.js"; import _custom_block_shape from "../addons/custom-block-shape/_manifest_entry.js"; +import _zebra_striping from "../addons/zebra-striping/_manifest_entry.js"; import _editor_theme3 from "../addons/editor-theme3/_manifest_entry.js"; import _custom_block_text from "../addons/custom-block-text/_manifest_entry.js"; import _editor_colored_context_menus from "../addons/editor-colored-context-menus/_manifest_entry.js"; @@ -82,6 +83,7 @@ export default { "2d-color-picker": _2d_color_picker, "better-img-uploads": _better_img_uploads, "custom-block-shape": _custom_block_shape, + "zebra-striping": _zebra_striping, "editor-theme3": _editor_theme3, "custom-block-text": _custom_block_text, "editor-colored-context-menus": _editor_colored_context_menus, diff --git a/src/addons/generated/upstream-meta.json b/src/addons/generated/upstream-meta.json index 24064d88b..c48a20a04 100644 --- a/src/addons/generated/upstream-meta.json +++ b/src/addons/generated/upstream-meta.json @@ -1 +1 @@ -{"commit":"b453963"} \ No newline at end of file +{"commit":"8f72734"} \ No newline at end of file