uicore-ts 1.1.101 → 1.1.102
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/compiledScripts/UICore.js +3 -0
- package/compiledScripts/UICore.js.map +2 -2
- package/compiledScripts/UITableView.d.ts +33 -0
- package/compiledScripts/UITableView.js +213 -25
- package/compiledScripts/UITableView.js.map +3 -3
- package/compiledScripts/UITextView.d.ts +49 -39
- package/compiledScripts/UITextView.js +131 -132
- package/compiledScripts/UITextView.js.map +2 -2
- package/compiledScripts/UIView.d.ts +21 -1
- package/compiledScripts/UIView.js +66 -8
- package/compiledScripts/UIView.js.map +2 -2
- package/package.json +1 -1
- package/scripts/UICore.ts +5 -0
- package/scripts/UITableView.ts +328 -93
- package/scripts/UITextView.ts +266 -376
- package/scripts/UIView.ts +131 -7
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "uicore-ts",
|
|
3
|
-
"version": "1.1.
|
|
3
|
+
"version": "1.1.102",
|
|
4
4
|
"description": "UICore is a library to build native-like user interfaces using pure Typescript. No HTML is needed at all. Components are described as TS classes and all user interactions are handled explicitly. This library is strongly inspired by the UIKit framework that is used in IOS. In addition, UICore has tools to handle URL based routing, array sorting and filtering and adds a number of other utilities for convenience.",
|
|
5
5
|
"main": "compiledScripts/index.js",
|
|
6
6
|
"types": "compiledScripts/index.d.ts",
|
package/scripts/UICore.ts
CHANGED
|
@@ -76,6 +76,11 @@ export class UICore extends UIObject {
|
|
|
76
76
|
|
|
77
77
|
const windowDidResize = () => {
|
|
78
78
|
|
|
79
|
+
this.rootViewController.view.forEachViewInSubtree((view) => {
|
|
80
|
+
|
|
81
|
+
view._frameCache = undefined
|
|
82
|
+
|
|
83
|
+
})
|
|
79
84
|
// Doing layout two times to prevent page scrollbars from confusing the layout
|
|
80
85
|
this.rootViewController.view.setNeedsLayout()
|
|
81
86
|
this.rootViewController._triggerLayoutViewSubviews()
|
package/scripts/UITableView.ts
CHANGED
|
@@ -60,6 +60,12 @@ export class UITableView extends UINativeScrollView {
|
|
|
60
60
|
|
|
61
61
|
override animationDuration = 0.25
|
|
62
62
|
|
|
63
|
+
// Viewport scrolling properties
|
|
64
|
+
private _useViewportScrolling = NO
|
|
65
|
+
private _windowScrollHandler?: () => void
|
|
66
|
+
private _resizeHandler?: () => void
|
|
67
|
+
private _intersectionObserver?: IntersectionObserver
|
|
68
|
+
|
|
63
69
|
|
|
64
70
|
constructor(elementID?: string) {
|
|
65
71
|
|
|
@@ -72,6 +78,260 @@ export class UITableView extends UINativeScrollView {
|
|
|
72
78
|
|
|
73
79
|
this.scrollsX = NO
|
|
74
80
|
|
|
81
|
+
// Automatically detect if we should use viewport scrolling
|
|
82
|
+
this._autoDetectScrollMode()
|
|
83
|
+
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
|
|
87
|
+
/**
|
|
88
|
+
* Automatically detect if this table should use viewport scrolling
|
|
89
|
+
* If the table's bounds height is >= the total content height,
|
|
90
|
+
* then it doesn't need internal scrolling and should use viewport scrolling
|
|
91
|
+
*/
|
|
92
|
+
private _autoDetectScrollMode() {
|
|
93
|
+
// Run detection after the view is added to the tree and layout has occurred
|
|
94
|
+
const checkScrollMode = () => {
|
|
95
|
+
if (!this.isMemberOfViewTree) {
|
|
96
|
+
return
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
this._calculateAllPositions()
|
|
100
|
+
|
|
101
|
+
const totalContentHeight = this._rowPositions.length > 0
|
|
102
|
+
? this._rowPositions[this._rowPositions.length - 1].bottomY
|
|
103
|
+
: 0
|
|
104
|
+
|
|
105
|
+
const tableBoundsHeight = this.bounds.height
|
|
106
|
+
|
|
107
|
+
// If the table's height can contain all content, use viewport scrolling
|
|
108
|
+
if (tableBoundsHeight >= totalContentHeight) {
|
|
109
|
+
this.enableViewportBasedVirtualScrolling()
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
// Check after first layout
|
|
114
|
+
UIView.runFunctionBeforeNextFrame(checkScrollMode)
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
|
|
118
|
+
/**
|
|
119
|
+
* Enable viewport-based virtual scrolling for full-height tables
|
|
120
|
+
* This allows the table to be part of the page flow while still
|
|
121
|
+
* benefiting from virtual scrolling performance
|
|
122
|
+
*/
|
|
123
|
+
enableViewportBasedVirtualScrolling() {
|
|
124
|
+
if (this._useViewportScrolling) {
|
|
125
|
+
return // Already enabled
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
this._useViewportScrolling = YES
|
|
129
|
+
this.scrollsX = NO
|
|
130
|
+
this.scrollsY = NO
|
|
131
|
+
|
|
132
|
+
// No style changes - respect the absolute positioning system
|
|
133
|
+
|
|
134
|
+
this._setupViewportScrollListeners()
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
|
|
138
|
+
/**
|
|
139
|
+
* Disable viewport scrolling and return to normal scroll behavior
|
|
140
|
+
*/
|
|
141
|
+
disableViewportBasedVirtualScrolling() {
|
|
142
|
+
if (!this._useViewportScrolling) {
|
|
143
|
+
return
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
this._useViewportScrolling = NO
|
|
147
|
+
this.scrollsY = YES
|
|
148
|
+
|
|
149
|
+
this._cleanupViewportScrollListeners()
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
|
|
153
|
+
private _setupViewportScrollListeners() {
|
|
154
|
+
this._windowScrollHandler = () => {
|
|
155
|
+
this._scheduleDrawVisibleRowsInViewport()
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
this._resizeHandler = () => {
|
|
159
|
+
// Invalidate all row positions on resize as widths may have changed
|
|
160
|
+
this._rowPositions.forEach(pos => pos.isValid = NO)
|
|
161
|
+
this._highestValidRowPositionIndex = -1
|
|
162
|
+
this._scheduleDrawVisibleRowsInViewport()
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
window.addEventListener('scroll', this._windowScrollHandler, { passive: true })
|
|
166
|
+
window.addEventListener('resize', this._resizeHandler, { passive: true })
|
|
167
|
+
|
|
168
|
+
// Use IntersectionObserver to detect when table enters/exits viewport
|
|
169
|
+
this._intersectionObserver = new IntersectionObserver(
|
|
170
|
+
(entries) => {
|
|
171
|
+
entries.forEach(entry => {
|
|
172
|
+
if (entry.isIntersecting) {
|
|
173
|
+
this._scheduleDrawVisibleRowsInViewport()
|
|
174
|
+
}
|
|
175
|
+
})
|
|
176
|
+
},
|
|
177
|
+
{
|
|
178
|
+
root: null,
|
|
179
|
+
rootMargin: '100% 0px', // Load rows 100% viewport height before/after
|
|
180
|
+
threshold: 0
|
|
181
|
+
}
|
|
182
|
+
)
|
|
183
|
+
|
|
184
|
+
this._intersectionObserver.observe(this.viewHTMLElement)
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
|
|
188
|
+
private _cleanupViewportScrollListeners() {
|
|
189
|
+
if (this._windowScrollHandler) {
|
|
190
|
+
window.removeEventListener('scroll', this._windowScrollHandler)
|
|
191
|
+
this._windowScrollHandler = undefined
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
if (this._resizeHandler) {
|
|
195
|
+
window.removeEventListener('resize', this._resizeHandler)
|
|
196
|
+
this._resizeHandler = undefined
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
if (this._intersectionObserver) {
|
|
200
|
+
this._intersectionObserver.disconnect()
|
|
201
|
+
this._intersectionObserver = undefined
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
|
|
206
|
+
private _scheduleDrawVisibleRowsInViewport() {
|
|
207
|
+
if (!this._isDrawVisibleRowsScheduled) {
|
|
208
|
+
this._isDrawVisibleRowsScheduled = YES
|
|
209
|
+
|
|
210
|
+
UIView.runFunctionBeforeNextFrame(() => {
|
|
211
|
+
this._calculateAllPositions()
|
|
212
|
+
this._drawVisibleRowsInViewport()
|
|
213
|
+
this.setNeedsLayout()
|
|
214
|
+
this._isDrawVisibleRowsScheduled = NO
|
|
215
|
+
})
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
|
|
220
|
+
/**
|
|
221
|
+
* Calculate which rows are visible in the browser viewport
|
|
222
|
+
* rather than in the scrollview's content area
|
|
223
|
+
*/
|
|
224
|
+
indexesForVisibleRowsInViewport(paddingRatio = 0.5): number[] {
|
|
225
|
+
const tableRect = this.viewHTMLElement.getBoundingClientRect()
|
|
226
|
+
const viewportHeight = window.innerHeight
|
|
227
|
+
const pageScale = UIView.pageScale
|
|
228
|
+
|
|
229
|
+
// Calculate which part of the table is visible in viewport
|
|
230
|
+
// Account for page scale when converting from screen to content coordinates
|
|
231
|
+
const visibleTop = Math.max(0, -tableRect.top / pageScale)
|
|
232
|
+
const visibleBottom = Math.min(tableRect.height / pageScale, (viewportHeight - tableRect.top) / pageScale)
|
|
233
|
+
|
|
234
|
+
// Add padding to render rows slightly before they enter viewport
|
|
235
|
+
const paddingPx = (viewportHeight / pageScale) * paddingRatio
|
|
236
|
+
const firstVisibleY = Math.max(0, visibleTop - paddingPx)
|
|
237
|
+
const lastVisibleY = Math.min(tableRect.height / pageScale, visibleBottom + paddingPx)
|
|
238
|
+
|
|
239
|
+
const numberOfRows = this.numberOfRows()
|
|
240
|
+
|
|
241
|
+
if (this.allRowsHaveEqualHeight) {
|
|
242
|
+
const rowHeight = this.heightForRowWithIndex(0)
|
|
243
|
+
|
|
244
|
+
let firstIndex = Math.floor(firstVisibleY / rowHeight)
|
|
245
|
+
let lastIndex = Math.floor(lastVisibleY / rowHeight)
|
|
246
|
+
|
|
247
|
+
firstIndex = Math.max(firstIndex, 0)
|
|
248
|
+
lastIndex = Math.min(lastIndex, numberOfRows - 1)
|
|
249
|
+
|
|
250
|
+
const result = []
|
|
251
|
+
for (let i = firstIndex; i <= lastIndex; i++) {
|
|
252
|
+
result.push(i)
|
|
253
|
+
}
|
|
254
|
+
return result
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
// Variable height rows
|
|
258
|
+
this._calculateAllPositions()
|
|
259
|
+
|
|
260
|
+
const rowPositions = this._rowPositions
|
|
261
|
+
const result = []
|
|
262
|
+
|
|
263
|
+
for (let i = 0; i < numberOfRows; i++) {
|
|
264
|
+
const position = rowPositions[i]
|
|
265
|
+
if (!position) break
|
|
266
|
+
|
|
267
|
+
const rowTop = position.topY
|
|
268
|
+
const rowBottom = position.bottomY
|
|
269
|
+
|
|
270
|
+
// Check if row intersects with visible area
|
|
271
|
+
if (rowBottom >= firstVisibleY && rowTop <= lastVisibleY) {
|
|
272
|
+
result.push(i)
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
// Early exit if we've passed the visible area
|
|
276
|
+
if (rowTop > lastVisibleY) {
|
|
277
|
+
break
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
return result
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
|
|
285
|
+
/**
|
|
286
|
+
* Draw visible rows based on viewport position
|
|
287
|
+
*/
|
|
288
|
+
private _drawVisibleRowsInViewport() {
|
|
289
|
+
if (!this.isMemberOfViewTree) {
|
|
290
|
+
return
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
const visibleIndexes = this.indexesForVisibleRowsInViewport()
|
|
294
|
+
|
|
295
|
+
const minIndex = visibleIndexes[0]
|
|
296
|
+
const maxIndex = visibleIndexes[visibleIndexes.length - 1]
|
|
297
|
+
|
|
298
|
+
const removedViews: UITableViewRowView[] = []
|
|
299
|
+
|
|
300
|
+
const visibleRows: UITableViewRowView[] = []
|
|
301
|
+
this._visibleRows.forEach((row) => {
|
|
302
|
+
if (IS_DEFINED(row._UITableViewRowIndex) &&
|
|
303
|
+
(row._UITableViewRowIndex < minIndex || row._UITableViewRowIndex > maxIndex)) {
|
|
304
|
+
|
|
305
|
+
this._persistedData[row._UITableViewRowIndex] = this.persistenceDataItemForRowWithIndex(
|
|
306
|
+
row._UITableViewRowIndex,
|
|
307
|
+
row
|
|
308
|
+
)
|
|
309
|
+
|
|
310
|
+
this._removedReusableViews[row._UITableViewReusabilityIdentifier].push(row)
|
|
311
|
+
removedViews.push(row)
|
|
312
|
+
}
|
|
313
|
+
else {
|
|
314
|
+
visibleRows.push(row)
|
|
315
|
+
}
|
|
316
|
+
})
|
|
317
|
+
this._visibleRows = visibleRows
|
|
318
|
+
|
|
319
|
+
visibleIndexes.forEach((rowIndex: number) => {
|
|
320
|
+
if (this.isRowWithIndexVisible(rowIndex)) {
|
|
321
|
+
return
|
|
322
|
+
}
|
|
323
|
+
const view: UITableViewRowView = this.viewForRowWithIndex(rowIndex)
|
|
324
|
+
this._firstLayoutVisibleRows.push(view)
|
|
325
|
+
this._visibleRows.push(view)
|
|
326
|
+
this.addSubview(view)
|
|
327
|
+
})
|
|
328
|
+
|
|
329
|
+
for (let i = 0; i < removedViews.length; i++) {
|
|
330
|
+
const view = removedViews[i]
|
|
331
|
+
if (this._visibleRows.indexOf(view) == -1) {
|
|
332
|
+
view.removeFromSuperview()
|
|
333
|
+
}
|
|
334
|
+
}
|
|
75
335
|
}
|
|
76
336
|
|
|
77
337
|
|
|
@@ -128,8 +388,8 @@ export class UITableView extends UINativeScrollView {
|
|
|
128
388
|
|
|
129
389
|
|
|
130
390
|
highlightRowAsNew(row: UIView) {
|
|
131
|
-
|
|
132
|
-
|
|
391
|
+
|
|
392
|
+
|
|
133
393
|
}
|
|
134
394
|
|
|
135
395
|
|
|
@@ -141,14 +401,6 @@ export class UITableView extends UINativeScrollView {
|
|
|
141
401
|
|
|
142
402
|
this._highestValidRowPositionIndex = Math.min(this._highestValidRowPositionIndex, index - 1)
|
|
143
403
|
|
|
144
|
-
// if (index == 0) {
|
|
145
|
-
|
|
146
|
-
// this._highestValidRowPositionIndex = 0;
|
|
147
|
-
|
|
148
|
-
// this._rowPositions = [];
|
|
149
|
-
|
|
150
|
-
// }
|
|
151
|
-
|
|
152
404
|
this._needsDrawingOfVisibleRowsBeforeLayout = YES
|
|
153
405
|
|
|
154
406
|
this._shouldAnimateNextLayout = animateChange
|
|
@@ -162,7 +414,7 @@ export class UITableView extends UINativeScrollView {
|
|
|
162
414
|
|
|
163
415
|
_calculatePositionsUntilIndex(maxIndex: number) {
|
|
164
416
|
|
|
165
|
-
|
|
417
|
+
let validPositionObject = this._rowPositions[this._highestValidRowPositionIndex]
|
|
166
418
|
if (!IS(validPositionObject)) {
|
|
167
419
|
validPositionObject = {
|
|
168
420
|
bottomY: 0,
|
|
@@ -171,7 +423,7 @@ export class UITableView extends UINativeScrollView {
|
|
|
171
423
|
}
|
|
172
424
|
}
|
|
173
425
|
|
|
174
|
-
|
|
426
|
+
let previousBottomY = validPositionObject.bottomY
|
|
175
427
|
|
|
176
428
|
if (!this._rowPositions.length) {
|
|
177
429
|
|
|
@@ -179,9 +431,9 @@ export class UITableView extends UINativeScrollView {
|
|
|
179
431
|
|
|
180
432
|
}
|
|
181
433
|
|
|
182
|
-
for (
|
|
434
|
+
for (let i = this._highestValidRowPositionIndex + 1; i <= maxIndex; i++) {
|
|
183
435
|
|
|
184
|
-
|
|
436
|
+
let height: number
|
|
185
437
|
|
|
186
438
|
const rowPositionObject = this._rowPositions[i]
|
|
187
439
|
|
|
@@ -219,6 +471,12 @@ export class UITableView extends UINativeScrollView {
|
|
|
219
471
|
|
|
220
472
|
indexesForVisibleRows(paddingRatio = 0.5): number[] {
|
|
221
473
|
|
|
474
|
+
// If using viewport scrolling, delegate to viewport method
|
|
475
|
+
if (this._useViewportScrolling) {
|
|
476
|
+
return this.indexesForVisibleRowsInViewport(paddingRatio)
|
|
477
|
+
}
|
|
478
|
+
|
|
479
|
+
// Original scroll-based logic
|
|
222
480
|
const firstVisibleY = this.contentOffset.y - this.bounds.height * paddingRatio
|
|
223
481
|
const lastVisibleY = firstVisibleY + this.bounds.height * (1 + paddingRatio)
|
|
224
482
|
|
|
@@ -228,8 +486,8 @@ export class UITableView extends UINativeScrollView {
|
|
|
228
486
|
|
|
229
487
|
const rowHeight = this.heightForRowWithIndex(0)
|
|
230
488
|
|
|
231
|
-
|
|
232
|
-
|
|
489
|
+
let firstIndex = firstVisibleY / rowHeight
|
|
490
|
+
let lastIndex = lastVisibleY / rowHeight
|
|
233
491
|
|
|
234
492
|
firstIndex = Math.trunc(firstIndex)
|
|
235
493
|
lastIndex = Math.trunc(lastIndex) + 1
|
|
@@ -237,23 +495,23 @@ export class UITableView extends UINativeScrollView {
|
|
|
237
495
|
firstIndex = Math.max(firstIndex, 0)
|
|
238
496
|
lastIndex = Math.min(lastIndex, numberOfRows - 1)
|
|
239
497
|
|
|
240
|
-
|
|
241
|
-
for (
|
|
498
|
+
const result = []
|
|
499
|
+
for (let i = firstIndex; i < lastIndex + 1; i++) {
|
|
242
500
|
result.push(i)
|
|
243
501
|
}
|
|
244
502
|
return result
|
|
245
503
|
}
|
|
246
504
|
|
|
247
|
-
|
|
248
|
-
|
|
505
|
+
let accumulatedHeight = 0
|
|
506
|
+
const result = []
|
|
249
507
|
|
|
250
508
|
this._calculateAllPositions()
|
|
251
509
|
|
|
252
510
|
const rowPositions = this._rowPositions
|
|
253
511
|
|
|
254
|
-
for (
|
|
512
|
+
for (let i = 0; i < numberOfRows; i++) {
|
|
255
513
|
|
|
256
|
-
const height = rowPositions[i].bottomY - rowPositions[i].topY
|
|
514
|
+
const height = rowPositions[i].bottomY - rowPositions[i].topY
|
|
257
515
|
|
|
258
516
|
accumulatedHeight = accumulatedHeight + height
|
|
259
517
|
if (accumulatedHeight >= firstVisibleY) {
|
|
@@ -329,8 +587,6 @@ export class UITableView extends UINativeScrollView {
|
|
|
329
587
|
this._visibleRows.forEach((row) => {
|
|
330
588
|
if (IS_DEFINED(row._UITableViewRowIndex) && (row._UITableViewRowIndex < minIndex || row._UITableViewRowIndex > maxIndex)) {
|
|
331
589
|
|
|
332
|
-
//row.removeFromSuperview();
|
|
333
|
-
|
|
334
590
|
this._persistedData[row._UITableViewRowIndex] = this.persistenceDataItemForRowWithIndex(
|
|
335
591
|
row._UITableViewRowIndex,
|
|
336
592
|
row
|
|
@@ -353,7 +609,6 @@ export class UITableView extends UINativeScrollView {
|
|
|
353
609
|
return
|
|
354
610
|
}
|
|
355
611
|
const view: UITableViewRowView = this.viewForRowWithIndex(rowIndex)
|
|
356
|
-
//view._UITableViewRowIndex = rowIndex;
|
|
357
612
|
this._firstLayoutVisibleRows.push(view)
|
|
358
613
|
this._visibleRows.push(view)
|
|
359
614
|
this.addSubview(view)
|
|
@@ -365,22 +620,17 @@ export class UITableView extends UINativeScrollView {
|
|
|
365
620
|
const view = removedViews[i]
|
|
366
621
|
if (this._visibleRows.indexOf(view) == -1) {
|
|
367
622
|
|
|
368
|
-
//this._persistedData[view._UITableViewRowIndex] = this.persistenceDataItemForRowWithIndex(view._UITableViewRowIndex, view);
|
|
369
623
|
view.removeFromSuperview()
|
|
370
624
|
|
|
371
|
-
//this._removedReusableViews[view._UITableViewReusabilityIdentifier].push(view);
|
|
372
|
-
|
|
373
625
|
}
|
|
374
626
|
|
|
375
627
|
}
|
|
376
628
|
|
|
377
|
-
//this.setNeedsLayout();
|
|
378
|
-
|
|
379
629
|
}
|
|
380
630
|
|
|
381
631
|
|
|
382
632
|
visibleRowWithIndex(rowIndex: number | undefined): UIView {
|
|
383
|
-
for (
|
|
633
|
+
for (let i = 0; i < this._visibleRows.length; i++) {
|
|
384
634
|
const row = this._visibleRows[i]
|
|
385
635
|
if (row._UITableViewRowIndex == rowIndex) {
|
|
386
636
|
return row
|
|
@@ -449,13 +699,13 @@ export class UITableView extends UINativeScrollView {
|
|
|
449
699
|
}
|
|
450
700
|
|
|
451
701
|
defaultRowPersistenceDataItem(): any {
|
|
452
|
-
|
|
453
|
-
|
|
702
|
+
|
|
703
|
+
|
|
454
704
|
}
|
|
455
705
|
|
|
456
706
|
persistenceDataItemForRowWithIndex(rowIndex: number, row: UIView): any {
|
|
457
|
-
|
|
458
|
-
|
|
707
|
+
|
|
708
|
+
|
|
459
709
|
}
|
|
460
710
|
|
|
461
711
|
viewForRowWithIndex(rowIndex: number): UITableViewRowView {
|
|
@@ -473,6 +723,11 @@ export class UITableView extends UINativeScrollView {
|
|
|
473
723
|
|
|
474
724
|
super.didScrollToPosition(offsetPosition)
|
|
475
725
|
|
|
726
|
+
// Skip if using viewport scrolling
|
|
727
|
+
if (this._useViewportScrolling) {
|
|
728
|
+
return
|
|
729
|
+
}
|
|
730
|
+
|
|
476
731
|
this.forEachViewInSubtree(function (view: UIView) {
|
|
477
732
|
|
|
478
733
|
view._isPointerValid = NO
|
|
@@ -483,7 +738,7 @@ export class UITableView extends UINativeScrollView {
|
|
|
483
738
|
|
|
484
739
|
this._isDrawVisibleRowsScheduled = YES
|
|
485
740
|
|
|
486
|
-
UIView.runFunctionBeforeNextFrame(
|
|
741
|
+
UIView.runFunctionBeforeNextFrame(() => {
|
|
487
742
|
|
|
488
743
|
this._calculateAllPositions()
|
|
489
744
|
|
|
@@ -493,14 +748,25 @@ export class UITableView extends UINativeScrollView {
|
|
|
493
748
|
|
|
494
749
|
this._isDrawVisibleRowsScheduled = NO
|
|
495
750
|
|
|
496
|
-
}
|
|
751
|
+
})
|
|
497
752
|
|
|
498
753
|
}
|
|
499
754
|
|
|
500
755
|
}
|
|
501
756
|
|
|
502
757
|
override wasAddedToViewTree() {
|
|
758
|
+
super.wasAddedToViewTree()
|
|
503
759
|
this.loadData()
|
|
760
|
+
|
|
761
|
+
// Re-check scroll mode in case CSS was applied after construction
|
|
762
|
+
if (!this._useViewportScrolling) {
|
|
763
|
+
this._autoDetectScrollMode()
|
|
764
|
+
}
|
|
765
|
+
}
|
|
766
|
+
|
|
767
|
+
override wasRemovedFromViewTree() {
|
|
768
|
+
super.wasRemovedFromViewTree()
|
|
769
|
+
this._cleanupViewportScrollListeners()
|
|
504
770
|
}
|
|
505
771
|
|
|
506
772
|
override setFrame(rectangle: UIRectangle, zIndex?: number, performUncheckedLayout?: boolean) {
|
|
@@ -552,8 +818,17 @@ export class UITableView extends UINativeScrollView {
|
|
|
552
818
|
|
|
553
819
|
})
|
|
554
820
|
|
|
555
|
-
|
|
556
|
-
|
|
821
|
+
// For viewport scrolling, the full height view needs to establish the total height
|
|
822
|
+
if (this._useViewportScrolling) {
|
|
823
|
+
this._fullHeightView.hidden = NO
|
|
824
|
+
this._fullHeightView.style.position = 'absolute'
|
|
825
|
+
this._fullHeightView.style.pointerEvents = 'none'
|
|
826
|
+
this._fullHeightView.frame = bounds.rectangleWithHeight((positions.lastElement || nil).bottomY)
|
|
827
|
+
.rectangleWithWidth(1) // Minimal width
|
|
828
|
+
} else {
|
|
829
|
+
this._fullHeightView.frame = bounds.rectangleWithHeight((positions.lastElement || nil).bottomY)
|
|
830
|
+
.rectangleWithWidth(bounds.width * 0.5)
|
|
831
|
+
}
|
|
557
832
|
|
|
558
833
|
this._firstLayoutVisibleRows = []
|
|
559
834
|
|
|
@@ -566,17 +841,15 @@ export class UITableView extends UINativeScrollView {
|
|
|
566
841
|
this.animationDuration,
|
|
567
842
|
0,
|
|
568
843
|
undefined,
|
|
569
|
-
|
|
844
|
+
() => {
|
|
570
845
|
|
|
571
846
|
this._layoutAllRows()
|
|
572
847
|
|
|
573
|
-
}
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
}.bind(this)
|
|
848
|
+
},
|
|
849
|
+
() => {
|
|
850
|
+
|
|
851
|
+
|
|
852
|
+
}
|
|
580
853
|
)
|
|
581
854
|
|
|
582
855
|
}
|
|
@@ -590,9 +863,11 @@ export class UITableView extends UINativeScrollView {
|
|
|
590
863
|
|
|
591
864
|
if (this._needsDrawingOfVisibleRowsBeforeLayout) {
|
|
592
865
|
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
866
|
+
if (this._useViewportScrolling) {
|
|
867
|
+
this._drawVisibleRowsInViewport()
|
|
868
|
+
} else {
|
|
869
|
+
this._drawVisibleRows()
|
|
870
|
+
}
|
|
596
871
|
|
|
597
872
|
this._needsDrawingOfVisibleRowsBeforeLayout = NO
|
|
598
873
|
|
|
@@ -620,11 +895,11 @@ export class UITableView extends UINativeScrollView {
|
|
|
620
895
|
if (previousVisibleRowsLength < this._visibleRows.length) {
|
|
621
896
|
|
|
622
897
|
|
|
623
|
-
UIView.runFunctionBeforeNextFrame(
|
|
898
|
+
UIView.runFunctionBeforeNextFrame(() => {
|
|
624
899
|
|
|
625
900
|
this._animateLayoutAllRows()
|
|
626
901
|
|
|
627
|
-
}
|
|
902
|
+
})
|
|
628
903
|
|
|
629
904
|
}
|
|
630
905
|
else {
|
|
@@ -639,14 +914,6 @@ export class UITableView extends UINativeScrollView {
|
|
|
639
914
|
}
|
|
640
915
|
else {
|
|
641
916
|
|
|
642
|
-
// if (this._needsDrawingOfVisibleRowsBeforeLayout) {
|
|
643
|
-
|
|
644
|
-
// this._drawVisibleRows();
|
|
645
|
-
|
|
646
|
-
// this._needsDrawingOfVisibleRowsBeforeLayout = NO;
|
|
647
|
-
|
|
648
|
-
// }
|
|
649
|
-
|
|
650
917
|
this._calculateAllPositions()
|
|
651
918
|
|
|
652
919
|
this._layoutAllRows()
|
|
@@ -661,7 +928,7 @@ export class UITableView extends UINativeScrollView {
|
|
|
661
928
|
override intrinsicContentHeight(constrainingWidth = 0) {
|
|
662
929
|
|
|
663
930
|
|
|
664
|
-
|
|
931
|
+
let result = 0
|
|
665
932
|
|
|
666
933
|
this._calculateAllPositions()
|
|
667
934
|
|
|
@@ -677,35 +944,3 @@ export class UITableView extends UINativeScrollView {
|
|
|
677
944
|
|
|
678
945
|
|
|
679
946
|
}
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|