react-native-screens 3.35.0-rc.0 → 3.35.0
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 +1 -1
- package/android/CMakeLists.txt +28 -19
- package/android/build.gradle +18 -2
- package/android/src/fabric/java/com/swmansion/rnscreens/FabricEnabledViewGroup.kt +4 -3
- package/android/src/main/java/com/swmansion/rnscreens/Screen.kt +18 -34
- package/android/src/main/java/com/swmansion/rnscreens/ScreenStack.kt +9 -3
- package/android/src/main/java/com/swmansion/rnscreens/ScreenViewManager.kt +2 -1
- package/android/src/main/java/com/swmansion/rnscreens/ScreenWindowTraits.kt +1 -1
- package/android/src/main/java/com/swmansion/rnscreens/events/HeaderHeightChangeEvent.kt +3 -3
- package/android/src/main/java/com/swmansion/rnscreens/ext/ViewExt.kt +56 -0
- package/android/src/main/java/com/swmansion/rnscreens/utils/ScreenDummyLayoutHelper.kt +45 -8
- package/android/src/main/jni/CMakeLists.txt +28 -19
- package/android/src/main/res/base/anim/rns_ios_from_left_background_close.xml +5 -0
- package/android/src/main/res/base/anim/{rns_slide_out_to_left_ios.xml → rns_ios_from_left_background_open.xml} +1 -1
- package/android/src/main/res/base/anim/rns_ios_from_left_foreground_close.xml +6 -0
- package/android/src/main/res/base/anim/rns_ios_from_left_foreground_open.xml +6 -0
- package/android/src/main/res/base/anim/rns_ios_from_right_background_open.xml +5 -0
- package/android/src/paper/java/com/swmansion/rnscreens/FabricEnabledViewGroup.kt +1 -1
- package/common/cpp/react/renderer/components/rnscreens/RNSScreenComponentDescriptor.h +5 -99
- package/common/cpp/react/renderer/components/rnscreens/RNSScreenShadowNode.cpp +101 -0
- package/common/cpp/react/renderer/components/rnscreens/RNSScreenShadowNode.h +2 -0
- package/ios/RNSConvert.h +13 -4
- package/ios/RNSConvert.mm +54 -29
- package/ios/RNSEnums.h +46 -0
- package/ios/RNSFullWindowOverlay.mm +6 -0
- package/ios/RNSModalScreen.mm +7 -0
- package/ios/RNSScreen.h +14 -0
- package/ios/RNSScreen.mm +22 -4
- package/ios/RNSScreenContainer.mm +6 -0
- package/ios/RNSScreenNavigationContainer.mm +7 -0
- package/ios/RNSScreenStack.mm +53 -7
- package/ios/RNSScreenStackHeaderConfig.h +1 -1
- package/ios/RNSScreenStackHeaderConfig.mm +54 -29
- package/ios/RNSScreenStackHeaderSubview.mm +30 -3
- package/ios/RNSSearchBar.mm +7 -0
- package/lib/commonjs/TransitionProgressContext.js +1 -0
- package/lib/commonjs/TransitionProgressContext.js.map +1 -1
- package/lib/commonjs/components/FullWindowOverlay.js +8 -5
- package/lib/commonjs/components/FullWindowOverlay.js.map +1 -1
- package/lib/commonjs/components/Screen.js +9 -0
- package/lib/commonjs/components/Screen.js.map +1 -1
- package/lib/commonjs/components/Screen.web.js +2 -0
- package/lib/commonjs/components/Screen.web.js.map +1 -1
- package/lib/commonjs/components/ScreenContainer.js +1 -0
- package/lib/commonjs/components/ScreenContainer.js.map +1 -1
- package/lib/commonjs/components/ScreenStack.js +1 -0
- package/lib/commonjs/components/ScreenStack.js.map +1 -1
- package/lib/commonjs/components/ScreenStackHeaderConfig.js +1 -0
- package/lib/commonjs/components/ScreenStackHeaderConfig.js.map +1 -1
- package/lib/commonjs/components/SearchBar.js +1 -0
- package/lib/commonjs/components/SearchBar.js.map +1 -1
- package/lib/commonjs/core.js +1 -0
- package/lib/commonjs/core.js.map +1 -1
- package/lib/commonjs/fabric/FullWindowOverlayNativeComponent.js +1 -0
- package/lib/commonjs/fabric/FullWindowOverlayNativeComponent.js.map +1 -1
- package/lib/commonjs/fabric/ModalScreenNativeComponent.js +1 -0
- package/lib/commonjs/fabric/ModalScreenNativeComponent.js.map +1 -1
- package/lib/commonjs/fabric/NativeScreensModule.js +2 -1
- package/lib/commonjs/fabric/NativeScreensModule.js.map +1 -1
- package/lib/commonjs/fabric/ScreenContainerNativeComponent.js +1 -0
- package/lib/commonjs/fabric/ScreenContainerNativeComponent.js.map +1 -1
- package/lib/commonjs/fabric/ScreenNativeComponent.js +1 -0
- package/lib/commonjs/fabric/ScreenNativeComponent.js.map +1 -1
- package/lib/commonjs/fabric/ScreenNavigationContainerNativeComponent.js +1 -0
- package/lib/commonjs/fabric/ScreenNavigationContainerNativeComponent.js.map +1 -1
- package/lib/commonjs/fabric/ScreenStackHeaderConfigNativeComponent.js +1 -0
- package/lib/commonjs/fabric/ScreenStackHeaderConfigNativeComponent.js.map +1 -1
- package/lib/commonjs/fabric/ScreenStackHeaderSubviewNativeComponent.js +1 -0
- package/lib/commonjs/fabric/ScreenStackHeaderSubviewNativeComponent.js.map +1 -1
- package/lib/commonjs/fabric/ScreenStackNativeComponent.js +1 -0
- package/lib/commonjs/fabric/ScreenStackNativeComponent.js.map +1 -1
- package/lib/commonjs/fabric/SearchBarNativeComponent.js +2 -2
- package/lib/commonjs/fabric/SearchBarNativeComponent.js.map +1 -1
- package/lib/commonjs/native-stack/contexts/GHContext.js +1 -0
- package/lib/commonjs/native-stack/contexts/GHContext.js.map +1 -1
- package/lib/module/TransitionProgressContext.js +2 -0
- package/lib/module/TransitionProgressContext.js.map +1 -1
- package/lib/module/components/FullWindowOverlay.js +9 -6
- package/lib/module/components/FullWindowOverlay.js.map +1 -1
- package/lib/module/components/Screen.js +10 -0
- package/lib/module/components/Screen.js.map +1 -1
- package/lib/module/components/Screen.web.js +3 -0
- package/lib/module/components/Screen.web.js.map +1 -1
- package/lib/module/components/ScreenContainer.js +2 -0
- package/lib/module/components/ScreenContainer.js.map +1 -1
- package/lib/module/components/ScreenStack.js +2 -0
- package/lib/module/components/ScreenStack.js.map +1 -1
- package/lib/module/components/ScreenStackHeaderConfig.js +2 -0
- package/lib/module/components/ScreenStackHeaderConfig.js.map +1 -1
- package/lib/module/components/SearchBar.js +2 -0
- package/lib/module/components/SearchBar.js.map +1 -1
- package/lib/module/core.js +2 -0
- package/lib/module/core.js.map +1 -1
- package/lib/module/fabric/FullWindowOverlayNativeComponent.js +2 -0
- package/lib/module/fabric/FullWindowOverlayNativeComponent.js.map +1 -1
- package/lib/module/fabric/ModalScreenNativeComponent.js +2 -0
- package/lib/module/fabric/ModalScreenNativeComponent.js.map +1 -1
- package/lib/module/fabric/NativeScreensModule.js +2 -1
- package/lib/module/fabric/NativeScreensModule.js.map +1 -1
- package/lib/module/fabric/ScreenContainerNativeComponent.js +2 -0
- package/lib/module/fabric/ScreenContainerNativeComponent.js.map +1 -1
- package/lib/module/fabric/ScreenNativeComponent.js +2 -0
- package/lib/module/fabric/ScreenNativeComponent.js.map +1 -1
- package/lib/module/fabric/ScreenNavigationContainerNativeComponent.js +2 -0
- package/lib/module/fabric/ScreenNavigationContainerNativeComponent.js.map +1 -1
- package/lib/module/fabric/ScreenStackHeaderConfigNativeComponent.js +2 -0
- package/lib/module/fabric/ScreenStackHeaderConfigNativeComponent.js.map +1 -1
- package/lib/module/fabric/ScreenStackHeaderSubviewNativeComponent.js +2 -0
- package/lib/module/fabric/ScreenStackHeaderSubviewNativeComponent.js.map +1 -1
- package/lib/module/fabric/ScreenStackNativeComponent.js +2 -0
- package/lib/module/fabric/ScreenStackNativeComponent.js.map +1 -1
- package/lib/module/fabric/SearchBarNativeComponent.js +2 -0
- package/lib/module/fabric/SearchBarNativeComponent.js.map +1 -1
- package/lib/module/native-stack/contexts/GHContext.js +2 -0
- package/lib/module/native-stack/contexts/GHContext.js.map +1 -1
- package/lib/typescript/TransitionProgressContext.d.ts.map +1 -1
- package/lib/typescript/components/FullWindowOverlay.d.ts.map +1 -1
- package/lib/typescript/components/Screen.d.ts.map +1 -1
- package/lib/typescript/components/Screen.web.d.ts.map +1 -1
- package/lib/typescript/components/ScreenContainer.d.ts.map +1 -1
- package/lib/typescript/components/ScreenStack.d.ts.map +1 -1
- package/lib/typescript/components/ScreenStackHeaderConfig.d.ts.map +1 -1
- package/lib/typescript/components/SearchBar.d.ts.map +1 -1
- package/lib/typescript/core.d.ts.map +1 -1
- package/lib/typescript/fabric/FullWindowOverlayNativeComponent.d.ts.map +1 -1
- package/lib/typescript/fabric/ModalScreenNativeComponent.d.ts.map +1 -1
- package/lib/typescript/fabric/NativeScreensModule.d.ts.map +1 -1
- package/lib/typescript/fabric/ScreenContainerNativeComponent.d.ts.map +1 -1
- package/lib/typescript/fabric/ScreenNativeComponent.d.ts +1 -1
- package/lib/typescript/fabric/ScreenNativeComponent.d.ts.map +1 -1
- package/lib/typescript/fabric/ScreenNavigationContainerNativeComponent.d.ts.map +1 -1
- package/lib/typescript/fabric/ScreenStackHeaderConfigNativeComponent.d.ts +2 -2
- package/lib/typescript/fabric/ScreenStackHeaderConfigNativeComponent.d.ts.map +1 -1
- package/lib/typescript/fabric/ScreenStackHeaderSubviewNativeComponent.d.ts.map +1 -1
- package/lib/typescript/fabric/ScreenStackNativeComponent.d.ts.map +1 -1
- package/lib/typescript/fabric/SearchBarNativeComponent.d.ts.map +1 -1
- package/lib/typescript/native-stack/contexts/GHContext.d.ts.map +1 -1
- package/lib/typescript/native-stack/types.d.ts +3 -1
- package/lib/typescript/native-stack/types.d.ts.map +1 -1
- package/lib/typescript/types.d.ts +5 -3
- package/lib/typescript/types.d.ts.map +1 -1
- package/native-stack/README.md +3 -1
- package/package.json +1 -1
- package/src/TransitionProgressContext.tsx +2 -0
- package/src/components/FullWindowOverlay.tsx +10 -2
- package/src/components/Screen.tsx +8 -0
- package/src/components/Screen.web.tsx +3 -0
- package/src/components/ScreenContainer.tsx +2 -0
- package/src/components/ScreenStack.tsx +2 -0
- package/src/components/ScreenStackHeaderConfig.tsx +2 -0
- package/src/components/SearchBar.tsx +2 -0
- package/src/core.ts +2 -0
- package/src/fabric/FullWindowOverlayNativeComponent.ts +2 -0
- package/src/fabric/ModalScreenNativeComponent.ts +2 -0
- package/src/fabric/NativeScreensModule.ts +2 -0
- package/src/fabric/ScreenContainerNativeComponent.ts +2 -0
- package/src/fabric/ScreenNativeComponent.ts +5 -1
- package/src/fabric/ScreenNavigationContainerNativeComponent.ts +2 -0
- package/src/fabric/ScreenStackHeaderConfigNativeComponent.ts +4 -1
- package/src/fabric/ScreenStackHeaderSubviewNativeComponent.ts +2 -0
- package/src/fabric/ScreenStackNativeComponent.ts +2 -0
- package/src/fabric/SearchBarNativeComponent.ts +2 -0
- package/src/native-stack/contexts/GHContext.tsx +2 -0
- package/src/native-stack/types.tsx +3 -1
- package/src/types.tsx +7 -2
- package/windows/RNScreens/Screen.h +3 -1
- /package/android/src/main/res/base/anim/{rns_slide_in_from_left_ios.xml → rns_ios_from_right_background_close.xml} +0 -0
- /package/android/src/main/res/base/anim/{rns_slide_out_to_right_ios.xml → rns_ios_from_right_foreground_close.xml} +0 -0
- /package/android/src/main/res/base/anim/{rns_slide_in_from_right_ios.xml → rns_ios_from_right_foreground_open.xml} +0 -0
package/README.md
CHANGED
|
@@ -188,7 +188,7 @@ To take advantage of the native stack navigator primitive for React Navigation t
|
|
|
188
188
|
|
|
189
189
|
## `FullWindowOverlay`
|
|
190
190
|
|
|
191
|
-
Native `iOS` component for rendering views straight under the `Window`. Based on `RCTPerfMonitor`. You should treat it as a wrapper, providing full-screen, transparent view which receives no props and should ideally render one child `View`, being the root of its view hierarchy. For the example usage, see https://github.com/software-mansion/react-native-screens/blob/main/
|
|
191
|
+
Native `iOS` component for rendering views straight under the `Window`. Based on `RCTPerfMonitor`. You should treat it as a wrapper, providing full-screen, transparent view which receives no props and should ideally render one child `View`, being the root of its view hierarchy. For the example usage, see https://github.com/software-mansion/react-native-screens/blob/main/apps/src/tests/Test1096.tsx
|
|
192
192
|
|
|
193
193
|
## Interop with [react-native-navigation](https://github.com/wix/react-native-navigation)
|
|
194
194
|
|
package/android/CMakeLists.txt
CHANGED
|
@@ -41,28 +41,37 @@ find_package(ReactAndroid REQUIRED CONFIG)
|
|
|
41
41
|
if(${RNS_NEW_ARCH_ENABLED})
|
|
42
42
|
find_package(fbjni REQUIRED CONFIG)
|
|
43
43
|
|
|
44
|
-
|
|
45
|
-
rnscreens
|
|
44
|
+
if(ReactAndroid_VERSION_MINOR GREATER_EQUAL 76)
|
|
45
|
+
target_link_libraries(rnscreens
|
|
46
|
+
ReactAndroid::reactnative
|
|
46
47
|
ReactAndroid::jsi
|
|
47
|
-
ReactAndroid::react_nativemodule_core
|
|
48
|
-
ReactAndroid::react_utils
|
|
49
|
-
ReactAndroid::reactnativejni
|
|
50
|
-
ReactAndroid::fabricjni
|
|
51
|
-
ReactAndroid::react_debug
|
|
52
|
-
ReactAndroid::react_render_core
|
|
53
|
-
ReactAndroid::runtimeexecutor
|
|
54
|
-
ReactAndroid::react_render_graphics
|
|
55
|
-
ReactAndroid::rrc_view
|
|
56
|
-
ReactAndroid::yoga
|
|
57
|
-
ReactAndroid::rrc_text
|
|
58
|
-
ReactAndroid::glog
|
|
59
|
-
ReactAndroid::react_render_componentregistry
|
|
60
|
-
ReactAndroid::react_render_consistency
|
|
61
|
-
ReactAndroid::react_performance_timeline
|
|
62
|
-
ReactAndroid::react_render_observers_events
|
|
63
48
|
fbjni::fbjni
|
|
64
49
|
android
|
|
65
|
-
|
|
50
|
+
)
|
|
51
|
+
else()
|
|
52
|
+
target_link_libraries(
|
|
53
|
+
rnscreens
|
|
54
|
+
ReactAndroid::jsi
|
|
55
|
+
ReactAndroid::react_nativemodule_core
|
|
56
|
+
ReactAndroid::react_utils
|
|
57
|
+
ReactAndroid::reactnativejni
|
|
58
|
+
ReactAndroid::fabricjni
|
|
59
|
+
ReactAndroid::react_debug
|
|
60
|
+
ReactAndroid::react_render_core
|
|
61
|
+
ReactAndroid::runtimeexecutor
|
|
62
|
+
ReactAndroid::react_render_graphics
|
|
63
|
+
ReactAndroid::rrc_view
|
|
64
|
+
ReactAndroid::yoga
|
|
65
|
+
ReactAndroid::rrc_text
|
|
66
|
+
ReactAndroid::glog
|
|
67
|
+
ReactAndroid::react_render_componentregistry
|
|
68
|
+
ReactAndroid::react_render_consistency
|
|
69
|
+
ReactAndroid::react_performance_timeline
|
|
70
|
+
ReactAndroid::react_render_observers_events
|
|
71
|
+
fbjni::fbjni
|
|
72
|
+
android
|
|
73
|
+
)
|
|
74
|
+
endif()
|
|
66
75
|
else()
|
|
67
76
|
target_link_libraries(rnscreens
|
|
68
77
|
ReactAndroid::jsi
|
package/android/build.gradle
CHANGED
|
@@ -148,10 +148,26 @@ android {
|
|
|
148
148
|
repositories {
|
|
149
149
|
maven {
|
|
150
150
|
// All of React Native (JS, Obj-C sources, Android binaries) is installed from npm
|
|
151
|
-
|
|
151
|
+
|
|
152
|
+
// First look for the standard location of react-native, as in RN Hello World template
|
|
152
153
|
// https://github.com/facebook/react-native/blob/1e8f3b11027fe0a7514b4fc97d0798d3c64bc895/local-cli/templates/HelloWorld/android/build.gradle#L21
|
|
153
|
-
|
|
154
|
+
// TODO(kkafar): Note, that in latest template app https://github.com/react-native-community/template/blob/0f4745b7a9d84232aeedec2def8d75ab9b050d11/template/android/build.gradle
|
|
155
|
+
// this is not specified at all.
|
|
156
|
+
File standardRnAndroidDirLocation = file("$rootDir/../node_modules/react-native/android")
|
|
157
|
+
if (standardRnAndroidDirLocation.exists()) {
|
|
158
|
+
url standardRnAndroidDirLocation
|
|
159
|
+
} else {
|
|
160
|
+
// We're in non standard setup - try to use node resolver to locate the react-native package.
|
|
161
|
+
File reactNativePackage = file(["node", "--print", "require.resolve('react-native/package.json')"].execute(null, rootDir).text.trim())
|
|
162
|
+
def rnAndroidDirLocation = "$reactNativePackage.parentFile/android"
|
|
163
|
+
if (reactNativePackage.exists()) {
|
|
164
|
+
url rnAndroidDirLocation
|
|
165
|
+
} else {
|
|
166
|
+
println "[RNScreens] Failed to resolve react-native directory. Attempted locations: ${standardRnAndroidDirLocation}, ${rnAndroidDirLocation}"
|
|
167
|
+
}
|
|
168
|
+
}
|
|
154
169
|
}
|
|
170
|
+
|
|
155
171
|
mavenCentral()
|
|
156
172
|
mavenLocal()
|
|
157
173
|
google()
|
|
@@ -24,7 +24,7 @@ abstract class FabricEnabledViewGroup(
|
|
|
24
24
|
protected fun updateScreenSizeFabric(
|
|
25
25
|
width: Int,
|
|
26
26
|
height: Int,
|
|
27
|
-
headerHeight:
|
|
27
|
+
headerHeight: Int,
|
|
28
28
|
) {
|
|
29
29
|
updateState(width, height, headerHeight)
|
|
30
30
|
}
|
|
@@ -33,10 +33,11 @@ abstract class FabricEnabledViewGroup(
|
|
|
33
33
|
fun updateState(
|
|
34
34
|
width: Int,
|
|
35
35
|
height: Int,
|
|
36
|
-
headerHeight:
|
|
36
|
+
headerHeight: Int,
|
|
37
37
|
) {
|
|
38
38
|
val realWidth: Float = PixelUtil.toDIPFromPixel(width.toFloat())
|
|
39
39
|
val realHeight: Float = PixelUtil.toDIPFromPixel(height.toFloat())
|
|
40
|
+
val realHeaderHeight: Float = PixelUtil.toDIPFromPixel(headerHeight.toFloat())
|
|
40
41
|
|
|
41
42
|
// Check incoming state values. If they're already the correct value, return early to prevent
|
|
42
43
|
// infinite UpdateState/SetState loop.
|
|
@@ -54,7 +55,7 @@ abstract class FabricEnabledViewGroup(
|
|
|
54
55
|
putDouble("frameWidth", realWidth.toDouble())
|
|
55
56
|
putDouble("frameHeight", realHeight.toDouble())
|
|
56
57
|
putDouble("contentOffsetX", 0.0)
|
|
57
|
-
putDouble("contentOffsetY",
|
|
58
|
+
putDouble("contentOffsetY", realHeaderHeight.toDouble())
|
|
58
59
|
}
|
|
59
60
|
mStateWrapper?.updateState(map)
|
|
60
61
|
}
|
|
@@ -5,19 +5,20 @@ import android.content.pm.ActivityInfo
|
|
|
5
5
|
import android.graphics.Paint
|
|
6
6
|
import android.os.Parcelable
|
|
7
7
|
import android.util.SparseArray
|
|
8
|
-
import android.util.TypedValue
|
|
9
8
|
import android.view.View
|
|
10
9
|
import android.view.ViewGroup
|
|
11
10
|
import android.view.WindowManager
|
|
12
11
|
import android.webkit.WebView
|
|
12
|
+
import android.widget.ImageView
|
|
13
13
|
import androidx.core.view.children
|
|
14
14
|
import androidx.fragment.app.Fragment
|
|
15
|
+
import androidx.swiperefreshlayout.widget.SwipeRefreshLayout
|
|
15
16
|
import com.facebook.react.bridge.GuardedRunnable
|
|
16
17
|
import com.facebook.react.bridge.ReactContext
|
|
17
|
-
import com.facebook.react.uimanager.PixelUtil
|
|
18
18
|
import com.facebook.react.uimanager.UIManagerHelper
|
|
19
19
|
import com.facebook.react.uimanager.UIManagerModule
|
|
20
20
|
import com.swmansion.rnscreens.events.HeaderHeightChangeEvent
|
|
21
|
+
import com.swmansion.rnscreens.ext.isInsideScrollViewWithRemoveClippedSubviews
|
|
21
22
|
|
|
22
23
|
@SuppressLint("ViewConstructor") // Only we construct this view, it is never inflated.
|
|
23
24
|
class Screen(
|
|
@@ -75,16 +76,13 @@ class Screen(
|
|
|
75
76
|
val width = r - l
|
|
76
77
|
val height = b - t
|
|
77
78
|
|
|
78
|
-
val headerHeight = calculateHeaderHeight()
|
|
79
|
-
val totalHeight =
|
|
80
|
-
headerHeight.first + headerHeight.second // action bar height + status bar height
|
|
81
79
|
if (BuildConfig.IS_NEW_ARCHITECTURE_ENABLED) {
|
|
82
|
-
updateScreenSizeFabric(width, height,
|
|
80
|
+
updateScreenSizeFabric(width, height, t)
|
|
83
81
|
} else {
|
|
84
82
|
updateScreenSizePaper(width, height)
|
|
85
83
|
}
|
|
86
84
|
|
|
87
|
-
notifyHeaderHeightChange(
|
|
85
|
+
notifyHeaderHeightChange(t)
|
|
88
86
|
}
|
|
89
87
|
}
|
|
90
88
|
|
|
@@ -295,7 +293,7 @@ class Screen(
|
|
|
295
293
|
parent?.let {
|
|
296
294
|
for (i in 0 until it.childCount) {
|
|
297
295
|
val child = it.getChildAt(i)
|
|
298
|
-
if (child
|
|
296
|
+
if (parent is SwipeRefreshLayout && child is ImageView) {
|
|
299
297
|
// SwipeRefreshLayout class which has CircleImageView as a child,
|
|
300
298
|
// does not handle `startViewTransition` properly.
|
|
301
299
|
// It has a custom `getChildDrawingOrder` method which returns
|
|
@@ -312,38 +310,22 @@ class Screen(
|
|
|
312
310
|
startTransitionRecursive(child.toolbar)
|
|
313
311
|
}
|
|
314
312
|
if (child is ViewGroup) {
|
|
313
|
+
// The children are miscounted when there's a FlatList with
|
|
314
|
+
// removeClippedSubviews set to true (default).
|
|
315
|
+
// We add a simple view for each item in the list to make it work as expected.
|
|
316
|
+
// See https://github.com/software-mansion/react-native-screens/pull/2383
|
|
317
|
+
if (child.isInsideScrollViewWithRemoveClippedSubviews()) {
|
|
318
|
+
for (j in 0 until child.childCount) {
|
|
319
|
+
child.addView(View(context))
|
|
320
|
+
}
|
|
321
|
+
}
|
|
315
322
|
startTransitionRecursive(child)
|
|
316
323
|
}
|
|
317
324
|
}
|
|
318
325
|
}
|
|
319
326
|
}
|
|
320
327
|
|
|
321
|
-
private fun
|
|
322
|
-
val actionBarTv = TypedValue()
|
|
323
|
-
val resolvedActionBarSize =
|
|
324
|
-
context.theme.resolveAttribute(android.R.attr.actionBarSize, actionBarTv, true)
|
|
325
|
-
|
|
326
|
-
// Check if it's possible to get an attribute from theme context and assign a value from it.
|
|
327
|
-
// Otherwise, the default value will be returned.
|
|
328
|
-
val actionBarHeight =
|
|
329
|
-
TypedValue
|
|
330
|
-
.complexToDimensionPixelSize(actionBarTv.data, resources.displayMetrics)
|
|
331
|
-
.takeIf { resolvedActionBarSize && headerConfig?.isHeaderHidden != true && headerConfig?.isHeaderTranslucent != true }
|
|
332
|
-
?.let { PixelUtil.toDIPFromPixel(it.toFloat()).toDouble() } ?: 0.0
|
|
333
|
-
|
|
334
|
-
val statusBarHeight =
|
|
335
|
-
context.resources
|
|
336
|
-
.getIdentifier("status_bar_height", "dimen", "android")
|
|
337
|
-
// Count only status bar when action bar is visible and status bar is not hidden
|
|
338
|
-
.takeIf { it > 0 && isStatusBarHidden != true && actionBarHeight > 0 }
|
|
339
|
-
?.let { (context.resources::getDimensionPixelSize)(it) }
|
|
340
|
-
?.let { PixelUtil.toDIPFromPixel(it.toFloat()).toDouble() }
|
|
341
|
-
?: 0.0
|
|
342
|
-
|
|
343
|
-
return actionBarHeight to statusBarHeight
|
|
344
|
-
}
|
|
345
|
-
|
|
346
|
-
private fun notifyHeaderHeightChange(headerHeight: Double) {
|
|
328
|
+
private fun notifyHeaderHeightChange(headerHeight: Int) {
|
|
347
329
|
val screenContext = context as ReactContext
|
|
348
330
|
val surfaceId = UIManagerHelper.getSurfaceId(screenContext)
|
|
349
331
|
UIManagerHelper
|
|
@@ -366,6 +348,8 @@ class Screen(
|
|
|
366
348
|
SLIDE_FROM_LEFT,
|
|
367
349
|
FADE_FROM_BOTTOM,
|
|
368
350
|
IOS,
|
|
351
|
+
IOS_FROM_RIGHT,
|
|
352
|
+
IOS_FROM_LEFT,
|
|
369
353
|
}
|
|
370
354
|
|
|
371
355
|
enum class ReplaceAnimation {
|
|
@@ -160,7 +160,9 @@ class ScreenStack(
|
|
|
160
160
|
R.anim.rns_no_animation_medium,
|
|
161
161
|
)
|
|
162
162
|
StackAnimation.FADE_FROM_BOTTOM -> it.setCustomAnimations(R.anim.rns_fade_from_bottom, R.anim.rns_no_animation_350)
|
|
163
|
-
StackAnimation.IOS -> it.setCustomAnimations(R.anim.
|
|
163
|
+
StackAnimation.IOS -> it.setCustomAnimations(R.anim.rns_ios_from_right_foreground_open, R.anim.rns_ios_from_right_background_open)
|
|
164
|
+
StackAnimation.IOS_FROM_RIGHT -> it.setCustomAnimations(R.anim.rns_ios_from_right_foreground_open, R.anim.rns_ios_from_right_background_open)
|
|
165
|
+
StackAnimation.IOS_FROM_LEFT -> it.setCustomAnimations(R.anim.rns_ios_from_left_foreground_open, R.anim.rns_ios_from_left_background_open)
|
|
164
166
|
}
|
|
165
167
|
} else {
|
|
166
168
|
when (stackAnimation) {
|
|
@@ -183,7 +185,9 @@ class ScreenStack(
|
|
|
183
185
|
R.anim.rns_slide_out_to_bottom,
|
|
184
186
|
)
|
|
185
187
|
StackAnimation.FADE_FROM_BOTTOM -> it.setCustomAnimations(R.anim.rns_no_animation_250, R.anim.rns_fade_to_bottom)
|
|
186
|
-
StackAnimation.IOS -> it.setCustomAnimations(R.anim.
|
|
188
|
+
StackAnimation.IOS -> it.setCustomAnimations(R.anim.rns_ios_from_right_foreground_close, R.anim.rns_ios_from_right_background_close)
|
|
189
|
+
StackAnimation.IOS_FROM_RIGHT -> it.setCustomAnimations(R.anim.rns_ios_from_right_background_close, R.anim.rns_ios_from_right_foreground_close)
|
|
190
|
+
StackAnimation.IOS_FROM_LEFT -> it.setCustomAnimations(R.anim.rns_ios_from_left_background_close, R.anim.rns_ios_from_left_foreground_close)
|
|
187
191
|
}
|
|
188
192
|
}
|
|
189
193
|
}
|
|
@@ -370,6 +374,8 @@ class ScreenStack(
|
|
|
370
374
|
Build.VERSION.SDK_INT >= 33 ||
|
|
371
375
|
fragmentWrapper.screen.stackAnimation === StackAnimation.SLIDE_FROM_BOTTOM ||
|
|
372
376
|
fragmentWrapper.screen.stackAnimation === StackAnimation.FADE_FROM_BOTTOM ||
|
|
373
|
-
fragmentWrapper.screen.stackAnimation === StackAnimation.IOS
|
|
377
|
+
fragmentWrapper.screen.stackAnimation === StackAnimation.IOS ||
|
|
378
|
+
fragmentWrapper.screen.stackAnimation === StackAnimation.IOS_FROM_RIGHT ||
|
|
379
|
+
fragmentWrapper.screen.stackAnimation === StackAnimation.IOS_FROM_LEFT
|
|
374
380
|
}
|
|
375
381
|
}
|
|
@@ -48,7 +48,6 @@ open class ScreenViewManager :
|
|
|
48
48
|
stateWrapper: StateWrapper?,
|
|
49
49
|
): Any? {
|
|
50
50
|
if (BuildConfig.IS_NEW_ARCHITECTURE_ENABLED) {
|
|
51
|
-
// fabricViewStateManager should never be null in Fabric. The null check is only for Paper's empty impl.
|
|
52
51
|
view.setStateWrapper(stateWrapper)
|
|
53
52
|
}
|
|
54
53
|
return super.updateState(view, props, stateWrapper)
|
|
@@ -104,6 +103,8 @@ open class ScreenViewManager :
|
|
|
104
103
|
"slide_from_bottom" -> Screen.StackAnimation.SLIDE_FROM_BOTTOM
|
|
105
104
|
"fade_from_bottom" -> Screen.StackAnimation.FADE_FROM_BOTTOM
|
|
106
105
|
"ios" -> Screen.StackAnimation.IOS
|
|
106
|
+
"ios_from_right" -> Screen.StackAnimation.IOS_FROM_RIGHT
|
|
107
|
+
"ios_from_left" -> Screen.StackAnimation.IOS_FROM_LEFT
|
|
107
108
|
else -> throw JSApplicationIllegalArgumentException("Unknown animation type $animation")
|
|
108
109
|
}
|
|
109
110
|
}
|
|
@@ -214,7 +214,7 @@ object ScreenWindowTraits {
|
|
|
214
214
|
val window = activity.window
|
|
215
215
|
|
|
216
216
|
val screenForNavBarTranslucent = findScreenForTrait(screen, WindowTraits.NAVIGATION_BAR_TRANSLUCENT)
|
|
217
|
-
val translucent = screenForNavBarTranslucent?.isNavigationBarTranslucent ?:
|
|
217
|
+
val translucent = screenForNavBarTranslucent?.isNavigationBarTranslucent ?: return
|
|
218
218
|
|
|
219
219
|
// Following method controls whether to display edge-to-edge content that draws behind the navigation bar
|
|
220
220
|
WindowCompat.setDecorFitsSystemWindows(window, !translucent)
|
|
@@ -7,16 +7,16 @@ import com.facebook.react.uimanager.events.Event
|
|
|
7
7
|
class HeaderHeightChangeEvent(
|
|
8
8
|
surfaceId: Int,
|
|
9
9
|
viewId: Int,
|
|
10
|
-
private val headerHeight:
|
|
10
|
+
private val headerHeight: Int,
|
|
11
11
|
) : Event<HeaderHeightChangeEvent>(surfaceId, viewId) {
|
|
12
12
|
override fun getEventName() = EVENT_NAME
|
|
13
13
|
|
|
14
14
|
// As the same header height could appear twice, use header height as a coalescing key.
|
|
15
|
-
override fun getCoalescingKey(): Short = headerHeight.
|
|
15
|
+
override fun getCoalescingKey(): Short = headerHeight.toShort()
|
|
16
16
|
|
|
17
17
|
override fun getEventData(): WritableMap? =
|
|
18
18
|
Arguments.createMap().apply {
|
|
19
|
-
putDouble("headerHeight", headerHeight)
|
|
19
|
+
putDouble("headerHeight", headerHeight.toDouble())
|
|
20
20
|
}
|
|
21
21
|
|
|
22
22
|
companion object {
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
package com.swmansion.rnscreens.ext
|
|
2
|
+
|
|
3
|
+
import android.graphics.drawable.ColorDrawable
|
|
4
|
+
import android.view.View
|
|
5
|
+
import android.view.ViewGroup
|
|
6
|
+
import com.facebook.react.views.scroll.ReactHorizontalScrollView
|
|
7
|
+
import com.facebook.react.views.scroll.ReactScrollView
|
|
8
|
+
import com.swmansion.rnscreens.ScreenStack
|
|
9
|
+
|
|
10
|
+
internal fun View.parentAsView() = this.parent as? View
|
|
11
|
+
|
|
12
|
+
internal fun View.parentAsViewGroup() = this.parent as? ViewGroup
|
|
13
|
+
|
|
14
|
+
internal fun View.recycle(): View {
|
|
15
|
+
// screen fragments reuse view instances instead of creating new ones. In order to reuse a given
|
|
16
|
+
// view it needs to be detached from the view hierarchy to allow the fragment to attach it back.
|
|
17
|
+
this.parentAsViewGroup()?.let { parent ->
|
|
18
|
+
parent.endViewTransition(this)
|
|
19
|
+
parent.removeView(this)
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
// view detached from fragment manager get their visibility changed to GONE after their state is
|
|
23
|
+
// dumped. Since we don't restore the state but want to reuse the view we need to change
|
|
24
|
+
// visibility back to VISIBLE in order for the fragment manager to animate in the view.
|
|
25
|
+
this.visibility = View.VISIBLE
|
|
26
|
+
return this
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
internal fun View.maybeBgColor(): Int? {
|
|
30
|
+
val bgDrawable = this.background
|
|
31
|
+
if (bgDrawable is ColorDrawable) {
|
|
32
|
+
return bgDrawable.color
|
|
33
|
+
}
|
|
34
|
+
return null
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
internal fun View.isInsideScrollViewWithRemoveClippedSubviews(): Boolean {
|
|
38
|
+
if (this is ReactHorizontalScrollView || this is ReactScrollView) {
|
|
39
|
+
return false
|
|
40
|
+
}
|
|
41
|
+
var parentView = this.parent
|
|
42
|
+
while (parentView is ViewGroup && parentView !is ScreenStack) {
|
|
43
|
+
when (parentView) {
|
|
44
|
+
is ReactHorizontalScrollView -> {
|
|
45
|
+
return parentView.removeClippedSubviews
|
|
46
|
+
}
|
|
47
|
+
is ReactScrollView -> {
|
|
48
|
+
return parentView.removeClippedSubviews
|
|
49
|
+
}
|
|
50
|
+
else -> {
|
|
51
|
+
parentView = parentView.parent
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
return false
|
|
56
|
+
}
|
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
package com.swmansion.rnscreens.utils
|
|
2
2
|
|
|
3
3
|
import android.app.Activity
|
|
4
|
+
import android.content.Context
|
|
4
5
|
import android.util.Log
|
|
5
6
|
import android.view.View
|
|
6
7
|
import androidx.appcompat.widget.Toolbar
|
|
7
8
|
import androidx.coordinatorlayout.widget.CoordinatorLayout
|
|
9
|
+
import com.facebook.jni.annotations.DoNotStrip
|
|
8
10
|
import com.facebook.react.bridge.LifecycleEventListener
|
|
9
11
|
import com.facebook.react.bridge.ReactApplicationContext
|
|
10
12
|
import com.facebook.react.uimanager.PixelUtil
|
|
@@ -18,6 +20,7 @@ import java.lang.ref.WeakReference
|
|
|
18
20
|
* See https://github.com/software-mansion/react-native-screens/pull/2169
|
|
19
21
|
* for more detailed description of the issue this code solves.
|
|
20
22
|
*/
|
|
23
|
+
@DoNotStrip
|
|
21
24
|
internal class ScreenDummyLayoutHelper(
|
|
22
25
|
reactContext: ReactApplicationContext,
|
|
23
26
|
) : LifecycleEventListener {
|
|
@@ -46,7 +49,7 @@ internal class ScreenDummyLayoutHelper(
|
|
|
46
49
|
try {
|
|
47
50
|
System.loadLibrary(LIBRARY_NAME)
|
|
48
51
|
} catch (e: UnsatisfiedLinkError) {
|
|
49
|
-
Log.w(TAG, "Failed to load $LIBRARY_NAME")
|
|
52
|
+
Log.w(TAG, "[RNScreens] Failed to load $LIBRARY_NAME library.")
|
|
50
53
|
}
|
|
51
54
|
|
|
52
55
|
weakInstance = WeakReference(this)
|
|
@@ -57,9 +60,13 @@ internal class ScreenDummyLayoutHelper(
|
|
|
57
60
|
}
|
|
58
61
|
|
|
59
62
|
/**
|
|
60
|
-
*
|
|
63
|
+
* Tries to initialize dummy view hierarchy with CoordinatorLayout, AppBarLayout and dummy View.
|
|
61
64
|
* We utilize this to compute header height (app bar layout height) from C++ layer when its needed.
|
|
62
65
|
*
|
|
66
|
+
* This method might fail in case there is activity attached to the react context.
|
|
67
|
+
*
|
|
68
|
+
* This method is called from various threads!
|
|
69
|
+
*
|
|
63
70
|
* @return boolean whether the layout was initialised or not
|
|
64
71
|
*/
|
|
65
72
|
private fun maybeInitDummyLayoutWithHeader(reactContext: ReactApplicationContext): Boolean {
|
|
@@ -67,6 +74,7 @@ internal class ScreenDummyLayoutHelper(
|
|
|
67
74
|
return true
|
|
68
75
|
}
|
|
69
76
|
|
|
77
|
+
// Possible data race here - activity is injected into context on UI thread.
|
|
70
78
|
if (!reactContext.hasCurrentActivity()) {
|
|
71
79
|
return false
|
|
72
80
|
}
|
|
@@ -74,8 +82,25 @@ internal class ScreenDummyLayoutHelper(
|
|
|
74
82
|
// We need to use activity here, as react context does not have theme attributes required by
|
|
75
83
|
// AppBarLayout attached leading to crash.
|
|
76
84
|
val contextWithTheme =
|
|
77
|
-
requireNotNull(reactContext.currentActivity) { "[RNScreens] Attempt to use context detached from activity" }
|
|
85
|
+
requireNotNull(reactContext.currentActivity) { "[RNScreens] Attempt to use context detached from activity. This could happen only due to race-condition." }
|
|
86
|
+
|
|
87
|
+
synchronized(this) {
|
|
88
|
+
// The layout could have been initialised when this thread waited for access to critical section.
|
|
89
|
+
if (isLayoutInitialized) {
|
|
90
|
+
return true
|
|
91
|
+
}
|
|
92
|
+
initDummyLayoutWithHeader(contextWithTheme)
|
|
93
|
+
}
|
|
94
|
+
return true
|
|
95
|
+
}
|
|
78
96
|
|
|
97
|
+
/**
|
|
98
|
+
* Initialises the dummy layout. This method is **not** thread-safe.
|
|
99
|
+
*
|
|
100
|
+
* @param contextWithTheme this function expects the context to have theme attributes required
|
|
101
|
+
* to initialize the AppBarLayout.
|
|
102
|
+
*/
|
|
103
|
+
private fun initDummyLayoutWithHeader(contextWithTheme: Context) {
|
|
79
104
|
coordinatorLayout = CoordinatorLayout(contextWithTheme)
|
|
80
105
|
|
|
81
106
|
appBarLayout =
|
|
@@ -119,7 +144,6 @@ internal class ScreenDummyLayoutHelper(
|
|
|
119
144
|
}
|
|
120
145
|
|
|
121
146
|
isLayoutInitialized = true
|
|
122
|
-
return true
|
|
123
147
|
}
|
|
124
148
|
|
|
125
149
|
/**
|
|
@@ -129,6 +153,7 @@ internal class ScreenDummyLayoutHelper(
|
|
|
129
153
|
* @param fontSize font size value as passed from JS
|
|
130
154
|
* @return header height in dp as consumed by Yoga
|
|
131
155
|
*/
|
|
156
|
+
@DoNotStrip
|
|
132
157
|
private fun computeDummyLayout(
|
|
133
158
|
fontSize: Int,
|
|
134
159
|
isTitleEmpty: Boolean,
|
|
@@ -141,7 +166,7 @@ internal class ScreenDummyLayoutHelper(
|
|
|
141
166
|
// is still null at this execution point. We don't wanna crash in such case, thus returning zeroed height.
|
|
142
167
|
Log.e(
|
|
143
168
|
TAG,
|
|
144
|
-
"[RNScreens] Failed to late-init layout while computing header height. This is a race-condition-bug in react-native-screens, please file an issue at https://github.com/software-mansion/react-native-screens/issues"
|
|
169
|
+
"[RNScreens] Failed to late-init layout while computing header height. This is most likely a race-condition-bug in react-native-screens, please file an issue at https://github.com/software-mansion/react-native-screens/issues"
|
|
145
170
|
)
|
|
146
171
|
return 0.0f
|
|
147
172
|
}
|
|
@@ -210,22 +235,34 @@ internal class ScreenDummyLayoutHelper(
|
|
|
210
235
|
// dummy view hierarchy.
|
|
211
236
|
private var weakInstance = WeakReference<ScreenDummyLayoutHelper>(null)
|
|
212
237
|
|
|
238
|
+
@DoNotStrip
|
|
213
239
|
@JvmStatic
|
|
214
240
|
fun getInstance(): ScreenDummyLayoutHelper? = weakInstance.get()
|
|
215
241
|
}
|
|
216
242
|
|
|
243
|
+
// This value is fetched / stored from UI and background thread. Volatile here ensures
|
|
244
|
+
// that updates are visible to the other thread.
|
|
245
|
+
@Volatile
|
|
217
246
|
private var isLayoutInitialized = false
|
|
218
247
|
|
|
219
248
|
override fun onHostResume() {
|
|
220
249
|
// This is the earliest we have guarantee that the context has a reference to an activity.
|
|
221
250
|
val reactContext = requireReactContext { "[RNScreens] ReactContext missing in onHostResume! This should not happen." }
|
|
222
|
-
|
|
223
|
-
|
|
251
|
+
|
|
252
|
+
// There are some exotic edge cases where activity might not be present in context
|
|
253
|
+
// at this point, e.g. when reloading RN in development after an error was reported with redbox.
|
|
254
|
+
if (maybeInitDummyLayoutWithHeader(reactContext)) {
|
|
255
|
+
reactContext.removeLifecycleEventListener(this)
|
|
256
|
+
} else {
|
|
257
|
+
Log.w(TAG, "[RNScreens] Failed to initialise dummy layout in onHostResume.")
|
|
258
|
+
}
|
|
224
259
|
}
|
|
225
260
|
|
|
226
261
|
override fun onHostPause() = Unit
|
|
227
262
|
|
|
228
|
-
override fun onHostDestroy()
|
|
263
|
+
override fun onHostDestroy() {
|
|
264
|
+
reactContextRef.get()?.removeLifecycleEventListener(this)
|
|
265
|
+
}
|
|
229
266
|
}
|
|
230
267
|
|
|
231
268
|
private data class CacheKey(
|
|
@@ -38,25 +38,34 @@ target_include_directories(
|
|
|
38
38
|
${LIB_ANDROID_GENERATED_COMPONENTS_DIR}
|
|
39
39
|
)
|
|
40
40
|
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
41
|
+
if(ReactAndroid_VERSION_MINOR GREATER_EQUAL 76)
|
|
42
|
+
target_link_libraries(
|
|
43
|
+
${LIB_TARGET_NAME}
|
|
44
|
+
ReactAndroid::reactnative
|
|
45
|
+
ReactAndroid::jsi
|
|
46
|
+
fbjni::fbjni
|
|
47
|
+
)
|
|
48
|
+
else()
|
|
49
|
+
target_link_libraries(
|
|
50
|
+
${LIB_TARGET_NAME}
|
|
51
|
+
fbjni
|
|
52
|
+
folly_runtime
|
|
53
|
+
glog
|
|
54
|
+
jsi
|
|
55
|
+
react_codegen_rncore
|
|
56
|
+
react_debug
|
|
57
|
+
react_nativemodule_core
|
|
58
|
+
react_render_core
|
|
59
|
+
react_render_debug
|
|
60
|
+
react_render_graphics
|
|
61
|
+
react_render_mapbuffer
|
|
62
|
+
react_render_componentregistry
|
|
63
|
+
react_utils
|
|
64
|
+
rrc_view
|
|
65
|
+
turbomodulejsijni
|
|
66
|
+
yoga
|
|
67
|
+
)
|
|
68
|
+
endif()
|
|
60
69
|
|
|
61
70
|
target_compile_options(
|
|
62
71
|
${LIB_TARGET_NAME}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
<?xml version="1.0" encoding="utf-8"?>
|
|
2
|
+
<translate xmlns:android="http://schemas.android.com/apk/res/android"
|
|
3
|
+
android:duration="@android:integer/config_shortAnimTime"
|
|
4
|
+
android:interpolator="@android:interpolator/accelerate_decelerate"
|
|
5
|
+
android:fromXDelta="0%"
|
|
6
|
+
android:toXDelta="-100%" />
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
<?xml version="1.0" encoding="utf-8"?>
|
|
2
|
+
<translate xmlns:android="http://schemas.android.com/apk/res/android"
|
|
3
|
+
android:duration="@android:integer/config_shortAnimTime"
|
|
4
|
+
android:interpolator="@android:interpolator/accelerate_decelerate"
|
|
5
|
+
android:fromXDelta="-100%"
|
|
6
|
+
android:toXDelta="0%" />
|