Skip to content

Commit 9aa726f

Browse files
committed
3 new features and remote disable
- Added stage on left side - Added hide disabled context menu options - Added project title input above player - Added color context menus - Added remote disable
1 parent 8be2347 commit 9aa726f

File tree

10 files changed

+237
-3
lines changed

10 files changed

+237
-3
lines changed

api/main.js

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -154,3 +154,9 @@ ScratchTools.disable = function (feature) {
154154
);
155155
};
156156
};
157+
158+
function GM_addStyle(styleData) {
159+
var style = document.createElement('style')
160+
style.textContent = styleData
161+
return document.querySelector('html').appendChild(style)
162+
}

extras/background.js

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -180,6 +180,8 @@ chrome.tabs.onUpdated.addListener(function (tabId, info) {
180180
}
181181
ScratchTools.console.log("Injected storage API.");
182182
Object.keys(data).forEach(async function (el) {
183+
var disabled = (await chrome.storage.sync.get("autoDisabled")).autoDisabled
184+
if (!disabled || !disabled.includes(data[el].file)) {
183185
if (data[el]["world"] === undefined) {
184186
var world = "MAIN";
185187
} else {
@@ -200,6 +202,7 @@ chrome.tabs.onUpdated.addListener(function (tabId, info) {
200202
ScratchTools.console.log("Injected feature: " + data[el].file);
201203
}
202204
});
205+
}
203206
});
204207
await chrome.storage.sync.get("version", async function (obj) {
205208
if (obj["version"] !== version) {
@@ -225,6 +228,9 @@ chrome.alarms.onAlarm.addListener(async function () {
225228
delayInMinutes: 0.1,
226229
periodInMinutes: 0.1,
227230
});
231+
var response = await fetch('https://scratchtools.app/disabled/')
232+
var data = await response.json()
233+
await chrome.storage.sync.set({"autoDisabled":data})
228234
var obj = await chrome.storage.sync.get("features")
229235
if (obj.features && obj.features.includes("display-message-count-in-icon")) {
230236
try {

extras/index.html

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -345,6 +345,12 @@ <h3>Blocked Users</h3>
345345
font-family: "Space Grotesk", sans-serif;
346346
}
347347

348+
.warning.disabled {
349+
background-color: #ff006a;
350+
color: white;
351+
border: 4px solid #ff006a50;
352+
}
353+
348354
.creditNames a:hover {
349355
text-decoration: none;
350356
color: #ff9f00;

extras/popup.html

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -465,6 +465,12 @@ <h3 class="count">
465465
font-family: "Space Grotesk", sans-serif;
466466
}
467467

468+
.warning.disabled {
469+
background-color: #ff006a;
470+
border: 4px solid #ff006a50;
471+
color: white;
472+
}
473+
468474
.eastereggFeature {
469475
display: none;
470476
}

extras/popup.js

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -576,6 +576,13 @@ function createFeature(
576576
}
577577
}
578578
});
579+
var disabled = (await chrome.storage.sync.get("autoDisabled")).autoDisabled
580+
if (disabled && disabled.includes(id)) {
581+
var warning = document.createElement("div");
582+
warning.textContent = "This feature has been disabled remotely by ScratchTools. You can still enable/disable it, but, for safety reasons, it won't work for now.";
583+
warning.className = "warning disabled";
584+
div23.insertBefore(warning, div23.querySelector("label"));
585+
}
579586
}
580587
getWarnings();
581588
if (

features/colored-context-menus.js

Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
// ==UserScript==
2+
// @name Colored Editor Context Menu for Scratch 3
3+
// @version 1.0
4+
// @namespace https://github.com/forkphorus/cat-plus
5+
// @match https://scratch.mit.edu/projects/*
6+
// @grant GM_addStyle
7+
// @run-at document-start
8+
// ==/UserScript==
9+
10+
function rgb2hsl(rgb) {
11+
const r = (rgb >> 16 & 0xff) / 0xff;
12+
const g = (rgb >> 8 & 0xff) / 0xff;
13+
const b = (rgb & 0xff) / 0xff;
14+
15+
const min = Math.min(r, g, b);
16+
const max = Math.max(r, g, b);
17+
18+
if (min === max) {
19+
return [0, 0, r * 100];
20+
}
21+
22+
const c = max - min;
23+
const l = (min + max) / 2;
24+
const s = c / (1 - Math.abs(2 * l - 1));
25+
26+
var h;
27+
switch (max) {
28+
case r: h = ((g - b) / c + 6) % 6; break;
29+
case g: h = (b - r) / c + 2; break;
30+
case b: h = (r - g) / c + 4; break;
31+
}
32+
h *= 60;
33+
34+
return [h, s * 100, l * 100];
35+
}
36+
37+
window.addEventListener('load', function() {
38+
document.body.addEventListener('mousedown', function(e) {
39+
if (e.button !== 2) {
40+
return;
41+
}
42+
43+
const widgetDiv = document.querySelector('.blocklyWidgetDiv');
44+
if (!widgetDiv) {
45+
return;
46+
}
47+
48+
if (e.target.closest('.blocklyMainBackground') || e.target.closest('.blocklyBubbleCanvas')) {
49+
widgetDiv.classList.remove('u-contextmenu-colored');
50+
return;
51+
}
52+
53+
const block = e.target.closest('.blocklyDraggable');
54+
if (!block) {
55+
return;
56+
}
57+
58+
const background = block.querySelector('.blocklyBlockBackground');
59+
if (!background) {
60+
return;
61+
}
62+
63+
const fill = background.getAttribute('fill');
64+
if (!fill) {
65+
return;
66+
}
67+
68+
const fillHex = fill.substr(1);
69+
const rgb = parseInt(fillHex, 16);
70+
const hsl = rgb2hsl(rgb);
71+
hsl[2] = Math.max(hsl[2] - 15, 0);
72+
const border = 'hsl(' + hsl[0] + ', ' + hsl[1] + '%, ' + hsl[2] + '%)';
73+
74+
widgetDiv.classList.add('u-contextmenu-colored');
75+
widgetDiv.style.setProperty('--u-contextmenu-bg', fill);
76+
widgetDiv.style.setProperty('--u-contextmenu-border', border);
77+
}, true);
78+
});
79+
80+
GM_addStyle(`
81+
.u-contextmenu-colored .blocklyContextMenu {
82+
background-color: var(--u-contextmenu-bg);
83+
border-color: var(--u-contextmenu-border);
84+
}
85+
.u-contextmenu-colored .blocklyContextMenu .goog-menuitem {
86+
color: white;
87+
}
88+
.u-contextmenu-colored .blocklyContextMenu .goog-menuitem:hover.goog-menuitem-highlight {
89+
border-color: transparent;
90+
}
91+
.u-contextmenu-colored .blocklyContextMenu .goog-menuitem:hover {
92+
background-color: rgba(0, 0, 0, 0.2);
93+
}
94+
`);

features/features.json

Lines changed: 47 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,42 @@
11
[
2+
{
3+
"title": "Stage on Left Side",
4+
"description": "Like in Scratch 2.0, moves the stage to the left side of the editor, rather than keeping it on the right.",
5+
"credits": ["GarboMuffin"],
6+
"urls": ["https://scratch.mit.edu/users/GarboMuffin/"],
7+
"file": "left-side-stage",
8+
"type": ["Editor"],
9+
"tags": ["New"],
10+
"dynamic":true
11+
},
12+
{
13+
"title": "Colored Context Menus",
14+
"description": "Like in Scratch 2.0, colors the context menus based on the color of the block they're for.",
15+
"credits": ["GarboMuffin"],
16+
"urls": ["https://scratch.mit.edu/users/GarboMuffin/"],
17+
"file": "colored-context-menus",
18+
"type": ["Editor"],
19+
"tags": ["New"]
20+
},
21+
{
22+
"title": "Hide Disabled Context Menu Options",
23+
"description": "Context menu options in the editor show even if they are disabled and unable to be used, so this feature will hide them if they are.",
24+
"credits": ["rgantzos"],
25+
"urls": ["https://scratch.mit.edu/users/rgantzos/"],
26+
"file": "hide-disabled-menu-options",
27+
"type": ["Editor"],
28+
"tags": ["New"],
29+
"dynamic":true
30+
},
31+
{
32+
"title": "Project Title Above Stage",
33+
"description": "Like in Scratch 2.0, moves the project title input box above the stage, rather than in the navbar. This only applies to the editor.",
34+
"credits": ["rgantzos"],
35+
"urls": ["https://scratch.mit.edu/users/rgantzos/"],
36+
"file": "move-project-title-input",
37+
"type": ["Editor"],
38+
"tags": ["New"]
39+
},
240
{
341
"title": "Display Message Count",
442
"description": "Displays your current message count in the extension icon for ScratchTools.",
@@ -12,18 +50,24 @@
1250
"title": "Pause Audio",
1351
"description": "Allows you to pause and resume audio in the sound editor of Scratch projects.",
1452
"credits": ["Giolaboman", "rgantzos"],
15-
"urls": ["https://scratch.mit.edu/users/Giolaboman/", "https://scratch.mit.edu/users/rgantzos/"],
53+
"urls": [
54+
"https://scratch.mit.edu/users/Giolaboman/",
55+
"https://scratch.mit.edu/users/rgantzos/"
56+
],
1657
"file": "pause-audio",
1758
"type": ["Website"],
1859
"tags": ["New", "Recommended"],
1960
"dynamic": true,
20-
"default":true
61+
"default": true
2162
},
2263
{
2364
"title": "Dumpster Fire",
2465
"description": "The Scratch homepage is a liar with their \"Featured Projects\" section. This changes the name to the proper form, which is \"Dumpster Fire\".",
2566
"credits": ["Kuzyn_Official", "rgantzos"],
26-
"urls": ["https://scratch.mit.edu/users/Kuzyn_Official/", "https://scratch.mit.edu/users/rgantzos/"],
67+
"urls": [
68+
"https://scratch.mit.edu/users/Kuzyn_Official/",
69+
"https://scratch.mit.edu/users/rgantzos/"
70+
],
2771
"file": "dumpster-fire",
2872
"type": ["Website"],
2973
"tags": ["New", "Egg"],
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
var style = document.createElement('style')
2+
style.textContent = `
3+
.blocklyContextMenu > [aria-disabled='true'] {
4+
display: none !important;
5+
}
6+
`
7+
style.className = 'scratchtoolsHideDisabledOptions'
8+
if (!document.querySelector('.scratchtoolsHideDisabledOptions')) {
9+
document.body.appendChild(style)
10+
}
11+
12+
ScratchTools.setDisable('hide-disabled-menu-options', function() {
13+
if (document.querySelector('.scratchtoolsHideDisabledOptions')) {
14+
document.querySelector('.scratchtoolsHideDisabledOptions').remove()
15+
}
16+
})

features/left-side-stage.js

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
// ==UserScript==
2+
// @name Left Side Stage for Scratch 3
3+
// @version 0.1
4+
// @namespace https://github.com/forkphorus/cat-plus
5+
// @homepageURL https://github.com/forkphorus/cat-plus#readme
6+
// @match https://scratch.mit.edu/projects/*
7+
// @grant GM_addStyle
8+
// ==/UserScript==
9+
10+
if (!document.querySelector('.scratchtoolsLeftSideStage')) {
11+
var style = GM_addStyle(`
12+
.gui_flex-wrapper_uXHkj {
13+
flex-direction: row-reverse !important;
14+
}
15+
.target-pane_target-pane_3S5E6 {
16+
flex-direction: row-reverse !important;
17+
}
18+
[dir="ltr"] .sprite-selector_sprite-selector_2KgCX {
19+
margin-left: calc(0.5rem / 2) !important;
20+
margin-right: 0 !important;
21+
}
22+
.target-pane_stage-selector-wrapper_qekSW {
23+
margin-left: 0 !important;
24+
margin-right: calc(0.5rem / 2) !important;
25+
}
26+
`);
27+
style.className = 'scratchtoolsLeftSideStage'
28+
29+
ScratchTools.setDisable('left-side-stage', function() {
30+
document.querySelector('.scratchtoolsLeftSideStage').remove()
31+
})
32+
}
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
ScratchTools.waitForElements("[class^='stage-header_stage-menu-wrapper_']", function() {
2+
var input = document.querySelector("[class*='project-title-input_title-field_']")
3+
input.style.marginLeft = '.2rem'
4+
input.style.marginRight = '.2rem'
5+
document.querySelector("[class^='stage-header_stage-menu-wrapper_']").insertBefore(input, document.querySelector("[class*='stage-header_stage-size-row_']"));
6+
var style = document.createElement('style')
7+
style.textContent = `
8+
[class*='project-title-input_title-field_'] {
9+
color: #595959 !important;
10+
}
11+
12+
[class*='menu-bar_menu-bar-item_'][class*='- menu-bar_growable_'] {
13+
display: none;
14+
}
15+
`
16+
document.body.appendChild(style)
17+
}, 'move project title input', false)

0 commit comments

Comments
 (0)