Skip to content

Conversation

@TheColaber
Copy link
Member

@TheColaber TheColaber commented Mar 8, 2021

Resolves #1749
Resolves #1968

@TheColaber
Copy link
Member Author

TheColaber commented Mar 8, 2021

How to use

createBlockContextMenu(
    callback,
    { workspace = false, blocks = false, flyout = false } = {}
)

The first param is the callback... the callback gets the param with all the items currently in the list, as well as, the blockly block (if there was one) that was right-clicked. The function should return the array of items back. Then the second param is the options params. workspace decides if it should run the callback when the user right-clicks on the workspace. blocks will run the callback when the user right-clicks on any block. flyout if true will also run the callback when the user right-clicks on a block in the flyout.

Here is an example:

addon.tab.createBlockContextMenu((items, block) => {
  if (block.type == "data_variable" && block.category_ == "data") { // Only allow blocks on the reporter blocks and data catagory blocks
    items.push({
      callback: (event) => {
        console.log("Clicked!!", event);
      },
      enabled: true,
      text: "Custom Item",
      separator: true
    });
  }
  return items;
}, {
  workspace: false, // Not on the workspace
  blocks: true, // Allow blocks in workspace
  flyout: true // Allow blocks in the flyout
});

How it works

Each addon has a property called addon.tab._blockContextMenu. When they use addon.tab.createBlockContextMenu, it appends some info into that array. module.js takes care of all the Blockly logic. It pollutes Blockly.ContextMenu.show, in which scratch passes in 3 parameters. event, items, rtl. The only useful and used parameter here is items. We make sure to run scripts first, adding more items from the addons, before having scratch's original code run. Remember, this is the show function, so once the original code runs, the context menu will be visible. We get the items to add by looking at scratchAddons.eventTargets.tab which is an array of all running addons that have userscripts. In there, we look for all addons' _blockContextMenu and put all items in one array. module.js does some logic to determine weather the item should be added to array based on the options that it was given. Each addon gets a callback called with 2 parameters. items and block. They must return the items array again, but they may modify and add items. block is a Blockly.Block when the user right clicks on a block. It determines which block the user right clicked by looking at Blockly.mainWorkspace.currentGesture_.targetBlock_. After all this, we call the original function, and finally, we make sure to add styles to items that add that as one of there settings. Make sure to refer to the example above again, and it may make more sense.

@mxmou
Copy link
Member

mxmou commented Mar 8, 2021

// TODO: Create Separators somehow... help!

Separators are not a Scratch feature, you need to add them using CSS after the menu loads.

@TheColaber TheColaber requested a review from apple502j as a code owner March 9, 2021 22:39
@WorldLanguages WorldLanguages added this to the v1.16.0 milestone May 15, 2021
@cobaltt7 cobaltt7 linked an issue May 24, 2021 that may be closed by this pull request
@apple502j apple502j modified the milestones: v1.16.0, Backlog Jun 12, 2021
@WorldLanguages WorldLanguages merged commit f8d98af into ScratchAddons:master Jul 30, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

scope: addon api Related to the addon.* JS APIs or other ways for addons to provide features scope: core Related to the core script/extension workings

Projects

None yet

6 participants