Skip to content
This repository was archived by the owner on May 5, 2021. It is now read-only.

Commit b622c5f

Browse files
committed
wip
1 parent c124f3f commit b622c5f

File tree

9 files changed

+227
-210
lines changed

9 files changed

+227
-210
lines changed

packages/plugin-dom-layout/src/DomLayout.ts

Lines changed: 17 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,8 @@ import { RuleProperty } from '../../core/src/Mode';
2525
import { isContentEditable } from '../../utils/src/utils';
2626
import { AbstractNode } from '../../core/src/VNodes/AbstractNode';
2727
import { VNode } from '../../core/src/VNodes/VNode';
28+
import { Modifier } from '../../core/src/Modifier';
29+
import { DomObjectRenderingEngine } from '../../plugin-renderer-dom-object/src/DomObjectRenderingEngine';
2830

2931
export interface DomLayoutConfig extends JWPluginConfig {
3032
location?: [Node, DomZonePosition];
@@ -56,6 +58,8 @@ export class DomLayout<T extends DomLayoutConfig = DomLayoutConfig> extends JWPl
5658
'commit': this._redraw,
5759
};
5860

61+
private _nodeToRedraw: VNode[] = [];
62+
5963
constructor(editor: JWEditor, configuration: T) {
6064
super(editor, configuration);
6165
this.loadables.layoutEngines.push(DomLayoutEngine);
@@ -77,8 +81,13 @@ export class DomLayout<T extends DomLayoutConfig = DomLayoutConfig> extends JWPl
7781
domLayoutEngine.location = this.configuration.location;
7882
await domLayoutEngine.start();
7983
window.addEventListener('keydown', this.processKeydown, true);
84+
85+
const renderer = this.dependencies.get(Renderer);
86+
const domObjectRendererEngine = renderer.engines['dom/object'] as DomObjectRenderingEngine;
87+
domObjectRendererEngine.onInvalidateCache(this._addNodeToRedraw.bind(this));
8088
}
8189
async stop(): Promise<void> {
90+
this._nodeToRedraw = [];
8291
window.removeEventListener('keydown', this.processKeydown, true);
8392
const layout = this.dependencies.get(Layout);
8493
const domLayoutEngine = layout.engines.dom;
@@ -183,54 +192,15 @@ export class DomLayout<T extends DomLayoutConfig = DomLayoutConfig> extends JWPl
183192
private async _redraw(): Promise<void> {
184193
const layout = this.dependencies.get(Layout);
185194
const domLayoutEngine = layout.engines.dom as DomLayoutEngine;
186-
const changedPath = new Map<AbstractNode, string[][]>();
187-
const pathChanges = this.editor.memory.getChanges();
188-
for (const [object, path] of pathChanges) {
189-
if (object instanceof AbstractNode) {
190-
if (!changedPath.has(object)) {
191-
changedPath.set(object, []);
192-
}
193-
changedPath.get(object).push(path);
194-
}
195-
for (const [parent, path] of this.editor.memory.getParents(object)) {
196-
if (parent instanceof AbstractNode) {
197-
if (!changedPath.has(parent)) {
198-
changedPath.set(parent, []);
199-
}
200-
changedPath.set(parent as VNode, path);
201-
}
202-
}
203-
}
204-
if (changedPath.size) {
205-
const nodes = [];
206-
for (const [root] of changedPath) {
207-
if (root === this.editor.selection.anchor || root === this.editor.selection.focus) {
208-
// Filter not VNode changes and selection change.
209-
changedPath.delete(root);
210-
}
211-
}
212-
let removedNode = false;
213-
for (const [root] of changedPath) {
214-
nodes.push(root);
215-
if (!root.parent) {
216-
removedNode = true;
217-
}
218-
}
219-
if (removedNode) {
220-
// Need to force redrawing of children if remove a child.
221-
for (const [node, paths] of changedPath) {
222-
if (paths.find(path => path[0] === 'childVNodes')) {
223-
for (const child of node.childVNodes) {
224-
const index = nodes.indexOf(child);
225-
if (index !== -1) {
226-
nodes.splice(index, 1);
227-
}
228-
nodes.push(child);
229-
}
230-
}
231-
}
195+
const nodes = this._nodeToRedraw;
196+
this._nodeToRedraw = [];
197+
await domLayoutEngine.redraw(nodes);
198+
}
199+
private _addNodeToRedraw(items: Array<VNode | Modifier>): void {
200+
for (const item of items) {
201+
if (item instanceof AbstractNode) {
202+
this._nodeToRedraw.push(item);
232203
}
233-
await domLayoutEngine.redraw(nodes);
234204
}
235205
}
236206
}

packages/plugin-dom-layout/src/DomLayoutEngine.ts

Lines changed: 1 addition & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,6 @@ import {
1919
} from '../../plugin-renderer-dom-object/src/DomObjectRenderingEngine';
2020
import { VElement } from '../../core/src/VNodes/VElement';
2121
import { flat } from '../../utils/src/utils';
22-
import { AbstractNode } from '../../core/src/VNodes/AbstractNode';
2322

2423
export type DomPoint = [Node, number];
2524
export type DomLayoutLocation = [Node, DomZonePosition];
@@ -126,60 +125,6 @@ export class DomLayoutEngine extends LayoutEngine {
126125
nodes = nodes.filter(node => {
127126
return node.ancestors().pop() === this.root;
128127
});
129-
130-
const nodeIds: Record<number, VNode> = {};
131-
for (let node of nodes) {
132-
nodeIds[node.id] = node;
133-
while (
134-
node.parent &&
135-
!nodeIds[node.parent.id] &&
136-
(this._domReconciliationEngine.getRenderedWith(node).length !== 1 ||
137-
!this._domReconciliationEngine.toDom(node).length)
138-
) {
139-
// If the node are redererd with some other nodes then redraw parent.
140-
// If not in layout then redraw the parent.
141-
node = node.parent;
142-
nodeIds[node.id] = node;
143-
}
144-
}
145-
146-
const parents: VNode[] = [];
147-
for (const node of nodes) {
148-
// Add direct siblings nodes for batched nodes with format.
149-
const next = node.next();
150-
if (next && next.parent === node.parent) {
151-
nodeIds[next.id] = next;
152-
}
153-
const previous = node.previous();
154-
if (previous && previous.parent === node.parent) {
155-
nodeIds[previous.id] = previous;
156-
}
157-
}
158-
159-
// Add grouped node for rendering.
160-
const nearests: Record<number, VNode> = {};
161-
for (const id in nodeIds) {
162-
if (!nearests[id]) {
163-
const node = nodeIds[id];
164-
for (const nearest of this._domReconciliationEngine.getRenderedWith(node)) {
165-
if (nearest instanceof AbstractNode) {
166-
const id = nearest.id;
167-
nodeIds[id] = nearests[id] = nearest;
168-
}
169-
}
170-
// Add parent for wrap/unwrapped node list formatted charNodes.
171-
const parent = node.parent;
172-
if (parent && !parents.includes(parent)) {
173-
parents.push(parent);
174-
}
175-
}
176-
}
177-
178-
for (const parent of parents) {
179-
nodeIds[parent.id] = parent;
180-
}
181-
182-
nodes = Object.values(nodeIds);
183128
} else {
184129
nodes = [];
185130
// Redraw all.
@@ -195,11 +140,9 @@ export class DomLayoutEngine extends LayoutEngine {
195140

196141
// Render nodes.
197142
const renderer = this.editor.plugins.get(Renderer);
198-
let domObjects = (await renderer.render<DomObject>('dom/object', nodes)) || [];
143+
const domObjects = (await renderer.render<DomObject>('dom/object', nodes)) || [];
199144
const engine = renderer.engines['dom/object'] as DomObjectRenderingEngine;
200145

201-
domObjects = domObjects.filter((node, index) => domObjects.indexOf(node) === index);
202-
203146
this._domReconciliationEngine.update(
204147
domObjects,
205148
engine.locations,

packages/plugin-dom-layout/test/DomLayout.test.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5020,7 +5020,7 @@ describe.only('DomLayout', () => {
50205020
afterEach(async () => {
50215021
await editor?.stop();
50225022
});
5023-
it.only('should add a component in a zone', async () => {
5023+
it('should add a component in a zone', async () => {
50245024
await editor.execBatch(() => {
50255025
return editor.plugins.get(Layout).append('aaa', 'main');
50265026
});
@@ -5071,7 +5071,7 @@ describe.only('DomLayout', () => {
50715071
await editor.execCommand('hide', { componentId: 'aaa' });
50725072
expect(container.innerHTML).to.equal('<jw-editor></jw-editor>');
50735073
});
5074-
it('should show a component', async () => {
5074+
it.only('should show a component', async () => {
50755075
await editor.execBatch(() => {
50765076
return editor.plugins.get(Layout).append('aaa', 'main');
50775077
});

packages/plugin-fullsreen/src/FullsreenButtonDomObjectRenderer.ts

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -43,9 +43,6 @@ export class FullsreenButtonDomObjectRenderer extends NodeRenderer<DomObject> {
4343
fullscreenPlugin.isFullscreen = true;
4444
document.body.classList.add('jw-fullscreen');
4545
element.classList.add('jw-fullscreen');
46-
domLayoutEngine.redraw([
47-
...domLayoutEngine.components.get('FullscreenButton'),
48-
]);
4946
window.dispatchEvent(new CustomEvent('resize'));
5047
return;
5148
}
@@ -54,7 +51,6 @@ export class FullsreenButtonDomObjectRenderer extends NodeRenderer<DomObject> {
5451
if (fullscreenPlugin.isFullscreen) {
5552
fullscreenPlugin.isFullscreen = false;
5653
document.body.classList.remove('jw-fullscreen');
57-
domLayoutEngine.redraw([...domLayoutEngine.components.get('FullscreenButton')]);
5854
window.dispatchEvent(new CustomEvent('resize'));
5955
}
6056
};

packages/plugin-html/src/HtmlDomRenderingEngine.ts

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,6 @@ import { RenderingEngine } from '../../plugin-renderer/src/RenderingEngine';
22
import { DefaultHtmlDomRenderer } from './DefaultHtmlDomRenderer';
33
import { DefaultHtmlDomModifierRenderer } from './DefaultHtmlDomModifierRenderer';
44
import { VNode } from '../../core/src/VNodes/VNode';
5-
import { Renderer } from '../../plugin-renderer/src/Renderer';
6-
import { DomObjectRenderingEngine } from '../../plugin-renderer-dom-object/src/DomObjectRenderingEngine';
75

86
export class HtmlDomRenderingEngine extends RenderingEngine<Node[]> {
97
static id = 'dom/html';
@@ -18,9 +16,6 @@ export class HtmlDomRenderingEngine extends RenderingEngine<Node[]> {
1816
async render(node: VNode): Promise<Node[]>;
1917
async render(nodes: VNode[]): Promise<Node[][]>;
2018
async render(nodes: VNode | VNode[]): Promise<Node[][] | Node[]> {
21-
const renderer = this.editor.plugins.get(Renderer);
22-
const objectEngine = renderer.engines['dom/object'] as DomObjectRenderingEngine;
23-
objectEngine.clear();
2419
if (nodes instanceof Array) {
2520
return super.render(nodes);
2621
} else {

packages/plugin-layout/src/ZoneNode.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,8 @@ export class ZoneNode extends ContainerNode {
4343
_removeAtIndex(index: number): void {
4444
const child = this.childVNodes[index];
4545
super._removeAtIndex(index);
46-
delete this.hidden[child.id];
46+
if (this.hidden) {
47+
delete this.hidden[child.id];
48+
}
4749
}
4850
}

packages/plugin-renderer-dom-object/src/DomObjectRenderingEngine.ts

Lines changed: 0 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -222,14 +222,10 @@ export type DomObject = DomObjectElement | DomObjectFragment | DomObjectText | D
222222

223223
type RenderingBatchUnit = [VNode, Modifier[], NodeRenderer<DomObject>];
224224

225-
let modifierId = 0;
226225
export class DomObjectRenderingEngine extends RenderingEngine<DomObject> {
227226
static readonly id: RenderingIdentifier = 'dom/object';
228227
static readonly defaultRenderer = DefaultDomObjectRenderer;
229228
static readonly defaultModifierRenderer = DefaultDomObjectModifierRenderer;
230-
private readonly cachedIsSameAsModifier: Record<string, boolean> = {};
231-
private readonly cachedIsSameAsModifierIds: Record<number, string[]> = {};
232-
private readonly cachedModifierId = new Map<Modifier | void, number>();
233229

234230
/**
235231
* Render the attributes of the given VNode onto the given DOM Element.
@@ -523,62 +519,4 @@ export class DomObjectRenderingEngine extends RenderingEngine<DomObject> {
523519
this.locations.set(domObject, [node]);
524520
}
525521
}
526-
private _modifierIsSameAs(modifierA: Modifier | void, modifierB: Modifier | void): boolean {
527-
if (modifierA === modifierB) {
528-
return true;
529-
}
530-
let idA = modifierA ? this.cachedModifierId.get(modifierA) : 'null';
531-
if (!idA) {
532-
idA = ++modifierId;
533-
this.cachedModifierId.set(modifierA, idA);
534-
}
535-
let idB = modifierB ? this.cachedModifierId.get(modifierB) : 'null';
536-
if (!idB) {
537-
idB = ++modifierId;
538-
this.cachedModifierId.set(modifierB, idB);
539-
}
540-
const key = idA + '-' + idB;
541-
if (key in this.cachedIsSameAsModifier) {
542-
return this.cachedIsSameAsModifier[key];
543-
}
544-
const reverseKey = idB + '-' + idA;
545-
if (reverseKey in this.cachedIsSameAsModifier) {
546-
return this.cachedIsSameAsModifier[reverseKey];
547-
}
548-
const isSame =
549-
(!modifierA || modifierA.isSameAs(modifierB)) &&
550-
(!modifierB || modifierB.isSameAs(modifierA));
551-
this.cachedIsSameAsModifier[key] = isSame;
552-
if (!this.cachedIsSameAsModifierIds[idA]) {
553-
this.cachedIsSameAsModifierIds[idA] = [key];
554-
} else {
555-
this.cachedIsSameAsModifierIds[idA].push(key);
556-
}
557-
if (!this.cachedIsSameAsModifierIds[idB]) {
558-
this.cachedIsSameAsModifierIds[idB] = [key];
559-
} else {
560-
this.cachedIsSameAsModifierIds[idB].push(key);
561-
}
562-
return this.cachedIsSameAsModifier[key];
563-
}
564-
/**
565-
* @override
566-
*/
567-
invalidateRendererCache(objects: Set<VNode | Modifier>): void {
568-
super.invalidateRendererCache(objects);
569-
for (const object of objects) {
570-
if (object instanceof Modifier) {
571-
const id = this.cachedModifierId.get(object);
572-
if (id) {
573-
const keys = this.cachedIsSameAsModifierIds[id];
574-
if (keys) {
575-
for (const key in keys) {
576-
delete this.cachedIsSameAsModifier[key];
577-
}
578-
delete this.cachedIsSameAsModifierIds[id];
579-
}
580-
}
581-
}
582-
}
583-
}
584522
}

0 commit comments

Comments
 (0)