@@ -2176,6 +2176,7 @@ export class Editor extends toolboxeditor.ToolboxEditor {
21762176
21772177 protected showFlyoutBlocks ( ns : string , color : string , blocks : toolbox . BlockDefinition [ ] ) {
21782178 const filters = this . parent . state . editorState ? this . parent . state . editorState . filters : undefined ;
2179+ let configBlocksShown = new Set < string > ( ) ;
21792180 blocks . sort ( ( f1 , f2 ) => {
21802181 // Sort the blocks
21812182 return ( f2 . attributes . weight != undefined ? f2 . attributes . weight : 50 )
@@ -2186,6 +2187,19 @@ export class Editor extends toolboxeditor.ToolboxEditor {
21862187 blockXmlList = this . getButtonXml ( block as toolbox . ButtonDefinition ) ;
21872188 } else {
21882189 blockXmlList = this . getBlockXml ( block as toolbox . BlockDefinition ) ;
2190+
2191+ if ( blockXmlList ?. some ( element => element ?. getAttribute ( "data-isBlockConfigOverride" ) === "true" ) ) {
2192+ // Some builtin blocks appear in the toolbox multiple times, for example the if/else
2193+ // and lists_create_with blocks. If one of those has its XML overridden by a block config,
2194+ // we need to make sure we only show it once since all of the snippets will have the same
2195+ // overridden XML.
2196+ if ( configBlocksShown . has ( block . attributes . blockId ) ) {
2197+ blockXmlList = undefined ;
2198+ }
2199+ else {
2200+ configBlocksShown . add ( block . attributes . blockId ) ;
2201+ }
2202+ }
21892203 }
21902204 if ( blockXmlList ) this . flyoutXmlList = this . flyoutXmlList . concat ( blockXmlList ) ;
21912205 } )
@@ -2268,12 +2282,29 @@ export class Editor extends toolboxeditor.ToolboxEditor {
22682282 private getBlockXml ( block : toolbox . BlockDefinition , ignoregap ?: boolean , shadow ?: boolean ) : Element [ ] {
22692283 const that = this ;
22702284 let blockXml : Element ;
2285+
2286+ // Check for custom config in scope of the current tutorial step.
2287+ const currTutorialStep = this . parent . state . tutorialOptions ?. tutorialStep ;
2288+ const currTutorialStepInfo = currTutorialStep !== undefined ? this . parent . state . tutorialOptions . tutorialStepInfo [ currTutorialStep ] : undefined ;
2289+ if ( currTutorialStepInfo ?. localBlockConfig ?. blocks ) {
2290+ blockXml = getBlockConfigXml ( block , currTutorialStepInfo . localBlockConfig ) ;
2291+ }
2292+
2293+ // Check for custom config in the tutorial's global scope.
2294+ if ( ! blockXml && this . parent . state . tutorialOptions ?. globalBlockConfig ?. blocks ) {
2295+ blockXml = getBlockConfigXml ( block , this . parent . state . tutorialOptions . globalBlockConfig ) ;
2296+ }
2297+
2298+ if ( blockXml ) {
2299+ blockXml . setAttribute ( "data-isBlockConfigOverride" , "true" ) ;
2300+ }
2301+
22712302 // Check if the block is built in, ignore it as it's already defined in snippets
22722303 if ( block . attributes . blockBuiltin ) {
22732304 pxt . log ( "ignoring built in block: " + block . attributes . blockId ) ;
22742305 return undefined ;
22752306 }
2276- if ( block . builtinBlock ) {
2307+ if ( block . builtinBlock && ! blockXml ) {
22772308 // function_return is conditionally added to the toolbox, so it needs a special case
22782309 if ( block . attributes . blockId === "function_return" ) {
22792310 return [ pxtblockly . mkReturnStatementBlock ( ) ] ;
@@ -2297,29 +2328,6 @@ export class Editor extends toolboxeditor.ToolboxEditor {
22972328 if ( ! shouldShowBlock ( fn ) ) return undefined ;
22982329 let comp = pxt . blocks . compileInfo ( fn ) ;
22992330
2300- function getBlockConfigXml ( blockConfig : pxt . tutorial . TutorialBlockConfig ) : Element | undefined {
2301- const entry = blockConfig . blocks . find ( entry => entry . blockId === block . attributes . blockId ) ;
2302- if ( entry ) {
2303- const xml = Blockly . utils . xml . textToDom ( entry . xml ) ;
2304- xml . setAttribute ( "gap" , `${ pxt . appTarget . appTheme
2305- && pxt . appTarget . appTheme . defaultBlockGap && pxt . appTarget . appTheme . defaultBlockGap . toString ( ) || 8 } `) ;
2306- return xml ;
2307- }
2308- return undefined ;
2309- }
2310-
2311- // Check for custom config in scope of the current tutorial step.
2312- const currTutorialStep = this . parent . state . tutorialOptions ?. tutorialStep ;
2313- const currTutorialStepInfo = currTutorialStep !== undefined ? this . parent . state . tutorialOptions . tutorialStepInfo [ currTutorialStep ] : undefined ;
2314- if ( currTutorialStepInfo ?. localBlockConfig ?. blocks ) {
2315- blockXml = getBlockConfigXml ( currTutorialStepInfo . localBlockConfig ) ;
2316- }
2317-
2318- // Check for custom config in the tutorial's global scope.
2319- if ( ! blockXml && this . parent . state . tutorialOptions ?. globalBlockConfig ?. blocks ) {
2320- blockXml = getBlockConfigXml ( this . parent . state . tutorialOptions . globalBlockConfig ) ;
2321- }
2322-
23232331 // Create the block XML from block definition.
23242332 if ( ! blockXml ) {
23252333 blockXml = pxtblockly . createToolboxBlock ( this . blockInfo , fn , comp , shadow ) ;
@@ -2393,7 +2401,7 @@ export class Editor extends toolboxeditor.ToolboxEditor {
23932401 pxt . log ( "Couldn't find block for: " + block . attributes . blockId ) ;
23942402 pxt . log ( block ) ;
23952403 }
2396- } else {
2404+ } else if ( ! blockXml ) {
23972405 blockXml = Blockly . utils . xml . textToDom ( block . blockXml ) ;
23982406 }
23992407 if ( blockXml ) {
@@ -2822,4 +2830,15 @@ function maybeCloneBlockForMove(workspace: Blockly.WorkspaceSvg) {
28222830
28232831 Blockly . getFocusManager ( ) . focusNode ( clone as Blockly . BlockSvg ) ;
28242832 }
2833+ }
2834+
2835+ function getBlockConfigXml ( block : toolbox . BlockDefinition , blockConfig : pxt . tutorial . TutorialBlockConfig ) : Element | undefined {
2836+ const entry = blockConfig . blocks . find ( entry => entry . blockId === block . attributes . blockId ) ;
2837+ if ( entry ) {
2838+ const xml = Blockly . utils . xml . textToDom ( entry . xml ) ;
2839+ xml . setAttribute ( "gap" , `${ pxt . appTarget . appTheme
2840+ && pxt . appTarget . appTheme . defaultBlockGap && pxt . appTarget . appTheme . defaultBlockGap . toString ( ) || 8 } `) ;
2841+ return xml ;
2842+ }
2843+ return undefined ;
28252844}
0 commit comments