From 656e8c2c77400d1ffe6233b9f1e5d5638c701cfa Mon Sep 17 00:00:00 2001 From: "Michael \"Z\" Goddard" Date: Thu, 21 Mar 2019 14:57:22 -0400 Subject: [PATCH 1/3] render only new toolbox xmls --- src/containers/blocks.jsx | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/containers/blocks.jsx b/src/containers/blocks.jsx index ecb998ea4..7cfb62fb6 100644 --- a/src/containers/blocks.jsx +++ b/src/containers/blocks.jsx @@ -199,8 +199,11 @@ class Blocks extends React.Component { const categoryId = this.workspace.toolbox_.getSelectedCategoryId(); const offset = this.workspace.toolbox_.getCategoryScrollOffset(); - this.workspace.updateToolbox(this.props.toolboxXML); - this._renderedToolboxXML = this.props.toolboxXML; + + if (this._renderedToolboxXML !== this.props.toolboxXML) { + this.workspace.updateToolbox(this.props.toolboxXML); + this._renderedToolboxXML = this.props.toolboxXML; + } // In order to catch any changes that mutate the toolbox during "normal runtime" // (variable changes/etc), re-enable toolbox refresh. From 866af2f766c37dafc21c934108d9d18a9c80248c Mon Sep 17 00:00:00 2001 From: "Michael \"Z\" Goddard" Date: Tue, 26 Mar 2019 17:33:42 -0400 Subject: [PATCH 2/3] render toolboxes once the workspace has rendered --- src/containers/blocks.jsx | 22 +++++++++++++++++----- 1 file changed, 17 insertions(+), 5 deletions(-) diff --git a/src/containers/blocks.jsx b/src/containers/blocks.jsx index 7cfb62fb6..c366da458 100644 --- a/src/containers/blocks.jsx +++ b/src/containers/blocks.jsx @@ -30,6 +30,10 @@ import { SOUNDS_TAB_INDEX } from '../reducers/editor-tab'; +const UNINITIALIZED_TOOLBOX_XML = ` + +`; + const addFunctionListener = (object, property, callback) => { const oldFn = object[property]; object[property] = function () { @@ -83,23 +87,26 @@ class Blocks extends React.Component { }; this.onTargetsUpdate = debounce(this.onTargetsUpdate, 100); this.toolboxUpdateQueue = []; + this.initializedWorkspace = false; } componentDidMount () { this.ScratchBlocks.FieldColourSlider.activateEyedropper_ = this.props.onActivateColorPicker; this.ScratchBlocks.Procedures.externalProcedureDefCallback = this.props.onActivateCustomProcedures; this.ScratchBlocks.ScratchMsgs.setLocale(this.props.locale); + const toolboxXML = UNINITIALIZED_TOOLBOX_XML; + const workspaceConfig = defaultsDeep({}, Blocks.defaultOptions, this.props.options, - {rtl: this.props.isRtl, toolbox: this.props.toolboxXML} + {rtl: this.props.isRtl, toolbox: toolboxXML} ); this.workspace = this.ScratchBlocks.inject(this.blocks, workspaceConfig); // Store the xml of the toolbox that is actually rendered. // This is used in componentDidUpdate instead of prevProps, because // the xml can change while e.g. on the costumes tab. - this._renderedToolboxXML = this.props.toolboxXML; + this._renderedToolboxXML = toolboxXML; // we actually never want the workspace to enable "refresh toolbox" - this basically re-renders the // entire toolbox every time we reset the workspace. We call updateToolbox as a part of @@ -200,9 +207,13 @@ class Blocks extends React.Component { const categoryId = this.workspace.toolbox_.getSelectedCategoryId(); const offset = this.workspace.toolbox_.getCategoryScrollOffset(); - if (this._renderedToolboxXML !== this.props.toolboxXML) { - this.workspace.updateToolbox(this.props.toolboxXML); - this._renderedToolboxXML = this.props.toolboxXML; + let toolboxXML = this.props.toolboxXML; + if (!this.initializedWorkspace) { + toolboxXML = UNINITIALIZED_TOOLBOX_XML; + } + if (this._renderedToolboxXML !== toolboxXML) { + this.workspace.updateToolbox(toolboxXML); + this._renderedToolboxXML = toolboxXML; } // In order to catch any changes that mutate the toolbox during "normal runtime" @@ -339,6 +350,7 @@ class Blocks extends React.Component { // When we change sprites, update the toolbox to have the new sprite's blocks const toolboxXML = this.getToolboxXML(); if (toolboxXML) { + this.initializedWorkspace = true; this.props.updateToolboxState(toolboxXML); } From d83ec5a0b5bafdff7807e2680baf9dd3fb8fcef7 Mon Sep 17 00:00:00 2001 From: "Michael \"Z\" Goddard" Date: Tue, 30 Apr 2019 10:37:43 -0400 Subject: [PATCH 3/3] replace blocks timeout with a promise The timeout as a promise lets us update the toolbox during the same render as the workspace so that the screen updates all together. This also means the toolbox will update before the loading screen is dismissed after loading, letting us avoid a second flash for the toolbox to update. --- src/containers/blocks.jsx | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/src/containers/blocks.jsx b/src/containers/blocks.jsx index c366da458..694c50cbd 100644 --- a/src/containers/blocks.jsx +++ b/src/containers/blocks.jsx @@ -180,13 +180,19 @@ class Blocks extends React.Component { componentWillUnmount () { this.detachVM(); this.workspace.dispose(); - clearTimeout(this.toolboxUpdateTimeout); + if (this.toolboxUpdateTimeout) this.toolboxUpdateTimeout.cancel(); } requestToolboxUpdate () { - clearTimeout(this.toolboxUpdateTimeout); - this.toolboxUpdateTimeout = setTimeout(() => { - this.updateToolbox(); - }, 0); + if (this.toolboxUpdateTimeout) this.toolboxUpdateTimeout.cancel(); + let running = true; + this.toolboxUpdateTimeout = Promise.resolve().then(() => { + if (running) { + this.updateToolbox(); + } + }); + this.toolboxUpdateTimeout.cancel = () => { + running = false; + }; } setLocale () { this.ScratchBlocks.ScratchMsgs.setLocale(this.props.locale);