@onekeyfe/react-native-pager-view 3.0.172 → 3.0.173

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.
@@ -123,7 +123,6 @@ class CollapsiblePagerHost(context: Context) : NestedScrollableHost(context), Ne
123
123
  private val originalScrollerPadding = WeakHashMap<ScrollView, ScrollerPadding>()
124
124
  private val restoredScrollerKeys = WeakHashMap<ScrollView, String>()
125
125
  private val ownedScrollerKeys = WeakHashMap<NativeScrollerViewport, String>()
126
- private val ownedScrollerRestoreRequests = HashMap<String, Pair<WeakReference<NativeScrollerViewport>, Int?>>()
127
126
  private var foregroundRefreshIndicator: WeakReference<ImageView>? = null
128
127
  private var refreshForegroundWasVisible = false
129
128
  private val refreshForegroundMatrix = Matrix()
@@ -131,51 +130,13 @@ class CollapsiblePagerHost(context: Context) : NestedScrollableHost(context), Ne
131
130
  private val refreshForegroundAncestors = ArrayList<View>()
132
131
  private var refreshForegroundAncestorAlpha = 1f
133
132
  private val pageOffsets = HashMap<String, Int>()
134
- private val pageHeaderOffsets = HashMap<String, Int>()
135
- private var transitionHeaderOffsets: Map<String, Int>? = null
136
- private var transitionPageOffsets: Map<String, Int>? = null
137
- private var transitionSourcePage = 0
138
- private var transitionTargetPage: Int? = null
139
- private var syntheticPageRestore = false
140
- private var resumeTransitionSource: Int? = null
141
- private val pendingPageRestores = HashSet<String>()
142
- private class PageRestoreRequest(view: View, val pageIndex: Int, val generation: Int) {
143
- val view = WeakReference(view)
144
- }
145
- private val pageRestoreRequests = HashMap<String, PageRestoreRequest>()
146
-
147
- private fun registerPageRestore(key: String, view: View, pageIndex: Int): PageRestoreRequest? {
148
- if (!nativeSmoothHeaderScrollEnabled) return null
149
- val previous = pageRestoreRequests[key]?.view?.get()
150
- if (previous is NativeScrollerViewport && previous !== view) previous.host.cancelPendingScrollRestore()
151
- ownedScrollerRestoreRequests.remove(key)
152
- return PageRestoreRequest(view, pageIndex, attachmentGeneration).also {
153
- pageRestoreRequests[key] = it
154
- pendingPageRestores.add(key)
155
- }
156
- }
157
-
158
- private fun isCurrentPageRestore(key: String, request: PageRestoreRequest?): Boolean =
159
- !nativeSmoothHeaderScrollEnabled || (request != null && pageRestoreRequests[key] === request &&
160
- key in pendingPageRestores && request.generation == attachmentGeneration &&
161
- pageKey(request.pageIndex) == key)
162
-
163
- private fun clearPageRestoreForView(key: String, view: View, request: PageRestoreRequest? = null) {
164
- if (request != null && pageRestoreRequests[key] !== request) return
165
- if (pageRestoreRequests[key]?.view?.get() !== view) return
166
- pageRestoreRequests.remove(key)
167
- pendingPageRestores.remove(key)
168
- ownedScrollerRestoreRequests.remove(key)
169
- }
170
133
  private var observedRecyclerView: RecyclerView? = null
171
- private var observedRecyclerKey: String? = null
172
134
  private var observedScrollListener: RecyclerView.OnScrollListener? = null
173
135
  private var observedOwnedScroller: NativeScrollerViewport? = null
174
136
  private var observedOwnedScrollerKey: String? = null
175
137
  private var observedOwnedScrollerListener: ViewTreeObserver.OnScrollChangedListener? = null
176
138
  private var observedOwnedScrollerTreeObserver: ViewTreeObserver? = null
177
139
  private var observedNativeScroller: ScrollView? = null
178
- private var observedNativeScrollerKey: String? = null
179
140
  private var observedNativeScrollerListener: ViewTreeObserver.OnScrollChangedListener? = null
180
141
  private var observedNativeScrollerTreeObserver: ViewTreeObserver? = null
181
142
  private var observedPageRemoved = false
@@ -228,18 +189,6 @@ class CollapsiblePagerHost(context: Context) : NestedScrollableHost(context), Ne
228
189
  var headerOffsetPx = 0
229
190
  private set
230
191
  var pageKeys: List<String> = emptyList()
231
- set(value) {
232
- if (field == value) return
233
- pageRestoreRequests.entries.toList().forEach { (key, request) ->
234
- if ((value.getOrNull(request.pageIndex) ?: "page-${request.pageIndex}") != key) {
235
- (request.view.get() as? NativeScrollerViewport)?.host?.cancelPendingScrollRestore()
236
- pageRestoreRequests.remove(key)
237
- pendingPageRestores.remove(key)
238
- ownedScrollerRestoreRequests.remove(key)
239
- }
240
- }
241
- field = value
242
- }
243
192
  var retainedPages: String = "[]"
244
193
  var onHeaderOffsetChanged: (() -> Unit)? = null
245
194
  var nativeSmoothHeaderScrollEnabled = false
@@ -281,19 +230,6 @@ class CollapsiblePagerHost(context: Context) : NestedScrollableHost(context), Ne
281
230
  OneKeyLog.debug("CollapsiblePager", "host=$hostIdentity $message")
282
231
  }
283
232
 
284
- private var offsetDiagSequence = 0L
285
-
286
- private fun offsetDiag(phase: String, view: View? = null, key: String = currentPageKey()) {
287
- if ((context.applicationInfo.flags and android.content.pm.ApplicationInfo.FLAG_DEBUGGABLE) == 0) return
288
- val safeKey = if (key in setOf("portfolio", "perps", "defi", "nft", "history")) key else "other"
289
- val observed = observedOwnedScroller ?: observedNativeScroller ?: observedRecyclerView
290
- OneKeyLog.debug("CollapsiblePager", "[HOME-OFFSET-DIAG] phase=$phase seq=${++offsetDiagSequence} " +
291
- "wallMs=${System.currentTimeMillis()} monoMs=${SystemClock.uptimeMillis()} host=$hostIdentity " +
292
- "generation=$attachmentGeneration page=$selectedPage key=$safeKey header=$headerOffsetPx headerHeight=$headerHeightPx " +
293
- "view=${view?.let { System.identityHashCode(it) }} tag=${view?.id} observed=${observed?.let { System.identityHashCode(it) }} " +
294
- "offset=${view?.let(::verticalScrollOffset)} cache=${pageOffsets[key]} boundsHeight=${view?.height}")
295
- }
296
-
297
233
  private fun outerPagerIndex(): Int {
298
234
  var ancestor = parent as? View
299
235
  while (ancestor != null) {
@@ -428,9 +364,6 @@ class CollapsiblePagerHost(context: Context) : NestedScrollableHost(context), Ne
428
364
  fun removeAllReactChildren() {
429
365
  releaseRefreshForeground()
430
366
  detachPrimaryScrollObserver()
431
- pageRestoreRequests.clear()
432
- pendingPageRestores.clear()
433
- ownedScrollerRestoreRequests.clear()
434
367
  // Weak keys may disappear after size is read; Collection.toArray tolerates this.
435
368
  for (recycler in originalRecyclerPadding.keys.toTypedArray()) {
436
369
  restoreRecyclerInsets(recycler)
@@ -453,80 +386,16 @@ class CollapsiblePagerHost(context: Context) : NestedScrollableHost(context), Ne
453
386
 
454
387
  fun reactChildAt(index: Int) = logicalChildren[index]
455
388
 
456
- internal fun beginPageTransition(target: Int? = null) {
457
- if (!nativeSmoothHeaderScrollEnabled || headerHeightPx <= 0) return
458
- if (transitionHeaderOffsets == null) {
459
- pageHeaderOffsets[currentPageKey()] = headerOffsetPx
460
- detachPrimaryScrollObserver()
461
- transitionSourcePage = selectedPage
462
- transitionHeaderOffsets = pageHeaderOffsets.toMap()
463
- transitionPageOffsets = pageOffsets.toMap()
464
- }
465
- if (target != null) transitionTargetPage = target
466
- }
467
-
468
- internal fun onPagerScrolled(position: Int, offset: Float) {
469
- val headers = transitionHeaderOffsets ?: return
470
- val target = transitionTargetPage
471
- val first = if (target != null) transitionSourcePage else position
472
- val second = target ?: (position + 1).coerceAtMost(adapter.itemCount - 1)
473
- val fraction = if (target != null && target != first) {
474
- ((position + offset - first) / (target - first)).coerceIn(0f, 1f)
475
- } else offset
476
- val firstH = headers[pageKey(first)] ?: 0
477
- val secondH = headers[pageKey(second)] ?: 0
478
- syntheticPageRestore = true
479
- setHeaderOffset((firstH + (secondH - firstH) * fraction).roundToInt())
480
- syntheticPageRestore = false
481
- updateNativeTabProgress(position, offset)
482
- }
483
-
484
- internal fun onPagerScrollStateChanged(state: Int) {
485
- if (state == ViewPager2.SCROLL_STATE_DRAGGING || state == ViewPager2.SCROLL_STATE_SETTLING) {
486
- beginPageTransition()
487
- } else if (state == ViewPager2.SCROLL_STATE_IDLE && transitionHeaderOffsets != null) {
488
- finishPageTransition(pager.currentItem)
489
- }
490
- }
491
-
492
- private fun finishPageTransition(position: Int) {
493
- val headers = transitionHeaderOffsets ?: return
494
- detachPrimaryScrollObserver(recordOffset = false)
495
- releaseRefreshForeground()
496
- selectedPage = position.coerceIn(0, adapter.itemCount - 1)
497
- syntheticPageRestore = true
498
- setHeaderOffset(headers[currentPageKey()] ?: 0)
499
- transitionHeaderOffsets = null
500
- transitionPageOffsets = null
501
- transitionTargetPage = null
502
- syntheticPageRestore = false
503
- pageHeaderOffsets[currentPageKey()] = headerOffsetPx
504
- prepareAdjacentPages()
505
- attachPrimaryScrollObserver()
506
- }
507
-
508
389
  fun selectPage(position: Int) {
509
- offsetDiag("select-begin-target=$position", observedOwnedScroller ?: observedNativeScroller ?: observedRecyclerView)
510
390
  pendingRefreshPull = null
511
391
  if (adapter.itemCount == 0) return
512
- if (nativeSmoothHeaderScrollEnabled && headerHeightPx > 0) {
513
- if (transitionHeaderOffsets != null) return
514
- beginPageTransition(position)
515
- finishPageTransition(position)
516
- return
517
- }
518
392
  detachPrimaryScrollObserver()
519
393
  releaseRefreshForeground()
520
394
  selectedPage = position.coerceIn(0, adapter.itemCount - 1)
521
395
  val savedOffset = pageOffsets[currentPageKey()]
522
396
  ?: primaryScrollableForPage(selectedPage)?.let(::verticalScrollOffset)
523
397
  ?: 0
524
- offsetDiag("select-offset=$savedOffset-source=${if (pageOffsets[currentPageKey()] != null) "saved" else "live"}")
525
- if (savedOffset > 0) {
526
- offsetDiag("select-force-collapse-before")
527
- setHeaderOffset(headerHeightPx)
528
- offsetDiag("select-force-collapse-after")
529
- }
398
+ if (savedOffset > 0) setHeaderOffset(headerHeightPx)
530
399
  postForCurrentAttachment {
531
400
  prepareAdjacentPages()
532
401
  attachPrimaryScrollObserver()
@@ -668,14 +537,9 @@ class CollapsiblePagerHost(context: Context) : NestedScrollableHost(context), Ne
668
537
 
669
538
  private fun setHeaderOffset(offset: Int) {
670
539
  // val next = offset.coerceIn(0, headerHeightPx)
671
- val pending = nativeSmoothHeaderScrollEnabled && currentPageKey() in pendingPageRestores
672
- val maximum = if (transitionHeaderOffsets != null || pending) headerHeightPx else maximumHeaderOffset()
673
- val next = offset.coerceIn(0, maximum)
540
+ val next = offset.coerceIn(0, maximumHeaderOffset())
674
541
  if (headerOffsetPx == next) return
675
542
  headerOffsetPx = next
676
- if (nativeSmoothHeaderScrollEnabled && transitionHeaderOffsets == null && !syntheticPageRestore && !pending) {
677
- pageHeaderOffsets[currentPageKey()] = next
678
- }
679
543
  applyHeaderOffset()
680
544
  }
681
545
 
@@ -792,17 +656,13 @@ class CollapsiblePagerHost(context: Context) : NestedScrollableHost(context), Ne
792
656
  }
793
657
 
794
658
  private fun attachPrimaryScrollObserver() {
795
- if (transitionHeaderOffsets != null) return
796
659
  if (selectedPage !in 0 until adapter.itemCount) return
797
660
  val previous = observedRecyclerView ?: observedOwnedScroller ?: observedNativeScroller
798
661
  if (observedPageRemoved || previous != null && !isDescendant(previous, adapter.pageAt(selectedPage))) {
799
- offsetDiag("primary-replacement-before-removed=$observedPageRemoved", previous)
800
662
  observedPageRemoved = false
801
- detachPrimaryScrollObserver(recordOffset = !nativeSmoothHeaderScrollEnabled)
663
+ detachPrimaryScrollObserver()
802
664
  // A replacement scroller starts at the beginning while retaining header collapse.
803
- offsetDiag("primary-replacement-cache-before", previous)
804
- if (!nativeSmoothHeaderScrollEnabled) pageOffsets[currentPageKey()] = 0
805
- offsetDiag("primary-replacement-cache-after", previous)
665
+ pageOffsets[currentPageKey()] = 0
806
666
  }
807
667
  when (val scrollable = primaryScrollableForPage(selectedPage)) {
808
668
  is RecyclerView -> attachRecyclerObserver(scrollable)
@@ -812,33 +672,24 @@ class CollapsiblePagerHost(context: Context) : NestedScrollableHost(context), Ne
812
672
  }
813
673
 
814
674
  private fun attachRecyclerObserver(recycler: RecyclerView) {
815
- if (observedRecyclerView === recycler && observedRecyclerKey == currentPageKey()) {
675
+ if (observedRecyclerView === recycler) {
816
676
  applyRecyclerInsets(recycler, selectedPage)
817
677
  publishConsumedOffset(recycler)
818
678
  return
819
679
  }
820
680
 
821
681
  detachPrimaryScrollObserver()
822
- offsetDiag("recycler-attach-before", recycler)
823
682
  observedRecyclerView = recycler
824
- observedRecyclerKey = currentPageKey()
825
683
  applyRecyclerInsets(recycler, selectedPage)
826
684
  publishConsumedOffset(recycler)
827
- val key = currentPageKey()
828
685
  val listener = object : RecyclerView.OnScrollListener() {
829
686
  override fun onScrolled(recyclerView: RecyclerView, dx: Int, dy: Int) {
830
- if (observedScrollListener !== this || observedRecyclerKey != key ||
831
- key != currentPageKey() || !isAttachedToWindow ||
832
- transitionHeaderOffsets != null || syntheticPageRestore || key in pendingPageRestores) return
833
687
  val contentOffset = recyclerView.computeVerticalScrollOffset()
834
- if (pageOffsets[currentPageKey()] != contentOffset) offsetDiag("recycler-cache-before-new=$contentOffset", recyclerView)
835
- pageOffsets[key] = contentOffset
688
+ pageOffsets[currentPageKey()] = contentOffset
836
689
  // Nested touch scrolling moves list content only after the header has
837
690
  // collapsed. Programmatic list jumps bypass those parent callbacks.
838
691
  if (contentOffset > 0 && headerOffsetPx < headerHeightPx) {
839
- offsetDiag("recycler-positive-collapse-before", recyclerView)
840
692
  setHeaderOffset(headerHeightPx)
841
- offsetDiag("recycler-positive-collapse-after", recyclerView)
842
693
  }
843
694
  }
844
695
  }
@@ -854,11 +705,7 @@ class CollapsiblePagerHost(context: Context) : NestedScrollableHost(context), Ne
854
705
  val recycler = observedRecyclerView
855
706
  val listener = observedScrollListener
856
707
  if (recycler != null) {
857
- offsetDiag("recycler-detach-save-before-record=$recordOffset", recycler)
858
- if (recordOffset && transitionPageOffsets == null) observedRecyclerKey?.let {
859
- if (it !in pendingPageRestores) pageOffsets[it] = recycler.computeVerticalScrollOffset()
860
- }
861
- offsetDiag("recycler-detach-save-after", recycler)
708
+ if (recordOffset) pageOffsets[currentPageKey()] = recycler.computeVerticalScrollOffset()
862
709
  publishConsumedOffset(recycler, remove = true)
863
710
  }
864
711
  if (recycler != null && listener != null) recycler.removeOnScrollListener(listener)
@@ -869,37 +716,28 @@ class CollapsiblePagerHost(context: Context) : NestedScrollableHost(context), Ne
869
716
  )
870
717
  }
871
718
  observedRecyclerView = null
872
- observedRecyclerKey = null
873
719
  observedScrollListener = null
874
720
  }
875
721
 
876
722
  private fun attachNativeScrollerObserver(scroller: ScrollView) {
877
- if (observedNativeScroller === scroller && observedNativeScrollerKey == currentPageKey()) {
723
+ if (observedNativeScroller === scroller) {
878
724
  applyNativeScrollerInsets(scroller, selectedPage)
879
725
  return
880
726
  }
881
727
 
882
728
  detachPrimaryScrollObserver()
883
- offsetDiag("scrollview-attach-before", scroller)
884
729
  observedNativeScroller = scroller
885
- observedNativeScrollerKey = currentPageKey()
886
730
  applyNativeScrollerInsets(scroller, selectedPage)
887
- val key = currentPageKey()
888
731
  val listener = object : ViewTreeObserver.OnScrollChangedListener {
889
732
  override fun onScrollChanged() {
890
733
  if (observedNativeScrollerListener !== this) {
891
734
  removeScrollChangedListener(null, scroller, this)
892
735
  return
893
736
  }
894
- if (key != currentPageKey() || !isAttachedToWindow ||
895
- transitionHeaderOffsets != null || syntheticPageRestore || key in pendingPageRestores) return
896
737
  val contentOffset = scroller.scrollY
897
- if (pageOffsets[currentPageKey()] != contentOffset) offsetDiag("scrollview-cache-before-new=$contentOffset", scroller)
898
- pageOffsets[key] = contentOffset
738
+ pageOffsets[currentPageKey()] = contentOffset
899
739
  if (contentOffset > 0 && headerOffsetPx < headerHeightPx) {
900
- offsetDiag("scrollview-positive-collapse-before", scroller)
901
740
  setHeaderOffset(headerHeightPx)
902
- offsetDiag("scrollview-positive-collapse-after", scroller)
903
741
  }
904
742
  }
905
743
  }
@@ -916,11 +754,7 @@ class CollapsiblePagerHost(context: Context) : NestedScrollableHost(context), Ne
916
754
  private fun detachNativeScrollerObserver(recordOffset: Boolean) {
917
755
  val scroller = observedNativeScroller
918
756
  val listener = observedNativeScrollerListener
919
- offsetDiag("scrollview-detach-save-before-record=$recordOffset", scroller)
920
- if (scroller != null && recordOffset && transitionPageOffsets == null) observedNativeScrollerKey?.let {
921
- if (it !in pendingPageRestores) pageOffsets[it] = scroller.scrollY
922
- }
923
- offsetDiag("scrollview-detach-save-after", scroller)
757
+ if (scroller != null && recordOffset) pageOffsets[currentPageKey()] = scroller.scrollY
924
758
  if (scroller != null && listener != null) {
925
759
  removeScrollChangedListener(observedNativeScrollerTreeObserver, scroller, listener)
926
760
  }
@@ -931,7 +765,6 @@ class CollapsiblePagerHost(context: Context) : NestedScrollableHost(context), Ne
931
765
  )
932
766
  }
933
767
  observedNativeScroller = null
934
- observedNativeScrollerKey = null
935
768
  observedNativeScrollerListener = null
936
769
  observedNativeScrollerTreeObserver = null
937
770
  }
@@ -960,21 +793,9 @@ class CollapsiblePagerHost(context: Context) : NestedScrollableHost(context), Ne
960
793
  val key = pageKey(pageIndex)
961
794
  if (ownedScrollerKeys[scroller] == key) return
962
795
  ownedScrollerKeys[scroller] = key
963
- val restoreRequest = registerPageRestore(key, scroller, pageIndex)
964
- if (nativeSmoothHeaderScrollEnabled) ownedScrollerRestoreRequests[key] = WeakReference(scroller) to null
965
- val generation = attachmentGeneration
966
796
  postForCurrentAttachment {
967
- if (isCurrentPageRestore(key, restoreRequest) && ownedScrollerKeys[scroller] == key && generation == attachmentGeneration &&
968
- scroller.isAttachedToWindow && (!nativeSmoothHeaderScrollEnabled ||
969
- (key in pendingPageRestores && ownedScrollerRestoreRequests[key]?.first?.get() === scroller))) {
970
- offsetDiag("owned-restore-before", scroller, key)
971
- val saved = transitionPageOffsets?.get(key) ?: pageOffsets[key] ?: 0
972
- scroller.host.restoreScrollOffset(saved)
973
- if (nativeSmoothHeaderScrollEnabled) {
974
- ownedScrollerRestoreRequests[key] = WeakReference(scroller) to generation
975
- recordOwnedScrollerOffset(scroller, key)
976
- }
977
- offsetDiag("owned-restore-after", scroller, key)
797
+ if (ownedScrollerKeys[scroller] == key && scroller.isAttachedToWindow) {
798
+ scroller.host.restoreScrollOffset(pageOffsets[key] ?: 0)
978
799
  }
979
800
  }
980
801
  }
@@ -982,10 +803,7 @@ class CollapsiblePagerHost(context: Context) : NestedScrollableHost(context), Ne
982
803
  private fun restoreOwnedScrollerInsets(scroller: NativeScrollerViewport) {
983
804
  scroller.stopMotion()
984
805
  scroller.host.cancelPendingScrollRestore()
985
- ownedScrollerKeys.remove(scroller)?.let { key ->
986
- clearPageRestoreForView(key, scroller)
987
- if (ownedScrollerRestoreRequests[key]?.first?.get() === scroller) ownedScrollerRestoreRequests.remove(key)
988
- }
806
+ ownedScrollerKeys.remove(scroller)
989
807
  publishConsumedOffset(scroller, remove = true)
990
808
  scroller.host.setPagerInset(this, null)
991
809
  }
@@ -993,11 +811,9 @@ class CollapsiblePagerHost(context: Context) : NestedScrollableHost(context), Ne
993
811
  private fun attachOwnedScrollerObserver(scroller: NativeScrollerViewport) {
994
812
  if (observedOwnedScroller === scroller && observedOwnedScrollerKey == currentPageKey()) {
995
813
  applyOwnedScrollerInsets(scroller, selectedPage)
996
- if (nativeSmoothHeaderScrollEnabled) recordOwnedScrollerOffset(scroller, currentPageKey())
997
814
  return
998
815
  }
999
816
  detachPrimaryScrollObserver()
1000
- offsetDiag("owned-attach-before", scroller)
1001
817
  observedOwnedScroller = scroller
1002
818
  observedOwnedScrollerKey = currentPageKey()
1003
819
  val key = currentPageKey()
@@ -1008,7 +824,9 @@ class CollapsiblePagerHost(context: Context) : NestedScrollableHost(context), Ne
1008
824
  removeScrollChangedListener(null, scroller, this)
1009
825
  return
1010
826
  }
1011
- recordOwnedScrollerOffset(scroller, key)
827
+ val contentOffset = scroller.scrollY
828
+ pageOffsets[key] = contentOffset
829
+ if (contentOffset > 0 && headerOffsetPx < headerHeightPx) setHeaderOffset(headerHeightPx)
1012
830
  }
1013
831
  }
1014
832
  observedOwnedScrollerListener = listener
@@ -1017,36 +835,11 @@ class CollapsiblePagerHost(context: Context) : NestedScrollableHost(context), Ne
1017
835
  }
1018
836
  }
1019
837
 
1020
- private fun recordOwnedScrollerOffset(scroller: NativeScrollerViewport, key: String) {
1021
- if (ownedScrollerKeys[scroller] != key || !isAttachedToWindow || !scroller.isAttachedToWindow) return
1022
- if (key in pendingPageRestores) {
1023
- // A false native pending flag before our posted request executes is not cancellation.
1024
- val request = ownedScrollerRestoreRequests[key]
1025
- if (request == null || request.first.get() !== scroller || request.second != attachmentGeneration ||
1026
- scroller.width <= 0 || scroller.height <= 0 || scroller.host.hasPendingScrollRestore()) return
1027
- clearPageRestoreForView(key, scroller)
1028
- }
1029
- if (observedOwnedScroller !== scroller || observedOwnedScrollerKey != key ||
1030
- key != currentPageKey() || transitionHeaderOffsets != null || syntheticPageRestore) return
1031
- val contentOffset = scroller.scrollY
1032
- if (pageOffsets[key] != contentOffset) offsetDiag("owned-cache-before-new=$contentOffset", scroller, key)
1033
- pageOffsets[key] = contentOffset
1034
- if (contentOffset > 0 && headerOffsetPx < headerHeightPx) {
1035
- offsetDiag("owned-positive-collapse-before", scroller, key)
1036
- setHeaderOffset(headerHeightPx)
1037
- offsetDiag("owned-positive-collapse-after", scroller, key)
1038
- }
1039
- }
1040
-
1041
838
  private fun detachOwnedScrollerObserver(recordOffset: Boolean) {
1042
839
  val scroller = observedOwnedScroller ?: return
1043
840
  scroller.stopMotion()
1044
841
  publishConsumedOffset(scroller, remove = true)
1045
- offsetDiag("owned-detach-save-before-record=$recordOffset", scroller)
1046
- if (recordOffset && transitionPageOffsets == null) observedOwnedScrollerKey?.let {
1047
- if (it !in pendingPageRestores) pageOffsets[it] = scroller.scrollY
1048
- }
1049
- offsetDiag("owned-detach-save-after", scroller)
842
+ if (recordOffset) observedOwnedScrollerKey?.let { pageOffsets[it] = scroller.scrollY }
1050
843
  observedOwnedScrollerListener?.let {
1051
844
  removeScrollChangedListener(observedOwnedScrollerTreeObserver, scroller, it)
1052
845
  }
@@ -1100,32 +893,17 @@ class CollapsiblePagerHost(context: Context) : NestedScrollableHost(context), Ne
1100
893
  val key = pageKey(pageIndex)
1101
894
  if (restoredRecyclerKeys[recycler] != key) {
1102
895
  restoredRecyclerKeys[recycler] = key
1103
- val restoreRequest = registerPageRestore(key, recycler, pageIndex)
1104
896
  val generation = attachmentGeneration
1105
897
  recycler.post {
1106
- if (!isCurrentPageRestore(key, restoreRequest)) {
1107
- offsetDiag("post-skip-cancelled-page=$pageIndex", recycler, key)
1108
- return@post
1109
- }
1110
898
  if (!isAttachedToWindow || generation != attachmentGeneration ||
1111
899
  restoredRecyclerKeys[recycler] != key ||
1112
900
  originalRecyclerPadding[recycler] !== original) {
1113
901
  if (restoredRecyclerKeys[recycler] == key) restoredRecyclerKeys.remove(recycler)
1114
- clearPageRestoreForView(key, recycler, restoreRequest)
1115
902
  return@post
1116
903
  }
1117
- val saved = transitionPageOffsets?.get(key) ?: pageOffsets[key] ?: 0
904
+ val saved = pageOffsets[key] ?: 0
1118
905
  val current = recycler.computeVerticalScrollOffset()
1119
- offsetDiag("recycler-restore-before-saved=$saved", recycler, key)
1120
- if (nativeSmoothHeaderScrollEnabled && (recycler.height <= 0 || recycler.childCount == 0)) {
1121
- restoredRecyclerKeys.remove(recycler)
1122
- if (pageRestoreRequests[key] === restoreRequest) pageRestoreRequests.remove(key)
1123
- return@post
1124
- }
1125
906
  if (saved != current) recycler.scrollBy(0, saved - current)
1126
- if (nativeSmoothHeaderScrollEnabled) clearPageRestoreForView(key, recycler, restoreRequest)
1127
- else pendingPageRestores.remove(key)
1128
- offsetDiag("recycler-restore-after", recycler, key)
1129
907
  }
1130
908
  }
1131
909
  }
@@ -1171,32 +949,16 @@ class CollapsiblePagerHost(context: Context) : NestedScrollableHost(context), Ne
1171
949
  val key = pageKey(pageIndex)
1172
950
  if (restoredScrollerKeys[scroller] != key) {
1173
951
  restoredScrollerKeys[scroller] = key
1174
- val restoreRequest = registerPageRestore(key, scroller, pageIndex)
1175
952
  val generation = attachmentGeneration
1176
953
  scroller.post {
1177
- if (!isCurrentPageRestore(key, restoreRequest)) {
1178
- offsetDiag("post-skip-cancelled-page=$pageIndex", scroller, key)
1179
- return@post
1180
- }
1181
954
  if (!isAttachedToWindow || generation != attachmentGeneration ||
1182
955
  restoredScrollerKeys[scroller] != key ||
1183
956
  originalScrollerPadding[scroller] !== original) {
1184
957
  if (restoredScrollerKeys[scroller] == key) restoredScrollerKeys.remove(scroller)
1185
- clearPageRestoreForView(key, scroller, restoreRequest)
1186
- return@post
1187
- }
1188
- val saved = transitionPageOffsets?.get(key) ?: pageOffsets[key] ?: 0
1189
- offsetDiag("scrollview-restore-before-saved=$saved", scroller, key)
1190
- if (nativeSmoothHeaderScrollEnabled &&
1191
- (scroller.height <= 0 || (scroller.getChildAt(0)?.height ?: 0) <= 0)) {
1192
- restoredScrollerKeys.remove(scroller)
1193
- if (pageRestoreRequests[key] === restoreRequest) pageRestoreRequests.remove(key)
1194
958
  return@post
1195
959
  }
960
+ val saved = pageOffsets[key] ?: 0
1196
961
  if (scroller.scrollY != saved) scroller.scrollTo(scroller.scrollX, saved)
1197
- if (nativeSmoothHeaderScrollEnabled) clearPageRestoreForView(key, scroller, restoreRequest)
1198
- else pendingPageRestores.remove(key)
1199
- offsetDiag("scrollview-restore-after", scroller, key)
1200
962
  }
1201
963
  }
1202
964
  }
@@ -1255,7 +1017,7 @@ class CollapsiblePagerHost(context: Context) : NestedScrollableHost(context), Ne
1255
1017
  publishConsumedOffset(recycler, remove = true)
1256
1018
  val original = originalRecyclerPadding.remove(recycler) ?: return
1257
1019
  updateRecyclerPaddingOwnership(recycler, original)
1258
- restoredRecyclerKeys.remove(recycler)?.let { clearPageRestoreForView(it, recycler) }
1020
+ restoredRecyclerKeys.remove(recycler)
1259
1021
  recycler.clipToPadding = original.clipToPadding
1260
1022
  recycler.setPadding(original.left, original.top, original.right, original.bottom)
1261
1023
  }
@@ -1263,7 +1025,7 @@ class CollapsiblePagerHost(context: Context) : NestedScrollableHost(context), Ne
1263
1025
  private fun restoreNativeScrollerInsets(scroller: ScrollView) {
1264
1026
  val original = originalScrollerPadding.remove(scroller) ?: return
1265
1027
  updateScrollerPaddingOwnership(scroller, original)
1266
- restoredScrollerKeys.remove(scroller)?.let { clearPageRestoreForView(it, scroller) }
1028
+ restoredScrollerKeys.remove(scroller)
1267
1029
  if (scroller is ReactScrollView) {
1268
1030
  val state = scroller.reactScrollViewScrollState
1269
1031
  scroller.setScrollAwayPaddingEnabledUnstable(
@@ -1637,11 +1399,6 @@ class CollapsiblePagerHost(context: Context) : NestedScrollableHost(context), Ne
1637
1399
  override fun onNestedScrollAccepted(child: View, target: View, axes: Int, type: Int) {
1638
1400
  if (type == ViewCompat.TYPE_TOUCH) pendingRefreshPull = null
1639
1401
  nestedScrollingParentHelper.onNestedScrollAccepted(child, target, axes, type)
1640
- if (type == ViewCompat.TYPE_TOUCH) {
1641
- pageRestoreRequests.remove(currentPageKey())
1642
- pendingPageRestores.remove(currentPageKey())
1643
- ownedScrollerRestoreRequests.remove(currentPageKey())
1644
- }
1645
1402
  }
1646
1403
 
1647
1404
  override fun onStopNestedScroll(target: View, type: Int) {
@@ -1735,13 +1492,6 @@ class CollapsiblePagerHost(context: Context) : NestedScrollableHost(context), Ne
1735
1492
  restoredRecyclerKeys.clear()
1736
1493
  restoredScrollerKeys.clear()
1737
1494
  viewTreeObserver.addOnPreDrawListener(pageContentLayoutListener)
1738
- resumeTransitionSource?.let { source ->
1739
- resumeTransitionSource = null
1740
- if (source in 0 until adapter.itemCount) {
1741
- pager.setCurrentItem(source, false)
1742
- selectPage(source)
1743
- }
1744
- }
1745
1495
  log(
1746
1496
  "host-attach generation=$attachmentGeneration inner=$selectedPage " +
1747
1497
  "outer=${outerPagerIndex()} nativePages=${adapter.itemCount}",
@@ -1761,18 +1511,6 @@ class CollapsiblePagerHost(context: Context) : NestedScrollableHost(context), Ne
1761
1511
  nestedNativeGestureStarted = false
1762
1512
  viewTreeObserver.removeOnPreDrawListener(pageContentLayoutListener)
1763
1513
  detachPrimaryScrollObserver()
1764
- pageRestoreRequests.clear()
1765
- pendingPageRestores.clear()
1766
- ownedScrollerRestoreRequests.clear()
1767
- transitionHeaderOffsets?.let { headers ->
1768
- resumeTransitionSource = transitionSourcePage
1769
- syntheticPageRestore = true
1770
- setHeaderOffset(headers[pageKey(transitionSourcePage)] ?: 0)
1771
- syntheticPageRestore = false
1772
- }
1773
- transitionHeaderOffsets = null
1774
- transitionPageOffsets = null
1775
- transitionTargetPage = null
1776
1514
  // Snapshot live keys before restoration removes their padding records.
1777
1515
  for (recycler in originalRecyclerPadding.keys.toTypedArray()) {
1778
1516
  restoreRecyclerInsets(recycler)
@@ -43,7 +43,6 @@ class CollapsiblePagerViewManager : ViewGroupManager<CollapsiblePagerHost>(),
43
43
  )
44
44
  host.pager.registerOnPageChangeCallback(object : ViewPager2.OnPageChangeCallback() {
45
45
  override fun onPageScrolled(position: Int, offset: Float, offsetPixels: Int) {
46
- host.onPagerScrolled(position, offset)
47
46
  dispatch(reactContext, host, PageScrollEvent(host.id, position, offset))
48
47
  }
49
48
 
@@ -56,7 +55,6 @@ class CollapsiblePagerViewManager : ViewGroupManager<CollapsiblePagerHost>(),
56
55
  }
57
56
 
58
57
  override fun onPageScrollStateChanged(state: Int) {
59
- host.onPagerScrollStateChanged(state)
60
58
  val value = when (state) {
61
59
  ViewPager2.SCROLL_STATE_IDLE -> "idle"
62
60
  ViewPager2.SCROLL_STATE_DRAGGING -> "dragging"
@@ -326,19 +324,13 @@ class CollapsiblePagerViewManager : ViewGroupManager<CollapsiblePagerHost>(),
326
324
 
327
325
  override fun setPage(view: CollapsiblePagerHost?, selectedPage: Int) {
328
326
  if (view != null && selectedPage in 0 until view.adapter.itemCount) {
329
- view.beginPageTransition(selectedPage)
330
327
  view.pager.setCurrentItem(selectedPage, true)
331
- if (view.pager.scrollState == ViewPager2.SCROLL_STATE_IDLE) {
332
- view.onPagerScrollStateChanged(ViewPager2.SCROLL_STATE_IDLE)
333
- }
334
328
  }
335
329
  }
336
330
 
337
331
  override fun setPageWithoutAnimation(view: CollapsiblePagerHost?, selectedPage: Int) {
338
332
  if (view != null && selectedPage in 0 until view.adapter.itemCount) {
339
- view.beginPageTransition(selectedPage)
340
333
  view.pager.setCurrentItem(selectedPage, false)
341
- view.onPagerScrollStateChanged(ViewPager2.SCROLL_STATE_IDLE)
342
334
  }
343
335
  }
344
336
 
@@ -255,8 +255,6 @@ class NativeScrollerView(context: Context) : FrameLayout(context) {
255
255
 
256
256
  internal fun cancelPendingScrollRestore() = pendingRestore.cancel()
257
257
 
258
- internal fun hasPendingScrollRestore(): Boolean = pendingRestore.target != null
259
-
260
258
  internal fun setRefreshOffset(value: Int) {
261
259
  refreshOffset = value
262
260
  applyRefreshOffset()
@@ -27,16 +27,5 @@ fun main() {
27
27
  restore.cancel()
28
28
  check(restore.target == null)
29
29
  check(restore.anchor(120) == 120)
30
- // Cancellation clears the old target without requiring the reached offset to change.
31
- restore.request(target = 640, reached = 120)
32
- check(restore.anchor(120) == 640)
33
- restore.cancel()
34
- check(restore.target == null)
35
- check(restore.anchor(120) == 120)
36
- // A fresh request owns its target after cancellation.
37
- restore.request(target = 320, reached = 120)
38
- check(restore.target == 320)
39
- restore.settle(reached = 320)
40
- check(restore.target == null)
41
30
  println("Native scroller pending restore: clamp retry, partial growth, settle and cancel passed")
42
31
  }