react-native-screens 3.31.1 → 3.33.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 (203) hide show
  1. package/README.md +21 -11
  2. package/RNScreens.podspec +11 -52
  3. package/android/CMakeLists.txt +48 -4
  4. package/android/build.gradle +16 -9
  5. package/android/src/fabric/java/com/swmansion/rnscreens/FabricEnabledViewGroup.kt +25 -16
  6. package/android/src/fabric/java/com/swmansion/rnscreens/NativeProxy.kt +53 -0
  7. package/android/src/main/cpp/NativeProxy.cpp +51 -0
  8. package/android/src/main/cpp/NativeProxy.h +35 -0
  9. package/android/src/main/cpp/OnLoad.cpp +8 -0
  10. package/android/src/main/cpp/jni-adapter.cpp +86 -93
  11. package/android/src/main/java/com/swmansion/rnscreens/CustomSearchView.kt +7 -2
  12. package/android/src/main/java/com/swmansion/rnscreens/CustomToolbar.kt +6 -1
  13. package/android/src/main/java/com/swmansion/rnscreens/FragmentBackPressOverrider.kt +2 -2
  14. package/android/src/main/java/com/swmansion/rnscreens/RNScreensPackage.kt +36 -17
  15. package/android/src/main/java/com/swmansion/rnscreens/Screen.kt +150 -40
  16. package/android/src/main/java/com/swmansion/rnscreens/ScreenContainer.kt +52 -30
  17. package/android/src/main/java/com/swmansion/rnscreens/ScreenContainerViewManager.kt +27 -4
  18. package/android/src/main/java/com/swmansion/rnscreens/ScreenEventDispatcher.kt +10 -2
  19. package/android/src/main/java/com/swmansion/rnscreens/ScreenFragment.kt +56 -27
  20. package/android/src/main/java/com/swmansion/rnscreens/ScreenFragmentWrapper.kt +8 -1
  21. package/android/src/main/java/com/swmansion/rnscreens/ScreenStack.kt +50 -19
  22. package/android/src/main/java/com/swmansion/rnscreens/ScreenStackFragment.kt +63 -39
  23. package/android/src/main/java/com/swmansion/rnscreens/ScreenStackFragmentWrapper.kt +4 -0
  24. package/android/src/main/java/com/swmansion/rnscreens/ScreenStackHeaderConfig.kt +88 -57
  25. package/android/src/main/java/com/swmansion/rnscreens/ScreenStackHeaderConfigViewManager.kt +131 -36
  26. package/android/src/main/java/com/swmansion/rnscreens/ScreenStackHeaderSubview.kt +19 -4
  27. package/android/src/main/java/com/swmansion/rnscreens/ScreenStackHeaderSubviewManager.kt +16 -10
  28. package/android/src/main/java/com/swmansion/rnscreens/ScreenStackViewManager.kt +28 -25
  29. package/android/src/main/java/com/swmansion/rnscreens/ScreenViewManager.kt +177 -77
  30. package/android/src/main/java/com/swmansion/rnscreens/ScreenWindowTraits.kt +77 -25
  31. package/android/src/main/java/com/swmansion/rnscreens/ScreensModule.kt +31 -9
  32. package/android/src/main/java/com/swmansion/rnscreens/ScreensShadowNode.kt +3 -1
  33. package/android/src/main/java/com/swmansion/rnscreens/SearchBarManager.kt +160 -54
  34. package/android/src/main/java/com/swmansion/rnscreens/SearchBarView.kt +29 -22
  35. package/android/src/main/java/com/swmansion/rnscreens/SearchViewFormatter.kt +7 -2
  36. package/android/src/main/java/com/swmansion/rnscreens/events/HeaderAttachedEvent.kt +4 -1
  37. package/android/src/main/java/com/swmansion/rnscreens/events/HeaderBackButtonClickedEvent.kt +4 -1
  38. package/android/src/main/java/com/swmansion/rnscreens/events/HeaderDetachedEvent.kt +4 -1
  39. package/android/src/main/java/com/swmansion/rnscreens/events/HeaderHeightChangeEvent.kt +5 -6
  40. package/android/src/main/java/com/swmansion/rnscreens/events/ScreenAppearEvent.kt +4 -1
  41. package/android/src/main/java/com/swmansion/rnscreens/events/ScreenDisappearEvent.kt +4 -1
  42. package/android/src/main/java/com/swmansion/rnscreens/events/ScreenDismissedEvent.kt +8 -4
  43. package/android/src/main/java/com/swmansion/rnscreens/events/ScreenTransitionProgressEvent.kt +7 -6
  44. package/android/src/main/java/com/swmansion/rnscreens/events/ScreenWillAppearEvent.kt +4 -1
  45. package/android/src/main/java/com/swmansion/rnscreens/events/ScreenWillDisappearEvent.kt +4 -1
  46. package/android/src/main/java/com/swmansion/rnscreens/events/SearchBarBlurEvent.kt +5 -2
  47. package/android/src/main/java/com/swmansion/rnscreens/events/SearchBarChangeTextEvent.kt +4 -3
  48. package/android/src/main/java/com/swmansion/rnscreens/events/SearchBarCloseEvent.kt +4 -1
  49. package/android/src/main/java/com/swmansion/rnscreens/events/SearchBarFocusEvent.kt +5 -2
  50. package/android/src/main/java/com/swmansion/rnscreens/events/SearchBarOpenEvent.kt +4 -1
  51. package/android/src/main/java/com/swmansion/rnscreens/events/SearchBarSearchButtonPressEvent.kt +9 -4
  52. package/android/src/main/java/com/swmansion/rnscreens/events/StackFinishTransitioningEvent.kt +4 -1
  53. package/android/src/main/java/com/swmansion/rnscreens/utils/DeviceUtils.kt +1 -5
  54. package/android/src/main/java/com/swmansion/rnscreens/utils/ScreenDummyLayoutHelper.kt +214 -0
  55. package/android/src/main/jni/CMakeLists.txt +5 -4
  56. package/android/src/paper/java/com/facebook/react/viewmanagers/RNSScreenContainerManagerDelegate.java +25 -0
  57. package/android/src/paper/java/com/facebook/react/viewmanagers/RNSScreenContainerManagerInterface.java +16 -0
  58. package/android/src/paper/java/com/facebook/react/viewmanagers/RNSScreenManagerDelegate.java +6 -0
  59. package/android/src/paper/java/com/facebook/react/viewmanagers/RNSScreenManagerInterface.java +2 -0
  60. package/android/src/paper/java/com/facebook/react/viewmanagers/RNSScreenStackHeaderConfigManagerDelegate.java +3 -0
  61. package/android/src/paper/java/com/facebook/react/viewmanagers/RNSScreenStackHeaderConfigManagerInterface.java +1 -0
  62. package/android/src/paper/java/com/facebook/react/viewmanagers/RNSSearchBarManagerDelegate.java +99 -0
  63. package/android/src/paper/java/com/facebook/react/viewmanagers/RNSSearchBarManagerInterface.java +37 -0
  64. package/android/src/paper/java/com/swmansion/rnscreens/FabricEnabledViewGroup.kt +10 -5
  65. package/android/src/paper/java/com/swmansion/rnscreens/NativeProxy.kt +19 -0
  66. package/android/src/paper/java/com/swmansion/rnscreens/NativeScreensModuleSpec.java +4 -0
  67. package/common/cpp/react/renderer/components/rnscreens/FrameCorrectionModes.h +51 -0
  68. package/common/cpp/react/renderer/components/rnscreens/RNSModalScreenComponentDescriptor.h +8 -9
  69. package/common/cpp/react/renderer/components/rnscreens/RNSModalScreenShadowNode.cpp +2 -1
  70. package/common/cpp/react/renderer/components/rnscreens/RNSModalScreenShadowNode.h +9 -8
  71. package/common/cpp/react/renderer/components/rnscreens/RNSScreenComponentDescriptor.h +147 -10
  72. package/common/cpp/react/renderer/components/rnscreens/RNSScreenShadowNode.cpp +51 -1
  73. package/common/cpp/react/renderer/components/rnscreens/RNSScreenShadowNode.h +29 -7
  74. package/common/cpp/react/renderer/components/rnscreens/RNSScreenState.cpp +22 -1
  75. package/common/cpp/react/renderer/components/rnscreens/RNSScreenState.h +30 -10
  76. package/common/cpp/react/renderer/components/rnscreens/utils/RectUtil.h +36 -0
  77. package/cpp/RNSScreenRemovalListener.cpp +25 -0
  78. package/cpp/RNSScreenRemovalListener.h +20 -0
  79. package/cpp/RNScreensTurboModule.cpp +31 -23
  80. package/cpp/RNScreensTurboModule.h +17 -20
  81. package/ios/RNSConvert.h +7 -0
  82. package/ios/RNSConvert.mm +24 -0
  83. package/ios/RNSModalScreen.mm +22 -0
  84. package/ios/RNSModule.mm +2 -3
  85. package/ios/RNSScreen.h +2 -1
  86. package/ios/RNSScreen.mm +35 -19
  87. package/ios/RNSScreenContainer.mm +1 -1
  88. package/ios/RNSScreenStack.mm +59 -54
  89. package/ios/RNSScreenStackAnimator.mm +43 -6
  90. package/ios/RNSScreenStackHeaderConfig.h +2 -0
  91. package/ios/RNSScreenStackHeaderConfig.mm +93 -28
  92. package/ios/RNSScreenStackHeaderSubview.mm +8 -0
  93. package/ios/RNSSearchBar.h +5 -5
  94. package/ios/RNSSearchBar.mm +11 -11
  95. package/ios/utils/RCTSurfaceTouchHandler+RNSUtility.h +15 -0
  96. package/ios/utils/RCTSurfaceTouchHandler+RNSUtility.mm +14 -0
  97. package/ios/utils/RCTTouchHandler+RNSUtility.h +15 -0
  98. package/ios/utils/RCTTouchHandler+RNSUtility.mm +15 -0
  99. package/ios/utils/UIView+RNSUtility.h +23 -0
  100. package/ios/utils/UIView+RNSUtility.mm +55 -0
  101. package/lib/commonjs/components/Screen.js +119 -127
  102. package/lib/commonjs/components/Screen.js.map +1 -1
  103. package/lib/commonjs/components/ScreenStack.js +8 -1
  104. package/lib/commonjs/components/ScreenStack.js.map +1 -1
  105. package/lib/commonjs/components/SearchBar.js +39 -36
  106. package/lib/commonjs/components/SearchBar.js.map +1 -1
  107. package/lib/commonjs/fabric/ModalScreenNativeComponent.js.map +1 -1
  108. package/lib/commonjs/fabric/ScreenNativeComponent.js.map +1 -1
  109. package/lib/commonjs/fabric/ScreenStackHeaderConfigNativeComponent.js.map +1 -1
  110. package/lib/commonjs/native-stack/views/HeaderConfig.js +2 -0
  111. package/lib/commonjs/native-stack/views/HeaderConfig.js.map +1 -1
  112. package/lib/commonjs/native-stack/views/NativeStackView.js +4 -0
  113. package/lib/commonjs/native-stack/views/NativeStackView.js.map +1 -1
  114. package/lib/module/components/Screen.js +118 -126
  115. package/lib/module/components/Screen.js.map +1 -1
  116. package/lib/module/components/ScreenStack.js +8 -1
  117. package/lib/module/components/ScreenStack.js.map +1 -1
  118. package/lib/module/components/SearchBar.js +39 -36
  119. package/lib/module/components/SearchBar.js.map +1 -1
  120. package/lib/module/fabric/ModalScreenNativeComponent.js.map +1 -1
  121. package/lib/module/fabric/ScreenNativeComponent.js.map +1 -1
  122. package/lib/module/fabric/ScreenStackHeaderConfigNativeComponent.js.map +1 -1
  123. package/lib/module/native-stack/views/HeaderConfig.js +2 -0
  124. package/lib/module/native-stack/views/HeaderConfig.js.map +1 -1
  125. package/lib/module/native-stack/views/NativeStackView.js +4 -0
  126. package/lib/module/native-stack/views/NativeStackView.js.map +1 -1
  127. package/lib/typescript/TransitionProgressContext.d.ts +1 -1
  128. package/lib/typescript/TransitionProgressContext.d.ts.map +1 -1
  129. package/lib/typescript/components/Screen.d.ts +3 -14
  130. package/lib/typescript/components/Screen.d.ts.map +1 -1
  131. package/lib/typescript/components/ScreenStack.d.ts.map +1 -1
  132. package/lib/typescript/components/SearchBar.d.ts +14 -21
  133. package/lib/typescript/components/SearchBar.d.ts.map +1 -1
  134. package/lib/typescript/fabric/ModalScreenNativeComponent.d.ts +12 -10
  135. package/lib/typescript/fabric/ModalScreenNativeComponent.d.ts.map +1 -1
  136. package/lib/typescript/fabric/ScreenNativeComponent.d.ts +12 -10
  137. package/lib/typescript/fabric/ScreenNativeComponent.d.ts.map +1 -1
  138. package/lib/typescript/fabric/ScreenStackHeaderConfigNativeComponent.d.ts +5 -3
  139. package/lib/typescript/fabric/ScreenStackHeaderConfigNativeComponent.d.ts.map +1 -1
  140. package/lib/typescript/fabric/ScreenStackHeaderSubviewNativeComponent.d.ts +1 -1
  141. package/lib/typescript/fabric/ScreenStackHeaderSubviewNativeComponent.d.ts.map +1 -1
  142. package/lib/typescript/fabric/ScreenStackNativeComponent.d.ts +1 -1
  143. package/lib/typescript/fabric/ScreenStackNativeComponent.d.ts.map +1 -1
  144. package/lib/typescript/fabric/SearchBarNativeComponent.d.ts +9 -9
  145. package/lib/typescript/fabric/SearchBarNativeComponent.d.ts.map +1 -1
  146. package/lib/typescript/gesture-handler/RNScreensTurboModule.d.ts +1 -1
  147. package/lib/typescript/gesture-handler/RNScreensTurboModule.d.ts.map +1 -1
  148. package/lib/typescript/native-stack/types.d.ts +39 -14
  149. package/lib/typescript/native-stack/types.d.ts.map +1 -1
  150. package/lib/typescript/native-stack/utils/SafeAreaProviderCompat.d.ts +1 -1
  151. package/lib/typescript/native-stack/utils/SafeAreaProviderCompat.d.ts.map +1 -1
  152. package/lib/typescript/native-stack/utils/getDefaultHeaderHeight.d.ts +1 -1
  153. package/lib/typescript/native-stack/utils/getDefaultHeaderHeight.d.ts.map +1 -1
  154. package/lib/typescript/native-stack/utils/useAnimatedHeaderHeight.d.ts +1 -1
  155. package/lib/typescript/native-stack/utils/useAnimatedHeaderHeight.d.ts.map +1 -1
  156. package/lib/typescript/native-stack/views/HeaderConfig.d.ts +2 -2
  157. package/lib/typescript/native-stack/views/HeaderConfig.d.ts.map +1 -1
  158. package/lib/typescript/native-stack/views/NativeStackView.d.ts +1 -1
  159. package/lib/typescript/native-stack/views/NativeStackView.d.ts.map +1 -1
  160. package/lib/typescript/reanimated/ReanimatedTransitionProgressContext.d.ts +1 -1
  161. package/lib/typescript/reanimated/ReanimatedTransitionProgressContext.d.ts.map +1 -1
  162. package/lib/typescript/types.d.ts +39 -13
  163. package/lib/typescript/types.d.ts.map +1 -1
  164. package/lib/typescript/useTransitionProgress.d.ts +3 -3
  165. package/native-stack/README.md +116 -98
  166. package/package.json +16 -7
  167. package/react-native.config.js +17 -15
  168. package/src/TransitionProgressContext.tsx +1 -1
  169. package/src/components/Screen.tsx +31 -37
  170. package/src/components/ScreenStack.tsx +11 -1
  171. package/src/components/ScreenStackHeaderConfig.tsx +5 -5
  172. package/src/components/ScreenStackHeaderConfig.web.tsx +6 -6
  173. package/src/components/SearchBar.tsx +77 -65
  174. package/src/core.ts +1 -1
  175. package/src/fabric/ModalScreenNativeComponent.ts +2 -0
  176. package/src/fabric/ScreenNativeComponent.ts +2 -0
  177. package/src/fabric/ScreenNavigationContainerNativeComponent.ts +1 -1
  178. package/src/fabric/ScreenStackHeaderConfigNativeComponent.ts +4 -1
  179. package/src/fabric/ScreenStackHeaderSubviewNativeComponent.ts +1 -1
  180. package/src/fabric/SearchBarNativeComponent.ts +7 -7
  181. package/src/gesture-handler/ScreenGestureDetector.tsx +5 -5
  182. package/src/gesture-handler/constraints.ts +5 -5
  183. package/src/gesture-handler/fabricUtils.ts +1 -1
  184. package/src/native-stack/contexts/GHContext.tsx +1 -1
  185. package/src/native-stack/navigators/createNativeStackNavigator.tsx +3 -3
  186. package/src/native-stack/types.tsx +29 -4
  187. package/src/native-stack/utils/getDefaultHeaderHeight.tsx +1 -1
  188. package/src/native-stack/utils/getStatusBarHeight.tsx +1 -1
  189. package/src/native-stack/utils/useAnimatedHeaderHeight.tsx +1 -1
  190. package/src/native-stack/utils/useBackPressSubscription.tsx +1 -1
  191. package/src/native-stack/utils/useHeaderHeight.tsx +1 -1
  192. package/src/native-stack/views/FontProcessor.tsx +1 -1
  193. package/src/native-stack/views/HeaderConfig.tsx +3 -1
  194. package/src/native-stack/views/NativeStackView.tsx +13 -9
  195. package/src/reanimated/ReanimatedHeaderHeightContext.tsx +1 -1
  196. package/src/reanimated/ReanimatedNativeStackScreen.tsx +5 -5
  197. package/src/reanimated/ReanimatedScreen.tsx +2 -2
  198. package/src/reanimated/ReanimatedScreenProvider.tsx +1 -1
  199. package/src/reanimated/useReanimatedHeaderHeight.tsx +1 -1
  200. package/src/reanimated/useReanimatedTransitionProgress.tsx +1 -1
  201. package/src/types.tsx +31 -5
  202. package/src/useTransitionProgress.tsx +1 -1
  203. package/windows/README.md +4 -1
@@ -19,27 +19,37 @@ import com.facebook.react.uimanager.UIManagerHelper
19
19
  import com.swmansion.rnscreens.Screen.ActivityState
20
20
  import com.swmansion.rnscreens.events.ScreenDismissedEvent
21
21
 
22
- open class ScreenContainer(context: Context?) : ViewGroup(context) {
22
+ open class ScreenContainer(
23
+ context: Context?,
24
+ ) : ViewGroup(context) {
23
25
  @JvmField
24
26
  protected val screenWrappers = ArrayList<ScreenFragmentWrapper>()
27
+
25
28
  @JvmField
26
29
  protected var fragmentManager: FragmentManager? = null
27
30
  private var isAttached = false
28
31
  private var needsUpdate = false
29
32
  private var isLayoutEnqueued = false
30
- private val layoutCallback: ChoreographerCompat.FrameCallback = object : ChoreographerCompat.FrameCallback() {
31
- override fun doFrame(frameTimeNanos: Long) {
32
- isLayoutEnqueued = false
33
- measure(
34
- MeasureSpec.makeMeasureSpec(width, MeasureSpec.EXACTLY),
35
- MeasureSpec.makeMeasureSpec(height, MeasureSpec.EXACTLY)
36
- )
37
- layout(left, top, right, bottom)
33
+ private val layoutCallback: ChoreographerCompat.FrameCallback =
34
+ object : ChoreographerCompat.FrameCallback() {
35
+ override fun doFrame(frameTimeNanos: Long) {
36
+ isLayoutEnqueued = false
37
+ measure(
38
+ MeasureSpec.makeMeasureSpec(width, MeasureSpec.EXACTLY),
39
+ MeasureSpec.makeMeasureSpec(height, MeasureSpec.EXACTLY),
40
+ )
41
+ layout(left, top, right, bottom)
42
+ }
38
43
  }
39
- }
40
44
  private var parentScreenWrapper: ScreenFragmentWrapper? = null
41
45
 
42
- override fun onLayout(changed: Boolean, l: Int, t: Int, r: Int, b: Int) {
46
+ override fun onLayout(
47
+ changed: Boolean,
48
+ l: Int,
49
+ t: Int,
50
+ r: Int,
51
+ b: Int,
52
+ ) {
43
53
  var i = 0
44
54
  val size = childCount
45
55
  while (i < size) {
@@ -69,9 +79,11 @@ open class ScreenContainer(context: Context?) : ViewGroup(context) {
69
79
  isLayoutEnqueued = true
70
80
  // we use NATIVE_ANIMATED_MODULE choreographer queue because it allows us to catch the current
71
81
  // looper loop instead of enqueueing the update in the next loop causing a one frame delay.
72
- ReactChoreographer.getInstance()
82
+ ReactChoreographer
83
+ .getInstance()
73
84
  .postFrameCallback(
74
- ReactChoreographer.CallbackType.NATIVE_ANIMATED_MODULE, layoutCallback
85
+ ReactChoreographer.CallbackType.NATIVE_ANIMATED_MODULE,
86
+ layoutCallback,
75
87
  )
76
88
  }
77
89
  }
@@ -85,7 +97,10 @@ open class ScreenContainer(context: Context?) : ViewGroup(context) {
85
97
 
86
98
  protected open fun adapt(screen: Screen): ScreenFragmentWrapper = ScreenFragment(screen)
87
99
 
88
- fun addScreen(screen: Screen, index: Int) {
100
+ fun addScreen(
101
+ screen: Screen,
102
+ index: Int,
103
+ ) {
89
104
  val fragment = adapt(screen)
90
105
  screen.fragmentWrapper = fragment
91
106
  screenWrappers.add(index, fragment)
@@ -173,7 +188,7 @@ open class ScreenContainer(context: Context?) : ViewGroup(context) {
173
188
  parentScreenWrapper = fragmentWrapper
174
189
  fragmentWrapper.addChildScreenContainer(this)
175
190
  setFragmentManager(fragmentWrapper.fragment.childFragmentManager)
176
- }
191
+ },
177
192
  ) { "Parent Screen does not have its Fragment attached" }
178
193
  } else {
179
194
  // we expect top level view to be of type ReactRootView, this isn't really necessary but in
@@ -186,13 +201,15 @@ open class ScreenContainer(context: Context?) : ViewGroup(context) {
186
201
  }
187
202
  }
188
203
 
189
- protected fun createTransaction(): FragmentTransaction {
190
- return requireNotNull(fragmentManager) { "fragment manager is null when creating transaction" }
204
+ protected fun createTransaction(): FragmentTransaction =
205
+ requireNotNull(fragmentManager) { "fragment manager is null when creating transaction" }
191
206
  .beginTransaction()
192
207
  .setReorderingAllowed(true)
193
- }
194
208
 
195
- private fun attachScreen(transaction: FragmentTransaction, fragment: Fragment) {
209
+ private fun attachScreen(
210
+ transaction: FragmentTransaction,
211
+ fragment: Fragment,
212
+ ) {
196
213
  transaction.add(id, fragment)
197
214
  }
198
215
 
@@ -228,15 +245,16 @@ open class ScreenContainer(context: Context?) : ViewGroup(context) {
228
245
  }
229
246
  }
230
247
 
231
- private fun detachScreen(transaction: FragmentTransaction, fragment: Fragment) {
248
+ private fun detachScreen(
249
+ transaction: FragmentTransaction,
250
+ fragment: Fragment,
251
+ ) {
232
252
  transaction.remove(fragment)
233
253
  }
234
254
 
235
- private fun getActivityState(screenFragmentWrapper: ScreenFragmentWrapper): ActivityState? =
236
- screenFragmentWrapper.screen.activityState
255
+ private fun getActivityState(screenFragmentWrapper: ScreenFragmentWrapper): ActivityState? = screenFragmentWrapper.screen.activityState
237
256
 
238
- open fun hasScreen(screenFragmentWrapper: ScreenFragmentWrapper?): Boolean =
239
- screenWrappers.contains(screenFragmentWrapper)
257
+ open fun hasScreen(screenFragmentWrapper: ScreenFragmentWrapper?): Boolean = screenWrappers.contains(screenFragmentWrapper)
240
258
 
241
259
  override fun onAttachedToWindow() {
242
260
  super.onAttachedToWindow()
@@ -295,7 +313,10 @@ open class ScreenContainer(context: Context?) : ViewGroup(context) {
295
313
  }
296
314
  }
297
315
 
298
- override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
316
+ override fun onMeasure(
317
+ widthMeasureSpec: Int,
318
+ heightMeasureSpec: Int,
319
+ ) {
299
320
  super.onMeasure(widthMeasureSpec, heightMeasureSpec)
300
321
  for (i in 0 until childCount) {
301
322
  getChildAt(i).measure(widthMeasureSpec, heightMeasureSpec)
@@ -342,11 +363,12 @@ open class ScreenContainer(context: Context?) : ViewGroup(context) {
342
363
  open fun onUpdate() {
343
364
  createTransaction().let {
344
365
  // detach screens that are no longer active
345
- val orphaned: MutableSet<Fragment> = HashSet(
346
- requireNotNull(fragmentManager) {
347
- "fragment manager is null when performing update in ScreenContainer"
348
- }.fragments
349
- )
366
+ val orphaned: MutableSet<Fragment> =
367
+ HashSet(
368
+ requireNotNull(fragmentManager) {
369
+ "fragment manager is null when performing update in ScreenContainer"
370
+ }.fragments,
371
+ )
350
372
  for (fragmentWrapper in screenWrappers) {
351
373
  if (getActivityState(fragmentWrapper) === ActivityState.INACTIVE &&
352
374
  fragmentWrapper.fragment.isAdded
@@ -6,19 +6,39 @@ import com.facebook.react.module.annotations.ReactModule
6
6
  import com.facebook.react.uimanager.LayoutShadowNode
7
7
  import com.facebook.react.uimanager.ThemedReactContext
8
8
  import com.facebook.react.uimanager.ViewGroupManager
9
+ import com.facebook.react.uimanager.ViewManagerDelegate
10
+ import com.facebook.react.viewmanagers.RNSScreenContainerManagerDelegate
11
+ import com.facebook.react.viewmanagers.RNSScreenContainerManagerInterface
9
12
 
10
13
  @ReactModule(name = ScreenContainerViewManager.REACT_CLASS)
11
- class ScreenContainerViewManager : ViewGroupManager<ScreenContainer>() {
14
+ class ScreenContainerViewManager :
15
+ ViewGroupManager<ScreenContainer>(),
16
+ RNSScreenContainerManagerInterface<ScreenContainer> {
17
+ private val delegate: ViewManagerDelegate<ScreenContainer>
18
+
19
+ init {
20
+ delegate = RNSScreenContainerManagerDelegate<ScreenContainer, ScreenContainerViewManager>(this)
21
+ }
22
+
23
+ protected override fun getDelegate(): ViewManagerDelegate<ScreenContainer> = delegate
24
+
12
25
  override fun getName(): String = REACT_CLASS
13
26
 
14
27
  override fun createViewInstance(reactContext: ThemedReactContext): ScreenContainer = ScreenContainer(reactContext)
15
28
 
16
- override fun addView(parent: ScreenContainer, child: View, index: Int) {
29
+ override fun addView(
30
+ parent: ScreenContainer,
31
+ child: View,
32
+ index: Int,
33
+ ) {
17
34
  require(child is Screen) { "Attempt attach child that is not of type RNScreens" }
18
35
  parent.addScreen(child, index)
19
36
  }
20
37
 
21
- override fun removeViewAt(parent: ScreenContainer, index: Int) {
38
+ override fun removeViewAt(
39
+ parent: ScreenContainer,
40
+ index: Int,
41
+ ) {
22
42
  parent.removeScreenAt(index)
23
43
  }
24
44
 
@@ -28,7 +48,10 @@ class ScreenContainerViewManager : ViewGroupManager<ScreenContainer>() {
28
48
 
29
49
  override fun getChildCount(parent: ScreenContainer): Int = parent.screenCount
30
50
 
31
- override fun getChildAt(parent: ScreenContainer, index: Int): View = parent.getScreenAt(index)
51
+ override fun getChildAt(
52
+ parent: ScreenContainer,
53
+ index: Int,
54
+ ): View = parent.getScreenAt(index)
32
55
 
33
56
  override fun createShadowNodeInstance(context: ReactApplicationContext): LayoutShadowNode = ScreensShadowNode(context)
34
57
 
@@ -2,12 +2,16 @@ package com.swmansion.rnscreens
2
2
 
3
3
  interface ScreenEventDispatcher {
4
4
  fun canDispatchLifecycleEvent(event: ScreenFragment.ScreenLifecycleEvent): Boolean
5
+
5
6
  fun updateLastEventDispatched(event: ScreenFragment.ScreenLifecycleEvent)
6
7
 
7
8
  /**
8
9
  * Dispatches given screen lifecycle event to JS using screen from given fragment `fragmentWrapper`
9
10
  */
10
- fun dispatchLifecycleEvent(event: ScreenFragment.ScreenLifecycleEvent, fragmentWrapper: ScreenFragmentWrapper)
11
+ fun dispatchLifecycleEvent(
12
+ event: ScreenFragment.ScreenLifecycleEvent,
13
+ fragmentWrapper: ScreenFragmentWrapper,
14
+ )
11
15
 
12
16
  /**
13
17
  * Dispatches given screen lifecycle event from all non-empty child containers to JS
@@ -15,7 +19,11 @@ interface ScreenEventDispatcher {
15
19
  fun dispatchLifecycleEventInChildContainers(event: ScreenFragment.ScreenLifecycleEvent)
16
20
 
17
21
  fun dispatchHeaderBackButtonClickedEvent()
18
- fun dispatchTransitionProgressEvent(alpha: Float, closing: Boolean)
22
+
23
+ fun dispatchTransitionProgressEvent(
24
+ alpha: Float,
25
+ closing: Boolean,
26
+ )
19
27
 
20
28
  // Concrete dispatchers
21
29
  }
@@ -25,9 +25,14 @@ import com.swmansion.rnscreens.events.ScreenWillDisappearEvent
25
25
  import kotlin.math.max
26
26
  import kotlin.math.min
27
27
 
28
- open class ScreenFragment : Fragment, ScreenFragmentWrapper {
28
+ open class ScreenFragment :
29
+ Fragment,
30
+ ScreenFragmentWrapper {
29
31
  enum class ScreenLifecycleEvent {
30
- DID_APPEAR, WILL_APPEAR, DID_DISAPPEAR, WILL_DISAPPEAR
32
+ DID_APPEAR,
33
+ WILL_APPEAR,
34
+ DID_DISAPPEAR,
35
+ WILL_DISAPPEAR,
31
36
  }
32
37
 
33
38
  override val fragment: Fragment
@@ -40,6 +45,7 @@ open class ScreenFragment : Fragment, ScreenFragmentWrapper {
40
45
  override val childScreenContainers: MutableList<ScreenContainer> = ArrayList()
41
46
 
42
47
  private var shouldUpdateOnResume = false
48
+
43
49
  // if we don't set it, it will be 0.0f at the beginning so the progress will not be sent
44
50
  // due to progress value being already 0.0f
45
51
  private var transitionProgress = -1f
@@ -57,7 +63,7 @@ open class ScreenFragment : Fragment, ScreenFragmentWrapper {
57
63
 
58
64
  constructor() {
59
65
  throw IllegalStateException(
60
- "Screen fragments should never be restored. Follow instructions from https://github.com/software-mansion/react-native-screens/issues/17#issuecomment-424704067 to properly configure your main activity."
66
+ "Screen fragments should never be restored. Follow instructions from https://github.com/software-mansion/react-native-screens/issues/17#issuecomment-424704067 to properly configure your main activity.",
61
67
  )
62
68
  }
63
69
 
@@ -77,14 +83,17 @@ open class ScreenFragment : Fragment, ScreenFragmentWrapper {
77
83
  override fun onCreateView(
78
84
  inflater: LayoutInflater,
79
85
  container: ViewGroup?,
80
- savedInstanceState: Bundle?
86
+ savedInstanceState: Bundle?,
81
87
  ): View? {
82
- screen.layoutParams = FrameLayout.LayoutParams(
83
- ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT
84
- )
85
- val wrapper = context?.let { ScreensFrameLayout(it) }?.apply {
86
- addView(recycleView(screen))
87
- }
88
+ screen.layoutParams =
89
+ FrameLayout.LayoutParams(
90
+ ViewGroup.LayoutParams.MATCH_PARENT,
91
+ ViewGroup.LayoutParams.MATCH_PARENT,
92
+ )
93
+ val wrapper =
94
+ context?.let { ScreensFrameLayout(it) }?.apply {
95
+ addView(recycleView(screen))
96
+ }
88
97
  return wrapper
89
98
  }
90
99
 
@@ -154,12 +163,13 @@ open class ScreenFragment : Fragment, ScreenFragmentWrapper {
154
163
  return null
155
164
  }
156
165
 
157
- override fun canDispatchLifecycleEvent(event: ScreenLifecycleEvent): Boolean = when (event) {
158
- ScreenLifecycleEvent.WILL_APPEAR -> canDispatchWillAppear
159
- ScreenLifecycleEvent.DID_APPEAR -> canDispatchAppear
160
- ScreenLifecycleEvent.WILL_DISAPPEAR -> !canDispatchWillAppear
161
- ScreenLifecycleEvent.DID_DISAPPEAR -> !canDispatchAppear
162
- }
166
+ override fun canDispatchLifecycleEvent(event: ScreenLifecycleEvent): Boolean =
167
+ when (event) {
168
+ ScreenLifecycleEvent.WILL_APPEAR -> canDispatchWillAppear
169
+ ScreenLifecycleEvent.DID_APPEAR -> canDispatchAppear
170
+ ScreenLifecycleEvent.WILL_DISAPPEAR -> !canDispatchWillAppear
171
+ ScreenLifecycleEvent.DID_DISAPPEAR -> !canDispatchAppear
172
+ }
163
173
 
164
174
  override fun updateLastEventDispatched(event: ScreenLifecycleEvent) {
165
175
  when (event) {
@@ -190,18 +200,22 @@ open class ScreenFragment : Fragment, ScreenFragmentWrapper {
190
200
  dispatchTransitionProgressEvent(1.0f, true)
191
201
  }
192
202
 
193
- override fun dispatchLifecycleEvent(event: ScreenLifecycleEvent, fragmentWrapper: ScreenFragmentWrapper) {
203
+ override fun dispatchLifecycleEvent(
204
+ event: ScreenLifecycleEvent,
205
+ fragmentWrapper: ScreenFragmentWrapper,
206
+ ) {
194
207
  val fragment = fragmentWrapper.fragment
195
208
  if (fragment is ScreenStackFragment && fragment.canDispatchLifecycleEvent(event)) {
196
209
  fragment.screen.let {
197
210
  fragmentWrapper.updateLastEventDispatched(event)
198
211
  val surfaceId = UIManagerHelper.getSurfaceId(it)
199
- val lifecycleEvent: Event<*> = when (event) {
200
- ScreenLifecycleEvent.WILL_APPEAR -> ScreenWillAppearEvent(surfaceId, it.id)
201
- ScreenLifecycleEvent.DID_APPEAR -> ScreenAppearEvent(surfaceId, it.id)
202
- ScreenLifecycleEvent.WILL_DISAPPEAR -> ScreenWillDisappearEvent(surfaceId, it.id)
203
- ScreenLifecycleEvent.DID_DISAPPEAR -> ScreenDisappearEvent(surfaceId, it.id)
204
- }
212
+ val lifecycleEvent: Event<*> =
213
+ when (event) {
214
+ ScreenLifecycleEvent.WILL_APPEAR -> ScreenWillAppearEvent(surfaceId, it.id)
215
+ ScreenLifecycleEvent.DID_APPEAR -> ScreenAppearEvent(surfaceId, it.id)
216
+ ScreenLifecycleEvent.WILL_DISAPPEAR -> ScreenWillDisappearEvent(surfaceId, it.id)
217
+ ScreenLifecycleEvent.DID_DISAPPEAR -> ScreenDisappearEvent(surfaceId, it.id)
218
+ }
205
219
  val screenContext = screen.context as ReactContext
206
220
  val eventDispatcher: EventDispatcher? =
207
221
  UIManagerHelper.getEventDispatcherForReactTag(screenContext, screen.id)
@@ -225,7 +239,10 @@ open class ScreenFragment : Fragment, ScreenFragmentWrapper {
225
239
  ?.dispatchEvent(HeaderBackButtonClickedEvent(surfaceId, screen.id))
226
240
  }
227
241
 
228
- override fun dispatchTransitionProgressEvent(alpha: Float, closing: Boolean) {
242
+ override fun dispatchTransitionProgressEvent(
243
+ alpha: Float,
244
+ closing: Boolean,
245
+ ) {
229
246
  if (this is ScreenStackFragment) {
230
247
  if (transitionProgress != alpha) {
231
248
  transitionProgress = max(0.0f, min(1.0f, alpha))
@@ -238,8 +255,12 @@ open class ScreenFragment : Fragment, ScreenFragmentWrapper {
238
255
  ?.dispatchEvent(
239
256
  ScreenTransitionProgressEvent(
240
257
  UIManagerHelper.getSurfaceId(screenContext),
241
- screen.id, transitionProgress, closing, goingForward, coalescingKey
242
- )
258
+ screen.id,
259
+ transitionProgress,
260
+ closing,
261
+ goingForward,
262
+ coalescingKey,
263
+ ),
243
264
  )
244
265
  }
245
266
  }
@@ -328,7 +349,15 @@ open class ScreenFragment : Fragment, ScreenFragmentWrapper {
328
349
  - progress is 1 -> key 2
329
350
  - progress is between 0 and 1 -> key 3
330
351
  */
331
- return (if (progress == 0.0f) 1 else if (progress == 1.0f) 2 else 3).toShort()
352
+ return (
353
+ if (progress == 0.0f) {
354
+ 1
355
+ } else if (progress == 1.0f) {
356
+ 2
357
+ } else {
358
+ 3
359
+ }
360
+ ).toShort()
332
361
  }
333
362
  }
334
363
  }
@@ -3,20 +3,27 @@ package com.swmansion.rnscreens
3
3
  import android.app.Activity
4
4
  import com.facebook.react.bridge.ReactContext
5
5
 
6
- interface ScreenFragmentWrapper : FragmentHolder, ScreenEventDispatcher {
6
+ interface ScreenFragmentWrapper :
7
+ FragmentHolder,
8
+ ScreenEventDispatcher {
7
9
  var screen: Screen
8
10
 
9
11
  // Communication with container
10
12
  val childScreenContainers: List<ScreenContainer>
13
+
11
14
  fun addChildScreenContainer(container: ScreenContainer)
15
+
12
16
  fun removeChildScreenContainer(container: ScreenContainer)
17
+
13
18
  fun onContainerUpdate()
14
19
 
15
20
  // Animation phase callbacks
16
21
  fun onViewAnimationStart()
22
+
17
23
  fun onViewAnimationEnd()
18
24
 
19
25
  // Helpers
20
26
  fun tryGetActivity(): Activity?
27
+
21
28
  fun tryGetContext(): ReactContext?
22
29
  }
@@ -12,7 +12,9 @@ import java.util.Collections
12
12
  import kotlin.collections.ArrayList
13
13
  import kotlin.collections.HashSet
14
14
 
15
- class ScreenStack(context: Context?) : ScreenContainer(context) {
15
+ class ScreenStack(
16
+ context: Context?,
17
+ ) : ScreenContainer(context) {
16
18
  private val stack = ArrayList<ScreenStackFragmentWrapper>()
17
19
  private val dismissedWrappers: MutableSet<ScreenStackFragmentWrapper> = HashSet()
18
20
  private val drawingOpPool: MutableList<DrawingOp> = ArrayList()
@@ -142,11 +144,21 @@ class ScreenStack(context: Context?) : ScreenContainer(context) {
142
144
  StackAnimation.DEFAULT -> it.setCustomAnimations(R.anim.rns_default_enter_in, R.anim.rns_default_enter_out)
143
145
  StackAnimation.NONE -> it.setCustomAnimations(R.anim.rns_no_animation_20, R.anim.rns_no_animation_20)
144
146
  StackAnimation.FADE -> it.setCustomAnimations(R.anim.rns_fade_in, R.anim.rns_fade_out)
145
- StackAnimation.SLIDE_FROM_RIGHT -> it.setCustomAnimations(R.anim.rns_slide_in_from_right, R.anim.rns_slide_out_to_left)
146
- StackAnimation.SLIDE_FROM_LEFT -> it.setCustomAnimations(R.anim.rns_slide_in_from_left, R.anim.rns_slide_out_to_right)
147
- StackAnimation.SLIDE_FROM_BOTTOM -> it.setCustomAnimations(
148
- R.anim.rns_slide_in_from_bottom, R.anim.rns_no_animation_medium
149
- )
147
+ StackAnimation.SLIDE_FROM_RIGHT ->
148
+ it.setCustomAnimations(
149
+ R.anim.rns_slide_in_from_right,
150
+ R.anim.rns_slide_out_to_left,
151
+ )
152
+ StackAnimation.SLIDE_FROM_LEFT ->
153
+ it.setCustomAnimations(
154
+ R.anim.rns_slide_in_from_left,
155
+ R.anim.rns_slide_out_to_right,
156
+ )
157
+ StackAnimation.SLIDE_FROM_BOTTOM ->
158
+ it.setCustomAnimations(
159
+ R.anim.rns_slide_in_from_bottom,
160
+ R.anim.rns_no_animation_medium,
161
+ )
150
162
  StackAnimation.FADE_FROM_BOTTOM -> it.setCustomAnimations(R.anim.rns_fade_from_bottom, R.anim.rns_no_animation_350)
151
163
  StackAnimation.IOS -> it.setCustomAnimations(R.anim.rns_slide_in_from_right_ios, R.anim.rns_slide_out_to_left_ios)
152
164
  }
@@ -155,11 +167,21 @@ class ScreenStack(context: Context?) : ScreenContainer(context) {
155
167
  StackAnimation.DEFAULT -> it.setCustomAnimations(R.anim.rns_default_exit_in, R.anim.rns_default_exit_out)
156
168
  StackAnimation.NONE -> it.setCustomAnimations(R.anim.rns_no_animation_20, R.anim.rns_no_animation_20)
157
169
  StackAnimation.FADE -> it.setCustomAnimations(R.anim.rns_fade_in, R.anim.rns_fade_out)
158
- StackAnimation.SLIDE_FROM_RIGHT -> it.setCustomAnimations(R.anim.rns_slide_in_from_left, R.anim.rns_slide_out_to_right)
159
- StackAnimation.SLIDE_FROM_LEFT -> it.setCustomAnimations(R.anim.rns_slide_in_from_right, R.anim.rns_slide_out_to_left)
160
- StackAnimation.SLIDE_FROM_BOTTOM -> it.setCustomAnimations(
161
- R.anim.rns_no_animation_medium, R.anim.rns_slide_out_to_bottom
162
- )
170
+ StackAnimation.SLIDE_FROM_RIGHT ->
171
+ it.setCustomAnimations(
172
+ R.anim.rns_slide_in_from_left,
173
+ R.anim.rns_slide_out_to_right,
174
+ )
175
+ StackAnimation.SLIDE_FROM_LEFT ->
176
+ it.setCustomAnimations(
177
+ R.anim.rns_slide_in_from_right,
178
+ R.anim.rns_slide_out_to_left,
179
+ )
180
+ StackAnimation.SLIDE_FROM_BOTTOM ->
181
+ it.setCustomAnimations(
182
+ R.anim.rns_no_animation_medium,
183
+ R.anim.rns_slide_out_to_bottom,
184
+ )
163
185
  StackAnimation.FADE_FROM_BOTTOM -> it.setCustomAnimations(R.anim.rns_no_animation_250, R.anim.rns_fade_to_bottom)
164
186
  StackAnimation.IOS -> it.setCustomAnimations(R.anim.rns_slide_in_from_left_ios, R.anim.rns_slide_out_to_right_ios)
165
187
  }
@@ -170,7 +192,8 @@ class ScreenStack(context: Context?) : ScreenContainer(context) {
170
192
  goingForward = shouldUseOpenAnimation
171
193
 
172
194
  if (shouldUseOpenAnimation &&
173
- newTop != null && needsDrawReordering(newTop) &&
195
+ newTop != null &&
196
+ needsDrawReordering(newTop) &&
174
197
  visibleBottom == null
175
198
  ) {
176
199
  // When using an open animation in which two screens overlap (eg. fade_from_bottom or
@@ -208,9 +231,12 @@ class ScreenStack(context: Context?) : ScreenContainer(context) {
208
231
  for (fragmentWrapper in screenWrappers) {
209
232
  // ignore all screens beneath the visible bottom
210
233
  if (beneathVisibleBottom) {
211
- beneathVisibleBottom = if (fragmentWrapper === visibleBottom) {
212
- false
213
- } else continue
234
+ beneathVisibleBottom =
235
+ if (fragmentWrapper === visibleBottom) {
236
+ false
237
+ } else {
238
+ continue
239
+ }
214
240
  }
215
241
  // when first visible screen found, make all screens after that visible
216
242
  it.add(id, fragmentWrapper.fragment).runOnCommit { top?.screen?.bringToFront() }
@@ -298,13 +324,17 @@ class ScreenStack(context: Context?) : ScreenContainer(context) {
298
324
  drawAndRelease()
299
325
  }
300
326
 
301
- override fun drawChild(canvas: Canvas, child: View, drawingTime: Long): Boolean {
327
+ override fun drawChild(
328
+ canvas: Canvas,
329
+ child: View,
330
+ drawingTime: Long,
331
+ ): Boolean {
302
332
  drawingOps.add(
303
333
  obtainDrawingOp().apply {
304
334
  this.canvas = canvas
305
335
  this.child = child
306
336
  this.drawingTime = drawingTime
307
- }
337
+ },
308
338
  )
309
339
  return true
310
340
  }
@@ -315,8 +345,9 @@ class ScreenStack(context: Context?) : ScreenContainer(context) {
315
345
  super.drawChild(op.canvas!!, op.child, op.drawingTime)
316
346
  }
317
347
 
318
- private fun obtainDrawingOp(): DrawingOp =
319
- if (drawingOpPool.isEmpty()) DrawingOp() else drawingOpPool.removeLast()
348
+ // Can't use `drawingOpPool.removeLast` here due to issues with static name resolution in Android SDK 35+.
349
+ // See: https://developer.android.com/about/versions/15/behavior-changes-15?hl=en#openjdk-api-changes
350
+ private fun obtainDrawingOp(): DrawingOp = if (drawingOpPool.isEmpty()) DrawingOp() else drawingOpPool.removeAt(drawingOpPool.lastIndex)
320
351
 
321
352
  private inner class DrawingOp {
322
353
  var canvas: Canvas? = null