-
Notifications
You must be signed in to change notification settings - Fork 77
/
ListViewElement.ts
129 lines (110 loc) · 4.83 KB
/
ListViewElement.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
import { ListView, ItemEventData, ItemsSource, View } from '@nativescript/core'
import TemplateElement from '../svelte/TemplateElement';
import { createElement, DocumentNode, logger as log, registerElement, ViewNode } from '../basicdom';
import NativeViewElementNode from './NativeViewElementNode';
export class SvelteKeyedTemplate {
_key: string;
_templateEl: TemplateElement;
constructor(key: string, templateEl: TemplateElement) {
this._key = key;
this._templateEl = templateEl;
}
get component() {
return this._templateEl.component;
}
get key() {
return this._key
}
createView(): View {
//create a proxy element to eventually contain our item (once we have one to render)
//TODO is StackLayout the best choice here?
log.debug(() => `creating view for key ${this.key}`)
let wrapper = createElement('StackLayout', this._templateEl.ownerDocument) as NativeViewElementNode<View>;
wrapper.setStyle("padding", 0)
wrapper.setStyle("margin", 0)
let nativeEl = wrapper.nativeView;
(nativeEl as any).__SvelteComponentBuilder__ = (props: any) => {
let instance = new this.component({
target: wrapper,
props: props
});
(nativeEl as any).__SvelteComponent__ = instance;
}
return nativeEl;
}
}
export default class ListViewElement extends NativeViewElementNode<ListView> {
constructor() {
super("ListView", ListView);
this.nativeView.on(ListView.itemLoadingEvent, (args) => { this.updateListItem(args as ItemEventData) });
}
updateListItem(args: ItemEventData) {
let item;
let listView = this.nativeView;
let items = listView.items;
if (args.index >= items.length) {
log.error(() => `Got request for item at index that didn't exist ${args.index}`)
return;
}
if ((items as ItemsSource).getItem) {
item = (items as ItemsSource).getItem(args.index);
} else {
item = (items as any)[args.index]
}
if (!args.view || !(args.view as any).__SvelteComponent__) {
let component;
if (args.view && (args.view as any).__SvelteComponentBuilder__) {
log.debug(() => `instantiating component in keyed view item at ${args.index}`);
//now we have an item, we can create and mount this component
(args.view as any).__SvelteComponentBuilder__({ item });
(args.view as any).__SvelteComponentBuilder__ = null; //free the memory
return;
}
log.debug(() => `creating default view for item at ${args.index}`)
if (typeof listView.itemTemplates == "object") {
component = listView.itemTemplates.filter(x => x.key == "default").map(x => (x as SvelteKeyedTemplate).component)[0]
}
if (!component) {
log.error(() => `Couldn't determine component to use for item at ${args.index}`);
return;
}
let wrapper = createElement('ProxyViewContainer', this.ownerDocument) as NativeViewElementNode<View>;
let componentInstance = new component({
target: wrapper,
props: {
item
}
});
let nativeEl = wrapper.nativeView;
(nativeEl as any).__SvelteComponent__ = componentInstance;
args.view = nativeEl;
} else {
let componentInstance: SvelteComponent = (args.view as any).__SvelteComponent__
log.debug(() => `updating view for ${args.index} which is a ${args.view}`)
componentInstance.$set({ item })
}
}
onInsertedChild(childNode: ViewNode, index: number) {
super.onInsertedChild(childNode, index);
if (childNode instanceof TemplateElement) {
let key = childNode.getAttribute('key') || "default"
log.debug(() => `Adding template for key ${key}`);
if (!this.nativeView.itemTemplates || typeof this.nativeView.itemTemplates == "string") {
this.nativeView.itemTemplates = []
}
this.nativeView.itemTemplates.push(new SvelteKeyedTemplate(key, childNode))
}
}
onRemovedChild(childNode: ViewNode) {
super.onRemovedChild(childNode);
if (childNode instanceof TemplateElement) {
let key = childNode.getAttribute('key') || "default"
if (this.nativeView.itemTemplates && typeof this.nativeView.itemTemplates != "string") {
this.nativeView.itemTemplates = this.nativeView.itemTemplates.filter(t => t.key != key);
}
}
}
static register() {
registerElement("ListView", () => new ListViewElement())
}
}