From 76a6718e4f0344b757b932f3d97b0ebab80cb204 Mon Sep 17 00:00:00 2001
From: rgantzos <86856959+rgantzos@users.noreply.github.com>
Date: Sun, 30 Mar 2025 11:11:05 -0700
Subject: [PATCH] Prepare for v4.1.0
---
api/update/index.js | 5 +-
extras/background.js | 38 +++-
features/features.json | 5 +
features/more-block-themes/script.js | 3 +
features/random-block-colors/check.svg | 3 +
features/random-block-colors/circle.svg | 17 ++
features/random-block-colors/colors.css | 40 ++++
features/random-block-colors/data.json | 28 +++
features/random-block-colors/script.js | 274 ++++++++++++++++++++++++
features/random-block-colors/style.css | 9 +
manifest.json | 2 +-
11 files changed, 417 insertions(+), 7 deletions(-)
create mode 100644 features/random-block-colors/check.svg
create mode 100644 features/random-block-colors/circle.svg
create mode 100644 features/random-block-colors/colors.css
create mode 100644 features/random-block-colors/data.json
create mode 100644 features/random-block-colors/script.js
create mode 100644 features/random-block-colors/style.css
diff --git a/api/update/index.js b/api/update/index.js
index 7c235ca0..06da0a1a 100644
--- a/api/update/index.js
+++ b/api/update/index.js
@@ -40,12 +40,13 @@ async function checkUpdate() {
forum: "0",
},
});
- checkUpdate()
+ // checkUpdate()
}
}
-checkUpdate();
+// checkUpdate();
function makeScreen(update) {
+ return
console.log(update);
if (document.querySelector(".ste-update-bg")) return;
let background = Object.assign(document.createElement("div"), {
diff --git a/extras/background.js b/extras/background.js
index 1e404847..9c6a10d5 100644
--- a/extras/background.js
+++ b/extras/background.js
@@ -49,8 +49,7 @@ async function checkBetaUpdates() {
).json();
if (
data.version !== chrome.runtime.getManifest().version_name ||
- (await (await fetch("/changelog/beta.json")).json()).beta !==
- data.beta
+ (await (await fetch("/changelog/beta.json")).json()).beta !== data.beta
) {
// chrome.tabs.create({
// url: "/extras/beta/index.html",
@@ -64,6 +63,7 @@ if (chrome.runtime.getManifest().version_name.endsWith("-beta")) {
}
chrome.runtime.onInstalled.addListener(async function (object) {
+ checkApril();
try {
var featureData = await (await fetch("/features/features.json")).json();
} catch (err) {
@@ -671,12 +671,17 @@ chrome.runtime.onMessageExternal.addListener(async function (
}
if (msg.msg === "openPong") {
await chrome.tabs.create({
- url: "/api/april/pong/index.html?username=" + msg.username + "&id=" + msg.id,
+ url:
+ "/api/april/pong/index.html?username=" + msg.username + "&id=" + msg.id,
});
}
if (msg.msg === "openDashboardPage") {
await chrome.tabs.create({
- url: "/extras/dashboard/index.html?code=" + msg.token + "&username=" + msg.username,
+ url:
+ "/extras/dashboard/index.html?code=" +
+ msg.token +
+ "&username=" +
+ msg.username,
});
chrome.tabs.remove(sender.tab.id, function () {});
}
@@ -821,7 +826,32 @@ chrome.runtime.onMessage.addListener(async function (
}
});
+async function checkApril() {
+ if (new Date().getMonth() === 3 && new Date().getDate() === 1) {
+ let features = (await chrome.storage.sync.get("features"))?.features || "";
+ if (!features.includes("random-block-colors")) {
+ await chrome.storage.sync.set({ aprilAutomatic2025: true });
+ features = features + ".random-block-colors";
+ await chrome.storage.sync.set({ features });
+ }
+ } else {
+ let aprilAutomatic = (await chrome.storage.sync.get("aprilAutomatic2025"))
+ ?.aprilAutomatic2025;
+
+ if (aprilAutomatic) {
+ let features =
+ (await chrome.storage.sync.get("features"))?.features || "";
+ if (features.includes("random-block-colors")) {
+ features = features.replaceAll("random-block-colors", "");
+ await chrome.storage.sync.set({ features });
+ await chrome.storage.sync.set({ aprilAutomatic2025: false });
+ }
+ }
+ }
+}
+
chrome.alarms.onAlarm.addListener(async function () {
+ checkApril();
chrome.alarms.clearAll();
chrome.alarms.create("test", {
delayInMinutes: 0.5,
diff --git a/features/features.json b/features/features.json
index 779defe0..144b6446 100644
--- a/features/features.json
+++ b/features/features.json
@@ -1,4 +1,9 @@
[
+ {
+ "version": 2,
+ "id": "random-block-colors",
+ "versionAdded": "v4.1.0"
+ },
{
"version": 2,
"id": "remove-confirmation",
diff --git a/features/more-block-themes/script.js b/features/more-block-themes/script.js
index 68ee6378..d89eb33e 100644
--- a/features/more-block-themes/script.js
+++ b/features/more-block-themes/script.js
@@ -1,4 +1,7 @@
export default async function ({ feature, console, scratchClass }) {
+ let randomBlockColorsEnabled = !!ScratchTools.modules.find((el) => el.feature.id === "random-block-colors")
+ if (randomBlockColorsEnabled) return;
+
let CIRCLE = await (await fetch(feature.self.getResource("circle"))).text();
let COLORS = document.createElement("link")
diff --git a/features/random-block-colors/check.svg b/features/random-block-colors/check.svg
new file mode 100644
index 00000000..241430a8
--- /dev/null
+++ b/features/random-block-colors/check.svg
@@ -0,0 +1,3 @@
+
\ No newline at end of file
diff --git a/features/random-block-colors/circle.svg b/features/random-block-colors/circle.svg
new file mode 100644
index 00000000..88012ccd
--- /dev/null
+++ b/features/random-block-colors/circle.svg
@@ -0,0 +1,17 @@
+
\ No newline at end of file
diff --git a/features/random-block-colors/colors.css b/features/random-block-colors/colors.css
new file mode 100644
index 00000000..c4fff376
--- /dev/null
+++ b/features/random-block-colors/colors.css
@@ -0,0 +1,40 @@
+:root {
+ --motion-fill: transparent;
+ --motion-stroke: #3373CC;
+
+ --looks-fill: transparent;
+ --looks-stroke: #774DCB;
+
+ --sound-fill: transparent;
+ --sound-stroke: #BD42BD;
+
+ --event-fill: transparent;
+ --event-stroke: #CC9900;
+
+ --control-fill: transparent;
+ --control-stroke: #CF8B17;
+
+ --sensing-fill: transparent;
+ --sensing-stroke: #2E8EB8;
+
+ --operators-fill: transparent;
+ --operators-stroke: #389438;
+
+ --data-fill: transparent;
+ --data-stroke: #DB6E00;
+ --data-lists-fill: transparent;
+ --data-lists-stroke: #E64D00;
+
+ --custom-fill: transparent;
+ --custom-stroke: #FF3355;
+
+ --other-fill: transparent;
+ --other-stroke: #0B8E69;
+
+ --text-light: #000000;
+ --text-normal: #000000;
+ --text-light: var(--editorDarkMode-primary-text);
+ --text-normal: var(--editorDarkMode-primary-text);
+
+ --arg-border: transparent;
+ }
\ No newline at end of file
diff --git a/features/random-block-colors/data.json b/features/random-block-colors/data.json
new file mode 100644
index 00000000..844bb51d
--- /dev/null
+++ b/features/random-block-colors/data.json
@@ -0,0 +1,28 @@
+{
+ "title": "Random Block Colors",
+ "description": "Swaps around the colors of all the blocks each time you press the green flag!",
+ "credits": [
+ {
+ "username": "Alan",
+ "url": "https://www.youtube.com/watch?v=z54AmH9Yi78&feature=youtu.be"
+ }
+ ],
+ "type": ["Editor", "Egg"],
+ "styles": [{ "file": "style.css", "runOn": "/projects/*" }],
+ "scripts": [{ "file": "script.js", "runOn": "/projects/*" }],
+ "resources": [
+ { "name": "check", "path": "/check.svg" },
+ { "name": "circle", "path": "/circle.svg" },
+ { "name": "colors", "path": "/colors.css" }
+ ],
+ "components": [
+ {
+ "type": "info",
+ "content": "This is an April Fool's Day feature. It was likely enabled automatically on April 1st, but you may disable it if you'd like."
+ },
+ {
+ "type": "warning",
+ "content": "This feature is not compatible with the \"More Block Themes\" feature. You will not be able to use other block themes while this feature is enabled."
+ }
+ ]
+}
diff --git a/features/random-block-colors/script.js b/features/random-block-colors/script.js
new file mode 100644
index 00000000..8c073d89
--- /dev/null
+++ b/features/random-block-colors/script.js
@@ -0,0 +1,274 @@
+export default async function ({ feature, console }) {
+ const COLORS = [
+ {
+ name: "motion",
+ primary: "#4C97FF",
+ secondary: "#4280D7",
+ quaternary: "#3373CC",
+ tertiary: "#3373CC",
+ },
+ {
+ name: "looks",
+ primary: "#9966FF",
+ secondary: "#855CD6",
+ quaternary: "#774DCB",
+ tertiary: "#774DCB",
+ },
+ {
+ name: "sounds",
+ primary: "#CF63CF",
+ secondary: "#C94FC9",
+ quaternary: "#BD42BD",
+ tertiary: "#BD42BD",
+ },
+ {
+ name: "control",
+ primary: "#FFAB19",
+ secondary: "#EC9C13",
+ quaternary: "#CF8B17",
+ tertiary: "#CF8B17",
+ },
+ {
+ name: "event",
+ primary: "#FFBF00",
+ secondary: "#E6AC00",
+ quaternary: "#CC9900",
+ tertiary: "#CC9900",
+ },
+ {
+ name: "sensing",
+ primary: "#5CB1D6",
+ secondary: "#47A8D1",
+ quaternary: "#2E8EB8",
+ tertiary: "#2E8EB8",
+ },
+ {
+ name: "pen",
+ primary: "#0fBD8C",
+ secondary: "#0DA57A",
+ quaternary: "#0B8E69",
+ tertiary: "#0B8E69",
+ },
+ {
+ name: "operators",
+ primary: "#59C059",
+ secondary: "#46B946",
+ quaternary: "#389438",
+ tertiary: "#389438",
+ },
+ {
+ name: "data",
+ primary: "#FF8C1A",
+ secondary: "#FF8000",
+ quaternary: "#DB6E00",
+ tertiary: "#DB6E00",
+ },
+ {
+ name: "data_lists",
+ primary: "#FF661A",
+ secondary: "#FF5500",
+ quaternary: "#E64D00",
+ tertiary: "#E64D00",
+ },
+ {
+ name: "more",
+ primary: "#FF6680",
+ secondary: "#FF4D6A",
+ quaternary: "#FF3355",
+ tertiary: "#FF3355",
+ },
+ ];
+
+ let activeColors = COLORS;
+
+ function updateColors() {
+ let newBlockColors = JSON.parse(JSON.stringify(COLORS));
+ randomizeArray(newBlockColors);
+
+ for (var i in newBlockColors) {
+ delete newBlockColors[i].name;
+ }
+
+ for (var i in COLORS) {
+ let newColors = newBlockColors[i];
+ Object.keys(newColors).forEach(function (colorType) {
+ ScratchTools.traps.getScratchBlocks().Colours[COLORS[i].name][
+ colorType
+ ] = newColors[colorType];
+ });
+ newBlockColors[i].name = COLORS[i].name;
+ }
+
+ activeColors = newBlockColors;
+
+ updateBlocks();
+ updateToolbar();
+ }
+
+ ScratchTools.waitForElements(
+ "img[class^='green-flag_green-flag_']",
+ function (flag) {
+ flag.addEventListener("click", updateColors);
+ }
+ );
+
+ function updateToolbar() {
+ for (var i in activeColors) {
+ let newCategoryName = activeColors[i].name
+ .replaceAll("data", "variables")
+ .replaceAll("event", "events")
+ .replaceAll("sounds", "sound")
+ .replaceAll("more", "myBlocks");
+ if (
+ document.querySelector(
+ `div.scratchCategoryId-${newCategoryName} .scratchCategoryItemBubble`
+ )
+ ) {
+ document.querySelector(
+ `div.scratchCategoryId-${newCategoryName} .scratchCategoryItemBubble`
+ ).style.backgroundColor = activeColors[i].primary;
+ document.querySelector(
+ `div.scratchCategoryId-${newCategoryName} .scratchCategoryItemBubble`
+ ).style.borderColor = activeColors[i].secondary;
+ }
+ }
+ }
+
+ ScratchTools.waitForElements(".scratchCategoryMenuItem", function (item) {
+ let colorValues = activeColors.find(
+ (el) =>
+ el.name ===
+ item.className
+ .split("scratchCategoryId-")[1]
+ .split(" ")[0]
+ .replaceAll("variables", "data")
+ .replaceAll("events", "event")
+ .replaceAll("myBlocks", "more")
+ .replaceAll("sound", "sounds")
+ );
+ if (colorValues && item.querySelector(".scratchCategoryItemBubble")) {
+ item.querySelector(".scratchCategoryItemBubble").style.backgroundColor =
+ colorValues.primary;
+ item.querySelector(".scratchCategoryItemBubble").style.borderColor =
+ colorValues.secondary;
+ }
+ });
+
+ window.updateColors = updateColors;
+
+ function randomizeArray(array) {
+ let currentIndex = array.length;
+
+ while (currentIndex != 0) {
+ let randomIndex = Math.floor(Math.random() * currentIndex);
+ currentIndex--;
+
+ [array[currentIndex], array[randomIndex]] = [
+ array[randomIndex],
+ array[currentIndex],
+ ];
+ }
+ }
+
+ function updateBlocks() {
+ let blocks = feature.traps.blocks();
+ let workspace = Blockly.getMainWorkspace();
+
+ let toolbox = workspace.getToolbox();
+ let flyout = workspace.getFlyout();
+
+ blocks.Events.disable();
+ blocks.Xml.clearWorkspaceAndLoadFromXml(
+ blocks.Xml.workspaceToDom(workspace),
+ workspace
+ );
+
+ if (flyout) {
+ let flyoutWorkspace = flyout.getWorkspace();
+ blocks.Xml.clearWorkspaceAndLoadFromXml(
+ blocks.Xml.workspaceToDom(flyoutWorkspace),
+ flyoutWorkspace
+ );
+ }
+
+ let selectedItemId = toolbox.getSelectedItem().id_;
+ if (blocks.registry) {
+ toolbox.render(workspace.options.languageTree);
+ toolbox.selectItem_(null, toolbox.contents.get(selectedItemId));
+ } else {
+ toolbox.categoryMenu_.populate(workspace.options.languageTree);
+ toolbox.selectCategoryById(selectedItemId, false);
+ }
+ toolbox.refreshSelection();
+ workspace.toolboxRefreshEnabled_ = true;
+
+ blocks.Events.enable();
+ }
+
+ ScratchTools.waitForElements(
+ "ul[class*='menu_menu_'][class*='menu_right_']",
+ async function (ul) {
+ if (
+ ul.parentNode?.previousSibling?.previousSibling?.className.startsWith(
+ "settings-menu_dropdown-label_"
+ )
+ ) {
+ let CIRCLE = await (
+ await fetch(feature.self.getResource("circle"))
+ ).text();
+ let css = await (
+ await fetch(feature.self.getResource("colors"))
+ ).text();
+ let list = ul.children[1].lastChild.firstChild;
+
+ if (list.querySelector(".ste-custom-april")) return;
+
+ let selected = list.querySelector(
+ "img[class*='settings-menu_selected_']"
+ );
+ let SELECTED_CLASS = [...selected.classList].find((el) =>
+ el.startsWith("settings-menu_selected_")
+ );
+
+ list.querySelectorAll("li:not(.ste-custom)").forEach(function (el) {
+ el.remove();
+ });
+
+ let li = document.createElement("li");
+ li.dataset.id = "ste-custom-april";
+ li.className = `${scratchClass("menu_menu-item_")} ${scratchClass(
+ "menu_hoverable_"
+ )} ste-custom-april`;
+
+ let div = document.createElement("div");
+ div.className = scratchClass("settings-menu_option_");
+
+ let check = document.createElement("img");
+ check.className = scratchClass("settings-menu_check_");
+ check.src = feature.self.getResource("check");
+
+ let img = document.createElement("span");
+ img.innerHTML = CIRCLE.replaceAll(
+ "-fill",
+ "-circle-fill" + "ste-custom-april"
+ ).replaceAll("-stroke", "-circle-stroke-" + "ste-custom-april");
+ img.className = scratchClass("settings-menu_icon_");
+
+ let circleCSS = document.createElement("style");
+ circleCSS.textContent = css
+ .replaceAll("-fill", "-circle-fill" + "ste-custom-april")
+ .replaceAll("-stroke", "-circle-stroke-" + "ste-custom-april");
+ img.firstChild.prepend(circleCSS);
+
+ check.classList.add(SELECTED_CLASS);
+
+ let span = document.createElement("span");
+ span.textContent = "Random Colors";
+
+ div.append(check, img, span);
+ li.appendChild(div);
+ list.appendChild(li);
+ }
+ }
+ );
+}
diff --git a/features/random-block-colors/style.css b/features/random-block-colors/style.css
new file mode 100644
index 00000000..0aedf492
--- /dev/null
+++ b/features/random-block-colors/style.css
@@ -0,0 +1,9 @@
+li.ste-custom-april svg {
+ height: 100%;
+ width: 100%;
+}
+
+li.ste-custom-april span[class^='settings-menu_icon_'] {
+ height: 1.5rem;
+ width: 1.5rem;
+}
\ No newline at end of file
diff --git a/manifest.json b/manifest.json
index 7b3929eb..3fa7ac20 100644
--- a/manifest.json
+++ b/manifest.json
@@ -3,7 +3,7 @@
"short_name": "ScratchTools",
"manifest_version": 3,
"version": "4.1.0",
- "version_name": "4.1.0-beta",
+ "version_name": "4.1.0",
"default_locale": "en",
"description": "__MSG_extDescription__",
"author": "rgantzos",