@@ -26,8 +26,114 @@ try {
2626 ScratchTools . console . warn ( "Unable to load Blockly." ) ;
2727}
2828
29- ScratchTools . Scratch . contextMenus = { } ;
29+ ScratchTools . Scratch . scratchSound = function ( ) {
30+ try {
31+ return document . querySelector ( "div.sound-editor_editor-container_iUSW-" ) [
32+ Object . keys (
33+ document . querySelector ( "div.sound-editor_editor-container_iUSW-" )
34+ ) . find ( ( key ) => key . startsWith ( "__reactInternalInstance" ) )
35+ ] . return . return . return . stateNode ;
36+ } catch ( err ) {
37+ return null ;
38+ }
39+ } ;
40+
41+ ScratchTools . Scratch . scratchGui = function ( ) {
42+ try {
43+ const app = document . querySelector ( "#app" ) ;
44+ return app [
45+ Object . keys ( app ) . find ( ( key ) => key . startsWith ( "__reactContainer" ) )
46+ ] . child . stateNode . store . getState ( ) . scratchGui ;
47+ } catch ( err ) {
48+ return null ;
49+ }
50+ } ;
51+
52+ ScratchTools . traps = {
53+ scratchGui : ScratchTools . Scratch . scratchGui ,
54+ scratchPaint : ScratchTools . Scratch . scratchPaint ,
55+ scratchSound : ScratchTools . Scratch . scratchSound ,
56+ getVm : function ( ) {
57+ return vm ;
58+ } ,
59+ getBlockly : function ( ) {
60+ return Blockly ;
61+ } ,
62+ getScratchBlocks,
63+ } ;
64+
65+ let openContextMenus = [ ] ;
66+
67+ const waitForContextMenu = function ( { id, callback, block, disabled, label } ) {
68+ var insertion = openContextMenus . push ( {
69+ id,
70+ block,
71+ callback,
72+ enabled : ! disabled ,
73+ label,
74+ } ) ;
75+ return {
76+ delete : function ( ) {
77+ delete openContextMenus [ openContextMenus . indexOf ( insertion ) ]
78+ }
79+ }
80+ } ;
81+
82+ let handledProcedures = { } ;
83+ ScratchTools . waitForElements (
84+ ".blocklyDraggable" ,
85+ function ( el ) {
86+ if ( el . dataset . id ) {
87+ var block = ScratchTools . traps
88+ . getBlockly ( )
89+ . getMainWorkspace ( )
90+ . getBlockById ( el . dataset . id ) ;
91+ if ( block ) {
92+ if ( block . type === "procedures_definition" ) {
93+ if ( ! handledProcedures [ block . id ] ) {
94+ handledProcedures [ block . id ] = block . customContextMenu ;
95+ }
96+ block . customContextMenu = function ( menu ) {
97+ handledProcedures [ block . id ] ( menu ) ;
98+ openContextMenus . forEach ( function ( option ) {
99+ if ( option . block === block . id ) {
100+ menu . push ( {
101+ enabled : option . enabled ,
102+ text : option . label ,
103+ callback : function ( e ) {
104+ option . callback ( e ) ;
105+ } ,
106+ } ) ;
107+ }
108+ } ) ;
109+ } ;
110+ } else {
111+ if ( ! block . customContextMenu ) {
112+ block . customContextMenu = function ( menu ) {
113+ openContextMenus . forEach ( function ( option ) {
114+ if ( option . block === block . id ) {
115+ menu . push ( {
116+ enabled : option . enabled ,
117+ text : option . label ,
118+ callback : function ( e ) {
119+ option . callback ( e ) ;
120+ } ,
121+ } ) ;
122+ }
123+ } ) ;
124+ } ;
125+ }
126+ }
127+ }
128+ }
129+ } ,
130+ "custom-menu-manager" ,
131+ false
132+ ) ;
133+
134+ ScratchTools . traps . createContextMenu = waitForContextMenu ;
30135
136+ ScratchTools . Scratch . contextMenus = { } ;
31137ScratchTools . Scratch . waitForContextMenu = function ( info ) {
32138 if ( ScratchTools . Scratch . contextMenus [ info . block ] !== undefined ) {
33139 ScratchTools . Scratch . contextMenus [ info . block ] [ info . id ] = info . callback ;
@@ -79,29 +185,6 @@ ScratchTools.Scratch.scratchPaint = function () {
79185 }
80186} ;
81187
82- ScratchTools . Scratch . scratchSound = function ( ) {
83- try {
84- return document . querySelector ( "div.sound-editor_editor-container_iUSW-" ) [
85- Object . keys (
86- document . querySelector ( "div.sound-editor_editor-container_iUSW-" )
87- ) . find ( ( key ) => key . startsWith ( "__reactInternalInstance" ) )
88- ] . return . return . return . stateNode ;
89- } catch ( err ) {
90- return null ;
91- }
92- } ;
93-
94- ScratchTools . Scratch . scratchGui = function ( ) {
95- try {
96- const app = document . querySelector ( "#app" ) ;
97- return app [
98- Object . keys ( app ) . find ( ( key ) => key . startsWith ( "__reactContainer" ) )
99- ] . child . stateNode . store . getState ( ) . scratchGui ;
100- } catch ( err ) {
101- return null ;
102- }
103- } ;
104-
105188async function alertForUpdates ( ) {
106189 if ( ScratchTools . Scratch . scratchGui ( ) . mode . hasEverEnteredEditor ) {
107190 var purple = await (
@@ -110,7 +193,8 @@ async function alertForUpdates() {
110193 )
111194 ) . json ( ) ;
112195 if ( purple . purple ) {
113- var alertedForPurple = await ScratchTools . storage . get ( "purpleAlert" ) || false ;
196+ var alertedForPurple =
197+ ( await ScratchTools . storage . get ( "purpleAlert" ) ) || false ;
114198 if ( ! alertedForPurple ) {
115199 await ScratchTools . storage . set ( { key : "purpleAlert" , value : true } ) ;
116200 ScratchTools . modals . create ( {
@@ -123,4 +207,24 @@ async function alertForUpdates() {
123207 }
124208}
125209
126- ScratchTools . waitForElements ( "div[class^='gui_menu-bar-position_']" , alertForUpdates , "purple-notification" , false )
210+ function getScratchBlocks ( ) {
211+ var blocksWrapper = document . querySelector (
212+ 'div[class^="gui_blocks-wrapper"]'
213+ ) ;
214+ var key = Object . keys ( blocksWrapper ) . find ( ( key ) =>
215+ key . startsWith ( "__reactInternalInstance$" )
216+ ) ;
217+ const internal = blocksWrapper [ key ] ;
218+ var recent = internal . child ;
219+ while ( ! recent . stateNode ?. ScratchBlocks ) {
220+ recent = recent . child ;
221+ }
222+ return recent . stateNode . ScratchBlocks || null ;
223+ }
224+
225+ ScratchTools . waitForElements (
226+ "div[class^='gui_menu-bar-position_']" ,
227+ alertForUpdates ,
228+ "purple-notification" ,
229+ false
230+ ) ;
0 commit comments