diff --git a/src/scratch_block_paster.ts b/src/scratch_block_paster.ts index f1d88c5465..2b07d64e26 100644 --- a/src/scratch_block_paster.ts +++ b/src/scratch_block_paster.ts @@ -5,6 +5,7 @@ */ import * as Blockly from "blockly/core"; +import type { ScratchCommentIcon } from "./scratch_comment_icon"; /** * Class responsible for handling the pasting of copied blocks. @@ -31,6 +32,15 @@ class ScratchBlockPaster extends Blockly.clipboard.BlockPaster { block.setDragStrategy(new Blockly.dragging.BlockDragStrategy(block)); } + // Deserialization of blocks suppresses events, so even though this gets + // fired for blocks with comments, the VM will never receive it, causing its + // state to get out of sync. Manually fire it here (after suppression has + // been turned off) if needed. + const commentIcon = block.getIcon(Blockly.icons.IconType.COMMENT); + if (commentIcon) { + (commentIcon as ScratchCommentIcon).fireCreateEvent(); + } + return block; } } diff --git a/src/scratch_comment_bubble.js b/src/scratch_comment_bubble.js index 5c958416b7..c5daf8ef7c 100644 --- a/src/scratch_comment_bubble.js +++ b/src/scratch_comment_bubble.js @@ -16,7 +16,7 @@ export class ScratchCommentBubble extends Blockly.comments.CommentView { super(sourceBlock.workspace); this.sourceBlock = sourceBlock; this.disposing = false; - this.id = Blockly.utils.idGenerator.genUid(); + this.id = `${sourceBlock.id}_comment`; this.setPlaceholderText(Blockly.Msg.WORKSPACE_COMMENT_DEFAULT_TEXT); this.getSvgRoot().setAttribute( "style", diff --git a/src/scratch_comment_icon.ts b/src/scratch_comment_icon.ts index df04ea0ed9..84c4c4611b 100644 --- a/src/scratch_comment_icon.ts +++ b/src/scratch_comment_icon.ts @@ -19,7 +19,7 @@ interface CommentState { /** * Custom comment icon that draws no icon indicator, used for block comments. */ -class ScratchCommentIcon +export class ScratchCommentIcon extends Blockly.icons.Icon implements Blockly.ISerializable, Blockly.IHasBubble { @@ -34,9 +34,7 @@ class ScratchCommentIcon constructor(protected sourceBlock: Blockly.BlockSvg) { super(sourceBlock); this.commentBubble = new ScratchCommentBubble(this.sourceBlock); - Blockly.Events.fire( - new (Blockly.Events.get("block_comment_create"))(this.commentBubble) - ); + this.fireCreateEvent(); this.onTextChangedListener = this.onTextChanged.bind(this); this.onSizeChangedListener = this.onSizeChanged.bind(this); this.onCollapseListener = this.onCollapsed.bind(this); @@ -202,6 +200,15 @@ class ScratchCommentIcon this.commentBubble.dispose(); super.dispose(); } + + /** + * Fires a block comment create event corresponding to this icon's comment. + */ + fireCreateEvent() { + Blockly.Events.fire( + new (Blockly.Events.get("block_comment_create"))(this.commentBubble) + ); + } } Blockly.registry.register(