Hello all!
First off, thank you! I have been a long time lurker on here - first time posting.
So we were able to solve this problem (Eric and I work together) largely thanks to your advice so far! Here is how we did it.
I really liked Adam's idea about using events, so I investigated that and ended up creating an Extension to listen for Create events by adding a `setOnChange` handler.
One thing I ran into was that I could not figure out how to change a mutation value from that extension, which actually led me to something great. While re-reading the docs I saw that our use case is better suited for the
Block.data property, since it's literally "Optional text data that round-trips between blocks and XML. Has no effect. May be used by 3rd parties for meta information." Aha! I moved the management of our system UUID over to data instead of using a mutator.
With that knowledge, we had the bulk of a solution! A way to listen to block create events and conditionally regenerate an ID. The problem then became that Blockly was obediently regenerating them on any change that triggered the create event - notably when re-opening a workspace (undesirable for us). I addressed this by cached the block ID as well as our system ID so we can check that before regenerating a new UUID.
Here is a pseudocode showing how that works (we use typescript - hopefully the markdown here comes out right):
```typescript
Blockly.Extensions.register(
"system_id_manager",
function (this: Blockly.Block) {
this.setOnChange((changeEvent: Blockly.Events.Abstract) => {
// Question: Is there a better way to get the event type than toJson?
if ((changeEvent.toJson() as { type: string }).type === "create") {
if (!this.data || JSON.parse(this.data).block_id !==
this.id) {
this.data = JSON.stringify({
system_id: generateSystemId(),
});
}
}
});
}
);
```
From there, the rest was fairly straightforward!
1) Update the original Mutator extension to migrate the IDs to block.data for older blocks
2) We have a custom copy/paste context menu, and there I added some massaging of the selected block's DocumentFragment before adding it to the clipboard, stripping off the block ID and the `<data>` node to ensure we get new values.
Question: I added a comment on the example code above where I had to serialize the ChangeEvent to access it's type. Is there a better way to get the event type that I a missing? I do not see it exposed on the
BlockCreate or on the
Events Abstract 🤔
Many thanks again to everyone who chipped in! Your time and help is appreciated!
Let me know if you have any suggestions (or questions)!
Cheers!
Augie
PS: To answer Adam's question regarding us using the UUIDs from Blockly: While that would be awesome, unfortunately our API will not accept them as they do not comply with our spec for IDs. Too bad though! That would have been perfect, I think we could have gotten away with simply removing the IDs in the custom Copy to clipboard context menu action.