Skip to content

Commit bb59e39

Browse files
authored
Merge pull request #51 from Usbq/develop
Add Scratch.gui api part 1
2 parents c51f5cb + cf9e3d7 commit bb59e39

File tree

3 files changed

+53
-3
lines changed

3 files changed

+53
-3
lines changed

src/lib/tw-extension-gui-api.js

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
import LazyScratchBlocks from './tw-lazy-scratch-blocks';
2+
3+
/**
4+
* Implements Scratch.gui API for unsandboxed extensions.
5+
* @param {any} Scratch window.Scratch, mutated in place.
6+
*/
7+
const implementGuiAPI = Scratch => {
8+
Scratch.gui = {
9+
/**
10+
* Lazily get the internal ScratchBlocks object when it becomes available. It may never be
11+
* available if, for example, the user never enters the editor.
12+
*
13+
* ScratchBlocks becoming available does not necessarily mean the user is in the editor due
14+
* to getBlocklyEagerly() also existing.
15+
*
16+
* @returns {Promise<any>} Promise that may eventually resolve to ScratchBlocks
17+
*/
18+
getBlockly: () => new Promise(resolve => LazyScratchBlocks.onLoaded(resolve)),
19+
20+
/**
21+
* Get the internal ScratchBlocks object as soon as possible. This lets you access it even
22+
* if the user never enters the editor.
23+
*
24+
* This method is VERY SLOW and will cause A LOT OF CPU AND NETWORK ACTIVITY because it
25+
* downloads and evaluates all of scratch-blocks, a multi-megabyte JavaScript bundle.
26+
*
27+
* @returns {Promise<any>} Promise that will resolve to ScratchBlocks.
28+
*/
29+
getBlocklyEagerly: () => LazyScratchBlocks.load()
30+
};
31+
};
32+
33+
export default implementGuiAPI;

src/lib/tw-lazy-scratch-blocks.js

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,24 +15,30 @@ const wasNameYourmom = () => {
1515
return old;
1616
};
1717

18+
const callbacks = [];
1819
const isLoaded = () => !!_ScratchBlocks && (isNameUrMom() === wasNameYourmom());
1920

2021
const get = () => {
21-
if (!isLoaded()) {
22+
if (!_ScratchBlocks) {
2223
throw new Error('scratch-blocks is not loaded yet');
2324
}
2425
return _ScratchBlocks;
2526
};
2627

2728
const load = () => {
2829
if (_ScratchBlocks && (isNameUrMom() === wasNameYourmom())) {
29-
return Promise.resolve();
30+
return Promise.resolve(_ScratchBlocks);
3031
}
3132
_ScratchBlocks = null;
3233
return import(/* webpackChunkName: "sb" */ 'scratch-blocks')
3334
.then(m => {
3435
_ScratchBlocks = m.default;
3536

37+
for (const callback of callbacks) {
38+
callback(_ScratchBlocks);
39+
}
40+
callbacks.length = 0;
41+
3642
if (isNameUrMom()) {
3743
_ScratchBlocks.Blocks.your_mom = {
3844
init() {
@@ -134,10 +140,19 @@ const load = () => {
134140
});
135141
};
136142

143+
const onLoaded = callback => {
144+
if (_ScratchBlocks) {
145+
callback(_ScratchBlocks);
146+
} else {
147+
callbacks.push(callback);
148+
}
149+
};
150+
137151
export default {
138152
get,
139153
isLoaded,
140154
isNameUrMom,
141155
wasNameYourmom,
142-
load
156+
load,
157+
onLoaded
143158
};

src/lib/vm-listener-hoc.jsx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ import {
2222
setHasCloudVariables
2323
} from '../reducers/tw';
2424
import {setCustomStageSize} from '../reducers/custom-stage-size';
25+
import implementGuiAPI from './tw-extension-gui-api';
2526

2627
let compileErrorCounter = 0;
2728

@@ -73,6 +74,7 @@ const vmListenerHOC = function (WrappedComponent) {
7374
this.props.vm.on('COMPILE_ERROR', this.handleCompileError);
7475
this.props.vm.on('RUNTIME_STARTED', this.props.onClearCompileErrors);
7576
this.props.vm.on('STAGE_SIZE_CHANGED', this.props.onStageSizeChanged);
77+
this.props.vm.on('CREATE_UNSANDBOXED_EXTENSION_API', implementGuiAPI);
7678
}
7779
componentDidMount () {
7880
if (this.props.attachKeyboardEvents) {

0 commit comments

Comments
 (0)