Skip to content

Commit a29da2d

Browse files
committed
refactor(renderer): keep internal sibling queue for views
1 parent e2e4f5a commit a29da2d

File tree

3 files changed

+69
-38
lines changed

3 files changed

+69
-38
lines changed

nativescript-angular/element-registry.ts

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,9 @@ export interface ViewExtensions {
88
nodeType: number;
99
nodeName: string;
1010
templateParent: NgView;
11+
previousSibling: NgElement;
12+
nextSibling: NgElement;
13+
lastChild: NgElement;
1114
ngCssClasses: Map<string, boolean>;
1215
meta: ViewClassMeta;
1316
}
@@ -22,6 +25,9 @@ export abstract class InvisibleNode extends View implements ViewExtensions {
2225
nodeType: number;
2326
nodeName: string;
2427
ngCssClasses: Map<string, boolean>;
28+
previousSibling: NgElement;
29+
nextSibling: NgElement;
30+
lastChild: NgElement;
2531

2632
constructor() {
2733
super();
@@ -42,7 +48,7 @@ export class CommentNode extends InvisibleNode {
4248
super();
4349

4450
this.meta = {
45-
skipAddToDom: false,
51+
skipAddToDom: true,
4652
};
4753
this.id = CommentNode.id.toString();
4854
CommentNode.id += 1;
@@ -67,7 +73,7 @@ const getClassName = instance => instance.constructor.name;
6773

6874
export interface ViewClassMeta {
6975
skipAddToDom?: boolean;
70-
insertChild?: (parent: NgView, child: NgView, atIndex: number) => void;
76+
insertChild?: (parent: NgView, child: NgView, atIndex?: number) => void;
7177
removeChild?: (parent: NgView, child: NgView) => void;
7278
}
7379

nativescript-angular/renderer.ts

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ import { profile } from "tns-core-modules/profiling";
1313
import { APP_ROOT_VIEW, DEVICE, getRootPage } from "./platform-providers";
1414
import { isBlank } from "./lang-facade";
1515
import { ViewUtil } from "./view-util";
16-
import { NgView, InvisibleNode } from "./element-registry";
16+
import { NgView, NgElement, InvisibleNode } from "./element-registry";
1717
import { rendererLog as traceLog } from "./trace";
1818

1919
// CONTENT_ATTR not exported from NativeScript_renderer - we need it for styles application.
@@ -91,9 +91,9 @@ export class NativeScriptRenderer extends Renderer2 {
9191
}
9292

9393
@profile
94-
insertBefore(parent: NgView, newChild: NgView, refChildIndex: number): void {
94+
insertBefore(parent: NgView, newChild: NgView, refChild: NgElement): void {
9595
traceLog(`NativeScriptRenderer.insertBefore child: ${newChild} parent: ${parent}`);
96-
this.viewUtil.insertChild(parent, newChild, refChildIndex);
96+
this.viewUtil.insertChild(parent, newChild, refChild);
9797
}
9898

9999
@profile
@@ -115,9 +115,9 @@ export class NativeScriptRenderer extends Renderer2 {
115115
}
116116

117117
@profile
118-
nextSibling(node: NgView): number {
118+
nextSibling(node: NgView): NgElement {
119119
traceLog(`NativeScriptRenderer.nextSibling ${node}`);
120-
return this.viewUtil.nextSiblingIndex(node);
120+
return node.nextSibling;
121121
}
122122

123123
@profile

nativescript-angular/view-util.ts

Lines changed: 56 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,8 @@ import {
1919
import { platformNames, Device } from "tns-core-modules/platform";
2020
import { rendererLog as traceLog } from "./trace";
2121

22-
const XML_ATTRIBUTES = Object.freeze(["style", "rows", "columns", "fontAttributes"]);
2322
const ELEMENT_NODE_TYPE = 1;
23+
const XML_ATTRIBUTES = Object.freeze(["style", "rows", "columns", "fontAttributes"]);
2424
const whiteSpaceSplitter = /\s+/;
2525

2626
export type ViewExtensions = ViewExtensions;
@@ -53,37 +53,65 @@ export class ViewUtil {
5353
this.isAndroid = device.os === platformNames.android;
5454
}
5555

56-
public insertChild(parent: any, child: NgElement, atIndex: number = -1) {
56+
public insertChild(parent: NgView, child: NgElement, refChild?: NgElement) {
57+
// handle invisible nodes..
5758
if (child instanceof InvisibleNode) {
5859
child.templateParent = parent;
5960
}
6061

62+
// add to queue
63+
if (!parent) {
64+
return;
65+
}
66+
const previousView = refChild || parent.lastChild;
67+
if (previousView) {
68+
previousView.nextSibling = child;
69+
child.previousSibling = previousView;
70+
} else {
71+
parent.lastChild = child;
72+
}
73+
74+
// create actual view
6175
if (!parent || isDetachedElement(child)) {
6276
return;
6377
}
6478

6579
if (parent.meta && parent.meta.insertChild) {
66-
parent.meta.insertChild(parent, child, atIndex);
80+
parent.meta.insertChild(parent, child);
6781
} else if (isLayout(parent)) {
82+
// remove child if already exists
6883
if (child.parent === parent) {
69-
const index = (<LayoutBase>parent).getChildIndex(child);
84+
const index = parent.getChildIndex(child);
7085
if (index !== -1) {
7186
parent.removeChild(child);
7287
}
7388
}
74-
if (atIndex !== -1) {
89+
90+
// insert child
91+
if (refChild) {
92+
const atIndex = parent.getChildIndex(refChild);
7593
parent.insertChild(child, atIndex);
7694
} else {
7795
parent.addChild(child);
7896
}
7997
} else if (isContentView(parent)) {
8098
parent.content = child;
81-
} else if (parent && parent._addChildFromBuilder) {
82-
parent._addChildFromBuilder(child.nodeName, child);
99+
} else if (parent && (<any>parent)._addChildFromBuilder) {
100+
(<any>parent)._addChildFromBuilder(child.nodeName, child);
83101
}
84102
}
85103

86-
public removeChild(parent: any, child: NgElement) {
104+
public removeChild(parent: NgView, child: NgElement) {
105+
// remove from qeueue
106+
if (child.previousSibling) {
107+
child.previousSibling.nextSibling = child.nextSibling;
108+
}
109+
110+
if (child.nextSibling) {
111+
child.nextSibling.previousSibling = child.previousSibling;
112+
}
113+
114+
// actual desctructuring
87115
if (!parent || isDetachedElement(child)) {
88116
return;
89117
}
@@ -131,9 +159,7 @@ export class ViewUtil {
131159

132160
// we're setting the node type of the view
133161
// to 'element' because of checks done in the
134-
// dom animation engine:
135-
// tslint:disable-next-line:max-line-length
136-
// https://github.com/angular/angular/blob/master/packages/animations/browser/src/render/dom_animation_engine.ts#L70-L81
162+
// dom animation engine
137163
view.nodeType = ELEMENT_NODE_TYPE;
138164

139165
return view;
@@ -170,32 +196,31 @@ export class ViewUtil {
170196

171197
// finds the node in the parent's views and returns the next index
172198
// returns -1 if the node has no parent or next sibling
173-
public nextSiblingIndex(node: NgView): number {
174-
const parent = node.parent;
175-
if (!parent) {
176-
return -1;
177-
}
178-
179-
let index = 0;
180-
let found = false;
181-
parent.eachChild(child => {
182-
if (child === node) {
183-
found = true;
184-
}
185-
186-
index += 1;
187-
return !found;
188-
});
189-
190-
return found ? index : -1;
191-
}
199+
// public nextSiblingIndex(node: NgView): number {
200+
// const parent = node.parent;
201+
// if (!parent) {
202+
// return -1;
203+
// }
204+
205+
// let index = 0;
206+
// let found = false;
207+
// parent.eachChild(child => {
208+
// if (child === node) {
209+
// found = true;
210+
// }
211+
212+
// index += 1;
213+
// return !found;
214+
// });
215+
216+
// return found ? index : -1;
217+
// }
192218

193219
private runsIn(platform: string): boolean {
194220
return (platform === "ios" && this.isIos) ||
195221
(platform === "android" && this.isAndroid);
196222
}
197223

198-
199224
private setPropertyInternal(view: NgView, attributeName: string, value: any): void {
200225
traceLog(`Setting attribute: ${attributeName}=${value} to ${view}`);
201226

0 commit comments

Comments
 (0)