@onekeyfe/react-native-pager-view 3.0.158 → 3.0.160
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/README.md +57 -4
- package/android/src/main/java/com/reactnativepagerview/CollapsiblePagerHost.kt +379 -31
- package/android/src/main/java/com/reactnativepagerview/NativeScrollCoordinatorContributions.kt +15 -0
- package/android/src/main/java/com/reactnativepagerview/NativeScrollerPendingRestore.kt +26 -0
- package/android/src/main/java/com/reactnativepagerview/NativeScrollerScrollAwayInsets.kt +41 -0
- package/android/src/main/java/com/reactnativepagerview/NativeScrollerView.kt +600 -0
- package/android/src/main/java/com/reactnativepagerview/NativeScrollerViewManager.kt +145 -0
- package/android/src/main/java/com/reactnativepagerview/PagerViewViewPackage.kt +1 -1
- package/android/src/main/jni/CMakeLists.txt +19 -0
- package/android/src/main/jni/pagerview.h +11 -0
- package/android/src/main/res/values/native_scroll_coordinator_ids.xml +5 -0
- package/android/src/test/java/com/reactnativepagerview/NativeScrollCoordinatorContributionsTest.kt +26 -0
- package/android/src/test/java/com/reactnativepagerview/NativeScrollerPendingRestoreTest.kt +31 -0
- package/android/src/test/java/com/reactnativepagerview/NativeScrollerScrollAwayInsetsTest.kt +75 -0
- package/common/cpp/react/renderer/components/pagerview/RNCNativeScrollerComponentDescriptor.h +8 -0
- package/common/cpp/react/renderer/components/pagerview/RNCNativeScrollerShadowNode.cpp +15 -0
- package/common/cpp/react/renderer/components/pagerview/RNCNativeScrollerShadowNode.h +23 -0
- package/common/cpp/react/renderer/components/pagerview/RNCNativeScrollerState.h +33 -0
- package/docs/SPEC.md +450 -0
- package/ios/RNCCollapsiblePagerReleasedStatePolicy.h +8 -0
- package/ios/RNCCollapsiblePagerReleasedStatePolicy.m +13 -0
- package/ios/RNCCollapsiblePagerViewComponentView.mm +414 -1
- package/ios/RNCNativeScrollerComponentView.h +17 -0
- package/ios/RNCNativeScrollerComponentView.mm +479 -0
- package/ios/tests/RNCCollapsiblePagerHitTestTests.mm +80 -0
- package/ios/tests/RNCCollapsiblePagerPressCancellationTests.mm +788 -0
- package/ios/tests/RNCCollapsiblePagerPressCancellationWiringTests.mm +109 -0
- package/ios/tests/RNCCollapsiblePagerRefreshControlTests.mm +218 -0
- package/ios/tests/RNCCollapsiblePagerReleasedStatePolicyTests.mm +23 -0
- package/ios/tests/RNCNativeScrollerTests.mm +252 -0
- package/lib/module/CollapsiblePagerView.js +10 -1
- package/lib/module/NativeScroller.js +171 -11
- package/lib/module/NativeScrollerNativeComponent.ts +101 -0
- package/lib/typescript/src/CollapsiblePagerView.d.ts +3 -3
- package/lib/typescript/src/NativeScroller.d.ts +15 -7
- package/lib/typescript/src/NativeScrollerNativeComponent.d.ts +79 -0
- package/package.json +8 -4
- package/react-native-pager-view.podspec +2 -1
- package/react-native.config.js +15 -0
- package/src/CollapsiblePagerView.tsx +14 -4
- package/src/NativeScroller.tsx +291 -14
- package/src/NativeScrollerNativeComponent.ts +101 -0
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
package com.reactnativepagerview
|
|
2
|
+
|
|
3
|
+
import android.graphics.Color
|
|
4
|
+
import android.view.View
|
|
5
|
+
import com.facebook.react.bridge.ColorPropConverter
|
|
6
|
+
import com.facebook.react.bridge.ReadableArray
|
|
7
|
+
import com.facebook.react.bridge.ReadableType
|
|
8
|
+
import com.facebook.react.module.annotations.ReactModule
|
|
9
|
+
import com.facebook.react.uimanager.ReactStylesDiffMap
|
|
10
|
+
import com.facebook.react.uimanager.StateWrapper
|
|
11
|
+
import com.facebook.react.uimanager.ThemedReactContext
|
|
12
|
+
import com.facebook.react.uimanager.ViewGroupManager
|
|
13
|
+
import com.facebook.react.uimanager.ViewManagerDelegate
|
|
14
|
+
import com.facebook.react.uimanager.annotations.ReactProp
|
|
15
|
+
import com.facebook.react.viewmanagers.RNCNativeScrollerManagerDelegate
|
|
16
|
+
import com.facebook.react.viewmanagers.RNCNativeScrollerManagerInterface
|
|
17
|
+
|
|
18
|
+
@ReactModule(name = NativeScrollerViewManager.NAME)
|
|
19
|
+
class NativeScrollerViewManager : ViewGroupManager<NativeScrollerView>(),
|
|
20
|
+
RNCNativeScrollerManagerInterface<NativeScrollerView> {
|
|
21
|
+
private val delegate: ViewManagerDelegate<NativeScrollerView> = RNCNativeScrollerManagerDelegate(this)
|
|
22
|
+
override fun getDelegate() = delegate
|
|
23
|
+
override fun getName() = NAME
|
|
24
|
+
override fun createViewInstance(context: ThemedReactContext) = NativeScrollerView(context)
|
|
25
|
+
override fun needsCustomLayoutForChildren() = false
|
|
26
|
+
override fun addView(parent: NativeScrollerView, child: View, index: Int) = parent.addReactChild(child, index)
|
|
27
|
+
override fun getChildCount(parent: NativeScrollerView) = parent.reactChildCount()
|
|
28
|
+
override fun getChildAt(parent: NativeScrollerView, index: Int) = parent.reactChildAt(index)
|
|
29
|
+
override fun removeViewAt(parent: NativeScrollerView, index: Int) {
|
|
30
|
+
require(index == 0)
|
|
31
|
+
parent.removeReactChild()
|
|
32
|
+
}
|
|
33
|
+
override fun removeAllViews(parent: NativeScrollerView) = parent.removeReactChild()
|
|
34
|
+
override fun onDropViewInstance(view: NativeScrollerView) {
|
|
35
|
+
view.viewport.stopMotion()
|
|
36
|
+
view.setFabricState(null)
|
|
37
|
+
super.onDropViewInstance(view)
|
|
38
|
+
}
|
|
39
|
+
override fun updateState(view: NativeScrollerView, props: ReactStylesDiffMap, stateWrapper: StateWrapper): Any? {
|
|
40
|
+
view.setFabricState(stateWrapper)
|
|
41
|
+
return null
|
|
42
|
+
}
|
|
43
|
+
override fun onAfterUpdateTransaction(view: NativeScrollerView) {
|
|
44
|
+
super.onAfterUpdateTransaction(view)
|
|
45
|
+
view.scheduleLayout()
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
@ReactProp(name = "contentWidth")
|
|
49
|
+
override fun setContentWidth(view: NativeScrollerView, value: Double) = view.setContentSize(width = view.dip(value))
|
|
50
|
+
@ReactProp(name = "contentHeight")
|
|
51
|
+
override fun setContentHeight(view: NativeScrollerView, value: Double) = view.setContentSize(height = view.dip(value))
|
|
52
|
+
@ReactProp(name = "scrollEnabled", defaultBoolean = true)
|
|
53
|
+
override fun setScrollEnabled(view: NativeScrollerView, value: Boolean) = view.setScrollEnabled(value)
|
|
54
|
+
@ReactProp(name = "nestedScrollEnabled", defaultBoolean = true)
|
|
55
|
+
override fun setNestedScrollEnabled(view: NativeScrollerView, value: Boolean) {
|
|
56
|
+
if (!value) view.viewport.stopMotion()
|
|
57
|
+
view.viewport.isNestedScrollingEnabled = value
|
|
58
|
+
}
|
|
59
|
+
@ReactProp(name = "showsVerticalScrollIndicator", defaultBoolean = true)
|
|
60
|
+
override fun setShowsVerticalScrollIndicator(view: NativeScrollerView, value: Boolean) {
|
|
61
|
+
view.viewport.isVerticalScrollBarEnabled = value
|
|
62
|
+
}
|
|
63
|
+
@ReactProp(name = "showsHorizontalScrollIndicator")
|
|
64
|
+
override fun setShowsHorizontalScrollIndicator(view: NativeScrollerView, value: Boolean) {
|
|
65
|
+
view.viewport.isHorizontalScrollBarEnabled = value
|
|
66
|
+
}
|
|
67
|
+
// UIKit-only properties: Android keeps the platform NestedScrollView fling/edge policy.
|
|
68
|
+
@ReactProp(name = "bounces", defaultBoolean = true)
|
|
69
|
+
override fun setBounces(view: NativeScrollerView, value: Boolean) = Unit
|
|
70
|
+
@ReactProp(name = "alwaysBounceVertical", defaultBoolean = true)
|
|
71
|
+
override fun setAlwaysBounceVertical(view: NativeScrollerView, value: Boolean) = Unit
|
|
72
|
+
@ReactProp(name = "decelerationRate", defaultDouble = 0.998)
|
|
73
|
+
override fun setDecelerationRate(view: NativeScrollerView, value: Double) = Unit
|
|
74
|
+
@ReactProp(name = "keyboardDismissMode")
|
|
75
|
+
override fun setKeyboardDismissMode(view: NativeScrollerView, value: String?) {
|
|
76
|
+
view.keyboardDismissMode = value ?: "none"
|
|
77
|
+
}
|
|
78
|
+
@ReactProp(name = "keyboardShouldPersistTaps")
|
|
79
|
+
override fun setKeyboardShouldPersistTaps(view: NativeScrollerView, value: String?) {
|
|
80
|
+
// The JS responder wrapper owns never/handled/always and TextInput exceptions.
|
|
81
|
+
view.keyboardShouldPersistTaps = value ?: "never"
|
|
82
|
+
}
|
|
83
|
+
@ReactProp(name = "scrollEventThrottle")
|
|
84
|
+
override fun setScrollEventThrottle(view: NativeScrollerView, value: Double) {
|
|
85
|
+
view.scrollEventThrottle = value.coerceAtLeast(0.0)
|
|
86
|
+
}
|
|
87
|
+
@ReactProp(name = "contentInsetTop")
|
|
88
|
+
override fun setContentInsetTop(view: NativeScrollerView, value: Double) { view.insetTop = view.dip(value).coerceAtLeast(0) }
|
|
89
|
+
@ReactProp(name = "contentInsetRight")
|
|
90
|
+
override fun setContentInsetRight(view: NativeScrollerView, value: Double) { view.insetRight = view.dip(value).coerceAtLeast(0) }
|
|
91
|
+
@ReactProp(name = "contentInsetBottom")
|
|
92
|
+
override fun setContentInsetBottom(view: NativeScrollerView, value: Double) { view.insetBottom = view.dip(value).coerceAtLeast(0) }
|
|
93
|
+
@ReactProp(name = "contentInsetLeft")
|
|
94
|
+
override fun setContentInsetLeft(view: NativeScrollerView, value: Double) { view.insetLeft = view.dip(value).coerceAtLeast(0) }
|
|
95
|
+
@ReactProp(name = "refreshEnabled")
|
|
96
|
+
override fun setRefreshEnabled(view: NativeScrollerView, value: Boolean) { view.refreshEnabled = value }
|
|
97
|
+
@ReactProp(name = "refreshing")
|
|
98
|
+
override fun setRefreshing(view: NativeScrollerView, value: Boolean) = view.setRefreshing(value)
|
|
99
|
+
@ReactProp(name = "refreshTintColor", customType = "Color")
|
|
100
|
+
override fun setRefreshTintColor(view: NativeScrollerView, value: Int?) {
|
|
101
|
+
// Android's refreshColors determines the native arc; tintColor is iOS-only.
|
|
102
|
+
}
|
|
103
|
+
@ReactProp(name = "refreshColors", customType = "ColorArray")
|
|
104
|
+
override fun setRefreshColors(view: NativeScrollerView, value: ReadableArray?) {
|
|
105
|
+
if (value == null) {
|
|
106
|
+
view.setRefreshColors(intArrayOf(Color.GRAY))
|
|
107
|
+
return
|
|
108
|
+
}
|
|
109
|
+
val colors = ArrayList<Int>(value.size())
|
|
110
|
+
for (index in 0 until value.size()) {
|
|
111
|
+
// PlatformColor/DynamicColorIOS values arrive as maps, as in RN's SwipeRefreshLayoutManager.
|
|
112
|
+
when (value.getType(index)) {
|
|
113
|
+
ReadableType.Map -> ColorPropConverter.getColor(value.getMap(index), view.context)?.let(colors::add)
|
|
114
|
+
ReadableType.Number -> colors.add(value.getInt(index))
|
|
115
|
+
else -> Unit
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
view.setRefreshColors(colors.toIntArray())
|
|
119
|
+
}
|
|
120
|
+
@ReactProp(name = "refreshProgressBackgroundColor", customType = "Color")
|
|
121
|
+
override fun setRefreshProgressBackgroundColor(view: NativeScrollerView, value: Int?) =
|
|
122
|
+
view.setRefreshBackground(value ?: Color.WHITE)
|
|
123
|
+
@ReactProp(name = "refreshProgressViewOffset")
|
|
124
|
+
override fun setRefreshProgressViewOffset(view: NativeScrollerView, value: Double) = view.setRefreshOffset(view.dip(value))
|
|
125
|
+
@ReactProp(name = "refreshTitle")
|
|
126
|
+
override fun setRefreshTitle(view: NativeScrollerView, value: String?) = Unit
|
|
127
|
+
@ReactProp(name = "refreshTitleColor", customType = "Color")
|
|
128
|
+
override fun setRefreshTitleColor(view: NativeScrollerView, value: Int?) = Unit
|
|
129
|
+
@ReactProp(name = "refreshSize")
|
|
130
|
+
override fun setRefreshSize(view: NativeScrollerView, value: String?) = view.setRefreshSize(value)
|
|
131
|
+
|
|
132
|
+
override fun receiveCommand(view: NativeScrollerView, commandId: String, args: ReadableArray?) =
|
|
133
|
+
delegate.receiveCommand(view, commandId, args)
|
|
134
|
+
override fun setRefreshState(view: NativeScrollerView, refreshing: Boolean) = view.setRefreshing(refreshing)
|
|
135
|
+
override fun scrollTo(view: NativeScrollerView, x: Double, y: Double, animated: Boolean) =
|
|
136
|
+
view.scrollToPosition(view.dip(x), view.dip(y), animated)
|
|
137
|
+
override fun scrollToEnd(view: NativeScrollerView, animated: Boolean) = view.scrollToEnd(animated)
|
|
138
|
+
override fun flashScrollIndicators(view: NativeScrollerView) { view.viewport.flashIndicators() }
|
|
139
|
+
|
|
140
|
+
override fun getExportedCustomDirectEventTypeConstants(): MutableMap<String, Map<String, String>> =
|
|
141
|
+
listOf("Scroll", "ScrollBeginDrag", "ScrollEndDrag", "MomentumScrollBegin", "MomentumScrollEnd", "Refresh", "ContentViewportChange")
|
|
142
|
+
.associate { "top$it" to mapOf("registrationName" to "on$it") }.toMutableMap()
|
|
143
|
+
|
|
144
|
+
companion object { const val NAME = "RNCNativeScroller" }
|
|
145
|
+
}
|
|
@@ -12,6 +12,6 @@ class PagerViewPackage : ReactPackage {
|
|
|
12
12
|
}
|
|
13
13
|
|
|
14
14
|
override fun createViewManagers(reactContext: ReactApplicationContext): List<ViewManager<*, *>> {
|
|
15
|
-
return listOf(PagerViewViewManager(), CollapsiblePagerViewManager())
|
|
15
|
+
return listOf(PagerViewViewManager(), CollapsiblePagerViewManager(), NativeScrollerViewManager())
|
|
16
16
|
}
|
|
17
17
|
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
cmake_minimum_required(VERSION 3.13)
|
|
2
|
+
|
|
3
|
+
set(PAGER_ROOT ${CMAKE_CURRENT_SOURCE_DIR}/../../../..)
|
|
4
|
+
set(PAGER_GENERATED ${PAGER_ROOT}/android/build/generated/source/codegen/jni)
|
|
5
|
+
set(PAGER_COMMON ${PAGER_ROOT}/common/cpp)
|
|
6
|
+
file(GLOB PAGER_GENERATED_SOURCES CONFIGURE_DEPENDS
|
|
7
|
+
${PAGER_GENERATED}/*.cpp
|
|
8
|
+
${PAGER_GENERATED}/react/renderer/components/pagerview/*.cpp)
|
|
9
|
+
|
|
10
|
+
add_library(react_codegen_pagerview OBJECT
|
|
11
|
+
${PAGER_GENERATED_SOURCES}
|
|
12
|
+
${PAGER_COMMON}/react/renderer/components/pagerview/RNCNativeScrollerShadowNode.cpp)
|
|
13
|
+
target_include_directories(react_codegen_pagerview PUBLIC
|
|
14
|
+
${CMAKE_CURRENT_SOURCE_DIR}
|
|
15
|
+
${PAGER_COMMON}
|
|
16
|
+
${PAGER_GENERATED}
|
|
17
|
+
${PAGER_GENERATED}/react/renderer/components/pagerview)
|
|
18
|
+
target_link_libraries(react_codegen_pagerview fbjni jsi reactnative)
|
|
19
|
+
target_compile_reactnative_options(react_codegen_pagerview PRIVATE)
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
#pragma once
|
|
2
|
+
|
|
3
|
+
#include <ReactCommon/JavaTurboModule.h>
|
|
4
|
+
#include <ReactCommon/TurboModule.h>
|
|
5
|
+
#include <jsi/jsi.h>
|
|
6
|
+
#include <react/renderer/components/pagerview/RNCNativeScrollerComponentDescriptor.h>
|
|
7
|
+
|
|
8
|
+
namespace facebook::react {
|
|
9
|
+
JSI_EXPORT std::shared_ptr<TurboModule> pagerview_ModuleProvider(
|
|
10
|
+
const std::string &moduleName, const JavaTurboModule::InitParams ¶ms);
|
|
11
|
+
} // namespace facebook::react
|
package/android/src/test/java/com/reactnativepagerview/NativeScrollCoordinatorContributionsTest.kt
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
package com.reactnativepagerview
|
|
2
|
+
|
|
3
|
+
/** Standalone JVM regression: compile together with the production helper. */
|
|
4
|
+
fun main() {
|
|
5
|
+
val outer = Any()
|
|
6
|
+
val inner = Any()
|
|
7
|
+
val firstChild = NativeScrollCoordinatorContributions()
|
|
8
|
+
check(firstChild.update(outer, 120))
|
|
9
|
+
check(firstChild.update(inner, 60))
|
|
10
|
+
check(firstChild.values.sum() == 180)
|
|
11
|
+
check(!firstChild.update(outer, 120))
|
|
12
|
+
check(firstChild.update(outer, 30))
|
|
13
|
+
check(firstChild.values.sum() == 90)
|
|
14
|
+
check(firstChild.clearOwner(outer))
|
|
15
|
+
check(firstChild.values.sum() == 60)
|
|
16
|
+
check(!firstChild.clearOwner(outer))
|
|
17
|
+
val secondChild = NativeScrollCoordinatorContributions()
|
|
18
|
+
check(secondChild.update(outer, 30))
|
|
19
|
+
check(secondChild.values.sum() == 30)
|
|
20
|
+
check(firstChild.values.sum() == 60)
|
|
21
|
+
check(firstChild.clearOwner(inner))
|
|
22
|
+
check(firstChild.isEmpty())
|
|
23
|
+
check(secondChild.update(outer, -1))
|
|
24
|
+
check(secondChild.values.sum() == 0)
|
|
25
|
+
println("Native coordinator contributions: nested owners, duplicate updates, cleanup, and replacement passed")
|
|
26
|
+
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
package com.reactnativepagerview
|
|
2
|
+
|
|
3
|
+
/** Standalone JVM regression: compile together with the production helper. */
|
|
4
|
+
fun main() {
|
|
5
|
+
val restore = NativeScrollerPendingRestore()
|
|
6
|
+
|
|
7
|
+
// Reachable immediately: nothing remains pending and layout keeps the current anchor.
|
|
8
|
+
restore.request(target = 640, reached = 640)
|
|
9
|
+
check(restore.target == null)
|
|
10
|
+
check(restore.anchor(320) == 320)
|
|
11
|
+
|
|
12
|
+
// Content height has not reached native: NestedScrollView clamped the request to 0.
|
|
13
|
+
restore.request(target = 640, reached = 0)
|
|
14
|
+
check(restore.target == 640)
|
|
15
|
+
check(restore.anchor(0) == 640)
|
|
16
|
+
// Partial growth keeps retrying the original target, not the partially clamped offset.
|
|
17
|
+
restore.settle(reached = 300)
|
|
18
|
+
check(restore.target == 640)
|
|
19
|
+
check(restore.anchor(300) == 640)
|
|
20
|
+
// Once reached, later layouts keep the live position again.
|
|
21
|
+
restore.settle(reached = 640)
|
|
22
|
+
check(restore.target == null)
|
|
23
|
+
check(restore.anchor(900) == 900)
|
|
24
|
+
|
|
25
|
+
// User touch, commands and content replacement cancel a pending target.
|
|
26
|
+
restore.request(target = 480, reached = 120)
|
|
27
|
+
restore.cancel()
|
|
28
|
+
check(restore.target == null)
|
|
29
|
+
check(restore.anchor(120) == 120)
|
|
30
|
+
println("Native scroller pending restore: clamp retry, partial growth, settle and cancel passed")
|
|
31
|
+
}
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
package com.reactnativepagerview
|
|
2
|
+
|
|
3
|
+
/** Standalone JVM contract regression for Fabric scroller inset ownership. */
|
|
4
|
+
fun main() {
|
|
5
|
+
val initialTop = 24
|
|
6
|
+
val firstHeader = 182 + 48
|
|
7
|
+
val initialApplied = nativeScrollerScrollAwayTop(initialTop, 0, firstHeader)
|
|
8
|
+
check(initialApplied == 254)
|
|
9
|
+
check(nativeScrollerScrollAwayTop(initialApplied, firstHeader, firstHeader) == initialApplied)
|
|
10
|
+
val measuredHeader = 310 + 48
|
|
11
|
+
val resized = nativeScrollerScrollAwayTop(initialApplied, firstHeader, measuredHeader)
|
|
12
|
+
check(resized == initialTop + measuredHeader)
|
|
13
|
+
// A second pager's contribution survives the first pager's detach.
|
|
14
|
+
val nested = nativeScrollerScrollAwayTop(resized, 0, 100)
|
|
15
|
+
val outerDetached = nativeScrollerScrollAwayTop(nested, measuredHeader, 0)
|
|
16
|
+
check(outerDetached == initialTop + 100)
|
|
17
|
+
check(nativeScrollerScrollAwayTop(outerDetached, 100, 0) == initialTop)
|
|
18
|
+
// Fabric may reset state while replacing its content root; do not apply a negative baseline.
|
|
19
|
+
check(nativeScrollerScrollAwayTop(0, measuredHeader, firstHeader) == firstHeader)
|
|
20
|
+
// Caller L/R/B = 16/16/40 must survive RN's setter replay after our 230px inset.
|
|
21
|
+
val caller = intArrayOf(16, 0, 16, 40)
|
|
22
|
+
val rnReplay = intArrayOf(0, 0, 0, 230)
|
|
23
|
+
val keepCaller = nativeScrollerPaddingWasResetByScrollAway(
|
|
24
|
+
230, rnReplay[0], rnReplay[1], rnReplay[2], rnReplay[3], 230, 0,
|
|
25
|
+
)
|
|
26
|
+
check(keepCaller)
|
|
27
|
+
val restored = if (keepCaller) caller else rnReplay
|
|
28
|
+
check(restored.contentEquals(intArrayOf(16, 0, 16, 40)))
|
|
29
|
+
// Nonzero native bottom state is part of RN's reset signature too.
|
|
30
|
+
check(nativeScrollerPaddingWasResetByScrollAway(230, 0, 0, 0, 278, 254, 24))
|
|
31
|
+
// Actual caller updates, including clearing all padding, remain observable.
|
|
32
|
+
check(!nativeScrollerPaddingWasResetByScrollAway(230, 24, 0, 24, 290, 230, 0))
|
|
33
|
+
check(!nativeScrollerPaddingWasResetByScrollAway(230, 0, 0, 0, 0, 230, 0))
|
|
34
|
+
// Initial discovery must capture caller values before this pager owns an inset.
|
|
35
|
+
check(!nativeScrollerPaddingWasResetByScrollAway(0, 0, 0, 0, 230, 230, 0))
|
|
36
|
+
println("NativeScroller ScrollAway ownership: initial, repeat, measured resize, nested detach, Fabric reset, RN padding replay, and caller updates passed")
|
|
37
|
+
|
|
38
|
+
val firstOwner = Any()
|
|
39
|
+
val secondOwner = Any()
|
|
40
|
+
val alpha = NativeRefreshForegroundAlpha(0.75f)
|
|
41
|
+
check(alpha.isEmpty)
|
|
42
|
+
var current = alpha.update(0.75f, firstOwner, acquire = true)
|
|
43
|
+
check(current == 0f && alpha.drawingAlpha == 0.75f && !alpha.isEmpty)
|
|
44
|
+
current = alpha.update(current, firstOwner, acquire = true)
|
|
45
|
+
check(current == 0f && alpha.drawingAlpha == 0.75f)
|
|
46
|
+
current = alpha.update(current, secondOwner, acquire = true)
|
|
47
|
+
current = alpha.update(current, firstOwner, acquire = false)
|
|
48
|
+
check(current == 0f && !alpha.isEmpty)
|
|
49
|
+
current = alpha.update(current, secondOwner, acquire = false)
|
|
50
|
+
check(current == 0.75f && alpha.isEmpty)
|
|
51
|
+
|
|
52
|
+
current = alpha.update(current, firstOwner, acquire = true)
|
|
53
|
+
current = alpha.update(current, secondOwner, acquire = true)
|
|
54
|
+
current = alpha.update(current, secondOwner, acquire = false)
|
|
55
|
+
check(current == 0f)
|
|
56
|
+
current = alpha.update(current, firstOwner, acquire = false)
|
|
57
|
+
check(current == 0.75f && alpha.isEmpty)
|
|
58
|
+
|
|
59
|
+
current = alpha.update(current, firstOwner, acquire = true)
|
|
60
|
+
current = alpha.update(0.4f, firstOwner, acquire = true)
|
|
61
|
+
check(current == 0f && alpha.drawingAlpha == 0.4f)
|
|
62
|
+
current = alpha.update(current, firstOwner, acquire = false)
|
|
63
|
+
check(current == 0.4f && alpha.isEmpty)
|
|
64
|
+
|
|
65
|
+
val transparent = NativeRefreshForegroundAlpha(0f)
|
|
66
|
+
check(transparent.update(0f, firstOwner, acquire = true) == 0f)
|
|
67
|
+
check(!transparent.isEmpty && transparent.drawingAlpha == 0f)
|
|
68
|
+
check(transparent.update(0f, firstOwner, acquire = false) == 0f && transparent.isEmpty)
|
|
69
|
+
// RN caller offset is already in top; an absent coordinator inset is zero.
|
|
70
|
+
check(nativeRefreshForegroundTop(37, 0f) == 37f)
|
|
71
|
+
// A list publishes the sum of both actual ancestor insets; subtract it once.
|
|
72
|
+
check(nativeRefreshForegroundTop(37 + 230 + 64, 294f) == 37f)
|
|
73
|
+
check(nativeRefreshForegroundTop(-40 + 294, 294f) == -40f)
|
|
74
|
+
println("Refresh foreground policy: repeat, owner transfer/release, external alpha, transparent baseline, caller offset, and combined nested inset passed")
|
|
75
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
#pragma once
|
|
2
|
+
|
|
3
|
+
#include <react/renderer/components/pagerview/RNCNativeScrollerShadowNode.h>
|
|
4
|
+
#include <react/renderer/core/ConcreteComponentDescriptor.h>
|
|
5
|
+
|
|
6
|
+
namespace facebook::react {
|
|
7
|
+
using RNCNativeScrollerComponentDescriptor = ConcreteComponentDescriptor<RNCNativeScrollerShadowNode>;
|
|
8
|
+
} // namespace facebook::react
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
#include <react/renderer/components/pagerview/RNCNativeScrollerShadowNode.h>
|
|
2
|
+
|
|
3
|
+
namespace facebook::react {
|
|
4
|
+
|
|
5
|
+
const char RNCNativeScrollerComponentName[] = "RNCNativeScroller";
|
|
6
|
+
|
|
7
|
+
Point RNCNativeScrollerShadowNode::getContentOriginOffset(bool includeTransform) const {
|
|
8
|
+
const auto state = getStateData();
|
|
9
|
+
const auto origin = state.contentOrigin;
|
|
10
|
+
const auto transform = includeTransform ? getTransform() : Transform::Identity();
|
|
11
|
+
const auto result = transform * Vector{origin.x, origin.y, 0.0f, 1.0f};
|
|
12
|
+
return {result.x + state.ancestorOffset.x, result.y + state.ancestorOffset.y};
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
} // namespace facebook::react
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
#pragma once
|
|
2
|
+
|
|
3
|
+
#include <jsi/jsi.h>
|
|
4
|
+
#include <react/renderer/components/pagerview/EventEmitters.h>
|
|
5
|
+
#include <react/renderer/components/pagerview/Props.h>
|
|
6
|
+
#include <react/renderer/components/pagerview/RNCNativeScrollerState.h>
|
|
7
|
+
#include <react/renderer/components/view/ConcreteViewShadowNode.h>
|
|
8
|
+
|
|
9
|
+
namespace facebook::react {
|
|
10
|
+
|
|
11
|
+
JSI_EXPORT extern const char RNCNativeScrollerComponentName[];
|
|
12
|
+
|
|
13
|
+
class JSI_EXPORT RNCNativeScrollerShadowNode final
|
|
14
|
+
: public ConcreteViewShadowNode<RNCNativeScrollerComponentName,
|
|
15
|
+
RNCNativeScrollerProps,
|
|
16
|
+
RNCNativeScrollerEventEmitter,
|
|
17
|
+
RNCNativeScrollerState> {
|
|
18
|
+
public:
|
|
19
|
+
using ConcreteViewShadowNode::ConcreteViewShadowNode;
|
|
20
|
+
Point getContentOriginOffset(bool includeTransform) const override;
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
} // namespace facebook::react
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
#pragma once
|
|
2
|
+
|
|
3
|
+
#include <react/renderer/graphics/Point.h>
|
|
4
|
+
#ifdef RN_SERIALIZABLE_STATE
|
|
5
|
+
#include <folly/dynamic.h>
|
|
6
|
+
#endif
|
|
7
|
+
|
|
8
|
+
namespace facebook::react {
|
|
9
|
+
|
|
10
|
+
// Local content displacement and ancestor translation have different transform spaces.
|
|
11
|
+
class RNCNativeScrollerState final {
|
|
12
|
+
public:
|
|
13
|
+
Point contentOrigin{};
|
|
14
|
+
Point ancestorOffset{};
|
|
15
|
+
RNCNativeScrollerState() = default;
|
|
16
|
+
explicit RNCNativeScrollerState(Point origin) : contentOrigin(origin) {}
|
|
17
|
+
|
|
18
|
+
#ifdef RN_SERIALIZABLE_STATE
|
|
19
|
+
RNCNativeScrollerState(const RNCNativeScrollerState &, folly::dynamic data)
|
|
20
|
+
: contentOrigin({static_cast<Float>(data["contentOriginX"].getDouble()),
|
|
21
|
+
static_cast<Float>(data["contentOriginY"].getDouble())}),
|
|
22
|
+
ancestorOffset({static_cast<Float>(data.getDefault("ancestorOffsetX", 0.0).getDouble()),
|
|
23
|
+
static_cast<Float>(data.getDefault("ancestorOffsetY", 0.0).getDouble())}) {}
|
|
24
|
+
|
|
25
|
+
folly::dynamic getDynamic() const {
|
|
26
|
+
return folly::dynamic::object("contentOriginX", contentOrigin.x)
|
|
27
|
+
("contentOriginY", contentOrigin.y)
|
|
28
|
+
("ancestorOffsetX", ancestorOffset.x)("ancestorOffsetY", ancestorOffset.y);
|
|
29
|
+
}
|
|
30
|
+
#endif
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
} // namespace facebook::react
|