(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
This commit is contained in:
Jarosław Sadziński 2023-09-13 09:33:25 +02:00
parent be995d4857
commit d13a75a453

View File

@ -53,15 +53,15 @@
*/ */
import dom, {detachNode, findAncestor} from '../lib/dom'; import dom, {detachNode, findAncestor} from 'app/client/lib/dom';
import koArray, {isKoArray, KoArray} from '../lib/koArray'; import koArray, {isKoArray, KoArray} from 'app/client/lib/koArray';
import {cssClass, domData, foreach, scope, style, toggleClass} from '../lib/koDom'; import {cssClass, domData, foreach, scope, style, toggleClass} from 'app/client/lib/koDom';
import {Disposable} from 'app/client/lib/dispose'; import {Disposable} from 'app/client/lib/dispose';
import assert from 'assert'; import assert from 'assert';
import {Events as BackboneEvents} from 'backbone'; import {Events as BackboneEvents} from 'backbone';
import * as ko from 'knockout'; import * as ko from 'knockout';
import {computed, isObservable, observable, utils} 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 { export interface ContentBox {
leafId: ko.Observable<any>; leafId: ko.Observable<any>;
@ -457,6 +457,12 @@ export class Layout extends Disposable {
return box; return box;
} }
public buildLayout(boxSpec: BoxSpec, needDynamic = false) { 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; this.needDynamic = needDynamic;
const oldRootBox = this.rootBox(); const oldRootBox = this.rootBox();
this.rootBox(this.buildLayoutBox(boxSpec)); this.rootBox(this.buildLayoutBox(boxSpec));
@ -481,7 +487,8 @@ export class Layout extends Disposable {
return spec; return spec;
} }
public getLayoutSpec() { 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 * Returns a Map object mapping leafId to its LayoutBox. This gets invalidated on layoutAdjust