react-native-screens 3.10.1 → 3.12.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 (128) hide show
  1. package/LICENSE +1 -1
  2. package/README.md +13 -7
  3. package/RNScreens.podspec +36 -6
  4. package/android/build.gradle +74 -3
  5. package/android/src/fabric/java/com/swmansion/rnscreens/FabricEnabledViewGroup.kt +49 -0
  6. package/android/src/fabric/java/com/swmansion/rnscreens/RNScreensComponentsRegistry.java +28 -0
  7. package/android/src/main/java/com/swmansion/rnscreens/RNScreensPackage.kt +11 -2
  8. package/android/src/main/java/com/swmansion/rnscreens/Screen.kt +52 -21
  9. package/android/src/main/java/com/swmansion/rnscreens/ScreenContainer.kt +1 -1
  10. package/android/src/main/java/com/swmansion/rnscreens/ScreenFragment.kt +64 -33
  11. package/android/src/main/java/com/swmansion/rnscreens/ScreenStack.kt +9 -31
  12. package/android/src/main/java/com/swmansion/rnscreens/ScreenStackFragment.kt +0 -30
  13. package/android/src/main/java/com/swmansion/rnscreens/ScreenStackHeaderConfig.kt +12 -5
  14. package/android/src/main/java/com/swmansion/rnscreens/ScreenStackHeaderConfigViewManager.kt +83 -18
  15. package/android/src/main/java/com/swmansion/rnscreens/ScreenStackHeaderSubviewManager.kt +17 -5
  16. package/android/src/main/java/com/swmansion/rnscreens/ScreenStackViewManager.kt +14 -1
  17. package/android/src/main/java/com/swmansion/rnscreens/ScreenViewManager.kt +41 -14
  18. package/android/src/main/java/com/swmansion/rnscreens/ScreenWindowTraits.kt +72 -11
  19. package/android/src/main/java/com/swmansion/rnscreens/SearchBarManager.kt +18 -1
  20. package/android/src/main/java/com/swmansion/rnscreens/SearchBarView.kt +7 -2
  21. package/android/src/main/java/com/swmansion/rnscreens/SearchViewFormatter.kt +29 -2
  22. package/android/src/main/jni/Android.mk +45 -0
  23. package/android/src/main/jni/OnLoad.cpp +9 -0
  24. package/android/src/main/jni/RNScreensComponentsRegistry.cpp +66 -0
  25. package/android/src/main/jni/RNScreensComponentsRegistry.h +34 -0
  26. package/android/src/main/res/anim/rns_default_enter_in.xml +18 -0
  27. package/android/src/main/res/anim/rns_default_enter_out.xml +19 -0
  28. package/android/src/main/res/anim/rns_default_exit_in.xml +17 -0
  29. package/android/src/main/res/anim/rns_default_exit_out.xml +18 -0
  30. package/android/src/main/res/anim/rns_fade_in.xml +7 -0
  31. package/android/src/main/res/anim/rns_fade_out.xml +7 -0
  32. package/android/src/main/res/anim/rns_no_animation_20.xml +6 -0
  33. package/android/src/paper/java/com/facebook/react/viewmanagers/RNSScreenManagerDelegate.java +71 -0
  34. package/android/src/paper/java/com/facebook/react/viewmanagers/RNSScreenManagerInterface.java +30 -0
  35. package/android/src/paper/java/com/facebook/react/viewmanagers/RNSScreenStackHeaderConfigManagerDelegate.java +104 -0
  36. package/android/src/paper/java/com/facebook/react/viewmanagers/RNSScreenStackHeaderConfigManagerInterface.java +41 -0
  37. package/android/src/paper/java/com/facebook/react/viewmanagers/RNSScreenStackHeaderSubviewManagerDelegate.java +31 -0
  38. package/android/src/paper/java/com/facebook/react/viewmanagers/RNSScreenStackHeaderSubviewManagerInterface.java +17 -0
  39. package/android/src/paper/java/com/facebook/react/viewmanagers/RNSScreenStackManagerDelegate.java +25 -0
  40. package/android/src/paper/java/com/facebook/react/viewmanagers/RNSScreenStackManagerInterface.java +16 -0
  41. package/android/src/paper/java/com/swmansion/rnscreens/FabricEnabledViewGroup.kt +16 -0
  42. package/common/cpp/Android.mk +38 -0
  43. package/common/cpp/rnscreens/RNSScreenComponentDescriptor.h +41 -0
  44. package/common/cpp/rnscreens/RNSScreenShadowNode.cpp +9 -0
  45. package/common/cpp/rnscreens/RNSScreenShadowNode.h +29 -0
  46. package/common/cpp/rnscreens/RNSScreenState.cpp +14 -0
  47. package/common/cpp/rnscreens/RNSScreenState.h +46 -0
  48. package/createNativeStackNavigator/README.md +12 -0
  49. package/ios/RNSScreen.h +10 -0
  50. package/ios/RNSScreen.m +34 -0
  51. package/ios/RNSScreenComponentView.h +23 -0
  52. package/ios/RNSScreenComponentView.mm +159 -0
  53. package/ios/RNSScreenContainer.m +5 -0
  54. package/ios/RNSScreenController.h +10 -0
  55. package/ios/RNSScreenController.mm +79 -0
  56. package/ios/RNSScreenStack.m +22 -7
  57. package/ios/RNSScreenStackAnimator.m +45 -14
  58. package/ios/RNSScreenStackComponentView.h +15 -0
  59. package/ios/RNSScreenStackComponentView.mm +295 -0
  60. package/ios/RNSScreenStackHeaderConfig.m +4 -1
  61. package/ios/RNSScreenStackHeaderConfigComponentView.h +42 -0
  62. package/ios/RNSScreenStackHeaderConfigComponentView.mm +662 -0
  63. package/ios/RNSScreenStackHeaderSubviewComponentView.h +14 -0
  64. package/ios/RNSScreenStackHeaderSubviewComponentView.mm +77 -0
  65. package/ios/RNSScreenWindowTraits.h +1 -0
  66. package/ios/RNSScreenWindowTraits.m +20 -0
  67. package/ios/UIViewController+RNScreens.m +10 -0
  68. package/ios/utils/RNSUIBarButtonItem.h +5 -0
  69. package/ios/utils/RNSUIBarButtonItem.mm +22 -0
  70. package/lib/commonjs/fabric/Screen.js +27 -0
  71. package/lib/commonjs/fabric/Screen.js.map +1 -0
  72. package/lib/commonjs/fabric/ScreenNativeComponent.js +23 -0
  73. package/lib/commonjs/fabric/ScreenNativeComponent.js.map +1 -0
  74. package/lib/commonjs/fabric/ScreenStack.js +27 -0
  75. package/lib/commonjs/fabric/ScreenStack.js.map +1 -0
  76. package/lib/commonjs/fabric/ScreenStackHeaderConfigNativeComponent.js +27 -0
  77. package/lib/commonjs/fabric/ScreenStackHeaderConfigNativeComponent.js.map +1 -0
  78. package/lib/commonjs/fabric/ScreenStackHeaderSubview.js +34 -0
  79. package/lib/commonjs/fabric/ScreenStackHeaderSubview.js.map +1 -0
  80. package/lib/commonjs/fabric/ScreenStackHeaderSubviewNativeComponent.js +27 -0
  81. package/lib/commonjs/fabric/ScreenStackHeaderSubviewNativeComponent.js.map +1 -0
  82. package/lib/commonjs/fabric/ScreenStackNativeComponent.js +21 -0
  83. package/lib/commonjs/fabric/ScreenStackNativeComponent.js.map +1 -0
  84. package/lib/commonjs/fabric/index.js +40 -0
  85. package/lib/commonjs/fabric/index.js.map +1 -0
  86. package/lib/commonjs/index.native.js +32 -15
  87. package/lib/commonjs/index.native.js.map +1 -1
  88. package/lib/commonjs/native-stack/views/NativeStackView.js +33 -4
  89. package/lib/commonjs/native-stack/views/NativeStackView.js.map +1 -1
  90. package/lib/module/fabric/Screen.js +11 -0
  91. package/lib/module/fabric/Screen.js.map +1 -0
  92. package/lib/module/fabric/ScreenNativeComponent.js +11 -0
  93. package/lib/module/fabric/ScreenNativeComponent.js.map +1 -0
  94. package/lib/module/fabric/ScreenStack.js +12 -0
  95. package/lib/module/fabric/ScreenStack.js.map +1 -0
  96. package/lib/module/fabric/ScreenStackHeaderConfigNativeComponent.js +10 -0
  97. package/lib/module/fabric/ScreenStackHeaderConfigNativeComponent.js.map +1 -0
  98. package/lib/module/fabric/ScreenStackHeaderSubview.js +21 -0
  99. package/lib/module/fabric/ScreenStackHeaderSubview.js.map +1 -0
  100. package/lib/module/fabric/ScreenStackHeaderSubviewNativeComponent.js +10 -0
  101. package/lib/module/fabric/ScreenStackHeaderSubviewNativeComponent.js.map +1 -0
  102. package/lib/module/fabric/ScreenStackNativeComponent.js +9 -0
  103. package/lib/module/fabric/ScreenStackNativeComponent.js.map +1 -0
  104. package/lib/module/fabric/index.js +6 -0
  105. package/lib/module/fabric/index.js.map +1 -0
  106. package/lib/module/index.native.js +32 -15
  107. package/lib/module/index.native.js.map +1 -1
  108. package/lib/module/native-stack/views/NativeStackView.js +33 -4
  109. package/lib/module/native-stack/views/NativeStackView.js.map +1 -1
  110. package/lib/typescript/native-stack/types.d.ts +34 -0
  111. package/lib/typescript/reanimated/ReanimatedNativeStackScreen.d.ts +1 -1
  112. package/lib/typescript/reanimated/ReanimatedScreen.d.ts +1 -1
  113. package/lib/typescript/types.d.ts +60 -5
  114. package/native-stack/README.md +39 -3
  115. package/package.json +17 -3
  116. package/reanimated/package.json +6 -0
  117. package/src/fabric/Screen.js +12 -0
  118. package/src/fabric/ScreenNativeComponent.js +64 -0
  119. package/src/fabric/ScreenStack.js +8 -0
  120. package/src/fabric/ScreenStackHeaderConfigNativeComponent.js +54 -0
  121. package/src/fabric/ScreenStackHeaderSubview.js +20 -0
  122. package/src/fabric/ScreenStackHeaderSubviewNativeComponent.js +31 -0
  123. package/src/fabric/ScreenStackNativeComponent.js +19 -0
  124. package/src/fabric/index.js +11 -0
  125. package/src/index.native.tsx +35 -14
  126. package/src/native-stack/types.tsx +34 -0
  127. package/src/native-stack/views/NativeStackView.tsx +33 -4
  128. package/src/types.tsx +60 -5
@@ -3,7 +3,6 @@ package com.swmansion.rnscreens
3
3
  import android.content.Context
4
4
  import android.graphics.Canvas
5
5
  import android.view.View
6
- import androidx.fragment.app.FragmentTransaction
7
6
  import com.facebook.react.bridge.ReactContext
8
7
  import com.facebook.react.uimanager.UIManagerModule
9
8
  import com.swmansion.rnscreens.Screen.StackAnimation
@@ -110,7 +109,6 @@ class ScreenStack(context: Context?) : ScreenContainer<ScreenStackFragment>(cont
110
109
  }
111
110
  }
112
111
  var shouldUseOpenAnimation = true
113
- var transition = FragmentTransaction.TRANSIT_FRAGMENT_OPEN
114
112
  var stackAnimation: StackAnimation? = null
115
113
  if (!mStack.contains(newTop)) {
116
114
  // if new top screen wasn't on stack we do "open animation" so long it is not the very first
@@ -127,17 +125,9 @@ class ScreenStack(context: Context?) : ScreenContainer<ScreenStackFragment>(cont
127
125
  stackAnimation = if (shouldUseOpenAnimation) newTop.screen.stackAnimation else mTopScreen?.screen?.stackAnimation
128
126
  } else if (mTopScreen == null && newTop != null) {
129
127
  // mTopScreen was not present before so newTop is the first screen added to a stack
130
- // and we don't want the animation when it is entering, but we want to send the
131
- // willAppear and Appear events to the user, which won't be sent by default if Screen's
132
- // stack animation is not NONE (see check for stackAnimation in onCreateAnimation in
133
- // ScreenStackFragment).
134
- // We don't do it if the stack is nested since the parent will trigger these events in child
128
+ // and we don't want the animation when it is entering
135
129
  stackAnimation = StackAnimation.NONE
136
- if (newTop.screen.stackAnimation !== StackAnimation.NONE && !isNested) {
137
- goingForward = true
138
- newTop.dispatchOnWillAppear()
139
- newTop.dispatchOnAppear()
140
- }
130
+ goingForward = true
141
131
  }
142
132
  } else if (mTopScreen != null && mTopScreen != newTop) {
143
133
  // otherwise if we are performing top screen change we do "close animation"
@@ -149,40 +139,32 @@ class ScreenStack(context: Context?) : ScreenContainer<ScreenStackFragment>(cont
149
139
  // animation logic start
150
140
  if (stackAnimation != null) {
151
141
  if (shouldUseOpenAnimation) {
152
- transition = FragmentTransaction.TRANSIT_FRAGMENT_OPEN
153
142
  when (stackAnimation) {
143
+ StackAnimation.DEFAULT -> it.setCustomAnimations(R.anim.rns_default_enter_in, R.anim.rns_default_enter_out)
144
+ StackAnimation.NONE -> it.setCustomAnimations(R.anim.rns_no_animation_20, R.anim.rns_no_animation_20)
145
+ StackAnimation.FADE -> it.setCustomAnimations(R.anim.rns_fade_in, R.anim.rns_fade_out)
154
146
  StackAnimation.SLIDE_FROM_RIGHT -> it.setCustomAnimations(R.anim.rns_slide_in_from_right, R.anim.rns_slide_out_to_left)
155
147
  StackAnimation.SLIDE_FROM_LEFT -> it.setCustomAnimations(R.anim.rns_slide_in_from_left, R.anim.rns_slide_out_to_right)
156
148
  StackAnimation.SLIDE_FROM_BOTTOM -> it.setCustomAnimations(
157
149
  R.anim.rns_slide_in_from_bottom, R.anim.rns_no_animation_medium
158
150
  )
159
151
  StackAnimation.FADE_FROM_BOTTOM -> it.setCustomAnimations(R.anim.rns_fade_from_bottom, R.anim.rns_no_animation_350)
160
- else -> {
161
- }
162
152
  }
163
153
  } else {
164
- transition = FragmentTransaction.TRANSIT_FRAGMENT_CLOSE
165
154
  when (stackAnimation) {
155
+ StackAnimation.DEFAULT -> it.setCustomAnimations(R.anim.rns_default_exit_in, R.anim.rns_default_exit_out)
156
+ StackAnimation.NONE -> it.setCustomAnimations(R.anim.rns_no_animation_20, R.anim.rns_no_animation_20)
157
+ StackAnimation.FADE -> it.setCustomAnimations(R.anim.rns_fade_in, R.anim.rns_fade_out)
166
158
  StackAnimation.SLIDE_FROM_RIGHT -> it.setCustomAnimations(R.anim.rns_slide_in_from_left, R.anim.rns_slide_out_to_right)
167
159
  StackAnimation.SLIDE_FROM_LEFT -> it.setCustomAnimations(R.anim.rns_slide_in_from_right, R.anim.rns_slide_out_to_left)
168
160
  StackAnimation.SLIDE_FROM_BOTTOM -> it.setCustomAnimations(
169
161
  R.anim.rns_no_animation_medium, R.anim.rns_slide_out_to_bottom
170
162
  )
171
163
  StackAnimation.FADE_FROM_BOTTOM -> it.setCustomAnimations(R.anim.rns_no_animation_250, R.anim.rns_fade_to_bottom)
172
- else -> {
173
- }
174
164
  }
175
165
  }
176
166
  }
177
- if (stackAnimation === StackAnimation.NONE) {
178
- transition = FragmentTransaction.TRANSIT_NONE
179
- }
180
- if (stackAnimation === StackAnimation.FADE) {
181
- transition = FragmentTransaction.TRANSIT_FRAGMENT_FADE
182
- }
183
- if (stackAnimation != null && isSystemAnimation(stackAnimation)) {
184
- it.setTransition(transition)
185
- }
167
+
186
168
  // animation logic end
187
169
  goingForward = shouldUseOpenAnimation
188
170
 
@@ -348,10 +330,6 @@ class ScreenStack(context: Context?) : ScreenContainer<ScreenStackFragment>(cont
348
330
  }
349
331
 
350
332
  companion object {
351
- private fun isSystemAnimation(stackAnimation: StackAnimation): Boolean {
352
- return stackAnimation === StackAnimation.DEFAULT || stackAnimation === StackAnimation.FADE || stackAnimation === StackAnimation.NONE
353
- }
354
-
355
333
  private fun isTransparent(fragment: ScreenStackFragment): Boolean {
356
334
  return (
357
335
  fragment.screen.stackPresentation
@@ -16,7 +16,6 @@ import android.view.animation.Transformation
16
16
  import android.widget.LinearLayout
17
17
  import androidx.appcompat.widget.Toolbar
18
18
  import androidx.coordinatorlayout.widget.CoordinatorLayout
19
- import com.facebook.react.bridge.UiThreadUtil
20
19
  import com.facebook.react.uimanager.PixelUtil
21
20
  import com.google.android.material.appbar.AppBarLayout
22
21
  import com.google.android.material.appbar.AppBarLayout.ScrollingViewBehavior
@@ -86,35 +85,6 @@ class ScreenStackFragment : ScreenFragment {
86
85
  notifyViewAppearTransitionEnd()
87
86
  }
88
87
 
89
- override fun onCreateAnimation(transit: Int, enter: Boolean, nextAnim: Int): Animation? {
90
- // this means that the fragment will appear with a custom transition, in the case
91
- // of animation: 'none', onViewAnimationStart and onViewAnimationEnd
92
- // won't be called and we need to notify stack directly from here.
93
- // When using the Toolbar back button this is called an extra time with transit = 0 but in
94
- // this case we don't want to notify. The way I found to detect is case is check isHidden.
95
- if (transit == 0 && !isHidden &&
96
- screen.stackAnimation === Screen.StackAnimation.NONE
97
- ) {
98
- if (enter) {
99
- // Android dispatches the animation start event for the fragment that is being added first
100
- // however we want the one being dismissed first to match iOS. It also makes more sense
101
- // from a navigation point of view to have the disappear event first.
102
- // Since there are no explicit relationships between the fragment being added / removed
103
- // the practical way to fix this is delaying dispatching the appear events at the end of
104
- // the frame.
105
- UiThreadUtil.runOnUiThread {
106
- dispatchOnWillAppear()
107
- dispatchOnAppear()
108
- }
109
- } else {
110
- dispatchOnWillDisappear()
111
- dispatchOnDisappear()
112
- notifyViewAppearTransitionEnd()
113
- }
114
- }
115
- return null
116
- }
117
-
118
88
  private fun notifyViewAppearTransitionEnd() {
119
89
  val screenStack = view?.parent
120
90
  if (screenStack is ScreenStack) {
@@ -24,6 +24,7 @@ import com.facebook.react.views.text.ReactTypefaceUtils
24
24
  class ScreenStackHeaderConfig(context: Context) : ViewGroup(context) {
25
25
  private val mConfigSubviews = ArrayList<ScreenStackHeaderSubview>(3)
26
26
  val toolbar: CustomToolbar
27
+ private var headerTopInset: Int? = null
27
28
  private var mTitle: String? = null
28
29
  private var mTitleColor = 0
29
30
  private var mTitleFontFamily: String? = null
@@ -81,6 +82,15 @@ class ScreenStackHeaderConfig(context: Context) : ViewGroup(context) {
81
82
  super.onAttachedToWindow()
82
83
  mIsAttachedToWindow = true
83
84
  sendEvent("onAttached", null)
85
+ // we want to save the top inset before the status bar can be hidden, which would resolve in
86
+ // inset being 0
87
+ if (headerTopInset == null) {
88
+ headerTopInset = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M)
89
+ rootWindowInsets.systemWindowInsetTop
90
+ else
91
+ // Hacky fallback for old android. Before Marshmallow, the status bar height was always 25
92
+ (25 * resources.displayMetrics.density).toInt()
93
+ }
84
94
  onUpdate()
85
95
  }
86
96
 
@@ -159,11 +169,8 @@ class ScreenStackHeaderConfig(context: Context) : ViewGroup(context) {
159
169
  screenFragment?.setToolbar(toolbar)
160
170
  }
161
171
  if (mIsTopInsetEnabled) {
162
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
163
- toolbar.setPadding(0, rootWindowInsets.systemWindowInsetTop, 0, 0)
164
- } else {
165
- // Hacky fallback for old android. Before Marshmallow, the status bar height was always 25
166
- toolbar.setPadding(0, (25 * resources.displayMetrics.density).toInt(), 0, 0)
172
+ headerTopInset.let {
173
+ toolbar.setPadding(0, it ?: 0, 0, 0)
167
174
  }
168
175
  } else {
169
176
  if (toolbar.paddingTop > 0) {
@@ -1,16 +1,26 @@
1
1
  package com.swmansion.rnscreens
2
2
 
3
+ import android.util.Log
3
4
  import android.view.View
4
5
  import com.facebook.react.bridge.JSApplicationCausedNativeException
5
6
  import com.facebook.react.common.MapBuilder
6
7
  import com.facebook.react.module.annotations.ReactModule
7
8
  import com.facebook.react.uimanager.ThemedReactContext
8
9
  import com.facebook.react.uimanager.ViewGroupManager
10
+ import com.facebook.react.uimanager.ViewManagerDelegate
9
11
  import com.facebook.react.uimanager.annotations.ReactProp
12
+ import com.facebook.react.viewmanagers.RNSScreenStackHeaderConfigManagerDelegate
13
+ import com.facebook.react.viewmanagers.RNSScreenStackHeaderConfigManagerInterface
10
14
  import javax.annotation.Nonnull
11
15
 
12
16
  @ReactModule(name = ScreenStackHeaderConfigViewManager.REACT_CLASS)
13
- class ScreenStackHeaderConfigViewManager : ViewGroupManager<ScreenStackHeaderConfig>() {
17
+ class ScreenStackHeaderConfigViewManager : ViewGroupManager<ScreenStackHeaderConfig>(), RNSScreenStackHeaderConfigManagerInterface<ScreenStackHeaderConfig> {
18
+ private val mDelegate: ViewManagerDelegate<ScreenStackHeaderConfig>
19
+
20
+ init {
21
+ mDelegate = RNSScreenStackHeaderConfigManagerDelegate<ScreenStackHeaderConfig, ScreenStackHeaderConfigViewManager>(this)
22
+ }
23
+
14
24
  override fun getName(): String {
15
25
  return REACT_CLASS
16
26
  }
@@ -58,67 +68,69 @@ class ScreenStackHeaderConfigViewManager : ViewGroupManager<ScreenStackHeaderCon
58
68
  }
59
69
 
60
70
  @ReactProp(name = "title")
61
- fun setTitle(config: ScreenStackHeaderConfig, title: String?) {
71
+ override fun setTitle(config: ScreenStackHeaderConfig, title: String?) {
62
72
  config.setTitle(title)
63
73
  }
64
74
 
65
75
  @ReactProp(name = "titleFontFamily")
66
- fun setTitleFontFamily(config: ScreenStackHeaderConfig, titleFontFamily: String?) {
76
+ override fun setTitleFontFamily(config: ScreenStackHeaderConfig, titleFontFamily: String?) {
67
77
  config.setTitleFontFamily(titleFontFamily)
68
78
  }
69
79
 
70
80
  @ReactProp(name = "titleFontSize")
71
- fun setTitleFontSize(config: ScreenStackHeaderConfig, titleFontSize: Float) {
72
- config.setTitleFontSize(titleFontSize)
81
+ override fun setTitleFontSize(config: ScreenStackHeaderConfig, titleFontSize: Int) {
82
+ config.setTitleFontSize(titleFontSize.toFloat())
73
83
  }
74
84
 
75
85
  @ReactProp(name = "titleFontWeight")
76
- fun setTitleFontWeight(config: ScreenStackHeaderConfig, titleFontWeight: String?) {
86
+ override fun setTitleFontWeight(config: ScreenStackHeaderConfig, titleFontWeight: String?) {
77
87
  config.setTitleFontWeight(titleFontWeight)
78
88
  }
79
89
 
80
90
  @ReactProp(name = "titleColor", customType = "Color")
81
- fun setTitleColor(config: ScreenStackHeaderConfig, titleColor: Int) {
82
- config.setTitleColor(titleColor)
91
+ override fun setTitleColor(config: ScreenStackHeaderConfig, titleColor: Int?) {
92
+ if (titleColor != null) {
93
+ config.setTitleColor(titleColor)
94
+ }
83
95
  }
84
96
 
85
97
  @ReactProp(name = "backgroundColor", customType = "Color")
86
- fun setBackgroundColor(config: ScreenStackHeaderConfig, backgroundColor: Int?) {
98
+ override fun setBackgroundColor(config: ScreenStackHeaderConfig, backgroundColor: Int?) {
87
99
  config.setBackgroundColor(backgroundColor)
88
100
  }
89
101
 
90
102
  @ReactProp(name = "hideShadow")
91
- fun setHideShadow(config: ScreenStackHeaderConfig, hideShadow: Boolean) {
103
+ override fun setHideShadow(config: ScreenStackHeaderConfig, hideShadow: Boolean) {
92
104
  config.setHideShadow(hideShadow)
93
105
  }
94
106
 
95
107
  @ReactProp(name = "hideBackButton")
96
- fun setHideBackButton(config: ScreenStackHeaderConfig, hideBackButton: Boolean) {
108
+ override fun setHideBackButton(config: ScreenStackHeaderConfig, hideBackButton: Boolean) {
97
109
  config.setHideBackButton(hideBackButton)
98
110
  }
99
111
 
100
112
  @ReactProp(name = "topInsetEnabled")
101
- fun setTopInsetEnabled(config: ScreenStackHeaderConfig, topInsetEnabled: Boolean) {
113
+ override fun setTopInsetEnabled(config: ScreenStackHeaderConfig, topInsetEnabled: Boolean) {
102
114
  config.setTopInsetEnabled(topInsetEnabled)
103
115
  }
104
116
 
105
117
  @ReactProp(name = "color", customType = "Color")
106
- fun setColor(config: ScreenStackHeaderConfig, color: Int) {
107
- config.setTintColor(color)
118
+ override fun setColor(config: ScreenStackHeaderConfig, color: Int?) {
119
+ config.setTintColor(color ?: 0)
108
120
  }
109
121
 
110
122
  @ReactProp(name = "hidden")
111
- fun setHidden(config: ScreenStackHeaderConfig, hidden: Boolean) {
123
+ override fun setHidden(config: ScreenStackHeaderConfig, hidden: Boolean) {
112
124
  config.setHidden(hidden)
113
125
  }
114
126
 
115
127
  @ReactProp(name = "translucent")
116
- fun setTranslucent(config: ScreenStackHeaderConfig, translucent: Boolean) {
128
+ override fun setTranslucent(config: ScreenStackHeaderConfig, translucent: Boolean) {
117
129
  config.setTranslucent(translucent)
118
130
  }
119
131
 
120
132
  @ReactProp(name = "backButtonInCustomView")
121
- fun setBackButtonInCustomView(
133
+ override fun setBackButtonInCustomView(
122
134
  config: ScreenStackHeaderConfig,
123
135
  backButtonInCustomView: Boolean
124
136
  ) {
@@ -126,7 +138,7 @@ class ScreenStackHeaderConfigViewManager : ViewGroupManager<ScreenStackHeaderCon
126
138
  }
127
139
 
128
140
  @ReactProp(name = "direction")
129
- fun setDirection(config: ScreenStackHeaderConfig, direction: String?) {
141
+ override fun setDirection(config: ScreenStackHeaderConfig, direction: String?) {
130
142
  config.setDirection(direction)
131
143
  }
132
144
 
@@ -137,7 +149,60 @@ class ScreenStackHeaderConfigViewManager : ViewGroupManager<ScreenStackHeaderCon
137
149
  .build()
138
150
  }
139
151
 
152
+ protected override fun getDelegate(): ViewManagerDelegate<ScreenStackHeaderConfig> {
153
+ return mDelegate
154
+ }
155
+
140
156
  companion object {
141
157
  const val REACT_CLASS = "RNSScreenStackHeaderConfig"
142
158
  }
159
+
160
+ // TODO: Find better way to handle platform specific props
161
+ private fun logNotAvailable(propName: String) {
162
+ Log.w("RN SCREENS", "$propName prop is not available on Android")
163
+ }
164
+
165
+ override fun setBackTitle(view: ScreenStackHeaderConfig?, value: String?) {
166
+ logNotAvailable("backTitle")
167
+ }
168
+
169
+ override fun setBackTitleFontFamily(view: ScreenStackHeaderConfig?, value: String?) {
170
+ logNotAvailable("backTitleFontFamily")
171
+ }
172
+
173
+ override fun setBackTitleFontSize(view: ScreenStackHeaderConfig?, value: Int) {
174
+ logNotAvailable("backTitleFontSize")
175
+ }
176
+
177
+ override fun setLargeTitle(view: ScreenStackHeaderConfig?, value: Boolean) {
178
+ logNotAvailable("largeTitle")
179
+ }
180
+
181
+ override fun setLargeTitleFontFamily(view: ScreenStackHeaderConfig?, value: String?) {
182
+ logNotAvailable("largeTitleFontFamily")
183
+ }
184
+
185
+ override fun setLargeTitleFontSize(view: ScreenStackHeaderConfig?, value: Int) {
186
+ logNotAvailable("largeTitleFontSize")
187
+ }
188
+
189
+ override fun setLargeTitleFontWeight(view: ScreenStackHeaderConfig?, value: String?) {
190
+ logNotAvailable("largeTitleFontWeight")
191
+ }
192
+
193
+ override fun setLargeTitleBackgroundColor(view: ScreenStackHeaderConfig?, value: Int?) {
194
+ logNotAvailable("largeTitleBackgroundColor")
195
+ }
196
+
197
+ override fun setLargeTitleHideShadow(view: ScreenStackHeaderConfig?, value: Boolean) {
198
+ logNotAvailable("largeTitleHideShadow")
199
+ }
200
+
201
+ override fun setLargeTitleColor(view: ScreenStackHeaderConfig?, value: Int?) {
202
+ logNotAvailable("largeTitleColor")
203
+ }
204
+
205
+ override fun setDisableBackButtonMenu(view: ScreenStackHeaderConfig?, value: Boolean) {
206
+ logNotAvailable("disableBackButtonMenu")
207
+ }
143
208
  }
@@ -3,22 +3,30 @@ package com.swmansion.rnscreens
3
3
  import com.facebook.react.bridge.JSApplicationIllegalArgumentException
4
4
  import com.facebook.react.module.annotations.ReactModule
5
5
  import com.facebook.react.uimanager.ThemedReactContext
6
+ import com.facebook.react.uimanager.ViewGroupManager
7
+ import com.facebook.react.uimanager.ViewManagerDelegate
6
8
  import com.facebook.react.uimanager.annotations.ReactProp
7
- import com.facebook.react.views.view.ReactViewGroup
8
- import com.facebook.react.views.view.ReactViewManager
9
+ import com.facebook.react.viewmanagers.RNSScreenStackHeaderSubviewManagerDelegate
10
+ import com.facebook.react.viewmanagers.RNSScreenStackHeaderSubviewManagerInterface
9
11
 
10
12
  @ReactModule(name = ScreenStackHeaderSubviewManager.REACT_CLASS)
11
- class ScreenStackHeaderSubviewManager : ReactViewManager() {
13
+ class ScreenStackHeaderSubviewManager : ViewGroupManager<ScreenStackHeaderSubview>(), RNSScreenStackHeaderSubviewManagerInterface<ScreenStackHeaderSubview> {
14
+ private val mDelegate: ViewManagerDelegate<ScreenStackHeaderSubview>
15
+
16
+ init {
17
+ mDelegate = RNSScreenStackHeaderSubviewManagerDelegate<ScreenStackHeaderSubview, ScreenStackHeaderSubviewManager>(this)
18
+ }
19
+
12
20
  override fun getName(): String {
13
21
  return REACT_CLASS
14
22
  }
15
23
 
16
- override fun createViewInstance(context: ThemedReactContext): ReactViewGroup {
24
+ override fun createViewInstance(context: ThemedReactContext): ScreenStackHeaderSubview {
17
25
  return ScreenStackHeaderSubview(context)
18
26
  }
19
27
 
20
28
  @ReactProp(name = "type")
21
- fun setType(view: ScreenStackHeaderSubview, type: String) {
29
+ override fun setType(view: ScreenStackHeaderSubview, type: String?) {
22
30
  view.type = when (type) {
23
31
  "left" -> ScreenStackHeaderSubview.Type.LEFT
24
32
  "center" -> ScreenStackHeaderSubview.Type.CENTER
@@ -29,6 +37,10 @@ class ScreenStackHeaderSubviewManager : ReactViewManager() {
29
37
  }
30
38
  }
31
39
 
40
+ protected override fun getDelegate(): ViewManagerDelegate<ScreenStackHeaderSubview> {
41
+ return mDelegate
42
+ }
43
+
32
44
  companion object {
33
45
  const val REACT_CLASS = "RNSScreenStackHeaderSubview"
34
46
  }
@@ -7,9 +7,18 @@ import com.facebook.react.module.annotations.ReactModule
7
7
  import com.facebook.react.uimanager.LayoutShadowNode
8
8
  import com.facebook.react.uimanager.ThemedReactContext
9
9
  import com.facebook.react.uimanager.ViewGroupManager
10
+ import com.facebook.react.uimanager.ViewManagerDelegate
11
+ import com.facebook.react.viewmanagers.RNSScreenStackManagerDelegate
12
+ import com.facebook.react.viewmanagers.RNSScreenStackManagerInterface
10
13
 
11
14
  @ReactModule(name = ScreenStackViewManager.REACT_CLASS)
12
- class ScreenStackViewManager : ViewGroupManager<ScreenStack>() {
15
+ class ScreenStackViewManager : ViewGroupManager<ScreenStack>(), RNSScreenStackManagerInterface<ScreenStack> {
16
+ private val mDelegate: ViewManagerDelegate<ScreenStack>
17
+
18
+ init {
19
+ mDelegate = RNSScreenStackManagerDelegate<ScreenStack, ScreenStackViewManager>(this)
20
+ }
21
+
13
22
  override fun getName(): String {
14
23
  return REACT_CLASS
15
24
  }
@@ -68,6 +77,10 @@ class ScreenStackViewManager : ViewGroupManager<ScreenStack>() {
68
77
  return true
69
78
  }
70
79
 
80
+ protected override fun getDelegate(): ViewManagerDelegate<ScreenStack> {
81
+ return mDelegate
82
+ }
83
+
71
84
  companion object {
72
85
  const val REACT_CLASS = "RNSScreenStack"
73
86
  }
@@ -1,11 +1,18 @@
1
1
  package com.swmansion.rnscreens
2
2
 
3
+ import androidx.annotation.NonNull
4
+ import androidx.annotation.Nullable
3
5
  import com.facebook.react.bridge.JSApplicationIllegalArgumentException
4
6
  import com.facebook.react.common.MapBuilder
5
7
  import com.facebook.react.module.annotations.ReactModule
8
+ import com.facebook.react.uimanager.ReactStylesDiffMap
9
+ import com.facebook.react.uimanager.StateWrapper
6
10
  import com.facebook.react.uimanager.ThemedReactContext
7
11
  import com.facebook.react.uimanager.ViewGroupManager
12
+ import com.facebook.react.uimanager.ViewManagerDelegate
8
13
  import com.facebook.react.uimanager.annotations.ReactProp
14
+ import com.facebook.react.viewmanagers.RNSScreenManagerDelegate
15
+ import com.facebook.react.viewmanagers.RNSScreenManagerInterface
9
16
  import com.swmansion.rnscreens.events.HeaderBackButtonClickedEvent
10
17
  import com.swmansion.rnscreens.events.ScreenAppearEvent
11
18
  import com.swmansion.rnscreens.events.ScreenDisappearEvent
@@ -16,7 +23,13 @@ import com.swmansion.rnscreens.events.ScreenWillDisappearEvent
16
23
  import com.swmansion.rnscreens.events.StackFinishTransitioningEvent
17
24
 
18
25
  @ReactModule(name = ScreenViewManager.REACT_CLASS)
19
- class ScreenViewManager : ViewGroupManager<Screen>() {
26
+ class ScreenViewManager : ViewGroupManager<Screen>(), RNSScreenManagerInterface<Screen> {
27
+ private val mDelegate: ViewManagerDelegate<Screen>
28
+
29
+ init {
30
+ mDelegate = RNSScreenManagerDelegate<Screen, ScreenViewManager>(this)
31
+ }
32
+
20
33
  override fun getName(): String {
21
34
  return REACT_CLASS
22
35
  }
@@ -26,8 +39,8 @@ class ScreenViewManager : ViewGroupManager<Screen>() {
26
39
  }
27
40
 
28
41
  @ReactProp(name = "activityState")
29
- fun setActivityState(view: Screen, activityState: Int?) {
30
- if (activityState == null) {
42
+ override fun setActivityState(view: Screen, activityState: Int) {
43
+ if (activityState == -1) {
31
44
  // Null will be provided when activityState is set as an animated value and we change
32
45
  // it from JS to be a plain value (non animated).
33
46
  // In case when null is received, we want to ignore such value and not make
@@ -42,7 +55,7 @@ class ScreenViewManager : ViewGroupManager<Screen>() {
42
55
  }
43
56
 
44
57
  @ReactProp(name = "stackPresentation")
45
- fun setStackPresentation(view: Screen, presentation: String) {
58
+ override fun setStackPresentation(view: Screen, presentation: String?) {
46
59
  view.stackPresentation = when (presentation) {
47
60
  "push" -> Screen.StackPresentation.PUSH
48
61
  "modal", "containedModal", "fullScreenModal", "formSheet" ->
@@ -54,7 +67,7 @@ class ScreenViewManager : ViewGroupManager<Screen>() {
54
67
  }
55
68
 
56
69
  @ReactProp(name = "stackAnimation")
57
- fun setStackAnimation(view: Screen, animation: String?) {
70
+ override fun setStackAnimation(view: Screen, animation: String?) {
58
71
  view.stackAnimation = when (animation) {
59
72
  null, "default", "flip", "simple_push" -> Screen.StackAnimation.DEFAULT
60
73
  "none" -> Screen.StackAnimation.NONE
@@ -68,12 +81,12 @@ class ScreenViewManager : ViewGroupManager<Screen>() {
68
81
  }
69
82
 
70
83
  @ReactProp(name = "gestureEnabled", defaultBoolean = true)
71
- fun setGestureEnabled(view: Screen, gestureEnabled: Boolean) {
84
+ override fun setGestureEnabled(view: Screen, gestureEnabled: Boolean) {
72
85
  view.isGestureEnabled = gestureEnabled
73
86
  }
74
87
 
75
88
  @ReactProp(name = "replaceAnimation")
76
- fun setReplaceAnimation(view: Screen, animation: String?) {
89
+ override fun setReplaceAnimation(view: Screen, animation: String?) {
77
90
  view.replaceAnimation = when (animation) {
78
91
  null, "pop" -> Screen.ReplaceAnimation.POP
79
92
  "push" -> Screen.ReplaceAnimation.PUSH
@@ -82,38 +95,48 @@ class ScreenViewManager : ViewGroupManager<Screen>() {
82
95
  }
83
96
 
84
97
  @ReactProp(name = "screenOrientation")
85
- fun setScreenOrientation(view: Screen, screenOrientation: String?) {
98
+ override fun setScreenOrientation(view: Screen, screenOrientation: String?) {
86
99
  view.setScreenOrientation(screenOrientation)
87
100
  }
88
101
 
89
102
  @ReactProp(name = "statusBarAnimation")
90
- fun setStatusBarAnimation(view: Screen, statusBarAnimation: String?) {
103
+ override fun setStatusBarAnimation(view: Screen, statusBarAnimation: String?) {
91
104
  val animated = statusBarAnimation != null && "none" != statusBarAnimation
92
105
  view.isStatusBarAnimated = animated
93
106
  }
94
107
 
95
108
  @ReactProp(name = "statusBarColor")
96
- fun setStatusBarColor(view: Screen, statusBarColor: Int?) {
109
+ override fun setStatusBarColor(view: Screen, statusBarColor: Int?) {
97
110
  view.statusBarColor = statusBarColor
98
111
  }
99
112
 
100
113
  @ReactProp(name = "statusBarStyle")
101
- fun setStatusBarStyle(view: Screen, statusBarStyle: String?) {
114
+ override fun setStatusBarStyle(view: Screen, statusBarStyle: String?) {
102
115
  view.statusBarStyle = statusBarStyle
103
116
  }
104
117
 
105
118
  @ReactProp(name = "statusBarTranslucent")
106
- fun setStatusBarTranslucent(view: Screen, statusBarTranslucent: Boolean?) {
119
+ override fun setStatusBarTranslucent(view: Screen, statusBarTranslucent: Boolean) {
107
120
  view.isStatusBarTranslucent = statusBarTranslucent
108
121
  }
109
122
 
110
123
  @ReactProp(name = "statusBarHidden")
111
- fun setStatusBarHidden(view: Screen, statusBarHidden: Boolean?) {
124
+ override fun setStatusBarHidden(view: Screen, statusBarHidden: Boolean) {
112
125
  view.isStatusBarHidden = statusBarHidden
113
126
  }
114
127
 
128
+ @ReactProp(name = "navigationBarColor", customType = "Color")
129
+ override fun setNavigationBarColor(view: Screen, navigationBarColor: Int?) {
130
+ view.navigationBarColor = navigationBarColor
131
+ }
132
+
133
+ @ReactProp(name = "navigationBarHidden")
134
+ override fun setNavigationBarHidden(view: Screen, navigationBarHidden: Boolean) {
135
+ view.isNavigationBarHidden = navigationBarHidden
136
+ }
137
+
115
138
  @ReactProp(name = "nativeBackButtonDismissalEnabled")
116
- fun setNativeBackButtonDismissalEnabled(
139
+ override fun setNativeBackButtonDismissalEnabled(
117
140
  view: Screen,
118
141
  nativeBackButtonDismissalEnabled: Boolean
119
142
  ) {
@@ -142,6 +165,10 @@ class ScreenViewManager : ViewGroupManager<Screen>() {
142
165
  return map
143
166
  }
144
167
 
168
+ protected override fun getDelegate(): ViewManagerDelegate<Screen> {
169
+ return mDelegate
170
+ }
171
+
145
172
  companion object {
146
173
  const val REACT_CLASS = "RNSScreen"
147
174
  }