From 809d1d07a5a4f6a7309e746d2cafb42c884c6c63 Mon Sep 17 00:00:00 2001 From: Aaron Dodson Date: Thu, 20 Feb 2025 10:35:23 -0800 Subject: [PATCH 1/2] refactor: use IDs based on the parent block ID for block comments --- src/scratch_comment_bubble.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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", From bfbc83ea5e10710d520244ff79d4106591b56fa1 Mon Sep 17 00:00:00 2001 From: Aaron Dodson Date: Thu, 20 Feb 2025 13:11:57 -0800 Subject: [PATCH 2/2] fix: fix bug that prevented comments from duplicated blocks from behaving properly --- src/scratch_block_paster.ts | 10 ++++++++++ src/scratch_comment_icon.ts | 15 +++++++++++---- 2 files changed, 21 insertions(+), 4 deletions(-) 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_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(