Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
63 changes: 60 additions & 3 deletions api/main.js
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,24 @@ ScratchTools.Storage = {};
ScratchTools.Resources = {};
ste.console.log("ScratchTools API Created", "ste-main");

ScratchTools.cssFiles = [];
async function updateCSSFiles() {
let activeCSSFiles = Array.from(document.styleSheets)
.filter((sheet) => sheet.href)
.map((sheet) => sheet.href)
.filter((el) => new URL(el).host === "scratch.mit.edu");
activeCSSFiles = activeCSSFiles.filter(
(el) => !ScratchTools.cssFiles.find((e) => e.url === el)
);

for (var i in activeCSSFiles) {
ScratchTools.cssFiles.push({
url: activeCSSFiles[i],
data: await (await fetch(activeCSSFiles[i])).text(),
});
}
}

if (
window.location.href.startsWith("https://scratch.mit.edu/projects/") &&
window.location.href.includes("/editor")
Expand Down Expand Up @@ -159,6 +177,7 @@ function enableScratchToolsSelectorsMutationObserver() {
enableScratchToolsSelectorsMutationObserver();

function returnScratchToolsSelectorsMutationObserverCallbacks() {
updateCSSFiles()
Object.keys(allWaitInstances).forEach(function (key) {
var waitInstance = allWaitInstances[key];
if (!waitInstance.removed) {
Expand Down Expand Up @@ -340,6 +359,39 @@ ScratchTools.styles = {
},
};

function scratchClass(name) {
let element = document.querySelector(`[class*='${name}']`);
if (element) {
let classes = [...element.classList];
return classes.find((el) => el.includes(name));
} else {
let text = []

for (var i in ScratchTools.cssFiles) {
text.push(ScratchTools.cssFiles[i].data)
}

text = text.join("\n\n")
let classes = getClassNamesFromCSSText(text)

let relClass = classes.find((el) => el.includes(name))
return relClass
}
}

ScratchTools.getClassNamesFromCSSText = function(cssText) {
const classNames = new Set();

const classRegex = /\.([a-zA-Z0-9_-]+)\b/g;

let match;
while ((match = classRegex.exec(cssText)) !== null) {
classNames.add(match[1]);
}

return Array.from(classNames);
}

ScratchTools.waitForElements(
"ul[class*='menu_menu_'][class*='menu_right_']",
function (ul) {
Expand All @@ -351,7 +403,10 @@ ScratchTools.waitForElements(
if (!ul.querySelector(".ste-menu-full-settings")) {
var li = document.createElement("li");
li.className =
"ste-menu-full-settings menu_menu-item_3EwYA menu_hoverable_3u9dt";
"ste-menu-full-settings " +
scratchClass("menu_menu-item_") +
" " +
scratchClass("menu_hoverable_");

var div = document.createElement("div");
div.className = "settings-menu_option_3rMur";
Expand Down Expand Up @@ -391,6 +446,8 @@ async function blockliveDetection() {
Object.keys(app).find((key) => key.startsWith("__reactContainer"))
].child.stateNode.store.getState()?.scratchGui;
if (!gui?.projectState) return;
let detectBlocklive = await import("./blocklive-detection/blocklive-detect.js");
let detectBlocklive = await import(
"./blocklive-detection/blocklive-detect.js"
);
detectBlocklive.default();
}
}
22 changes: 22 additions & 0 deletions api/module.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,26 @@
let allFeatures = []
let alreadyInjected = [];

function scratchClass(name) {
let element = document.querySelector(`[class*='${name}']`);
if (element) {
let classes = [...element.classList];
return classes.find((el) => el.includes(name));
} else {
let text = []

for (var i in ScratchTools.cssFiles) {
text.push(ScratchTools.cssFiles[i].data)
}

text = text.join("\n\n")
let classes = getClassNamesFromCSSText(text)

let relClass = classes.find((el) => el.includes(name))
return relClass
}
}

ScratchTools.modules.forEach(async function (script) {
var feature = await import(ScratchTools.dir + "/api/feature/index.js");
var shouldBeRun = true;
Expand All @@ -20,6 +40,7 @@ ScratchTools.modules.forEach(async function (script) {
allFeatures.push(featureGenerated)
fun.default({
feature: featureGenerated,
scratchClass,
console: {
log: function (content) {
ste.console.log(content, script.feature.id);
Expand Down Expand Up @@ -56,6 +77,7 @@ ScratchTools.injectModule = async function (script) {
allFeatures.push(featureGenerated)
fun.default({
feature: featureGenerated,
scratchClass,
console: {
log: function (content) {
ste.console.log(content, script.feature.id);
Expand Down
6 changes: 3 additions & 3 deletions features/dark-paint-editor/script.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
export default async function ({ feature, console }) {
export default async function ({ feature, console, scratchClass }) {
let isDark;

const BACKGROUND_LIGHT = "#FFFFFF";
Expand All @@ -18,10 +18,10 @@ export default async function ({ feature, console }) {
if (document.querySelector(".ste-dark-paint-btn")) return;

let button = document.createElement("div")
button.className = "button-group_button-group_2_h4y ste-dark-paint-btn"
button.className = `${scratchClass("button-group_button-group_2_")} ste-dark-paint-btn`

let span = document.createElement("span")
span.className = "button_button_u6SE2 paint-editor_button-group-button_1I1tm"
span.className = `${scratchClass("button_button_")} ${scratchClass("paint-editor_button-group-button_")}`
span.role = "button"
button.appendChild(span)

Expand Down
2 changes: 1 addition & 1 deletion features/delete-all.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ function checkForContextMenu() {
) {
var div = document.createElement("div");
div.className =
"react-contextmenu-item context-menu_menu-item_3cioN context-menu_menu-item-bordered_29CJG context-menu_menu-item-danger_1tJg0 scratchtools deleteall";
`react-contextmenu-item ${scratchClass("context-menu_menu-item_")} ${scratchClass("context-menu_menu-item-bordered_")} ${scratchClass("context-menu_menu-item-danger_")} scratchtools deleteall`;
div.role = "menuitem";
div.tabindex = "-1";
div.arialDisabled = "false";
Expand Down
6 changes: 3 additions & 3 deletions features/echo-effect/script.js
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
export default function ({ feature, console }) {
export default function ({ feature, console, scratchClass }) {
ScratchTools.waitForElements(
"div[class^='sound-editor_row_'][class*='sound-editor_row-reverse_']",
function (container) {
if (container.querySelector(".ste-echo")) return;
let button = document.createElement("div");
button.className =
"icon-button_container_278u5 sound-editor_effect-button_2zuzT ste-echo";
`${scratchClass("icon-button_container_")} ${scratchClass("sound-editor_effect-button_")} ste-echo`;
button.role = "button";

feature.self.hideOnDisable(button)
Expand All @@ -20,7 +20,7 @@ export default function ({ feature, console }) {
button.appendChild(img);

let title = document.createElement("div");
title.className = "icon-button_title_36ChS";
title.className = scratchClass("icon-button_title_");
title.textContent = feature.msg("echo");
button.appendChild(title);

Expand Down
2 changes: 1 addition & 1 deletion features/go-to-parent/script.js
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ if (
if (data.remix !== undefined) {
if (data.remix.parent !== null) {
var div = document.createElement("div");
div.className = "menu-bar_menu-bar-item_oLDa- scratchtools remix";
div.className = `${scratchClass("menu-bar_menu-bar-item_")} scratchtools remix`;
div.innerHTML = `<a href="https://scratch.mit.edu/projects/${data.remix.parent}/editor" style="color: white;"><span class="button_outlined-button_1bS__ menu-bar_menu-bar-button_3IDN0 community-button_community-button_2Lo_g" role="button"><div class="button_content_3jdgj"><span>Go to Parent</span></div></span></a>`;
document.querySelectorAll("div").forEach(function (el) {
if (el.className.includes("menu-bar_main-menu_")) {
Expand Down
2 changes: 1 addition & 1 deletion features/last-key-pressed.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ function addKeyPressed() {

function addKeyPressedEditor() {
var div = document.createElement("div");
div.className = "menu-bar_file-group_1_CHX scratchtools navlastkey";
div.className = `${scratchClass("menu-bar_file-group_1_")} scratchtools navlastkey`;
div.innerHTML = `
<span>No Key Pressed</span>
`;
Expand Down
10 changes: 5 additions & 5 deletions features/more-block-themes/script.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
export default async function ({ feature, console }) {
export default async function ({ feature, console, scratchClass }) {
let CIRCLE = await (await fetch(feature.self.getResource("circle"))).text();

let COLORS = document.createElement("link")
Expand Down Expand Up @@ -118,18 +118,18 @@ export default async function ({ feature, console }) {

let li = document.createElement("li");
li.dataset.id = THEMES[i].id;
li.className = "menu_menu-item_3EwYA menu_hoverable_3u9dt ste-custom";
li.className = `${scratchClass("menu_menu-item_")} ${scratchClass("menu_hoverable_")} ste-custom`;

let div = document.createElement("div");
div.className = "settings-menu_option_3rMur";
div.className = scratchClass("settings-menu_option_");

let check = document.createElement("img");
check.className = "settings-menu_check_3ssaq";
check.className = scratchClass("settings-menu_check_");
check.src = feature.self.getResource("check");

let img = document.createElement("span");
img.innerHTML = CIRCLE.replaceAll("-fill", "-circle-fill" + THEMES[i].id).replaceAll("-stroke", "-circle-stroke-" + THEMES[i].id);
img.className = "settings-menu_icon_3QaRk";
img.className = scratchClass("settings-menu_icon_");

let circleCSS = document.createElement("style");
circleCSS.textContent = css.replaceAll("-fill", "-circle-fill" + THEMES[i].id).replaceAll("-stroke", "-circle-stroke-" + THEMES[i].id)
Expand Down
8 changes: 4 additions & 4 deletions features/more-editor-fonts/script.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
export default async function ({ feature, console }) {
export default async function ({ feature, console, scratchClass }) {
let { default: openTypeDefault } = await import(
"../../libraries/opentype.js"
);
Expand Down Expand Up @@ -26,20 +26,20 @@ export default async function ({ feature, console }) {
button.currentitem = false;
button.ariaLabel = "Add Font";
button.className =
"action-menu_button_1qbot action-menu_more-button_1fMGZ ste-more-fonts-btn";
`${scratchClass("action-menu_button_")} ${scratchClass("action-menu_more-button_")} ste-more-fonts-btn`;
div.appendChild(button);

let img = Object.assign(document.createElement("img"), {
src: feature.self.getResource("more-text-icon"),
draggable: false,
className: "action-menu_more-icon_TJUQ7",
className: scratchClass("action-menu_more-icon_"),
width: 10,
});
button.appendChild(img);

let tooltip = Object.assign(document.createElement("div"), {
className:
"__react_component_tooltip place-right type-dark action-menu_tooltip_3Bkh5",
`__react_component_tooltip place-right type-dark ${scratchClass("action-menu_tooltip_")}`,
id: `ste-${id}-Add Font`,
textContent: "Add Font",
});
Expand Down
8 changes: 4 additions & 4 deletions features/more-paint-functions/script.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
export default async function ({ feature, console }) {
export default async function ({ feature, console, scratchClass }) {
function unite() {
let paper = feature.traps.getPaper();
let items = paper.project.selectedItems;
Expand Down Expand Up @@ -133,20 +133,20 @@ export default async function ({ feature, console }) {
function makeButton({ name, icon, callback }) {
let span = document.createElement("span");
span.className =
"button_button_u6SE2 labeled-icon-button_mod-edit-field_1bXYC ste-more-functions";
`${scratchClass("button_button_")} ${scratchClass("labeled-icon-button_mod-edit-field_")} ste-more-functions`;
span.role = "button";

let img = document.createElement("img");
img.src = feature.self.getResource(icon);
img.className = "labeled-icon-button_edit-field-icon_3j-Pf";
img.className = scratchClass("labeled-icon-button_edit-field-icon_");
img.alt = name;
img.title = name;
img.draggable = false;
span.appendChild(img);

let label = document.createElement("span");
label.textContent = name;
label.className = "labeled-icon-button_edit-field-title_1ZoEV";
label.className = scratchClass("labeled-icon-button_edit-field-title_");
span.appendChild(label);

span.addEventListener("click", function (e) {
Expand Down
2 changes: 1 addition & 1 deletion features/move-project-title-input.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ ScratchTools.waitForElements(
if (!document.querySelector(".st-new-title-input") && !document.querySelector("span[class*='menu-bar_remix-button_']")) {
var input = document.createElement("input");
input.className =
"input_input-form_l9eYg project-title-input_title-field_en5Gd menu-bar_title-field-growable_3qr4G";
`${scratchClass("input_input-form_")} ${scratchClass("project-title-input_title-field_")} ${scratchClass("menu-bar_title-field-growable_")}`;
input.value = window.newTitle || ScratchTools.Scratch.scratchGui().projectTitle;
input.placeholder = "Title";
input.style.width = "100%";
Expand Down
12 changes: 6 additions & 6 deletions features/opacity-slider/script.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
export default function ({ feature, console }) {
export default function ({ feature, console, scratchClass }) {
ScratchTools.waitForElements(".Popover-body", function (body) {
if (!feature.traps.paint().modals.fillColor) return;
if (!feature.traps.paint().selectedItems[0]) return;
Expand All @@ -11,15 +11,15 @@ export default function ({ feature, console }) {
feature.self.hideOnDisable(div);

let data = document.createElement("div");
data.className = "color-picker_row-header_173LQ";
data.className = scratchClass("color-picker_row-header_");
div.appendChild(data);

let name = document.createElement("span");
name.className = "color-picker_label-name_17igY";
name.className = scratchClass("color-picker_label-name_");
name.textContent = "Opacity";

let value = document.createElement("span");
value.className = "color-picker_label-readout_9vjb2";
value.className = scratchClass("color-picker_label-readout_");
value.textContent = Math.floor(
(feature.traps.paint().selectedItems[0]?.opacity || 1) * 100
)?.toString();
Expand All @@ -29,7 +29,7 @@ export default function ({ feature, console }) {

let slider = document.createElement("div");
slider.className =
"ste-opacity-slider-checkered slider_container_o2aIb slider_last_10jvO";
`ste-opacity-slider-checkered ${scratchClass("slider_container_")} ${scratchClass("slider_last_")}`;
div.appendChild(slider);

let sliderBg = document.createElement("div");
Expand All @@ -41,7 +41,7 @@ export default function ({ feature, console }) {

let handle = document.createElement("div");
handleSlider(handle, value);
handle.className = "ste-opacity-handle slider_handle_3f0xk";
handle.className = `ste-opacity-handle ${scratchClass("slider_handle_")}`;
handle.style.left = "124px";
if (feature.traps.paint().selectedItems[0]?.opacity) {
handle.style.left =
Expand Down
8 changes: 4 additions & 4 deletions features/paint-align/script.js
Original file line number Diff line number Diff line change
@@ -1,25 +1,25 @@
export default async function ({ feature }) {
export default async function ({ feature, scratchClass }) {
ScratchTools.waitForElements(
"div[class^='mode-tools_mod-labeled-icon-height_']",
function (row) {
if (row.querySelector(".ste-align-items")) return;

let span = document.createElement("span");
span.className =
"button_button_u6SE2 labeled-icon-button_mod-edit-field_1bXYC ste-align-items";
`${scratchClass("button_button_")} ${scratchClass("labeled-icon-button_mod-edit-field_")} ste-align-items`;
span.role = "button";

let img = document.createElement("img");
img.src = feature.self.getResource("paint-align");
img.className = "labeled-icon-button_edit-field-icon_3j-Pf";
img.className = scratchClass("labeled-icon-button_edit-field-icon_");
img.alt = feature.msg("align");
img.title = feature.msg("align");
img.draggable = false;
span.appendChild(img);

let label = document.createElement("span");
label.textContent = feature.msg("align");
label.className = "labeled-icon-button_edit-field-title_1ZoEV";
label.className = scratchClass("labeled-icon-button_edit-field-title_");
span.appendChild(label);

span.addEventListener("click", function (e) {
Expand Down
Loading
Loading