@onekeyfe/react-native-native-list 3.0.167 → 3.0.169

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.
@@ -185,6 +185,8 @@ class NativeListView(
185
185
  private val adapter = NativeListAdapter(reactContext)
186
186
  private val containerSlots = mutableListOf<View>()
187
187
  private val slotHeights = IntArray(3)
188
+ private var containerSlotRelayoutPending = false
189
+ private var containerSlotRelayoutScheduled = false
188
190
  private val headerSlotAdapter = NativeListContainerSlotAdapter()
189
191
  private val emptySlotAdapter = NativeListContainerSlotAdapter()
190
192
  private val footerSlotAdapter = NativeListContainerSlotAdapter()
@@ -193,6 +195,7 @@ class NativeListView(
193
195
  fun mountContainerSlot(view: View, index: Int) {
194
196
  containerSlots.add(index.coerceIn(0, containerSlots.size), view)
195
197
  updateContainerSlots()
198
+ scheduleContainerSlotRelayout()
196
199
  }
197
200
 
198
201
  fun containerSlotCount(): Int = containerSlots.size
@@ -201,6 +204,7 @@ class NativeListView(
201
204
  val view = containerSlots.removeAt(index)
202
205
  (view.parent as? ViewGroup)?.removeView(view)
203
206
  updateContainerSlots()
207
+ scheduleContainerSlotRelayout()
204
208
  }
205
209
 
206
210
  fun setContainerSlotHeightsJson(json: String) {
@@ -210,8 +214,32 @@ class NativeListView(
210
214
  val value = values.optDouble(index)
211
215
  if (!value.isFinite() || value < 0) return
212
216
  }
213
- for (index in 0..2) slotHeights[index] = (values.getDouble(index) * density).roundToInt()
217
+ var changed = false
218
+ for (index in 0..2) {
219
+ val height = (values.getDouble(index) * density).roundToInt()
220
+ if (slotHeights[index] != height) changed = true
221
+ slotHeights[index] = height
222
+ }
214
223
  updateContainerSlots()
224
+ if (changed) scheduleContainerSlotRelayout()
225
+ }
226
+
227
+ private fun scheduleContainerSlotRelayout() {
228
+ if (disposed) return
229
+ containerSlotRelayoutPending = true
230
+ if (containerSlotRelayoutScheduled) return
231
+ containerSlotRelayoutScheduled = true
232
+ recyclerView.post {
233
+ containerSlotRelayoutScheduled = false
234
+ if (disposed) {
235
+ containerSlotRelayoutPending = false
236
+ return@post
237
+ }
238
+ if (!containerSlotRelayoutPending || recyclerView.width <= 0 ||
239
+ recyclerView.height <= 0 || recyclerView.isComputingLayout) return@post
240
+ containerSlotRelayoutPending = false
241
+ relayoutRecyclerViewImmediately()
242
+ }
215
243
  }
216
244
 
217
245
  private fun updateContainerSlots() {
@@ -487,7 +515,10 @@ class NativeListView(
487
515
  recyclerView.addItemDecoration(SelectorBackgroundDecoration(adapter))
488
516
  recyclerView.addItemDecoration(ContainerSlotInsetDecoration { slotInsetPx })
489
517
  layoutManager.onChildLaidOut = ::recordLaidOutRowExtent
490
- layoutManager.onLayoutPassCompleted = { emitScrollPositionThresholdIfNeeded(resync = true) }
518
+ layoutManager.onLayoutPassCompleted = {
519
+ emitScrollPositionThresholdIfNeeded(resync = true)
520
+ if (containerSlotRelayoutPending) scheduleContainerSlotRelayout()
521
+ }
491
522
  recyclerView.setHasFixedSize(false)
492
523
  layoutManager.spanSizeLookup = object : GridLayoutManager.SpanSizeLookup() {
493
524
  override fun getSpanSize(position: Int): Int {
@@ -641,6 +672,7 @@ class NativeListView(
641
672
 
642
673
  override fun onLayout(changed: Boolean, left: Int, top: Int, right: Int, bottom: Int) {
643
674
  super.onLayout(changed, left, top, right, bottom)
675
+ if (containerSlotRelayoutPending) scheduleContainerSlotRelayout()
644
676
  val first = config?.items?.firstOrNull()
645
677
  if (recyclerView.isLayoutRequested && (first?.type == "market" || first?.json?.optString("presentation") == "market")) {
646
678
  // A retained Market page can keep cached parent measurements after its diff.
@@ -675,6 +707,7 @@ class NativeListView(
675
707
 
676
708
  override fun onAttachedToWindow() {
677
709
  super.onAttachedToWindow()
710
+ if (containerSlotRelayoutPending) scheduleContainerSlotRelayout()
678
711
  recyclerView.setTag(R.id.onekey_native_scroll_coordinator_offset_listener, coordinatorOffsetListener)
679
712
  emitScrollPositionThresholdIfNeeded()
680
713
  startStickyHeaderTracking()
@@ -1364,6 +1397,7 @@ class NativeListView(
1364
1397
  fun dispose() {
1365
1398
  if (disposed) return
1366
1399
  disposed = true
1400
+ containerSlotRelayoutPending = false
1367
1401
  onScrollPositionThresholdChange = null
1368
1402
  if (!isAttachedToWindow) disposeResources()
1369
1403
  }
package/docs/SPEC.md CHANGED
@@ -507,6 +507,15 @@ data adapter; adapter binding indices stay local while layout-manager positions
507
507
  are explicitly translated. Slots span all grid columns, do not select/reorder,
508
508
  and do not emit row actions, visible-row indices, or image-prefetch work.
509
509
 
510
+ On Android, mounting/unmounting a slot or changing its actual rounded native
511
+ height MUST request one coalesced RecyclerView measurement/layout repair. The
512
+ repair runs after the current layout completes and only with a positive viewport
513
+ size. A zero-sized or currently computing viewport retains the pending repair
514
+ for the next layout/attachment opportunity rather than posting an unbounded
515
+ retry loop. Disposal cancels the pending work. Equal height reports MUST NOT
516
+ request another repair. This leaves Fabric-owned slot content and row indices
517
+ unchanged; source checks alone do not establish first-layout visibility.
518
+
510
519
  Fabric mount/unmount ownership remains explicit even when RecyclerView detaches a
511
520
  slot holder. The native manager retains at most three roots until Fabric unmount;
512
521
  recycling detaches slot content without disposing its React tree. Unmount removes
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@onekeyfe/react-native-native-list",
3
- "version": "3.0.167",
3
+ "version": "3.0.169",
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",
@@ -87,8 +87,8 @@
87
87
  "typescript": "^5.9.2"
88
88
  },
89
89
  "peerDependencies": {
90
- "@onekeyfe/react-native-image": "3.0.167",
91
- "@onekeyfe/react-native-native-logger": "3.0.167",
90
+ "@onekeyfe/react-native-image": "3.0.169",
91
+ "@onekeyfe/react-native-native-logger": "3.0.169",
92
92
  "react": "*",
93
93
  "react-native": "*",
94
94
  "react-native-nitro-modules": "0.37.0"