react-native-screens 3.35.0-rc.1 → 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.
Files changed (168) hide show
  1. package/README.md +1 -1
  2. package/android/CMakeLists.txt +28 -19
  3. package/android/build.gradle +18 -2
  4. package/android/src/fabric/java/com/swmansion/rnscreens/FabricEnabledViewGroup.kt +4 -3
  5. package/android/src/main/java/com/swmansion/rnscreens/Screen.kt +18 -34
  6. package/android/src/main/java/com/swmansion/rnscreens/ScreenStack.kt +9 -3
  7. package/android/src/main/java/com/swmansion/rnscreens/ScreenViewManager.kt +2 -1
  8. package/android/src/main/java/com/swmansion/rnscreens/ScreenWindowTraits.kt +1 -1
  9. package/android/src/main/java/com/swmansion/rnscreens/events/HeaderHeightChangeEvent.kt +3 -3
  10. package/android/src/main/java/com/swmansion/rnscreens/ext/ViewExt.kt +56 -0
  11. package/android/src/main/jni/CMakeLists.txt +28 -19
  12. package/android/src/main/res/base/anim/rns_ios_from_left_background_close.xml +5 -0
  13. package/android/src/main/res/base/anim/{rns_slide_out_to_left_ios.xml → rns_ios_from_left_background_open.xml} +1 -1
  14. package/android/src/main/res/base/anim/rns_ios_from_left_foreground_close.xml +6 -0
  15. package/android/src/main/res/base/anim/rns_ios_from_left_foreground_open.xml +6 -0
  16. package/android/src/main/res/base/anim/rns_ios_from_right_background_open.xml +5 -0
  17. package/android/src/paper/java/com/swmansion/rnscreens/FabricEnabledViewGroup.kt +1 -1
  18. package/common/cpp/react/renderer/components/rnscreens/RNSScreenComponentDescriptor.h +5 -99
  19. package/common/cpp/react/renderer/components/rnscreens/RNSScreenShadowNode.cpp +101 -0
  20. package/common/cpp/react/renderer/components/rnscreens/RNSScreenShadowNode.h +2 -0
  21. package/ios/RNSConvert.h +13 -4
  22. package/ios/RNSConvert.mm +54 -29
  23. package/ios/RNSEnums.h +46 -0
  24. package/ios/RNSFullWindowOverlay.mm +6 -0
  25. package/ios/RNSModalScreen.mm +7 -0
  26. package/ios/RNSScreen.h +14 -0
  27. package/ios/RNSScreen.mm +22 -4
  28. package/ios/RNSScreenContainer.mm +6 -0
  29. package/ios/RNSScreenNavigationContainer.mm +7 -0
  30. package/ios/RNSScreenStack.mm +53 -7
  31. package/ios/RNSScreenStackHeaderConfig.h +1 -1
  32. package/ios/RNSScreenStackHeaderConfig.mm +54 -29
  33. package/ios/RNSScreenStackHeaderSubview.mm +30 -3
  34. package/ios/RNSSearchBar.mm +7 -0
  35. package/lib/commonjs/TransitionProgressContext.js +1 -0
  36. package/lib/commonjs/TransitionProgressContext.js.map +1 -1
  37. package/lib/commonjs/components/FullWindowOverlay.js +8 -5
  38. package/lib/commonjs/components/FullWindowOverlay.js.map +1 -1
  39. package/lib/commonjs/components/Screen.js +9 -0
  40. package/lib/commonjs/components/Screen.js.map +1 -1
  41. package/lib/commonjs/components/Screen.web.js +2 -0
  42. package/lib/commonjs/components/Screen.web.js.map +1 -1
  43. package/lib/commonjs/components/ScreenContainer.js +1 -0
  44. package/lib/commonjs/components/ScreenContainer.js.map +1 -1
  45. package/lib/commonjs/components/ScreenStack.js +1 -0
  46. package/lib/commonjs/components/ScreenStack.js.map +1 -1
  47. package/lib/commonjs/components/ScreenStackHeaderConfig.js +1 -0
  48. package/lib/commonjs/components/ScreenStackHeaderConfig.js.map +1 -1
  49. package/lib/commonjs/components/SearchBar.js +1 -0
  50. package/lib/commonjs/components/SearchBar.js.map +1 -1
  51. package/lib/commonjs/core.js +1 -0
  52. package/lib/commonjs/core.js.map +1 -1
  53. package/lib/commonjs/fabric/FullWindowOverlayNativeComponent.js +1 -0
  54. package/lib/commonjs/fabric/FullWindowOverlayNativeComponent.js.map +1 -1
  55. package/lib/commonjs/fabric/ModalScreenNativeComponent.js +1 -0
  56. package/lib/commonjs/fabric/ModalScreenNativeComponent.js.map +1 -1
  57. package/lib/commonjs/fabric/NativeScreensModule.js +2 -1
  58. package/lib/commonjs/fabric/NativeScreensModule.js.map +1 -1
  59. package/lib/commonjs/fabric/ScreenContainerNativeComponent.js +1 -0
  60. package/lib/commonjs/fabric/ScreenContainerNativeComponent.js.map +1 -1
  61. package/lib/commonjs/fabric/ScreenNativeComponent.js +1 -0
  62. package/lib/commonjs/fabric/ScreenNativeComponent.js.map +1 -1
  63. package/lib/commonjs/fabric/ScreenNavigationContainerNativeComponent.js +1 -0
  64. package/lib/commonjs/fabric/ScreenNavigationContainerNativeComponent.js.map +1 -1
  65. package/lib/commonjs/fabric/ScreenStackHeaderConfigNativeComponent.js +1 -0
  66. package/lib/commonjs/fabric/ScreenStackHeaderConfigNativeComponent.js.map +1 -1
  67. package/lib/commonjs/fabric/ScreenStackHeaderSubviewNativeComponent.js +1 -0
  68. package/lib/commonjs/fabric/ScreenStackHeaderSubviewNativeComponent.js.map +1 -1
  69. package/lib/commonjs/fabric/ScreenStackNativeComponent.js +1 -0
  70. package/lib/commonjs/fabric/ScreenStackNativeComponent.js.map +1 -1
  71. package/lib/commonjs/fabric/SearchBarNativeComponent.js +2 -2
  72. package/lib/commonjs/fabric/SearchBarNativeComponent.js.map +1 -1
  73. package/lib/commonjs/native-stack/contexts/GHContext.js +1 -0
  74. package/lib/commonjs/native-stack/contexts/GHContext.js.map +1 -1
  75. package/lib/module/TransitionProgressContext.js +2 -0
  76. package/lib/module/TransitionProgressContext.js.map +1 -1
  77. package/lib/module/components/FullWindowOverlay.js +9 -6
  78. package/lib/module/components/FullWindowOverlay.js.map +1 -1
  79. package/lib/module/components/Screen.js +10 -0
  80. package/lib/module/components/Screen.js.map +1 -1
  81. package/lib/module/components/Screen.web.js +3 -0
  82. package/lib/module/components/Screen.web.js.map +1 -1
  83. package/lib/module/components/ScreenContainer.js +2 -0
  84. package/lib/module/components/ScreenContainer.js.map +1 -1
  85. package/lib/module/components/ScreenStack.js +2 -0
  86. package/lib/module/components/ScreenStack.js.map +1 -1
  87. package/lib/module/components/ScreenStackHeaderConfig.js +2 -0
  88. package/lib/module/components/ScreenStackHeaderConfig.js.map +1 -1
  89. package/lib/module/components/SearchBar.js +2 -0
  90. package/lib/module/components/SearchBar.js.map +1 -1
  91. package/lib/module/core.js +2 -0
  92. package/lib/module/core.js.map +1 -1
  93. package/lib/module/fabric/FullWindowOverlayNativeComponent.js +2 -0
  94. package/lib/module/fabric/FullWindowOverlayNativeComponent.js.map +1 -1
  95. package/lib/module/fabric/ModalScreenNativeComponent.js +2 -0
  96. package/lib/module/fabric/ModalScreenNativeComponent.js.map +1 -1
  97. package/lib/module/fabric/NativeScreensModule.js +2 -1
  98. package/lib/module/fabric/NativeScreensModule.js.map +1 -1
  99. package/lib/module/fabric/ScreenContainerNativeComponent.js +2 -0
  100. package/lib/module/fabric/ScreenContainerNativeComponent.js.map +1 -1
  101. package/lib/module/fabric/ScreenNativeComponent.js +2 -0
  102. package/lib/module/fabric/ScreenNativeComponent.js.map +1 -1
  103. package/lib/module/fabric/ScreenNavigationContainerNativeComponent.js +2 -0
  104. package/lib/module/fabric/ScreenNavigationContainerNativeComponent.js.map +1 -1
  105. package/lib/module/fabric/ScreenStackHeaderConfigNativeComponent.js +2 -0
  106. package/lib/module/fabric/ScreenStackHeaderConfigNativeComponent.js.map +1 -1
  107. package/lib/module/fabric/ScreenStackHeaderSubviewNativeComponent.js +2 -0
  108. package/lib/module/fabric/ScreenStackHeaderSubviewNativeComponent.js.map +1 -1
  109. package/lib/module/fabric/ScreenStackNativeComponent.js +2 -0
  110. package/lib/module/fabric/ScreenStackNativeComponent.js.map +1 -1
  111. package/lib/module/fabric/SearchBarNativeComponent.js +2 -0
  112. package/lib/module/fabric/SearchBarNativeComponent.js.map +1 -1
  113. package/lib/module/native-stack/contexts/GHContext.js +2 -0
  114. package/lib/module/native-stack/contexts/GHContext.js.map +1 -1
  115. package/lib/typescript/TransitionProgressContext.d.ts.map +1 -1
  116. package/lib/typescript/components/FullWindowOverlay.d.ts.map +1 -1
  117. package/lib/typescript/components/Screen.d.ts.map +1 -1
  118. package/lib/typescript/components/Screen.web.d.ts.map +1 -1
  119. package/lib/typescript/components/ScreenContainer.d.ts.map +1 -1
  120. package/lib/typescript/components/ScreenStack.d.ts.map +1 -1
  121. package/lib/typescript/components/ScreenStackHeaderConfig.d.ts.map +1 -1
  122. package/lib/typescript/components/SearchBar.d.ts.map +1 -1
  123. package/lib/typescript/core.d.ts.map +1 -1
  124. package/lib/typescript/fabric/FullWindowOverlayNativeComponent.d.ts.map +1 -1
  125. package/lib/typescript/fabric/ModalScreenNativeComponent.d.ts.map +1 -1
  126. package/lib/typescript/fabric/NativeScreensModule.d.ts.map +1 -1
  127. package/lib/typescript/fabric/ScreenContainerNativeComponent.d.ts.map +1 -1
  128. package/lib/typescript/fabric/ScreenNativeComponent.d.ts +1 -1
  129. package/lib/typescript/fabric/ScreenNativeComponent.d.ts.map +1 -1
  130. package/lib/typescript/fabric/ScreenNavigationContainerNativeComponent.d.ts.map +1 -1
  131. package/lib/typescript/fabric/ScreenStackHeaderConfigNativeComponent.d.ts +2 -2
  132. package/lib/typescript/fabric/ScreenStackHeaderConfigNativeComponent.d.ts.map +1 -1
  133. package/lib/typescript/fabric/ScreenStackHeaderSubviewNativeComponent.d.ts.map +1 -1
  134. package/lib/typescript/fabric/ScreenStackNativeComponent.d.ts.map +1 -1
  135. package/lib/typescript/fabric/SearchBarNativeComponent.d.ts.map +1 -1
  136. package/lib/typescript/native-stack/contexts/GHContext.d.ts.map +1 -1
  137. package/lib/typescript/native-stack/types.d.ts +3 -1
  138. package/lib/typescript/native-stack/types.d.ts.map +1 -1
  139. package/lib/typescript/types.d.ts +5 -3
  140. package/lib/typescript/types.d.ts.map +1 -1
  141. package/native-stack/README.md +3 -1
  142. package/package.json +1 -1
  143. package/src/TransitionProgressContext.tsx +2 -0
  144. package/src/components/FullWindowOverlay.tsx +10 -2
  145. package/src/components/Screen.tsx +8 -0
  146. package/src/components/Screen.web.tsx +3 -0
  147. package/src/components/ScreenContainer.tsx +2 -0
  148. package/src/components/ScreenStack.tsx +2 -0
  149. package/src/components/ScreenStackHeaderConfig.tsx +2 -0
  150. package/src/components/SearchBar.tsx +2 -0
  151. package/src/core.ts +2 -0
  152. package/src/fabric/FullWindowOverlayNativeComponent.ts +2 -0
  153. package/src/fabric/ModalScreenNativeComponent.ts +2 -0
  154. package/src/fabric/NativeScreensModule.ts +2 -0
  155. package/src/fabric/ScreenContainerNativeComponent.ts +2 -0
  156. package/src/fabric/ScreenNativeComponent.ts +5 -1
  157. package/src/fabric/ScreenNavigationContainerNativeComponent.ts +2 -0
  158. package/src/fabric/ScreenStackHeaderConfigNativeComponent.ts +4 -1
  159. package/src/fabric/ScreenStackHeaderSubviewNativeComponent.ts +2 -0
  160. package/src/fabric/ScreenStackNativeComponent.ts +2 -0
  161. package/src/fabric/SearchBarNativeComponent.ts +2 -0
  162. package/src/native-stack/contexts/GHContext.tsx +2 -0
  163. package/src/native-stack/types.tsx +3 -1
  164. package/src/types.tsx +7 -2
  165. package/windows/RNScreens/Screen.h +3 -1
  166. /package/android/src/main/res/base/anim/{rns_slide_in_from_left_ios.xml → rns_ios_from_right_background_close.xml} +0 -0
  167. /package/android/src/main/res/base/anim/{rns_slide_out_to_right_ios.xml → rns_ios_from_right_foreground_close.xml} +0 -0
  168. /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/TestsExample/src/Test1096.tsx
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
 
@@ -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
- target_link_libraries(
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
@@ -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
- // Matches the RN Hello World template
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
- url "$projectDir/../node_modules/react-native/android"
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: Double,
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: Double,
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", headerHeight)
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, totalHeight)
80
+ updateScreenSizeFabric(width, height, t)
83
81
  } else {
84
82
  updateScreenSizePaper(width, height)
85
83
  }
86
84
 
87
- notifyHeaderHeightChange(totalHeight)
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.javaClass.simpleName.equals("CircleImageView")) {
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 calculateHeaderHeight(): Pair<Double, Double> {
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.rns_slide_in_from_right_ios, R.anim.rns_slide_out_to_left_ios)
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.rns_slide_in_from_left_ios, R.anim.rns_slide_out_to_right_ios)
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 ?: false
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: Double,
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.toInt().toShort()
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
+ }
@@ -38,25 +38,34 @@ target_include_directories(
38
38
  ${LIB_ANDROID_GENERATED_COMPONENTS_DIR}
39
39
  )
40
40
 
41
- target_link_libraries(
42
- ${LIB_TARGET_NAME}
43
- fbjni
44
- folly_runtime
45
- glog
46
- jsi
47
- react_codegen_rncore
48
- react_debug
49
- react_nativemodule_core
50
- react_render_core
51
- react_render_debug
52
- react_render_graphics
53
- react_render_mapbuffer
54
- react_render_componentregistry
55
- react_utils
56
- rrc_view
57
- turbomodulejsijni
58
- yoga
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,5 @@
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:fromXDelta="30%"
5
+ android:toXDelta="0%" />
@@ -2,4 +2,4 @@
2
2
  <translate xmlns:android="http://schemas.android.com/apk/res/android"
3
3
  android:duration="@android:integer/config_shortAnimTime"
4
4
  android:fromXDelta="0%"
5
- android:toXDelta="-30%"/>
5
+ android:toXDelta="30%" />
@@ -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%" />
@@ -0,0 +1,5 @@
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:fromXDelta="0%"
5
+ android:toXDelta="-30%" />
@@ -12,7 +12,7 @@ abstract class FabricEnabledViewGroup(
12
12
  protected fun updateScreenSizeFabric(
13
13
  width: Int,
14
14
  height: Int,
15
- headerHeight: Double,
15
+ headerHeight: Int,
16
16
  ) {
17
17
  // do nothing
18
18
  }
@@ -5,9 +5,9 @@
5
5
  #endif
6
6
  #include <react/debug/react_native_assert.h>
7
7
  #include <react/renderer/components/rnscreens/Props.h>
8
+ #include <react/renderer/components/rnscreens/utils/RectUtil.h>
8
9
  #include <react/renderer/core/ConcreteComponentDescriptor.h>
9
10
  #include "RNSScreenShadowNode.h"
10
- #include "utils/RectUtil.h"
11
11
 
12
12
  namespace facebook {
13
13
  namespace react {
@@ -19,9 +19,6 @@ class RNSScreenComponentDescriptor final
19
19
  public:
20
20
  using ConcreteComponentDescriptor::ConcreteComponentDescriptor;
21
21
 
22
- static constexpr const char *kScreenDummyLayoutHelperClass =
23
- "com/swmansion/rnscreens/utils/ScreenDummyLayoutHelper";
24
-
25
22
  void adopt(ShadowNode &shadowNode) const override {
26
23
  react_native_assert(dynamic_cast<RNSScreenShadowNode *>(&shadowNode));
27
24
  auto &screenShadowNode = static_cast<RNSScreenShadowNode &>(shadowNode);
@@ -39,8 +36,8 @@ class RNSScreenComponentDescriptor final
39
36
  #ifdef ANDROID
40
37
  if (stateData.frameSize.width != 0 && stateData.frameSize.height != 0) {
41
38
  // When we receive dimensions from JVM side we can remove padding used for
42
- // correction, and we can stop applying height correction for the frame.
43
- // We want to leave top offset correction though intact.
39
+ // correction, and we can stop applying height and offset corrections for
40
+ // the frame.
44
41
  // TODO: In future, when we have dynamic header height we might want to
45
42
  // update Y offset correction here.
46
43
 
@@ -67,36 +64,11 @@ class RNSScreenComponentDescriptor final
67
64
  screenShadowNode.setPadding({0, 0, 0, 0});
68
65
  screenShadowNode.getFrameCorrectionModes().unset(
69
66
  FrameCorrectionModes::Mode::FrameHeightCorrection);
67
+ screenShadowNode.getFrameCorrectionModes().unset(
68
+ FrameCorrectionModes::Mode::FrameOriginCorrection);
70
69
 
71
70
  layoutableShadowNode.setSize(
72
71
  Size{stateData.frameSize.width, stateData.frameSize.height});
73
- } else {
74
- // This code path should be executed only on the very first (few)
75
- // layout(s), when we haven't received state update from JVM side yet.
76
-
77
- auto headerConfigChildOpt = findHeaderConfigChild(layoutableShadowNode);
78
-
79
- // During creation of the shadow node children are not attached yet.
80
- // We also do not want to set any padding in case.
81
- if (headerConfigChildOpt) {
82
- const auto &headerConfigChild = headerConfigChildOpt->get();
83
- const auto &headerProps =
84
- *std::static_pointer_cast<const RNSScreenStackHeaderConfigProps>(
85
- headerConfigChild->getProps());
86
-
87
- const auto headerHeight = headerProps.hidden
88
- ? 0.f
89
- : findHeaderHeight(
90
- headerProps.titleFontSize, headerProps.title.empty())
91
- .value_or(0.f);
92
-
93
- screenShadowNode.setPadding({0, 0, 0, headerHeight});
94
- screenShadowNode.setHeaderHeight(headerHeight);
95
- screenShadowNode.getFrameCorrectionModes().set(
96
- FrameCorrectionModes::Mode(
97
- FrameCorrectionModes::Mode::FrameHeightCorrection |
98
- FrameCorrectionModes::Mode::FrameOriginCorrection));
99
- }
100
72
  }
101
73
  #else
102
74
  if (stateData.frameSize.width != 0 && stateData.frameSize.height != 0) {
@@ -106,72 +78,6 @@ class RNSScreenComponentDescriptor final
106
78
  #endif // ANDROID
107
79
  ConcreteComponentDescriptor::adopt(shadowNode);
108
80
  }
109
-
110
- std::optional<std::reference_wrapper<const ShadowNode::Shared>>
111
- findHeaderConfigChild(
112
- const YogaLayoutableShadowNode &screenShadowNode) const {
113
- for (const ShadowNode::Shared &child : screenShadowNode.getChildren()) {
114
- if (std::strcmp(
115
- child->getComponentName(), "RNSScreenStackHeaderConfig") == 0) {
116
- return {std::cref(child)};
117
- }
118
- }
119
- return {};
120
- }
121
-
122
- #ifdef ANDROID
123
- std::optional<float> findHeaderHeight(
124
- const int fontSize,
125
- const bool isTitleEmpty) const {
126
- JNIEnv *env = facebook::jni::Environment::current();
127
-
128
- if (env == nullptr) {
129
- LOG(ERROR) << "[RNScreens] Failed to retrieve env\n";
130
- return {};
131
- }
132
-
133
- jclass layoutHelperClass = env->FindClass(kScreenDummyLayoutHelperClass);
134
-
135
- if (layoutHelperClass == nullptr) {
136
- LOG(ERROR) << "[RNScreens] Failed to find class with id "
137
- << kScreenDummyLayoutHelperClass;
138
- return {};
139
- }
140
-
141
- jmethodID computeDummyLayoutID =
142
- env->GetMethodID(layoutHelperClass, "computeDummyLayout", "(IZ)F");
143
-
144
- if (computeDummyLayoutID == nullptr) {
145
- LOG(ERROR)
146
- << "[RNScreens] Failed to retrieve computeDummyLayout method ID";
147
- return {};
148
- }
149
-
150
- jmethodID getInstanceMethodID = env->GetStaticMethodID(
151
- layoutHelperClass,
152
- "getInstance",
153
- "()Lcom/swmansion/rnscreens/utils/ScreenDummyLayoutHelper;");
154
-
155
- if (getInstanceMethodID == nullptr) {
156
- LOG(ERROR) << "[RNScreens] Failed to retrieve getInstanceMethodID";
157
- return {};
158
- }
159
-
160
- jobject packageInstance =
161
- env->CallStaticObjectMethod(layoutHelperClass, getInstanceMethodID);
162
-
163
- if (packageInstance == nullptr) {
164
- LOG(ERROR)
165
- << "[RNScreens] Failed to retrieve packageInstance or the package instance was null on JVM side";
166
- return {};
167
- }
168
-
169
- jfloat headerHeight = env->CallFloatMethod(
170
- packageInstance, computeDummyLayoutID, fontSize, isTitleEmpty);
171
-
172
- return {headerHeight};
173
- }
174
- #endif // ANDROID
175
81
  };
176
82
 
177
83
  } // namespace react