react-native-screens 4.21.0 → 4.22.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.
@@ -3,6 +3,8 @@ package com.swmansion.rnscreens.ext
3
3
  import android.graphics.drawable.ColorDrawable
4
4
  import android.view.View
5
5
  import android.view.ViewGroup
6
+ import androidx.fragment.app.Fragment
7
+ import androidx.fragment.app.findFragment
6
8
 
7
9
  internal fun View.parentAsView() = this.parent as? View
8
10
 
@@ -37,3 +39,10 @@ internal fun View.maybeBgColor(): Int? {
37
39
  }
38
40
 
39
41
  internal fun View.asViewGroupOrNull(): ViewGroup? = this as? ViewGroup
42
+
43
+ internal fun View.findFragmentOrNull(): Fragment? =
44
+ try {
45
+ this.findFragment()
46
+ } catch (_: IllegalStateException) {
47
+ null
48
+ }
@@ -0,0 +1,69 @@
1
+ package com.swmansion.rnscreens.gamma.stack.host
2
+
3
+ import androidx.fragment.app.FragmentManager
4
+ import com.swmansion.rnscreens.gamma.stack.screen.StackScreenFragment
5
+
6
+ internal sealed class FragmentOperation {
7
+ internal abstract fun execute(
8
+ fragmentManager: FragmentManager,
9
+ executor: FragmentOperationExecutor,
10
+ )
11
+ }
12
+
13
+ internal class AddOp(
14
+ val fragment: StackScreenFragment,
15
+ val containerViewId: Int,
16
+ val addToBackStack: Boolean,
17
+ val allowStateLoss: Boolean = true,
18
+ ) : FragmentOperation() {
19
+ override fun execute(
20
+ fragmentManager: FragmentManager,
21
+ executor: FragmentOperationExecutor,
22
+ ) {
23
+ executor.executeAddOp(fragmentManager, this)
24
+ }
25
+ }
26
+
27
+ internal class PopBackStackOp(
28
+ val fragment: StackScreenFragment,
29
+ ) : FragmentOperation() {
30
+ override fun execute(
31
+ fragmentManager: FragmentManager,
32
+ executor: FragmentOperationExecutor,
33
+ ) {
34
+ executor.executePopBackStackOp(fragmentManager, this)
35
+ }
36
+ }
37
+
38
+ internal class RemoveOp(
39
+ val fragment: StackScreenFragment,
40
+ val allowStateLoss: Boolean = true,
41
+ val flushSync: Boolean = false,
42
+ ) : FragmentOperation() {
43
+ override fun execute(
44
+ fragmentManager: FragmentManager,
45
+ executor: FragmentOperationExecutor,
46
+ ) {
47
+ executor.executeRemoveOp(fragmentManager, this)
48
+ }
49
+ }
50
+
51
+ internal class FlushNowOp : FragmentOperation() {
52
+ override fun execute(
53
+ fragmentManager: FragmentManager,
54
+ executor: FragmentOperationExecutor,
55
+ ) {
56
+ executor.executeFlushOp(fragmentManager, this)
57
+ }
58
+ }
59
+
60
+ internal class SetPrimaryNavFragmentOp(
61
+ val fragment: StackScreenFragment,
62
+ ) : FragmentOperation() {
63
+ override fun execute(
64
+ fragmentManager: FragmentManager,
65
+ executor: FragmentOperationExecutor,
66
+ ) {
67
+ executor.executeSetPrimaryNavFragmentOp(fragmentManager, this)
68
+ }
69
+ }
@@ -0,0 +1,82 @@
1
+ package com.swmansion.rnscreens.gamma.stack.host
2
+
3
+ import androidx.fragment.app.FragmentManager
4
+ import androidx.fragment.app.FragmentTransaction
5
+ import com.swmansion.rnscreens.gamma.helpers.createTransactionWithReordering
6
+
7
+ internal class FragmentOperationExecutor {
8
+ internal fun executeOperations(
9
+ fragmentManager: FragmentManager,
10
+ ops: List<FragmentOperation>,
11
+ flushSync: Boolean = false
12
+ ) {
13
+ ops.forEach { it.execute(fragmentManager, this) }
14
+
15
+ if (flushSync) {
16
+ fragmentManager.executePendingTransactions()
17
+ }
18
+ }
19
+
20
+ internal fun executeAddOp(fragmentManager: FragmentManager, op: AddOp) {
21
+ fragmentManager.createTransactionWithReordering().let { tx ->
22
+ tx.add(op.containerViewId, op.fragment)
23
+ if (op.addToBackStack) {
24
+ tx.addToBackStack(op.fragment.stackScreen.screenKey)
25
+ }
26
+ commitTransaction(tx, op.allowStateLoss)
27
+ }
28
+ }
29
+
30
+ internal fun executePopBackStackOp(fragmentManager: FragmentManager, op: PopBackStackOp) {
31
+ fragmentManager.popBackStack(
32
+ op.fragment.stackScreen.screenKey,
33
+ FragmentManager.POP_BACK_STACK_INCLUSIVE
34
+ )
35
+ }
36
+
37
+ internal fun executeRemoveOp(fragmentManager: FragmentManager, op: RemoveOp) {
38
+ fragmentManager.createTransactionWithReordering().let { tx ->
39
+ tx.remove(op.fragment)
40
+ commitTransaction(tx, op.allowStateLoss, op.flushSync)
41
+ }
42
+ }
43
+
44
+ internal fun executeFlushOp(fragmentManager: FragmentManager, op: FlushNowOp) {
45
+ fragmentManager.executePendingTransactions()
46
+ }
47
+
48
+ internal fun executeSetPrimaryNavFragmentOp(fragmentManager: FragmentManager, op: SetPrimaryNavFragmentOp) {
49
+ fragmentManager.createTransactionWithReordering().let { tx ->
50
+ tx.setPrimaryNavigationFragment(op.fragment)
51
+ commitTransaction(tx, allowStateLoss = true, flushSync = false)
52
+ }
53
+ }
54
+
55
+ private fun commitTransaction(
56
+ tx: FragmentTransaction,
57
+ allowStateLoss: Boolean,
58
+ flushSync: Boolean = false
59
+ ) {
60
+ if (flushSync) {
61
+ commitSync(tx, allowStateLoss)
62
+ } else {
63
+ commitAsync(tx, allowStateLoss)
64
+ }
65
+ }
66
+
67
+ private fun commitAsync(tx: FragmentTransaction, allowStateLoss: Boolean) {
68
+ if (allowStateLoss) {
69
+ tx.commitAllowingStateLoss()
70
+ } else {
71
+ tx.commit()
72
+ }
73
+ }
74
+
75
+ private fun commitSync(tx: FragmentTransaction, allowStateLoss: Boolean) {
76
+ if (allowStateLoss) {
77
+ tx.commitNowAllowingStateLoss()
78
+ } else {
79
+ tx.commitNow()
80
+ }
81
+ }
82
+ }
@@ -2,11 +2,12 @@ package com.swmansion.rnscreens.gamma.stack.host
2
2
 
3
3
  import android.annotation.SuppressLint
4
4
  import android.content.Context
5
+ import android.util.Log
5
6
  import androidx.coordinatorlayout.widget.CoordinatorLayout
7
+ import androidx.fragment.app.Fragment
6
8
  import androidx.fragment.app.FragmentManager
7
9
  import com.swmansion.rnscreens.gamma.helpers.FragmentManagerHelper
8
10
  import com.swmansion.rnscreens.gamma.helpers.ViewIdGenerator
9
- import com.swmansion.rnscreens.gamma.helpers.createTransactionWithReordering
10
11
  import com.swmansion.rnscreens.gamma.stack.screen.StackScreen
11
12
  import com.swmansion.rnscreens.gamma.stack.screen.StackScreenFragment
12
13
  import com.swmansion.rnscreens.utils.RNSLog
@@ -16,16 +17,27 @@ import java.lang.ref.WeakReference
16
17
  internal class StackContainer(
17
18
  context: Context,
18
19
  private val delegate: WeakReference<StackContainerDelegate>,
19
- ) : CoordinatorLayout(context) {
20
+ ) : CoordinatorLayout(context),
21
+ FragmentManager.OnBackStackChangedListener {
20
22
  private var fragmentManager: FragmentManager? = null
21
23
 
22
- private val stackScreenFragments: MutableList<StackScreenFragment> = arrayListOf()
24
+ private fun requireFragmentManager(): FragmentManager =
25
+ checkNotNull(fragmentManager) { "[RNScreens] Attempt to use nullish FragmentManager" }
26
+
27
+ /**
28
+ * Describes most up-to-date view of the stack. It might be different from
29
+ * state kept by FragmentManager as this data structure is updated immediately,
30
+ * while operations on fragment manager are scheduled.
31
+ */
32
+ private val stackModel: MutableList<StackScreenFragment> = arrayListOf()
23
33
 
24
34
  private val pendingPopOperations: MutableList<PopOperation> = arrayListOf()
25
35
  private val pendingPushOperations: MutableList<PushOperation> = arrayListOf()
26
36
  private val hasPendingOperations: Boolean
27
37
  get() = pendingPushOperations.isNotEmpty() || pendingPopOperations.isNotEmpty()
28
38
 
39
+ private val fragmentOpExecutor: FragmentOperationExecutor = FragmentOperationExecutor()
40
+
29
41
  init {
30
42
  id = ViewIdGenerator.generateViewId()
31
43
  }
@@ -34,16 +46,28 @@ internal class StackContainer(
34
46
  RNSLog.d(TAG, "StackContainer [$id] attached to window")
35
47
  super.onAttachedToWindow()
36
48
 
37
- fragmentManager =
38
- checkNotNull(FragmentManagerHelper.findFragmentManagerForView(this)) {
39
- "[RNScreens] Nullish fragment manager - can't run container operations"
40
- }
49
+ setupFragmentManger()
41
50
 
42
51
  // We run container update to handle any pending updates requested before container was
43
52
  // attached to window.
44
53
  performContainerUpdateIfNeeded()
45
54
  }
46
55
 
56
+ override fun onDetachedFromWindow() {
57
+ super.onDetachedFromWindow()
58
+ requireFragmentManager().removeOnBackStackChangedListener(this)
59
+ fragmentManager = null
60
+ }
61
+
62
+ internal fun setupFragmentManger() {
63
+ fragmentManager =
64
+ checkNotNull(FragmentManagerHelper.findFragmentManagerForView(this)) {
65
+ "[RNScreens] Nullish fragment manager - can't run container operations"
66
+ }.also {
67
+ it.addOnBackStackChangedListener(this)
68
+ }
69
+ }
70
+
47
71
  /**
48
72
  * Call this function to trigger container update
49
73
  */
@@ -52,9 +76,7 @@ internal class StackContainer(
52
76
  // the call because we don't have valid fragmentManager yet.
53
77
  // Update will be eventually executed in onAttachedToWindow().
54
78
  if (hasPendingOperations && isAttachedToWindow) {
55
- val fragmentManager =
56
- checkNotNull(fragmentManager) { "[RNScreens] Fragment manager was null during stack container update" }
57
- performOperations(fragmentManager)
79
+ performOperations(requireFragmentManager())
58
80
  }
59
81
  }
60
82
 
@@ -67,59 +89,107 @@ internal class StackContainer(
67
89
  }
68
90
 
69
91
  private fun performOperations(fragmentManager: FragmentManager) {
70
- pendingPopOperations.forEach { performPopOperation(fragmentManager, it) }
71
- pendingPushOperations.forEach { performPushOperation(fragmentManager, it) }
92
+ val fragmentOps = applyOperationsAndComputeFragmentManagerOperations()
93
+ fragmentOpExecutor.executeOperations(fragmentManager, fragmentOps, flushSync = false)
72
94
 
73
- pendingPopOperations.clear()
74
- pendingPushOperations.clear()
95
+ dumpStackModel()
75
96
  }
76
97
 
77
- private fun performPushOperation(
78
- fragmentManager: FragmentManager,
79
- operation: PushOperation,
80
- ) {
81
- val transaction = fragmentManager.createTransactionWithReordering()
98
+ private fun applyOperationsAndComputeFragmentManagerOperations(): List<FragmentOperation> {
99
+ val fragmentOps = mutableListOf<FragmentOperation>()
82
100
 
83
- val associatedFragment = StackScreenFragment(WeakReference(this), operation.screen)
84
- stackScreenFragments.add(associatedFragment)
101
+ // Handle pop operations first.
102
+ // We don't care about pop/push duplicates, as long as we don't let the main loop progress
103
+ // before we commit all the transactions, FragmentManager will handle that for us.
85
104
 
86
- transaction.add(this.id, associatedFragment)
105
+ pendingPopOperations.forEach { operation ->
106
+ val fragment =
107
+ checkNotNull(stackModel.find { it.stackScreen === operation.screen }) {
108
+ "[RNScreens] Unable to find a fragment to pop"
109
+ }
87
110
 
88
- // Don't add root screen to back stack to handle exiting from app.
89
- if (fragmentManager.fragments.isNotEmpty()) {
90
- transaction.addToBackStack(operation.screen.screenKey)
91
- }
111
+ check(stackModel.size > 1) {
112
+ "[RNScreens] Attempt to pop last screen from the stack"
113
+ }
92
114
 
93
- transaction.commitAllowingStateLoss()
94
- }
115
+ fragmentOps.add(PopBackStackOp(fragment))
95
116
 
96
- private fun performPopOperation(
97
- fragmentManager: FragmentManager,
98
- operation: PopOperation,
99
- ) {
100
- val associatedFragment = stackScreenFragments.find { it.stackScreen === operation.screen }
101
- require(associatedFragment != null) {
102
- "[RNScreens] Unable to find a fragment to pop."
117
+ check(stackModel.removeAt(stackModel.lastIndex) === fragment) {
118
+ "[RNScreens] Attempt to pop non-top screen"
119
+ }
103
120
  }
104
121
 
105
- val backStackEntryCount = fragmentManager.backStackEntryCount
106
- if (backStackEntryCount > 0) {
107
- fragmentManager.popBackStack(
108
- operation.screen.screenKey,
109
- FragmentManager.POP_BACK_STACK_INCLUSIVE,
122
+ pendingPushOperations.forEach { operation ->
123
+ val newFragment = createFragmentForScreen(operation.screen)
124
+ fragmentOps.add(
125
+ AddOp(
126
+ newFragment,
127
+ containerViewId = this.id,
128
+ addToBackStack = stackModel.isNotEmpty(),
129
+ ),
110
130
  )
111
- } else {
112
- // When fast refresh is used on root screen, we need to remove the screen manually.
113
- val transaction = fragmentManager.createTransactionWithReordering()
114
- transaction.remove(associatedFragment)
115
- transaction.commitNowAllowingStateLoss()
131
+ stackModel.add(newFragment)
116
132
  }
117
133
 
118
- stackScreenFragments.remove(associatedFragment)
134
+ check(stackModel.isNotEmpty()) { "[RNScreens] Stack should never be empty after updates" }
135
+
136
+ // Top fragment is the primary navigation fragment.
137
+ fragmentOps.add(SetPrimaryNavFragmentOp(stackModel.last()))
138
+
139
+ pendingPopOperations.clear()
140
+ pendingPushOperations.clear()
141
+
142
+ return fragmentOps
143
+ }
144
+
145
+ private fun onNativeFragmentPop(fragment: StackScreenFragment) {
146
+ Log.d(TAG, "StackContainer [$id] natively removed fragment ${fragment.stackScreen.screenKey}")
147
+ require(stackModel.remove(fragment)) { "[RNScreens] onNativeFragmentPop must be called with the fragment present in stack model" }
148
+ check(stackModel.isNotEmpty()) { "[RNScreens] Stack model should not be empty after a native pop" }
149
+
150
+ val fragmentManager = requireFragmentManager()
151
+ if (fragmentManager.primaryNavigationFragment === fragment) {
152
+ // We need to update the primary navigation fragment, otherwise the fragment manager
153
+ // will have invalid state, pointing to the dismissed fragment.
154
+ fragmentOpExecutor.executeOperations(
155
+ fragmentManager,
156
+ listOf(SetPrimaryNavFragmentOp(stackModel.last())),
157
+ )
158
+ }
119
159
  }
120
160
 
121
- internal fun onFragmentDestroyView(fragment: StackScreenFragment) {
122
- delegate.get()?.onScreenDismiss(fragment.stackScreen)
161
+ private fun dumpStackModel() {
162
+ Log.d(TAG, "StackContainer [$id] MODEL BEGIN")
163
+ stackModel.forEach {
164
+ Log.d(TAG, "${it.stackScreen.screenKey}")
165
+ }
166
+ }
167
+
168
+ private fun createFragmentForScreen(screen: StackScreen): StackScreenFragment =
169
+ StackScreenFragment(screen).also {
170
+ Log.d(TAG, "Created Fragment $it for screen ${screen.screenKey}")
171
+ }
172
+
173
+ // This is called after special effects (animations) are dispatched
174
+ override fun onBackStackChanged() = Unit
175
+
176
+ // This is called before the special effects (animations) are dispatched, however mid transaction!
177
+ // Therefore make sure to not execute any action that might cause synchronous transaction synchronously
178
+ // from this callback.
179
+ override fun onBackStackChangeCommitted(
180
+ fragment: Fragment,
181
+ pop: Boolean,
182
+ ) {
183
+ if (fragment !is StackScreenFragment) {
184
+ Log.w(TAG, "[RNScreens] Unexpected type of fragment: ${fragment.javaClass.simpleName}")
185
+ return
186
+ }
187
+ if (pop) {
188
+ delegate.get()?.onScreenDismiss(fragment.stackScreen)
189
+ if (stackModel.contains(fragment)) {
190
+ onNativeFragmentPop(fragment)
191
+ }
192
+ }
123
193
  }
124
194
 
125
195
  companion object {
@@ -1,6 +1,7 @@
1
1
  package com.swmansion.rnscreens.gamma.stack.host
2
2
 
3
3
  import android.annotation.SuppressLint
4
+ import android.util.Log
4
5
  import android.view.ViewGroup
5
6
  import com.facebook.react.bridge.UIManager
6
7
  import com.facebook.react.bridge.UIManagerListener
@@ -75,6 +76,8 @@ class StackHost(
75
76
  if (stackScreen.activityMode == StackScreen.ActivityMode.ATTACHED && !stackScreen.isNativelyDismissed) {
76
77
  // This shouldn't happen in typical scenarios but it can happen with fast-refresh.
77
78
  containerUpdateCoordinator.addPopOperation(stackScreen)
79
+ } else {
80
+ Log.d(TAG, "Ignoring pop operation of ${stackScreen.screenKey}, already not attached or natively dismissed")
78
81
  }
79
82
  }
80
83
 
@@ -85,7 +88,11 @@ class StackHost(
85
88
  }
86
89
  }
87
90
 
88
- override fun onScreenDismiss(stackScreen: StackScreen) = Unit
91
+ override fun onScreenDismiss(stackScreen: StackScreen) {
92
+ if (stackScreen.activityMode == StackScreen.ActivityMode.ATTACHED) {
93
+ stackScreen.isNativelyDismissed = true
94
+ }
95
+ }
89
96
 
90
97
  override fun onMeasure(
91
98
  widthMeasureSpec: Int,
@@ -2,8 +2,11 @@ package com.swmansion.rnscreens.gamma.stack.screen
2
2
 
3
3
  import android.annotation.SuppressLint
4
4
  import android.view.ViewGroup
5
+ import androidx.fragment.app.Fragment
5
6
  import androidx.lifecycle.LifecycleOwner
6
7
  import com.facebook.react.uimanager.ThemedReactContext
8
+ import com.swmansion.rnscreens.ext.findFragmentOrNull
9
+ import com.swmansion.rnscreens.gamma.common.FragmentProviding
7
10
  import com.swmansion.rnscreens.gamma.stack.host.StackHost
8
11
  import java.lang.ref.WeakReference
9
12
  import kotlin.properties.Delegates
@@ -11,7 +14,7 @@ import kotlin.properties.Delegates
11
14
  @SuppressLint("ViewConstructor") // should never be restored
12
15
  class StackScreen(
13
16
  private val reactContext: ThemedReactContext,
14
- ) : ViewGroup(reactContext) {
17
+ ) : ViewGroup(reactContext), FragmentProviding {
15
18
  enum class ActivityMode {
16
19
  DETACHED,
17
20
  ATTACHED,
@@ -65,4 +68,8 @@ class StackScreen(
65
68
  r: Int,
66
69
  b: Int,
67
70
  ) = Unit
71
+
72
+ override fun getAssociatedFragment(): Fragment? = this.findFragmentOrNull()?.also {
73
+ check(it is StackScreenFragment) { "[RNScreens] Unexpected fragment type: ${it.javaClass.simpleName}"}
74
+ }
68
75
  }
@@ -1,15 +1,13 @@
1
1
  package com.swmansion.rnscreens.gamma.stack.screen
2
2
 
3
3
  import android.os.Bundle
4
+ import android.util.Log
4
5
  import android.view.LayoutInflater
5
6
  import android.view.View
6
7
  import android.view.ViewGroup
7
8
  import androidx.fragment.app.Fragment
8
- import com.swmansion.rnscreens.gamma.stack.host.StackContainer
9
- import java.lang.ref.WeakReference
10
9
 
11
10
  internal class StackScreenFragment(
12
- private val stackContainer: WeakReference<StackContainer>,
13
11
  internal val stackScreen: StackScreen,
14
12
  ) : Fragment() {
15
13
  private var screenLifecycleEventEmitter: StackScreenAppearanceEventsEmitter? = null
@@ -30,8 +28,12 @@ internal class StackScreenFragment(
30
28
 
31
29
  override fun onDestroyView() {
32
30
  super.onDestroyView()
33
- stackScreen.onDismiss()
34
- stackContainer.get()?.onFragmentDestroyView(this)
35
31
  screenLifecycleEventEmitter = null
36
32
  }
33
+
34
+ override fun onDestroy() {
35
+ super.onDestroy()
36
+ Log.i("StackScreenFragment", "onDestroy")
37
+ stackScreen.onDismiss()
38
+ }
37
39
  }
@@ -382,8 +382,9 @@ class TabsHost(
382
382
  private fun updateSelectedTab() {
383
383
  val newFocusedTab = currentFocusedTab
384
384
 
385
- check(requireFragmentManager.fragments.size <= 1) { "[RNScreens] There can be only a single focused tab" }
386
- val oldFocusedTab = requireFragmentManager.fragments.firstOrNull()
385
+ val tabFragments = requireFragmentManager.fragments.filterIsInstance<TabScreenFragment>()
386
+ check(tabFragments.size <= 1) { "[RNScreens] There can be only a single focused tab" }
387
+ val oldFocusedTab = tabFragments.firstOrNull()
387
388
 
388
389
  if (newFocusedTab === oldFocusedTab) {
389
390
  return
package/ios/RNSScreen.mm CHANGED
@@ -2097,6 +2097,9 @@ Class<RCTComponentViewProtocol> RNSScreenCls(void)
2097
2097
  if ([vc isKindOfClass:[RNSScreen class]]) {
2098
2098
  return ((RNSScreen *)vc).screenView.screenOrientation;
2099
2099
  }
2100
+ if ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPad) {
2101
+ return UIInterfaceOrientationMaskAll;
2102
+ }
2100
2103
  return UIInterfaceOrientationMaskAllButUpsideDown;
2101
2104
  }
2102
2105
 
@@ -1 +1 @@
1
- {"version":3,"file":"prepareHeaderBarButtonItems.d.ts","sourceRoot":"","sources":["../../../../src/components/helpers/prepareHeaderBarButtonItems.ts"],"names":[],"mappings":"AACA,OAAO,EACL,mBAAmB,EAEpB,MAAM,4BAA4B,CAAC;AAkCpC,eAAO,MAAM,2BAA2B,GACtC,gBAAgB,mBAAmB,EAAE,EACrC,MAAM,MAAM,GAAG,OAAO;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;aAoD47yC,CAAC;;uBAAwG,CAAC;wBAA+B,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;WAD7lzC,CAAC"}
1
+ {"version":3,"file":"prepareHeaderBarButtonItems.d.ts","sourceRoot":"","sources":["../../../../src/components/helpers/prepareHeaderBarButtonItems.ts"],"names":[],"mappings":"AACA,OAAO,EACL,mBAAmB,EAEpB,MAAM,4BAA4B,CAAC;AAkCpC,eAAO,MAAM,2BAA2B,GACtC,gBAAgB,mBAAmB,EAAE,EACrC,MAAM,MAAM,GAAG,OAAO;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;aAoD89yC,CAAC;;uBAAwG,CAAC;wBAA+B,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;WAD/nzC,CAAC"}
@@ -287,7 +287,7 @@ export interface ScreenProps extends ViewProps {
287
287
  /**
288
288
  * In which orientation should the screen appear.
289
289
  * The following values are currently supported:
290
- * - "default" - resolves to "all" without "portrait_down" on iOS. On Android, this lets the system decide the best orientation.
290
+ * - "default" - resolves to "all" without "portrait_down" on iPhone devices, "all" on iPad devices. On Android, this lets the system decide the best orientation.
291
291
  * - "all" – all orientations are permitted
292
292
  * - "portrait" – portrait orientations are permitted
293
293
  * - "portrait_up" – right-side portrait orientation is permitted
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "react-native-screens",
3
- "version": "4.21.0",
3
+ "version": "4.22.0",
4
4
  "description": "Native navigation primitives for your React Native app.",
5
5
  "scripts": {
6
6
  "submodules": "git submodule update --init --recursive && (cd react-navigation && yarn && yarn build && cd ../)",
package/src/types.tsx CHANGED
@@ -378,7 +378,7 @@ export interface ScreenProps extends ViewProps {
378
378
  /**
379
379
  * In which orientation should the screen appear.
380
380
  * The following values are currently supported:
381
- * - "default" - resolves to "all" without "portrait_down" on iOS. On Android, this lets the system decide the best orientation.
381
+ * - "default" - resolves to "all" without "portrait_down" on iPhone devices, "all" on iPad devices. On Android, this lets the system decide the best orientation.
382
382
  * - "all" – all orientations are permitted
383
383
  * - "portrait" – portrait orientations are permitted
384
384
  * - "portrait_up" – right-side portrait orientation is permitted