@onekeyfe/react-native-native-list 3.0.121 → 3.0.123
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.
|
@@ -51,6 +51,11 @@ import kotlin.math.sqrt
|
|
|
51
51
|
class NativeListView(
|
|
52
52
|
private val reactContext: ThemedReactContext,
|
|
53
53
|
) : LinearLayout(reactContext) {
|
|
54
|
+
private data class VisibleMarketAnchor(
|
|
55
|
+
val key: String,
|
|
56
|
+
val offset: Int,
|
|
57
|
+
)
|
|
58
|
+
|
|
54
59
|
private class ActionAnchorRecord(
|
|
55
60
|
val token: String,
|
|
56
61
|
origin: NativeListActionOrigin,
|
|
@@ -170,6 +175,7 @@ class NativeListView(
|
|
|
170
175
|
private var lastLayoutWidth = -1
|
|
171
176
|
private var lastLayoutHeight = -1
|
|
172
177
|
private var lastLayoutDirection = layoutDirection
|
|
178
|
+
private var lastMarketPaginationAnchorLogAtMs = 0L
|
|
173
179
|
private var disposed = false
|
|
174
180
|
|
|
175
181
|
init {
|
|
@@ -363,6 +369,9 @@ class NativeListView(
|
|
|
363
369
|
}
|
|
364
370
|
return
|
|
365
371
|
}
|
|
372
|
+
val preserveMarketPaginationAnchor = previous?.let {
|
|
373
|
+
isMarketPaginationUpdate(it, next)
|
|
374
|
+
} ?: false
|
|
366
375
|
// Keep the first Market row at its current pixel offset when it is
|
|
367
376
|
// reordered. RecyclerView otherwise follows the previous first key.
|
|
368
377
|
val marketStartOffset = if (
|
|
@@ -390,7 +399,7 @@ class NativeListView(
|
|
|
390
399
|
if (marketStartOffset != null) {
|
|
391
400
|
layoutManager.scrollToPositionWithOffset(0, marketStartOffset)
|
|
392
401
|
}
|
|
393
|
-
relayoutContents()
|
|
402
|
+
relayoutContents(preserveMarketPaginationAnchor)
|
|
394
403
|
performPendingScrollIfNeeded()
|
|
395
404
|
syncSectionIndexToVisibleRows()
|
|
396
405
|
scheduleVisibleEvent()
|
|
@@ -402,6 +411,40 @@ class NativeListView(
|
|
|
402
411
|
updateReordering(next)
|
|
403
412
|
}
|
|
404
413
|
|
|
414
|
+
private fun captureVisibleMarketAnchor(): VisibleMarketAnchor? {
|
|
415
|
+
val position = layoutManager.findFirstVisibleItemPosition()
|
|
416
|
+
if (position == RecyclerView.NO_POSITION) return null
|
|
417
|
+
val item = adapter.itemAt(position) ?: return null
|
|
418
|
+
val view = layoutManager.findViewByPosition(position) ?: return null
|
|
419
|
+
return VisibleMarketAnchor(
|
|
420
|
+
key = item.key,
|
|
421
|
+
offset = layoutManager.getDecoratedTop(view) - recyclerView.paddingTop,
|
|
422
|
+
)
|
|
423
|
+
}
|
|
424
|
+
|
|
425
|
+
private fun isMarketPaginationUpdate(
|
|
426
|
+
previous: NativeListConfig,
|
|
427
|
+
next: NativeListConfig,
|
|
428
|
+
): Boolean {
|
|
429
|
+
if (!previous.loadMore && !next.loadMore) return false
|
|
430
|
+
val previousRows = previous.items.dropLastWhile {
|
|
431
|
+
it.key in MARKET_PAGINATION_KEYS
|
|
432
|
+
}
|
|
433
|
+
val nextRows = next.items.dropLastWhile {
|
|
434
|
+
it.key in MARKET_PAGINATION_KEYS
|
|
435
|
+
}
|
|
436
|
+
if (previousRows.isEmpty() || previousRows.size > nextRows.size) return false
|
|
437
|
+
if (
|
|
438
|
+
previousRows.firstOrNull()?.type != "market" ||
|
|
439
|
+
nextRows.firstOrNull()?.type != "market"
|
|
440
|
+
) {
|
|
441
|
+
return false
|
|
442
|
+
}
|
|
443
|
+
return previousRows.indices.all { index ->
|
|
444
|
+
previousRows[index].key == nextRows[index].key
|
|
445
|
+
}
|
|
446
|
+
}
|
|
447
|
+
|
|
405
448
|
/**
|
|
406
449
|
* A controlled selection update sends the snapshot back after the native
|
|
407
450
|
* selection delta. Its structure is unchanged; only selectedKeys and the
|
|
@@ -1839,15 +1882,36 @@ class NativeListView(
|
|
|
1839
1882
|
* already-sized host once after a committed data update so the native rows
|
|
1840
1883
|
* are measured and rebound without rebuilding the adapter.
|
|
1841
1884
|
*/
|
|
1842
|
-
private fun relayoutContents() {
|
|
1885
|
+
private fun relayoutContents(preserveMarketPaginationAnchor: Boolean = false) {
|
|
1843
1886
|
post {
|
|
1844
1887
|
if (disposed || width <= 0 || height <= 0) return@post
|
|
1888
|
+
val anchor = if (preserveMarketPaginationAnchor) {
|
|
1889
|
+
captureVisibleMarketAnchor()
|
|
1890
|
+
} else {
|
|
1891
|
+
null
|
|
1892
|
+
}
|
|
1893
|
+
val anchorIndex = anchor?.let { currentAnchor ->
|
|
1894
|
+
adapter.currentList.indexOfFirst { it.key == currentAnchor.key }
|
|
1895
|
+
} ?: RecyclerView.NO_POSITION
|
|
1896
|
+
if (anchor != null && anchorIndex >= 0) {
|
|
1897
|
+
layoutManager.scrollToPositionWithOffset(anchorIndex, anchor.offset)
|
|
1898
|
+
}
|
|
1845
1899
|
forceLayout()
|
|
1846
1900
|
measure(
|
|
1847
1901
|
MeasureSpec.makeMeasureSpec(width, MeasureSpec.EXACTLY),
|
|
1848
1902
|
MeasureSpec.makeMeasureSpec(height, MeasureSpec.EXACTLY),
|
|
1849
1903
|
)
|
|
1850
1904
|
layout(left, top, right, bottom)
|
|
1905
|
+
if (anchorIndex >= 0) {
|
|
1906
|
+
val now = SystemClock.uptimeMillis()
|
|
1907
|
+
if (now - lastMarketPaginationAnchorLogAtMs >= 1_000L) {
|
|
1908
|
+
lastMarketPaginationAnchorLogAtMs = now
|
|
1909
|
+
OneKeyLog.debug(
|
|
1910
|
+
"NativeList",
|
|
1911
|
+
"market-pagination-anchor-restored generation=${config?.generation} index=$anchorIndex",
|
|
1912
|
+
)
|
|
1913
|
+
}
|
|
1914
|
+
}
|
|
1851
1915
|
}
|
|
1852
1916
|
}
|
|
1853
1917
|
|
|
@@ -1937,6 +2001,11 @@ class NativeListView(
|
|
|
1937
2001
|
private fun sectionIndexDp(value: Int): Int = (value * density).roundToInt()
|
|
1938
2002
|
|
|
1939
2003
|
companion object {
|
|
2004
|
+
private val MARKET_PAGINATION_KEYS = setOf(
|
|
2005
|
+
"market-loading-more",
|
|
2006
|
+
"market-load-more-retry",
|
|
2007
|
+
"market-end",
|
|
2008
|
+
)
|
|
1940
2009
|
private val MARKET_QUOTE_FIELDS = setOf(
|
|
1941
2010
|
"revision",
|
|
1942
2011
|
"price",
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@onekeyfe/react-native-native-list",
|
|
3
|
-
"version": "3.0.
|
|
3
|
+
"version": "3.0.123",
|
|
4
4
|
"description": "Template-driven native RecyclerView and UICollectionView for React Native",
|
|
5
5
|
"source": "./src/index.ts",
|
|
6
6
|
"main": "./lib/module/index.js",
|
|
@@ -83,8 +83,8 @@
|
|
|
83
83
|
"typescript": "^5.9.2"
|
|
84
84
|
},
|
|
85
85
|
"peerDependencies": {
|
|
86
|
-
"@onekeyfe/react-native-image": "3.0.
|
|
87
|
-
"@onekeyfe/react-native-native-logger": "3.0.
|
|
86
|
+
"@onekeyfe/react-native-image": "3.0.123",
|
|
87
|
+
"@onekeyfe/react-native-native-logger": "3.0.123",
|
|
88
88
|
"react": "*",
|
|
89
89
|
"react-native": "*",
|
|
90
90
|
"react-native-nitro-modules": "0.37.0"
|