From 36ba408b794928fe642ceecb76344a56323c7b59 Mon Sep 17 00:00:00 2001 From: Beka Westberg Date: Mon, 24 Jul 2023 14:43:14 -0700 Subject: [PATCH] fix: have icons use the new render management system (#7296) * feat: add method for triggering renders * chore: switch icon methods to use queue --- core/block_svg.ts | 12 ++++++------ core/render_management.ts | 25 ++++++++++++++++++++++++- tests/mocha/block_test.js | 4 ++-- 3 files changed, 32 insertions(+), 9 deletions(-) diff --git a/core/block_svg.ts b/core/block_svg.ts index 0b320c2e0..d87e042be 100644 --- a/core/block_svg.ts +++ b/core/block_svg.ts @@ -59,7 +59,7 @@ import * as svgMath from './utils/svg_math.js'; import {WarningIcon} from './icons/warning_icon.js'; import type {Workspace} from './workspace.js'; import type {WorkspaceSvg} from './workspace_svg.js'; -import {queueRender} from './render_management.js'; +import * as renderManagement from './render_management.js'; import * as deprecation from './utils/deprecation.js'; import {IconType} from './icons/icon_types.js'; @@ -983,8 +983,8 @@ export class BlockSvg icon.initView(this.createIconPointerDownListener(icon)); icon.applyColour(); icon.updateEditable(); - // TODO: Change this based on #7068. - this.render(); + this.queueRender(); + renderManagement.triggerQueuedRenders(); this.bumpNeighbours(); } @@ -1012,8 +1012,8 @@ export class BlockSvg if (type.equals(MutatorIcon.TYPE)) this.mutator = null; if (this.rendered) { - // TODO: Change this based on #7068. - this.render(); + this.queueRender(); + renderManagement.triggerQueuedRenders(); this.bumpNeighbours(); } return removed; @@ -1542,7 +1542,7 @@ export class BlockSvg * @internal */ queueRender(): Promise { - return queueRender(this); + return renderManagement.queueRender(this); } /** diff --git a/core/render_management.ts b/core/render_management.ts index 8c469f856..9a9a4d0cf 100644 --- a/core/render_management.ts +++ b/core/render_management.ts @@ -21,6 +21,15 @@ let dirtyBlocks = new WeakSet(); */ let afterRendersPromise: Promise | null = null; +/** The function to call to resolve the `afterRendersPromise`. */ +let afterRendersResolver: (() => void) | null = null; + +/** + * The ID of the current animation frame request. Used to cancel the request + * if necessary. + */ +let animationRequestId = 0; + /** * Registers that the given block and all of its parents need to be rerendered, * and registers a callback to do so after a delay, to allowf or batching. @@ -35,7 +44,8 @@ export function queueRender(block: BlockSvg): Promise { queueBlock(block); if (!afterRendersPromise) { afterRendersPromise = new Promise((resolve) => { - window.requestAnimationFrame(() => { + afterRendersResolver = resolve; + animationRequestId = window.requestAnimationFrame(() => { doRenders(); resolve(); }); @@ -54,6 +64,19 @@ export function finishQueuedRenders(): Promise { return afterRendersPromise ? afterRendersPromise : Promise.resolve(); } +/** + * Triggers an immediate render of all queued renders. Should only be used in + * cases where queueing renders breaks functionality + backwards compatibility + * (such as rendering icons). + * + * @internal + */ +export function triggerQueuedRenders() { + window.cancelAnimationFrame(animationRequestId); + doRenders(); + if (afterRendersResolver) afterRendersResolver(); +} + /** * Adds the given block and its parents to the render queue. Adds the root block * to the list of root blocks. diff --git a/tests/mocha/block_test.js b/tests/mocha/block_test.js index 4da49a08c..fd640ddbb 100644 --- a/tests/mocha/block_test.js +++ b/tests/mocha/block_test.js @@ -1468,7 +1468,7 @@ suite('Blocks', function () { this.block = this.workspace.newBlock('stack_block'); this.block.initSvg(); this.block.render(); - this.renderSpy = sinon.spy(this.block, 'render'); + this.renderSpy = sinon.spy(this.block, 'queueRender'); }); teardown(function () { @@ -1513,7 +1513,7 @@ suite('Blocks', function () { this.block = this.workspace.newBlock('stack_block'); this.block.initSvg(); this.block.render(); - this.renderSpy = sinon.spy(this.block, 'render'); + this.renderSpy = sinon.spy(this.block, 'queueRender'); }); teardown(function () {