From d13a75a453e1e3671795433e7bf09f4d422f92e5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jaros=C5=82aw=20Sadzi=C5=84ski?= Date: Wed, 13 Sep 2023 09:33:25 +0200 Subject: [PATCH] (core) Avoiding the view layout's rebuild, when nothing has changed. Summary: Layout is rebuild when it is updated from outside, for example after saving. But actually we don't need to rebuild it, because most of the time nothing has changed. This is important for custom widgets, which will reload the iframe, even though the dom is not changed, but just moved from previous layout to the new one. Test Plan: Manual and existing. Reviewers: georgegevoian Reviewed By: georgegevoian Differential Revision: https://phab.getgrist.com/D4039 --- app/client/components/Layout.ts | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/app/client/components/Layout.ts b/app/client/components/Layout.ts index de881ce4..ac3fc1f8 100644 --- a/app/client/components/Layout.ts +++ b/app/client/components/Layout.ts @@ -53,15 +53,15 @@ */ -import dom, {detachNode, findAncestor} from '../lib/dom'; -import koArray, {isKoArray, KoArray} from '../lib/koArray'; -import {cssClass, domData, foreach, scope, style, toggleClass} from '../lib/koDom'; +import dom, {detachNode, findAncestor} from 'app/client/lib/dom'; +import koArray, {isKoArray, KoArray} from 'app/client/lib/koArray'; +import {cssClass, domData, foreach, scope, style, toggleClass} from 'app/client/lib/koDom'; import {Disposable} from 'app/client/lib/dispose'; import assert from 'assert'; import {Events as BackboneEvents} from 'backbone'; import * as ko from 'knockout'; import {computed, isObservable, observable, utils} from 'knockout'; -import {identity, last, uniqueId} from 'underscore'; +import {identity, isEqual, last, uniqueId} from 'underscore'; export interface ContentBox { leafId: ko.Observable; @@ -457,6 +457,12 @@ export class Layout extends Disposable { return box; } public buildLayout(boxSpec: BoxSpec, needDynamic = false) { + if (needDynamic === this.needDynamic && + this.rootBox() && + isEqual(boxSpec, this.getLayoutSpec())) { + // Nothing has changed, and we already have a layout. No need to rebuild. + return; + } this.needDynamic = needDynamic; const oldRootBox = this.rootBox(); this.rootBox(this.buildLayoutBox(boxSpec)); @@ -481,7 +487,8 @@ export class Layout extends Disposable { return spec; } public getLayoutSpec() { - return this._getBoxSpec(this.rootBox()!); + const rootBox = this.rootBox(); + return rootBox ? this._getBoxSpec(rootBox) : {}; } /** * Returns a Map object mapping leafId to its LayoutBox. This gets invalidated on layoutAdjust