react-native-screens 3.16.0 → 3.18.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 (52) hide show
  1. package/README.md +5 -1
  2. package/android/build.gradle +0 -34
  3. package/android/src/main/java/com/swmansion/rnscreens/CustomSearchView.kt +2 -0
  4. package/android/src/main/java/com/swmansion/rnscreens/LifecycleHelper.kt +1 -2
  5. package/android/src/main/java/com/swmansion/rnscreens/RNScreensPackage.kt +2 -11
  6. package/android/src/main/java/com/swmansion/rnscreens/Screen.kt +1 -6
  7. package/android/src/main/java/com/swmansion/rnscreens/ScreenContainer.kt +20 -33
  8. package/android/src/main/java/com/swmansion/rnscreens/ScreenContainerViewManager.kt +6 -18
  9. package/android/src/main/java/com/swmansion/rnscreens/ScreenFragment.kt +23 -34
  10. package/android/src/main/java/com/swmansion/rnscreens/ScreenStack.kt +19 -38
  11. package/android/src/main/java/com/swmansion/rnscreens/ScreenStackFragment.kt +37 -32
  12. package/android/src/main/java/com/swmansion/rnscreens/ScreenStackHeaderConfig.kt +14 -26
  13. package/android/src/main/java/com/swmansion/rnscreens/ScreenStackHeaderConfigViewManager.kt +6 -18
  14. package/android/src/main/java/com/swmansion/rnscreens/ScreenStackHeaderSubview.kt +2 -6
  15. package/android/src/main/java/com/swmansion/rnscreens/ScreenStackHeaderSubviewManager.kt +3 -9
  16. package/android/src/main/java/com/swmansion/rnscreens/ScreenStackViewManager.kt +11 -32
  17. package/android/src/main/java/com/swmansion/rnscreens/ScreenViewManager.kt +3 -10
  18. package/android/src/main/java/com/swmansion/rnscreens/ScreenWindowTraits.kt +1 -0
  19. package/android/src/main/jni/CMakeLists.txt +72 -0
  20. package/android/src/main/jni/rnscreens.cpp +16 -0
  21. package/android/src/main/jni/rnscreens.h +28 -0
  22. package/common/cpp/{rnscreens → react/renderer/components/rnscreens}/RNSScreenComponentDescriptor.h +0 -0
  23. package/common/cpp/{rnscreens → react/renderer/components/rnscreens}/RNSScreenShadowNode.cpp +0 -0
  24. package/common/cpp/{rnscreens → react/renderer/components/rnscreens}/RNSScreenShadowNode.h +3 -2
  25. package/common/cpp/{rnscreens → react/renderer/components/rnscreens}/RNSScreenState.cpp +0 -0
  26. package/common/cpp/{rnscreens → react/renderer/components/rnscreens}/RNSScreenState.h +1 -1
  27. package/ios/RNSFullWindowOverlay.mm +1 -1
  28. package/ios/RNSScreen.mm +1 -1
  29. package/ios/RNSScreenContainer.mm +1 -1
  30. package/ios/RNSScreenNavigationContainer.mm +1 -1
  31. package/ios/RNSScreenStack.mm +1 -1
  32. package/ios/RNSScreenStackHeaderConfig.mm +5 -2
  33. package/ios/RNSScreenStackHeaderSubview.mm +1 -1
  34. package/ios/RNSSearchBar.mm +1 -1
  35. package/lib/commonjs/native-stack/utils/getDefaultHeaderHeight.js +1 -1
  36. package/lib/commonjs/native-stack/utils/getDefaultHeaderHeight.js.map +1 -1
  37. package/lib/module/native-stack/utils/getDefaultHeaderHeight.js +1 -1
  38. package/lib/module/native-stack/utils/getDefaultHeaderHeight.js.map +1 -1
  39. package/lib/typescript/native-stack/types.d.ts +5 -5
  40. package/lib/typescript/reanimated/ReanimatedNativeStackScreen.d.ts +1 -1
  41. package/lib/typescript/reanimated/ReanimatedScreen.d.ts +1 -1
  42. package/lib/typescript/types.d.ts +20 -5
  43. package/package.json +7 -8
  44. package/src/native-stack/types.tsx +5 -5
  45. package/src/native-stack/utils/getDefaultHeaderHeight.tsx +1 -1
  46. package/src/types.tsx +20 -5
  47. package/android/src/fabric/java/com/swmansion/rnscreens/RNScreensComponentsRegistry.java +0 -28
  48. package/android/src/main/jni/Android.mk +0 -44
  49. package/android/src/main/jni/OnLoad.cpp +0 -9
  50. package/android/src/main/jni/RNScreensComponentsRegistry.cpp +0 -66
  51. package/android/src/main/jni/RNScreensComponentsRegistry.h +0 -34
  52. package/common/cpp/Android.mk +0 -37
package/README.md CHANGED
@@ -100,10 +100,14 @@ Screens are already integrated with the React Native's most popular navigation l
100
100
  | 2.0.0+ | 0.60.0+ |
101
101
 
102
102
  ### Support for Fabric
103
- [Fabric](https://reactnative.dev/architecture/fabric-renderer) is React Native's new rendering system. As of [version `3.14.0`](https://github.com/software-mansion/react-native-screens/releases/tag/3.14.0) of this project, Fabric is supported only for react-native 0.69+. Support for `0.68.x` has been dropped.
103
+ [Fabric](https://reactnative.dev/architecture/fabric-renderer) is React Native's new rendering system.
104
+
105
+ * As of [version `3.18.0`](https://github.com/software-mansion/react-native-screens/releases/tag/3.18.0) of this project, Fabric is supported only for react-native 0.70+. Support for lower versions has been dropped.
106
+ * As of [version `3.14.0`](https://github.com/software-mansion/react-native-screens/releases/tag/3.14.0) of this project, Fabric is supported only for react-native 0.69+. Support for lower versions has been dropped.
104
107
 
105
108
  | version | react-native version |
106
109
  | ------- | -------------------- |
110
+ | 3.18.0+ | 0.70.0+ |
107
111
  | 3.14.0+ | 0.69.0+ |
108
112
 
109
113
 
@@ -55,23 +55,6 @@ android {
55
55
  versionCode 1
56
56
  versionName "1.0"
57
57
  buildConfigField "boolean", "IS_NEW_ARCHITECTURE_ENABLED", isNewArchitectureEnabled().toString()
58
- if (isNewArchitectureEnabled()) {
59
- var appProject = rootProject.allprojects.find {it.plugins.hasPlugin('com.android.application')}
60
- externalNativeBuild {
61
- ndkBuild {
62
- arguments "APP_PLATFORM=android-21",
63
- "APP_STL=c++_shared",
64
- "NDK_TOOLCHAIN_VERSION=clang",
65
- "GENERATED_SRC_DIR=${appProject.buildDir}/generated/source",
66
- "PROJECT_BUILD_DIR=${appProject.buildDir}",
67
- "REACT_ANDROID_DIR=${appProject.rootDir}/../node_modules/react-native/ReactAndroid",
68
- "REACT_ANDROID_BUILD_DIR=${appProject.rootDir}/../node_modules/react-native/ReactAndroid/build"
69
- cFlags "-Wall", "-Werror", "-fexceptions", "-frtti", "-DWITH_INSPECTOR=1"
70
- cppFlags "-std=c++17"
71
- targets "rnscreens_modules"
72
- }
73
- }
74
- }
75
58
  ndk {
76
59
  abiFilters (*reactNativeArchitectures())
77
60
  }
@@ -83,13 +66,6 @@ android {
83
66
  sourceCompatibility JavaVersion.VERSION_1_8
84
67
  targetCompatibility JavaVersion.VERSION_1_8
85
68
  }
86
- if (isNewArchitectureEnabled()) {
87
- externalNativeBuild {
88
- ndkBuild {
89
- path "src/main/jni/Android.mk"
90
- }
91
- }
92
- }
93
69
  packagingOptions {
94
70
  // For some reason gradle only complains about the duplicated version of libreact_render libraries
95
71
  // while there are more libraries copied in intermediates folder of the lib build directory, we exlude
@@ -139,13 +115,3 @@ dependencies {
139
115
  implementation 'com.google.android.material:material:1.1.0'
140
116
  implementation "androidx.core:core-ktx:1.5.0"
141
117
  }
142
-
143
- if (isNewArchitectureEnabled()) {
144
- react {
145
- reactRoot = rootProject.file("../node_modules/react-native/")
146
- jsRootDir = file("../src/fabric/")
147
- codegenDir = rootProject.file("../node_modules/react-native-codegen/")
148
- libraryName = "rnscreens"
149
- codegenJavaPackageName = "com.swmansion.rnscreens"
150
- }
151
- }
@@ -22,7 +22,9 @@ class CustomSearchView(context: Context, fragment: Fragment) : SearchView(contex
22
22
  isIconified = true
23
23
  }
24
24
  }
25
+
25
26
  private val backPressOverrider = FragmentBackPressOverrider(fragment, mOnBackPressedCallback)
27
+
26
28
  var overrideBackAction: Boolean
27
29
  set(value) {
28
30
  backPressOverrider.overrideBackAction = value
@@ -43,8 +43,7 @@ class LifecycleHelper {
43
43
  }
44
44
 
45
45
  fun <T> unregister(view: T) where T : View, T : LifecycleObserver? {
46
- val lifecycle = mViewToLifecycleMap[view]
47
- lifecycle?.removeObserver(view)
46
+ mViewToLifecycleMap[view]?.removeObserver(view)
48
47
  }
49
48
 
50
49
  companion object {
@@ -4,19 +4,10 @@ import com.facebook.react.ReactPackage
4
4
  import com.facebook.react.bridge.NativeModule
5
5
  import com.facebook.react.bridge.ReactApplicationContext
6
6
  import com.facebook.react.uimanager.ViewManager
7
- import com.facebook.soloader.SoLoader
8
7
 
9
8
  class RNScreensPackage : ReactPackage {
10
- override fun createNativeModules(reactContext: ReactApplicationContext): List<NativeModule> {
11
- if (BuildConfig.IS_NEW_ARCHITECTURE_ENABLED) {
12
- // For Fabric, we load c++ native library here, this triggers screen's Fabric
13
- // component registration which is necessary in order to avoid asking users
14
- // to manually add init calls in their application code.
15
- // This should no longer be needed if RN's autolink mechanism has Fabric support
16
- SoLoader.loadLibrary("rnscreens_modules")
17
- }
18
- return emptyList<NativeModule>()
19
- }
9
+ override fun createNativeModules(reactContext: ReactApplicationContext): List<NativeModule> =
10
+ emptyList()
20
11
 
21
12
  override fun createViewManagers(reactContext: ReactApplicationContext) =
22
13
  listOf<ViewManager<*, *>>(
@@ -84,12 +84,7 @@ class Screen constructor(context: ReactContext?) : FabricEnabledViewGroup(contex
84
84
  }
85
85
 
86
86
  val headerConfig: ScreenStackHeaderConfig?
87
- get() {
88
- val child = getChildAt(0)
89
- return if (child is ScreenStackHeaderConfig) {
90
- child
91
- } else null
92
- }
87
+ get() = getChildAt(0) as? ScreenStackHeaderConfig
93
88
 
94
89
  /**
95
90
  * While transitioning this property allows to optimize rendering behavior on Android and provide
@@ -35,6 +35,7 @@ open class ScreenContainer<T : ScreenFragment>(context: Context?) : ViewGroup(co
35
35
  }
36
36
  }
37
37
  private var mParentScreenFragment: ScreenFragment? = null
38
+
38
39
  override fun onLayout(changed: Boolean, l: Int, t: Int, r: Int, b: Int) {
39
40
  var i = 0
40
41
  val size = childCount
@@ -116,19 +117,10 @@ open class ScreenContainer<T : ScreenFragment>(context: Context?) : ViewGroup(co
116
117
  val screenCount: Int
117
118
  get() = mScreenFragments.size
118
119
 
119
- fun getScreenAt(index: Int): Screen {
120
- return mScreenFragments[index].screen
121
- }
120
+ fun getScreenAt(index: Int): Screen = mScreenFragments[index].screen
122
121
 
123
122
  open val topScreen: Screen?
124
- get() {
125
- for (screenFragment in mScreenFragments) {
126
- if (getActivityState(screenFragment) === ActivityState.ON_TOP) {
127
- return screenFragment.screen
128
- }
129
- }
130
- return null
131
- }
123
+ get() = mScreenFragments.firstOrNull { getActivityState(it) === ActivityState.ON_TOP }?.screen
132
124
 
133
125
  private fun setFragmentManager(fm: FragmentManager) {
134
126
  mFragmentManager = fm
@@ -161,11 +153,11 @@ open class ScreenContainer<T : ScreenFragment>(context: Context?) : ViewGroup(co
161
153
  // `findFragment` method throws IllegalStateException when it fails to resolve appropriate
162
154
  // fragment. It might happen when e.g. React Native is loaded directly in Activity
163
155
  // but some custom fragments are still used. Such use case seems highly unlikely
164
- // so, as for now we let application crash.
156
+ // so, as for now we fallback to activity's FragmentManager in hope for the best.
165
157
  try {
166
158
  FragmentManager.findFragment<Fragment>(rootView).childFragmentManager
167
159
  } catch (ex: IllegalStateException) {
168
- throw IllegalStateException("Failed to find fragment for React Root View")
160
+ context.supportFragmentManager
169
161
  }
170
162
  }
171
163
  }
@@ -200,10 +192,9 @@ open class ScreenContainer<T : ScreenFragment>(context: Context?) : ViewGroup(co
200
192
  }
201
193
 
202
194
  protected fun createTransaction(): FragmentTransaction {
203
- val fragmentManager = requireNotNull(mFragmentManager, { "mFragmentManager is null when creating transaction" })
204
- val transaction = fragmentManager.beginTransaction()
205
- transaction.setReorderingAllowed(true)
206
- return transaction
195
+ return requireNotNull(mFragmentManager) { "mFragmentManager is null when creating transaction" }
196
+ .beginTransaction()
197
+ .setReorderingAllowed(true)
207
198
  }
208
199
 
209
200
  private fun attachScreen(transaction: FragmentTransaction, screenFragment: ScreenFragment) {
@@ -214,13 +205,11 @@ open class ScreenContainer<T : ScreenFragment>(context: Context?) : ViewGroup(co
214
205
  transaction.remove(screenFragment)
215
206
  }
216
207
 
217
- private fun getActivityState(screenFragment: ScreenFragment): ActivityState? {
218
- return screenFragment.screen.activityState
219
- }
208
+ private fun getActivityState(screenFragment: ScreenFragment): ActivityState? =
209
+ screenFragment.screen.activityState
220
210
 
221
- open fun hasScreen(screenFragment: ScreenFragment?): Boolean {
222
- return mScreenFragments.contains(screenFragment)
223
- }
211
+ open fun hasScreen(screenFragment: ScreenFragment?): Boolean =
212
+ mScreenFragments.contains(screenFragment)
224
213
 
225
214
  override fun onAttachedToWindow() {
226
215
  super.onAttachedToWindow()
@@ -233,9 +222,7 @@ open class ScreenContainer<T : ScreenFragment>(context: Context?) : ViewGroup(co
233
222
  val transaction = fragmentManager.beginTransaction()
234
223
  var hasFragments = false
235
224
  for (fragment in fragmentManager.fragments) {
236
- if (fragment is ScreenFragment &&
237
- fragment.screen.container === this
238
- ) {
225
+ if (fragment is ScreenFragment && fragment.screen.container === this) {
239
226
  transaction.remove(fragment)
240
227
  hasFragments = true
241
228
  }
@@ -276,19 +263,15 @@ open class ScreenContainer<T : ScreenFragment>(context: Context?) : ViewGroup(co
276
263
  // children are not already detached, which may lead to calling `onDetachedFromWindow` on them
277
264
  // twice.
278
265
  // We also get the size earlier, because we will be removing child views in `for` loop.
279
- val size = childCount
280
- for (i in size - 1 downTo 0) {
266
+ for (i in childCount - 1 downTo 0) {
281
267
  removeViewAt(i)
282
268
  }
283
269
  }
284
270
 
285
271
  override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
286
272
  super.onMeasure(widthMeasureSpec, heightMeasureSpec)
287
- var i = 0
288
- val size = childCount
289
- while (i < size) {
273
+ for (i in 0 until childCount) {
290
274
  getChildAt(i).measure(widthMeasureSpec, heightMeasureSpec)
291
- i++
292
275
  }
293
276
  }
294
277
 
@@ -332,7 +315,11 @@ open class ScreenContainer<T : ScreenFragment>(context: Context?) : ViewGroup(co
332
315
  open fun onUpdate() {
333
316
  createTransaction().let {
334
317
  // detach screens that are no longer active
335
- val orphaned: MutableSet<Fragment> = HashSet(requireNotNull(mFragmentManager, { "mFragmentManager is null when performing update in ScreenContainer" }).fragments)
318
+ val orphaned: MutableSet<Fragment> = HashSet(
319
+ requireNotNull(mFragmentManager) {
320
+ "mFragmentManager is null when performing update in ScreenContainer"
321
+ }.fragments
322
+ )
336
323
  for (screenFragment in mScreenFragments) {
337
324
  if (getActivityState(screenFragment) === ActivityState.INACTIVE &&
338
325
  screenFragment.isAdded
@@ -9,13 +9,9 @@ import com.facebook.react.uimanager.ViewGroupManager
9
9
 
10
10
  @ReactModule(name = ScreenContainerViewManager.REACT_CLASS)
11
11
  class ScreenContainerViewManager : ViewGroupManager<ScreenContainer<*>>() {
12
- override fun getName(): String {
13
- return REACT_CLASS
14
- }
12
+ override fun getName(): String = REACT_CLASS
15
13
 
16
- override fun createViewInstance(reactContext: ThemedReactContext): ScreenContainer<ScreenFragment> {
17
- return ScreenContainer(reactContext)
18
- }
14
+ override fun createViewInstance(reactContext: ThemedReactContext): ScreenContainer<ScreenFragment> = ScreenContainer(reactContext)
19
15
 
20
16
  override fun addView(parent: ScreenContainer<*>, child: View, index: Int) {
21
17
  require(child is Screen) { "Attempt attach child that is not of type RNScreens" }
@@ -30,21 +26,13 @@ class ScreenContainerViewManager : ViewGroupManager<ScreenContainer<*>>() {
30
26
  parent.removeAllScreens()
31
27
  }
32
28
 
33
- override fun getChildCount(parent: ScreenContainer<*>): Int {
34
- return parent.screenCount
35
- }
29
+ override fun getChildCount(parent: ScreenContainer<*>): Int = parent.screenCount
36
30
 
37
- override fun getChildAt(parent: ScreenContainer<*>, index: Int): View {
38
- return parent.getScreenAt(index)
39
- }
31
+ override fun getChildAt(parent: ScreenContainer<*>, index: Int): View = parent.getScreenAt(index)
40
32
 
41
- override fun createShadowNodeInstance(context: ReactApplicationContext): LayoutShadowNode {
42
- return ScreensShadowNode(context)
43
- }
33
+ override fun createShadowNodeInstance(context: ReactApplicationContext): LayoutShadowNode = ScreensShadowNode(context)
44
34
 
45
- override fun needsCustomLayoutForChildren(): Boolean {
46
- return true
47
- }
35
+ override fun needsCustomLayoutForChildren(): Boolean = true
48
36
 
49
37
  companion object {
50
38
  const val REACT_CLASS = "RNSScreenContainer"
@@ -74,13 +74,12 @@ open class ScreenFragment : Fragment {
74
74
  container: ViewGroup?,
75
75
  savedInstanceState: Bundle?
76
76
  ): View? {
77
- val wrapper = context?.let { ScreensFrameLayout(it) }
78
-
79
- val params = FrameLayout.LayoutParams(
77
+ screen.layoutParams = FrameLayout.LayoutParams(
80
78
  ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT
81
79
  )
82
- screen.layoutParams = params
83
- wrapper?.addView(recycleView(screen))
80
+ val wrapper = context?.let { ScreensFrameLayout(it) }?.apply {
81
+ addView(recycleView(screen))
82
+ }
84
83
  return wrapper
85
84
  }
86
85
 
@@ -153,13 +152,11 @@ open class ScreenFragment : Fragment {
153
152
  val childScreenContainers: List<ScreenContainer<*>>
154
153
  get() = mChildScreenContainers
155
154
 
156
- private fun canDispatchEvent(event: ScreenLifecycleEvent): Boolean {
157
- return when (event) {
158
- ScreenLifecycleEvent.WillAppear -> canDispatchWillAppear
159
- ScreenLifecycleEvent.Appear -> canDispatchAppear
160
- ScreenLifecycleEvent.WillDisappear -> !canDispatchWillAppear
161
- ScreenLifecycleEvent.Disappear -> !canDispatchAppear
162
- }
155
+ private fun canDispatchEvent(event: ScreenLifecycleEvent): Boolean = when (event) {
156
+ ScreenLifecycleEvent.WillAppear -> canDispatchWillAppear
157
+ ScreenLifecycleEvent.Appear -> canDispatchAppear
158
+ ScreenLifecycleEvent.WillDisappear -> !canDispatchWillAppear
159
+ ScreenLifecycleEvent.Disappear -> !canDispatchAppear
163
160
  }
164
161
 
165
162
  private fun setLastEventDispatched(event: ScreenLifecycleEvent) {
@@ -173,25 +170,21 @@ open class ScreenFragment : Fragment {
173
170
 
174
171
  private fun dispatchOnWillAppear() {
175
172
  dispatchEvent(ScreenLifecycleEvent.WillAppear, this)
176
-
177
173
  dispatchTransitionProgress(0.0f, false)
178
174
  }
179
175
 
180
176
  private fun dispatchOnAppear() {
181
177
  dispatchEvent(ScreenLifecycleEvent.Appear, this)
182
-
183
178
  dispatchTransitionProgress(1.0f, false)
184
179
  }
185
180
 
186
181
  private fun dispatchOnWillDisappear() {
187
182
  dispatchEvent(ScreenLifecycleEvent.WillDisappear, this)
188
-
189
183
  dispatchTransitionProgress(0.0f, true)
190
184
  }
191
185
 
192
186
  private fun dispatchOnDisappear() {
193
187
  dispatchEvent(ScreenLifecycleEvent.Disappear, this)
194
-
195
188
  dispatchTransitionProgress(1.0f, true)
196
189
  }
197
190
 
@@ -215,20 +208,16 @@ open class ScreenFragment : Fragment {
215
208
  }
216
209
 
217
210
  private fun dispatchEventInChildContainers(event: ScreenLifecycleEvent) {
218
- for (sc in mChildScreenContainers) {
219
- if (sc.screenCount > 0) {
220
- sc.topScreen?.let {
221
- sc.topScreen?.fragment?.let { fragment -> dispatchEvent(event, fragment) }
222
- }
223
- }
211
+ mChildScreenContainers.filter { it.screenCount > 0 }.forEach {
212
+ it.topScreen?.fragment?.let { fragment -> dispatchEvent(event, fragment) }
224
213
  }
225
214
  }
226
215
 
227
216
  fun dispatchHeaderBackButtonClickedEvent() {
228
217
  val screenContext = screen.context as ReactContext
229
- val eventDispatcher: EventDispatcher? =
230
- UIManagerHelper.getEventDispatcherForReactTag(screenContext, screen.id)
231
- eventDispatcher?.dispatchEvent(HeaderBackButtonClickedEvent(screen.id))
218
+ UIManagerHelper
219
+ .getEventDispatcherForReactTag(screenContext, screen.id)
220
+ ?.dispatchEvent(HeaderBackButtonClickedEvent(screen.id))
232
221
  }
233
222
 
234
223
  fun dispatchTransitionProgress(alpha: Float, closing: Boolean) {
@@ -244,13 +233,13 @@ open class ScreenFragment : Fragment {
244
233
  val container: ScreenContainer<*>? = screen.container
245
234
  val goingForward = if (container is ScreenStack) container.goingForward else false
246
235
  val screenContext = screen.context as ReactContext
247
- val eventDispatcher: EventDispatcher? =
248
- UIManagerHelper.getEventDispatcherForReactTag(screenContext, screen.id)
249
- eventDispatcher?.dispatchEvent(
250
- ScreenTransitionProgressEvent(
251
- screen.id, mProgress, closing, goingForward, coalescingKey
236
+ UIManagerHelper
237
+ .getEventDispatcherForReactTag(screenContext, screen.id)
238
+ ?.dispatchEvent(
239
+ ScreenTransitionProgressEvent(
240
+ screen.id, mProgress, closing, goingForward, coalescingKey
241
+ )
252
242
  )
253
- )
254
243
  }
255
244
  }
256
245
  }
@@ -305,9 +294,9 @@ open class ScreenFragment : Fragment {
305
294
  // we only send dismissed even when the screen has been removed from its container
306
295
  val screenContext = screen.context
307
296
  if (screenContext is ReactContext) {
308
- val eventDispatcher: EventDispatcher? =
309
- UIManagerHelper.getEventDispatcherForReactTag(screenContext, screen.id)
310
- eventDispatcher?.dispatchEvent(ScreenDismissedEvent(screen.id))
297
+ UIManagerHelper
298
+ .getEventDispatcherForReactTag(screenContext, screen.id)
299
+ ?.dispatchEvent(ScreenDismissedEvent(screen.id))
311
300
  }
312
301
  }
313
302
  mChildScreenContainers.clear()
@@ -5,7 +5,6 @@ import android.graphics.Canvas
5
5
  import android.view.View
6
6
  import com.facebook.react.bridge.ReactContext
7
7
  import com.facebook.react.uimanager.UIManagerHelper
8
- import com.facebook.react.uimanager.events.EventDispatcher
9
8
  import com.swmansion.rnscreens.Screen.StackAnimation
10
9
  import com.swmansion.rnscreens.events.StackFinishTransitioningEvent
11
10
  import java.util.Collections
@@ -23,6 +22,7 @@ class ScreenStack(context: Context?) : ScreenContainer<ScreenStackFragment>(cont
23
22
  private var reverseLastTwoChildren = false
24
23
  private var previousChildrenCount = 0
25
24
  var goingForward = false
25
+
26
26
  fun dismiss(screenFragment: ScreenStackFragment) {
27
27
  mDismissed.add(screenFragment)
28
28
  performUpdatesNow()
@@ -30,23 +30,19 @@ class ScreenStack(context: Context?) : ScreenContainer<ScreenStackFragment>(cont
30
30
 
31
31
  override val topScreen: Screen?
32
32
  get() = mTopScreen?.screen
33
+
33
34
  val rootScreen: Screen
34
35
  get() {
35
- var i = 0
36
- val size = screenCount
37
- while (i < size) {
36
+ for (i in 0 until screenCount) {
38
37
  val screen = getScreenAt(i)
39
38
  if (!mDismissed.contains(screen.fragment)) {
40
39
  return screen
41
40
  }
42
- i++
43
41
  }
44
42
  throw IllegalStateException("Stack has no root screen set")
45
43
  }
46
44
 
47
- override fun adapt(screen: Screen): ScreenStackFragment {
48
- return ScreenStackFragment(screen)
49
- }
45
+ override fun adapt(screen: Screen) = ScreenStackFragment(screen)
50
46
 
51
47
  override fun startViewTransition(view: View) {
52
48
  super.startViewTransition(view)
@@ -68,16 +64,13 @@ class ScreenStack(context: Context?) : ScreenContainer<ScreenStackFragment>(cont
68
64
  }
69
65
 
70
66
  private fun dispatchOnFinishTransitioning() {
71
- val eventDispatcher: EventDispatcher? =
72
- UIManagerHelper.getEventDispatcherForReactTag((context as ReactContext), id)
73
- eventDispatcher?.dispatchEvent(
74
- StackFinishTransitioningEvent(id)
75
- )
67
+ UIManagerHelper
68
+ .getEventDispatcherForReactTag((context as ReactContext), id)
69
+ ?.dispatchEvent(StackFinishTransitioningEvent(id))
76
70
  }
77
71
 
78
72
  override fun removeScreenAt(index: Int) {
79
- val toBeRemoved = getScreenAt(index)
80
- mDismissed.remove(toBeRemoved.fragment)
73
+ mDismissed.remove(getScreenAt(index).fragment)
81
74
  super.removeScreenAt(index)
82
75
  }
83
76
 
@@ -86,9 +79,8 @@ class ScreenStack(context: Context?) : ScreenContainer<ScreenStackFragment>(cont
86
79
  super.removeAllScreens()
87
80
  }
88
81
 
89
- override fun hasScreen(screenFragment: ScreenFragment?): Boolean {
90
- return super.hasScreen(screenFragment) && !mDismissed.contains(screenFragment)
91
- }
82
+ override fun hasScreen(screenFragment: ScreenFragment?): Boolean =
83
+ super.hasScreen(screenFragment) && !mDismissed.contains(screenFragment)
92
84
 
93
85
  override fun onUpdate() {
94
86
  // When going back from a nested stack with a single screen on it, we may hit an edge case
@@ -252,9 +244,7 @@ class ScreenStack(context: Context?) : ScreenContainer<ScreenStackFragment>(cont
252
244
  }
253
245
 
254
246
  override fun notifyContainerUpdate() {
255
- for (screen in mStack) {
256
- screen.onContainerUpdate()
257
- }
247
+ mStack.forEach { it.onContainerUpdate() }
258
248
  }
259
249
 
260
250
  // below methods are taken from
@@ -310,16 +300,14 @@ class ScreenStack(context: Context?) : ScreenContainer<ScreenStackFragment>(cont
310
300
  super.drawChild(op.canvas, op.child, op.drawingTime)
311
301
  }
312
302
 
313
- private fun obtainDrawingOp(): DrawingOp {
314
- return if (drawingOpPool.isEmpty()) {
315
- DrawingOp()
316
- } else drawingOpPool.removeAt(drawingOpPool.size - 1)
317
- }
303
+ private fun obtainDrawingOp(): DrawingOp =
304
+ if (drawingOpPool.isEmpty()) DrawingOp() else drawingOpPool.removeAt(drawingOpPool.size - 1)
318
305
 
319
306
  private inner class DrawingOp {
320
307
  var canvas: Canvas? = null
321
308
  var child: View? = null
322
309
  var drawingTime: Long = 0
310
+
323
311
  operator fun set(canvas: Canvas?, child: View?, drawingTime: Long): DrawingOp {
324
312
  this.canvas = canvas
325
313
  this.child = child
@@ -336,18 +324,11 @@ class ScreenStack(context: Context?) : ScreenContainer<ScreenStackFragment>(cont
336
324
  }
337
325
 
338
326
  companion object {
339
- private fun isTransparent(fragment: ScreenStackFragment): Boolean {
340
- return (
341
- fragment.screen.stackPresentation
342
- === Screen.StackPresentation.TRANSPARENT_MODAL
343
- )
344
- }
327
+ private fun isTransparent(fragment: ScreenStackFragment): Boolean =
328
+ fragment.screen.stackPresentation === Screen.StackPresentation.TRANSPARENT_MODAL
345
329
 
346
- private fun needsDrawReordering(fragment: ScreenStackFragment): Boolean {
347
- return (
348
- fragment.screen.stackAnimation === StackAnimation.SLIDE_FROM_BOTTOM ||
349
- fragment.screen.stackAnimation === StackAnimation.FADE_FROM_BOTTOM
350
- )
351
- }
330
+ private fun needsDrawReordering(fragment: ScreenStackFragment): Boolean =
331
+ fragment.screen.stackAnimation === StackAnimation.SLIDE_FROM_BOTTOM ||
332
+ fragment.screen.stackAnimation === StackAnimation.FADE_FROM_BOTTOM
352
333
  }
353
334
  }
@@ -51,11 +51,9 @@ class ScreenStackFragment : ScreenFragment {
51
51
 
52
52
  fun setToolbar(toolbar: Toolbar) {
53
53
  mAppBarLayout?.addView(toolbar)
54
- val params = AppBarLayout.LayoutParams(
54
+ toolbar.layoutParams = AppBarLayout.LayoutParams(
55
55
  AppBarLayout.LayoutParams.MATCH_PARENT, AppBarLayout.LayoutParams.WRAP_CONTENT
56
- )
57
- params.scrollFlags = 0
58
- toolbar.layoutParams = params
56
+ ).apply { scrollFlags = 0 }
59
57
  mToolbar = toolbar
60
58
  }
61
59
 
@@ -76,8 +74,7 @@ class ScreenStackFragment : ScreenFragment {
76
74
  }
77
75
 
78
76
  override fun onContainerUpdate() {
79
- val headerConfig = screen.headerConfig
80
- headerConfig?.onUpdate()
77
+ screen.headerConfig?.onUpdate()
81
78
  }
82
79
 
83
80
  override fun onViewAnimationEnd() {
@@ -99,22 +96,24 @@ class ScreenStackFragment : ScreenFragment {
99
96
  ): View? {
100
97
  val view: ScreensCoordinatorLayout? =
101
98
  context?.let { ScreensCoordinatorLayout(it, this) }
102
- val params = CoordinatorLayout.LayoutParams(
99
+
100
+ screen.layoutParams = CoordinatorLayout.LayoutParams(
103
101
  LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.MATCH_PARENT
104
- )
105
- params.behavior = if (mIsTranslucent) null else ScrollingViewBehavior()
106
- screen.layoutParams = params
102
+ ).apply { behavior = if (mIsTranslucent) null else ScrollingViewBehavior() }
103
+
107
104
  view?.addView(recycleView(screen))
108
105
 
109
- mAppBarLayout = context?.let { AppBarLayout(it) }
110
- // By default AppBarLayout will have a background color set but since we cover the whole layout
111
- // with toolbar (that can be semi-transparent) the bar layout background color does not pay a
112
- // role. On top of that it breaks screens animations when alfa offscreen compositing is off
113
- // (which is the default)
114
- mAppBarLayout?.setBackgroundColor(Color.TRANSPARENT)
115
- mAppBarLayout?.layoutParams = AppBarLayout.LayoutParams(
116
- AppBarLayout.LayoutParams.MATCH_PARENT, AppBarLayout.LayoutParams.WRAP_CONTENT
117
- )
106
+ mAppBarLayout = context?.let { AppBarLayout(it) }?.apply {
107
+ // By default AppBarLayout will have a background color set but since we cover the whole layout
108
+ // with toolbar (that can be semi-transparent) the bar layout background color does not pay a
109
+ // role. On top of that it breaks screens animations when alfa offscreen compositing is off
110
+ // (which is the default)
111
+ setBackgroundColor(Color.TRANSPARENT)
112
+ layoutParams = AppBarLayout.LayoutParams(
113
+ AppBarLayout.LayoutParams.MATCH_PARENT, AppBarLayout.LayoutParams.WRAP_CONTENT
114
+ )
115
+ }
116
+
118
117
  view?.addView(mAppBarLayout)
119
118
  if (mShadowHidden) {
120
119
  mAppBarLayout?.targetElevation = 0f
@@ -157,9 +156,10 @@ class ScreenStackFragment : ScreenFragment {
157
156
  searchView = newSearchView
158
157
  onSearchViewCreate?.invoke(newSearchView)
159
158
  }
160
- val item = menu.add("")
161
- item.setShowAsAction(MenuItem.SHOW_AS_ACTION_ALWAYS)
162
- item.actionView = searchView
159
+ menu.add("").apply {
160
+ setShowAsAction(MenuItem.SHOW_AS_ACTION_ALWAYS)
161
+ actionView = searchView
162
+ }
163
163
  }
164
164
  }
165
165
 
@@ -213,18 +213,23 @@ class ScreenStackFragment : ScreenFragment {
213
213
  // and also this is not necessary when going back since the lifecycle methods
214
214
  // are correctly dispatched then.
215
215
  // We also add fakeAnimation to the set of animations, which sends the progress of animation
216
- val fakeAnimation = ScreensAnimation(mFragment)
217
- fakeAnimation.duration = animation.duration
216
+ val fakeAnimation = ScreensAnimation(mFragment).apply { duration = animation.duration }
217
+
218
218
  if (animation is AnimationSet && !mFragment.isRemoving) {
219
- animation.addAnimation(fakeAnimation)
220
- animation.setAnimationListener(mAnimationListener)
221
- super.startAnimation(animation)
219
+ animation.apply {
220
+ addAnimation(fakeAnimation)
221
+ setAnimationListener(mAnimationListener)
222
+ }.also {
223
+ super.startAnimation(it)
224
+ }
222
225
  } else {
223
- val set = AnimationSet(true)
224
- set.addAnimation(animation)
225
- set.addAnimation(fakeAnimation)
226
- set.setAnimationListener(mAnimationListener)
227
- super.startAnimation(set)
226
+ AnimationSet(true).apply {
227
+ addAnimation(animation)
228
+ addAnimation(fakeAnimation)
229
+ setAnimationListener(mAnimationListener)
230
+ }.also {
231
+ super.startAnimation(it)
232
+ }
228
233
  }
229
234
  }
230
235