Skip to content

Commit 59f71c1

Browse files
authored
Rewrite Block Count addon (optimized)
1 parent 503a78e commit 59f71c1

File tree

1 file changed

+66
-48
lines changed

1 file changed

+66
-48
lines changed
Lines changed: 66 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -1,60 +1,78 @@
11
export default async function ({ addon, console, msg }) {
2+
const Blockly = await addon.tab.traps.getBlockly();
23
const vm = addon.tab.traps.vm;
34

5+
let counterElement;
6+
47
const getBlockCount = () => {
5-
let blockCount = 0;
6-
let scriptCount = 0;
7-
let sprites = new Set(vm.runtime.targets.map((i) => i.sprite.blocks._blocks));
8-
sprites.forEach((sprite, i) => {
9-
scriptCount += Object.values(sprite).filter((o) => !o.parent).length; // Filter blocks that don't have a parent (meaning it's the top of a stack)
10-
blockCount += Object.values(sprite).filter((o) => !o.shadow).length; // shadow blocks should be filtered out
8+
let allBlockCount = 0; // number of blocks in project
9+
let thisBlockCount = 0; // number of blocks in this sprite
10+
11+
const targetBlocks = vm.runtime.targets.map((target) => {
12+
return [
13+
target.id,
14+
Object.values(target.blocks._blocks)
15+
.filter((b) => !b.shadow).length // shadow blocks should be filtered out
16+
];
1117
});
12-
return {
13-
blockCount,
14-
scriptCount,
15-
spriteCount: sprites.size - 1, // Backdrop counts as a target so we can subtract it
16-
};
18+
19+
// project block count
20+
for (const info of targetBlocks) allBlockCount += info[1];
21+
22+
// this sprite's block count
23+
const thisTargetID = vm.editingTarget?.id;
24+
const thisWS = targetBlocks.find((i) => i[0] === thisTargetID);
25+
if (thisWS) thisBlockCount += thisWS[1];
26+
27+
if (thisBlockCount === allBlockCount) return allBlockCount;
28+
return `${thisBlockCount} / ${allBlockCount}`;
1729
};
1830

19-
const addLiveBlockCount = async () => {
20-
if (vm.editingTarget) {
21-
let handler = null;
22-
while (true) {
23-
const topBar = await addon.tab.waitForElement("[class^='menu-bar_main-menu']", {
24-
markAsSeen: true,
25-
reduxEvents: [
26-
"scratch-gui/mode/SET_PLAYER",
27-
"fontsLoaded/SET_FONTS_LOADED",
28-
"scratch-gui/locales/SELECT_LOCALE",
29-
],
30-
reduxCondition: (state) => !state.scratchGui.mode.isPlayerOnly,
31-
});
32-
let display = topBar.appendChild(document.createElement("span"));
33-
addon.tab.displayNoneWhileDisabled(display);
34-
display.style.order = 1;
35-
display.style.padding = "9px";
36-
display.innerText = msg("blocks", { num: getBlockCount().blockCount });
37-
let debounce; // debouncing values because of the way 'PROJECT_CHANGED' works
38-
if (handler) {
39-
vm.off("PROJECT_CHANGED", handler);
40-
vm.runtime.off("PROJECT_LOADED", handler);
31+
const addCounter = () => {
32+
ReduxStore.subscribe(() => {
33+
if (!counterElement) {
34+
// init counter
35+
const topBar = document.querySelector("div[class^='menu-bar_main-menu']");
36+
if (!topBar) return;
37+
38+
counterElement = topBar.appendChild(document.createElement("span"));
39+
counterElement.style.order = 1;
40+
counterElement.style.padding = "9px";
41+
42+
addLiveBlockCount();
43+
} else {
44+
// hide display if not in editor
45+
const state = ReduxStore.getState().scratchGui;
46+
counterElement.style.display = state.mode.isPlayerOnly ? "none" : "";
47+
}
48+
});
49+
}
50+
51+
const addLiveBlockCount = () => {
52+
let lastWorkspaceID;
53+
let lastUpdateTime = 0;
54+
vm.on("workspaceUpdate", () => {
55+
const workspace = Blockly.mainWorkspace;
56+
const events = Blockly.Events;
57+
58+
const blocklyHandler = (event) => {
59+
const now = Date.now();
60+
if (
61+
counterElement &&
62+
now > lastUpdateTime + 1000 && // dont update the count multiple times in a second
63+
(event.type === events.DELETE || event.type === events.CREATE)
64+
) {
65+
lasUpdateTime = now;
66+
counterElement.innerText = msg("blocks", { num: getBlockCount() });
4167
}
42-
handler = async () => {
43-
clearTimeout(debounce);
44-
debounce = setTimeout(async () => {
45-
display.innerText = msg("blocks", { num: getBlockCount().blockCount });
46-
}, 1000);
47-
};
48-
vm.on("PROJECT_CHANGED", handler);
49-
vm.runtime.on("PROJECT_LOADED", handler);
68+
};
69+
70+
if (lastWorkspaceID !== workspace.id) {
71+
workspace.addChangeListener(blocklyHandler);
72+
lastWorkspaceID = workspace.id;
5073
}
51-
} else {
52-
let timeout = setTimeout(function () {
53-
addLiveBlockCount();
54-
clearTimeout(timeout);
55-
}, 1000);
56-
}
74+
});
5775
};
5876

59-
addLiveBlockCount();
77+
addCounter();
6078
}

0 commit comments

Comments
 (0)