react-native-screens 3.31.0 → 3.32.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 (119) hide show
  1. package/README.md +6 -0
  2. package/RNScreens.podspec +1 -0
  3. package/android/build.gradle +83 -4
  4. package/android/src/main/cpp/jni-adapter.cpp +86 -93
  5. package/android/src/main/java/com/swmansion/rnscreens/CustomSearchView.kt +2 -0
  6. package/android/src/main/java/com/swmansion/rnscreens/CustomToolbar.kt +2 -0
  7. package/android/src/main/java/com/swmansion/rnscreens/Screen.kt +17 -3
  8. package/android/src/main/java/com/swmansion/rnscreens/ScreenContainerViewManager.kt +14 -1
  9. package/android/src/main/java/com/swmansion/rnscreens/ScreenStackFragment.kt +3 -2
  10. package/android/src/main/java/com/swmansion/rnscreens/ScreenStackHeaderConfig.kt +6 -2
  11. package/android/src/main/java/com/swmansion/rnscreens/ScreenStackHeaderConfigViewManager.kt +4 -0
  12. package/android/src/main/java/com/swmansion/rnscreens/ScreenViewManager.kt +5 -0
  13. package/android/src/main/java/com/swmansion/rnscreens/ScreenWindowTraits.kt +19 -2
  14. package/android/src/main/java/com/swmansion/rnscreens/ScreensModule.kt +1 -1
  15. package/android/src/main/java/com/swmansion/rnscreens/SearchBarManager.kt +82 -27
  16. package/android/src/main/java/com/swmansion/rnscreens/events/HeaderHeightChangeEvent.kt +0 -1
  17. package/android/src/main/java/com/swmansion/rnscreens/events/SearchBarBlurEvent.kt +1 -1
  18. package/android/src/main/java/com/swmansion/rnscreens/events/SearchBarFocusEvent.kt +1 -1
  19. package/android/src/paper/java/com/facebook/react/viewmanagers/RNSScreenContainerManagerDelegate.java +25 -0
  20. package/android/src/paper/java/com/facebook/react/viewmanagers/RNSScreenContainerManagerInterface.java +16 -0
  21. package/android/src/paper/java/com/facebook/react/viewmanagers/RNSScreenManagerDelegate.java +3 -0
  22. package/android/src/paper/java/com/facebook/react/viewmanagers/RNSScreenManagerInterface.java +1 -0
  23. package/android/src/paper/java/com/facebook/react/viewmanagers/RNSScreenStackHeaderConfigManagerDelegate.java +3 -0
  24. package/android/src/paper/java/com/facebook/react/viewmanagers/RNSScreenStackHeaderConfigManagerInterface.java +1 -0
  25. package/android/src/paper/java/com/facebook/react/viewmanagers/RNSSearchBarManagerDelegate.java +99 -0
  26. package/android/src/paper/java/com/facebook/react/viewmanagers/RNSSearchBarManagerInterface.java +37 -0
  27. package/common/cpp/react/renderer/components/rnscreens/RNSModalScreenComponentDescriptor.h +8 -9
  28. package/common/cpp/react/renderer/components/rnscreens/RNSModalScreenShadowNode.h +8 -7
  29. package/common/cpp/react/renderer/components/rnscreens/RNSScreenComponentDescriptor.h +7 -9
  30. package/common/cpp/react/renderer/components/rnscreens/RNSScreenShadowNode.h +6 -6
  31. package/common/cpp/react/renderer/components/rnscreens/RNSScreenState.cpp +2 -1
  32. package/common/cpp/react/renderer/components/rnscreens/RNSScreenState.h +8 -10
  33. package/cpp/RNScreensTurboModule.cpp +31 -23
  34. package/cpp/RNScreensTurboModule.h +17 -20
  35. package/ios/RNSConvert.h +6 -0
  36. package/ios/RNSConvert.mm +24 -0
  37. package/ios/RNSModule.mm +1 -2
  38. package/ios/RNSScreen.mm +8 -0
  39. package/ios/RNSScreenContainer.mm +1 -1
  40. package/ios/RNSScreenStack.mm +71 -13
  41. package/ios/RNSScreenStackHeaderConfig.h +2 -0
  42. package/ios/RNSScreenStackHeaderConfig.mm +44 -17
  43. package/ios/RNSSearchBar.h +5 -5
  44. package/ios/RNSSearchBar.mm +11 -11
  45. package/ios/utils/RCTSurfaceTouchHandler+RNSUtility.h +15 -0
  46. package/ios/utils/RCTSurfaceTouchHandler+RNSUtility.mm +14 -0
  47. package/ios/utils/RCTTouchHandler+RNSUtility.h +15 -0
  48. package/ios/utils/RCTTouchHandler+RNSUtility.mm +15 -0
  49. package/lib/commonjs/components/Screen.js +119 -127
  50. package/lib/commonjs/components/Screen.js.map +1 -1
  51. package/lib/commonjs/components/SearchBar.js +39 -36
  52. package/lib/commonjs/components/SearchBar.js.map +1 -1
  53. package/lib/commonjs/fabric/ModalScreenNativeComponent.js.map +1 -1
  54. package/lib/commonjs/fabric/ScreenNativeComponent.js.map +1 -1
  55. package/lib/commonjs/fabric/ScreenStackHeaderConfigNativeComponent.js.map +1 -1
  56. package/lib/commonjs/native-stack/views/HeaderConfig.js +2 -0
  57. package/lib/commonjs/native-stack/views/HeaderConfig.js.map +1 -1
  58. package/lib/commonjs/native-stack/views/NativeStackView.js +2 -0
  59. package/lib/commonjs/native-stack/views/NativeStackView.js.map +1 -1
  60. package/lib/module/components/Screen.js +118 -126
  61. package/lib/module/components/Screen.js.map +1 -1
  62. package/lib/module/components/SearchBar.js +39 -36
  63. package/lib/module/components/SearchBar.js.map +1 -1
  64. package/lib/module/fabric/ModalScreenNativeComponent.js.map +1 -1
  65. package/lib/module/fabric/ScreenNativeComponent.js.map +1 -1
  66. package/lib/module/fabric/ScreenStackHeaderConfigNativeComponent.js.map +1 -1
  67. package/lib/module/native-stack/views/HeaderConfig.js +2 -0
  68. package/lib/module/native-stack/views/HeaderConfig.js.map +1 -1
  69. package/lib/module/native-stack/views/NativeStackView.js +2 -0
  70. package/lib/module/native-stack/views/NativeStackView.js.map +1 -1
  71. package/lib/typescript/TransitionProgressContext.d.ts +1 -1
  72. package/lib/typescript/TransitionProgressContext.d.ts.map +1 -1
  73. package/lib/typescript/components/Screen.d.ts +3 -14
  74. package/lib/typescript/components/Screen.d.ts.map +1 -1
  75. package/lib/typescript/components/SearchBar.d.ts +14 -21
  76. package/lib/typescript/components/SearchBar.d.ts.map +1 -1
  77. package/lib/typescript/fabric/ModalScreenNativeComponent.d.ts +11 -10
  78. package/lib/typescript/fabric/ModalScreenNativeComponent.d.ts.map +1 -1
  79. package/lib/typescript/fabric/ScreenNativeComponent.d.ts +11 -10
  80. package/lib/typescript/fabric/ScreenNativeComponent.d.ts.map +1 -1
  81. package/lib/typescript/fabric/ScreenStackHeaderConfigNativeComponent.d.ts +5 -3
  82. package/lib/typescript/fabric/ScreenStackHeaderConfigNativeComponent.d.ts.map +1 -1
  83. package/lib/typescript/fabric/ScreenStackHeaderSubviewNativeComponent.d.ts +1 -1
  84. package/lib/typescript/fabric/ScreenStackHeaderSubviewNativeComponent.d.ts.map +1 -1
  85. package/lib/typescript/fabric/ScreenStackNativeComponent.d.ts +1 -1
  86. package/lib/typescript/fabric/ScreenStackNativeComponent.d.ts.map +1 -1
  87. package/lib/typescript/fabric/SearchBarNativeComponent.d.ts +9 -9
  88. package/lib/typescript/fabric/SearchBarNativeComponent.d.ts.map +1 -1
  89. package/lib/typescript/gesture-handler/RNScreensTurboModule.d.ts +1 -1
  90. package/lib/typescript/gesture-handler/RNScreensTurboModule.d.ts.map +1 -1
  91. package/lib/typescript/native-stack/types.d.ts +29 -14
  92. package/lib/typescript/native-stack/types.d.ts.map +1 -1
  93. package/lib/typescript/native-stack/utils/SafeAreaProviderCompat.d.ts +1 -1
  94. package/lib/typescript/native-stack/utils/SafeAreaProviderCompat.d.ts.map +1 -1
  95. package/lib/typescript/native-stack/utils/getDefaultHeaderHeight.d.ts +1 -1
  96. package/lib/typescript/native-stack/utils/getDefaultHeaderHeight.d.ts.map +1 -1
  97. package/lib/typescript/native-stack/utils/useAnimatedHeaderHeight.d.ts +1 -1
  98. package/lib/typescript/native-stack/utils/useAnimatedHeaderHeight.d.ts.map +1 -1
  99. package/lib/typescript/native-stack/views/HeaderConfig.d.ts +2 -2
  100. package/lib/typescript/native-stack/views/HeaderConfig.d.ts.map +1 -1
  101. package/lib/typescript/native-stack/views/NativeStackView.d.ts +1 -1
  102. package/lib/typescript/native-stack/views/NativeStackView.d.ts.map +1 -1
  103. package/lib/typescript/reanimated/ReanimatedTransitionProgressContext.d.ts +1 -1
  104. package/lib/typescript/reanimated/ReanimatedTransitionProgressContext.d.ts.map +1 -1
  105. package/lib/typescript/types.d.ts +29 -13
  106. package/lib/typescript/types.d.ts.map +1 -1
  107. package/lib/typescript/useTransitionProgress.d.ts +3 -3
  108. package/native-stack/README.md +7 -0
  109. package/package.json +13 -7
  110. package/src/components/Screen.tsx +27 -33
  111. package/src/components/SearchBar.tsx +77 -65
  112. package/src/fabric/ModalScreenNativeComponent.ts +1 -0
  113. package/src/fabric/ScreenNativeComponent.ts +1 -0
  114. package/src/fabric/ScreenStackHeaderConfigNativeComponent.ts +3 -0
  115. package/src/fabric/SearchBarNativeComponent.ts +6 -6
  116. package/src/native-stack/types.tsx +15 -0
  117. package/src/native-stack/views/HeaderConfig.tsx +2 -0
  118. package/src/native-stack/views/NativeStackView.tsx +2 -0
  119. package/src/types.tsx +16 -0
@@ -12,49 +12,54 @@ std::function<void(int, bool)> RNScreensTurboModule::finishTransition_;
12
12
  std::function<void(int)> RNScreensTurboModule::disableSwipeBackForTopScreen_;
13
13
 
14
14
  RNScreensTurboModule::RNScreensTurboModule(
15
- std::function<std::array<int, 2>(int)> startTransition,
16
- std::function<void(int, double)> updateTransition,
17
- std::function<void(int, bool)> finishTransition,
18
- std::function<void(int)> disableSwipeBackForTopScreen
19
- ) {
15
+ std::function<std::array<int, 2>(int)> startTransition,
16
+ std::function<void(int, double)> updateTransition,
17
+ std::function<void(int, bool)> finishTransition,
18
+ std::function<void(int)> disableSwipeBackForTopScreen) {
20
19
  startTransition_ = startTransition;
21
20
  updateTransition_ = updateTransition;
22
21
  finishTransition_ = finishTransition;
23
22
  disableSwipeBackForTopScreen_ = disableSwipeBackForTopScreen;
24
23
  }
25
24
 
26
- RNScreensTurboModule::~RNScreensTurboModule() {};
25
+ RNScreensTurboModule::~RNScreensTurboModule(){};
27
26
 
28
- jsi::Value RNScreensTurboModule::get(jsi::Runtime& rt, const jsi::PropNameID& name) {
27
+ jsi::Value RNScreensTurboModule::get(
28
+ jsi::Runtime &rt,
29
+ const jsi::PropNameID &name) {
29
30
  if (name.utf8(rt) == "startTransition") {
30
31
  return jsi::Function::createFromHostFunction(rt, name, 1, startTransition);
31
- }
32
- else if (name.utf8(rt) == "updateTransition") {
32
+ } else if (name.utf8(rt) == "updateTransition") {
33
33
  return jsi::Function::createFromHostFunction(rt, name, 2, updateTransition);
34
- }
35
- else if (name.utf8(rt) == "finishTransition") {
34
+ } else if (name.utf8(rt) == "finishTransition") {
36
35
  return jsi::Function::createFromHostFunction(rt, name, 2, finishTransition);
37
- }
38
- else if (name.utf8(rt) == "disableSwipeBackForTopScreen") {
39
- return jsi::Function::createFromHostFunction(rt, name, 1, disableSwipeBackForTopScreen);
36
+ } else if (name.utf8(rt) == "disableSwipeBackForTopScreen") {
37
+ return jsi::Function::createFromHostFunction(
38
+ rt, name, 1, disableSwipeBackForTopScreen);
40
39
  }
41
40
  return jsi::Value::undefined();
42
41
  }
43
42
 
44
- void RNScreensTurboModule::set(jsi::Runtime&, const jsi::PropNameID&, const jsi::Value&) {};
43
+ void RNScreensTurboModule::set(
44
+ jsi::Runtime &,
45
+ const jsi::PropNameID &,
46
+ const jsi::Value &){};
45
47
 
46
- std::vector<jsi::PropNameID> RNScreensTurboModule::getPropertyNames(jsi::Runtime& rt) {
48
+ std::vector<jsi::PropNameID> RNScreensTurboModule::getPropertyNames(
49
+ jsi::Runtime &rt) {
47
50
  std::vector<jsi::PropNameID> properties;
48
51
  properties.push_back(jsi::PropNameID::forUtf8(rt, "startTransition"));
49
52
  properties.push_back(jsi::PropNameID::forUtf8(rt, "updateTransition"));
50
53
  properties.push_back(jsi::PropNameID::forUtf8(rt, "finishTransition"));
51
- properties.push_back(jsi::PropNameID::forUtf8(rt, "disableSwipeBackForTopScreen"));
54
+ properties.push_back(
55
+ jsi::PropNameID::forUtf8(rt, "disableSwipeBackForTopScreen"));
52
56
  return properties;
53
57
  }
54
58
 
55
59
  JSI_HOST_FUNCTION(RNScreensTurboModule::startTransition) {
56
60
  if (count < 1) {
57
- throw jsi::JSError(rt, "[RNScreens] `startTransition` method requires 1 argument.");
61
+ throw jsi::JSError(
62
+ rt, "[RNScreens] `startTransition` method requires 1 argument.");
58
63
  }
59
64
  int stackTag = arguments[0].asNumber();
60
65
  auto screenTags = startTransition_(stackTag);
@@ -77,7 +82,8 @@ JSI_HOST_FUNCTION(RNScreensTurboModule::startTransition) {
77
82
 
78
83
  JSI_HOST_FUNCTION(RNScreensTurboModule::updateTransition) {
79
84
  if (count < 2) {
80
- throw jsi::JSError(rt, "[RNScreens] `updateTransition` requires 2 arguments.");
85
+ throw jsi::JSError(
86
+ rt, "[RNScreens] `updateTransition` requires 2 arguments.");
81
87
  }
82
88
  int stackTag = arguments[0].asNumber();
83
89
  double progress = arguments[1].asNumber();
@@ -87,7 +93,8 @@ JSI_HOST_FUNCTION(RNScreensTurboModule::updateTransition) {
87
93
 
88
94
  JSI_HOST_FUNCTION(RNScreensTurboModule::finishTransition) {
89
95
  if (count < 2) {
90
- throw jsi::JSError(rt, "[RNScreens] `finishTransition` requires 2 arguments.");
96
+ throw jsi::JSError(
97
+ rt, "[RNScreens] `finishTransition` requires 2 arguments.");
91
98
  }
92
99
  int stackTag = arguments[0].asNumber();
93
100
  bool canceled = arguments[1].getBool();
@@ -96,12 +103,13 @@ JSI_HOST_FUNCTION(RNScreensTurboModule::finishTransition) {
96
103
  }
97
104
 
98
105
  JSI_HOST_FUNCTION(RNScreensTurboModule::disableSwipeBackForTopScreen) {
99
- if (count < 1) {
100
- throw jsi::JSError(rt, "[RNScreens] `startTransition` method requires 1 argument.");
106
+ if (count < 1) {
107
+ throw jsi::JSError(
108
+ rt, "[RNScreens] `startTransition` method requires 1 argument.");
101
109
  }
102
110
  int stackTag = arguments[0].asNumber();
103
111
  disableSwipeBackForTopScreen_(stackTag);
104
112
  return jsi::Value::undefined();
105
113
  }
106
114
 
107
- }
115
+ } // namespace RNScreens
@@ -1,43 +1,40 @@
1
- #include <array>
2
1
  #include <jsi/jsi.h>
2
+ #include <array>
3
3
 
4
- #define JSI_HOST_FUNCTION(NAME) \
5
- jsi::Value NAME( \
6
- jsi::Runtime &rt, \
7
- const jsi::Value &thisValue, \
8
- const jsi::Value *arguments, \
9
- size_t count \
10
- )
4
+ #define JSI_HOST_FUNCTION(NAME) \
5
+ jsi::Value NAME( \
6
+ jsi::Runtime &rt, \
7
+ const jsi::Value &thisValue, \
8
+ const jsi::Value *arguments, \
9
+ size_t count)
11
10
 
12
11
  using namespace facebook;
13
12
 
14
13
  namespace RNScreens {
15
14
 
16
15
  class RNScreensTurboModule : public jsi::HostObject {
17
-
18
16
  static std::function<std::array<int, 2>(int)> startTransition_;
19
17
  static std::function<void(int, double)> updateTransition_;
20
18
  static std::function<void(int, bool)> finishTransition_;
21
19
  static std::function<void(int)> disableSwipeBackForTopScreen_;
22
20
 
23
- public:
21
+ public:
24
22
  static const char MODULE_NAME[];
25
23
 
26
24
  RNScreensTurboModule(
27
- std::function<std::array<int, 2>(int)> startTransition,
28
- std::function<void(int, double)> updateTransition,
29
- std::function<void(int, bool)> finishTransition,
30
- std::function<void(int)> disableSwipeBackForTopScreen
31
- );
25
+ std::function<std::array<int, 2>(int)> startTransition,
26
+ std::function<void(int, double)> updateTransition,
27
+ std::function<void(int, bool)> finishTransition,
28
+ std::function<void(int)> disableSwipeBackForTopScreen);
32
29
  ~RNScreensTurboModule() override;
33
- jsi::Value get(jsi::Runtime& rt, const jsi::PropNameID& name) override;
34
- void set(jsi::Runtime&, const jsi::PropNameID&, const jsi::Value&) override;
35
- std::vector<jsi::PropNameID> getPropertyNames(jsi::Runtime& rt) override;
30
+ jsi::Value get(jsi::Runtime &rt, const jsi::PropNameID &name) override;
31
+ void set(jsi::Runtime &, const jsi::PropNameID &, const jsi::Value &)
32
+ override;
33
+ std::vector<jsi::PropNameID> getPropertyNames(jsi::Runtime &rt) override;
36
34
  static JSI_HOST_FUNCTION(startTransition);
37
35
  static JSI_HOST_FUNCTION(updateTransition);
38
36
  static JSI_HOST_FUNCTION(finishTransition);
39
37
  static JSI_HOST_FUNCTION(disableSwipeBackForTopScreen);
40
-
41
38
  };
42
39
 
43
- }
40
+ } // namespace RNScreens
package/ios/RNSConvert.h CHANGED
@@ -6,6 +6,12 @@ namespace react = facebook::react;
6
6
 
7
7
  @interface RNSConvert : NSObject
8
8
 
9
+ + (UISemanticContentAttribute)UISemanticContentAttributeFromCppEquivalent:
10
+ (react::RNSScreenStackHeaderConfigDirection)direction;
11
+
12
+ + (UINavigationItemBackButtonDisplayMode)UINavigationItemBackButtonDisplayModeFromCppEquivalent:
13
+ (react::RNSScreenStackHeaderConfigBackButtonDisplayMode)backButtonDisplayMode;
14
+
9
15
  + (RNSScreenStackPresentation)RNSScreenStackPresentationFromCppEquivalent:
10
16
  (react::RNSScreenStackPresentation)stackPresentation;
11
17
 
package/ios/RNSConvert.mm CHANGED
@@ -3,6 +3,30 @@
3
3
  #ifdef RCT_NEW_ARCH_ENABLED
4
4
  @implementation RNSConvert
5
5
 
6
+ + (UISemanticContentAttribute)UISemanticContentAttributeFromCppEquivalent:
7
+ (react::RNSScreenStackHeaderConfigDirection)direction
8
+ {
9
+ switch (direction) {
10
+ case react::RNSScreenStackHeaderConfigDirection::Rtl:
11
+ return UISemanticContentAttributeForceRightToLeft;
12
+ case react::RNSScreenStackHeaderConfigDirection::Ltr:
13
+ return UISemanticContentAttributeForceLeftToRight;
14
+ }
15
+ }
16
+
17
+ + (UINavigationItemBackButtonDisplayMode)UINavigationItemBackButtonDisplayModeFromCppEquivalent:
18
+ (react::RNSScreenStackHeaderConfigBackButtonDisplayMode)backButtonDisplayMode
19
+ {
20
+ switch (backButtonDisplayMode) {
21
+ case react::RNSScreenStackHeaderConfigBackButtonDisplayMode::Default:
22
+ return UINavigationItemBackButtonDisplayModeDefault;
23
+ case react::RNSScreenStackHeaderConfigBackButtonDisplayMode::Generic:
24
+ return UINavigationItemBackButtonDisplayModeGeneric;
25
+ case react::RNSScreenStackHeaderConfigBackButtonDisplayMode::Minimal:
26
+ return UINavigationItemBackButtonDisplayModeMinimal;
27
+ }
28
+ }
29
+
6
30
  + (RNSScreenStackPresentation)RNSScreenStackPresentationFromCppEquivalent:
7
31
  (react::RNSScreenStackPresentation)stackPresentation
8
32
  {
package/ios/RNSModule.mm CHANGED
@@ -138,8 +138,7 @@ RCT_EXPORT_MODULE()
138
138
  because depending on the selected architecture, only one method will be called.
139
139
  For `Paper`, it will be constantsToExport, and for `Fabric`, it will be getTurboModule.
140
140
  */
141
- RCTBridge *bridge = [RCTBridge currentBridge];
142
- RCTCxxBridge *cxxBridge = (RCTCxxBridge *)bridge;
141
+ RCTCxxBridge *cxxBridge = (RCTCxxBridge *)self.bridge;
143
142
  if (cxxBridge != nil) {
144
143
  auto jsiRuntime = (jsi::Runtime *)cxxBridge.runtime;
145
144
  if (jsiRuntime != nil) {
package/ios/RNSScreen.mm CHANGED
@@ -521,6 +521,14 @@ namespace react = facebook::react;
521
521
  #endif
522
522
  }
523
523
 
524
+ #if defined(__IPHONE_OS_VERSION_MAX_ALLOWED) && defined(__IPHONE_13_0) && \
525
+ __IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_13_0
526
+ - (void)presentationControllerDidAttemptToDismiss:(UIPresentationController *)presentationController
527
+ {
528
+ [self notifyGestureCancel];
529
+ }
530
+ #endif
531
+
524
532
  - (void)presentationControllerWillDismiss:(UIPresentationController *)presentationController
525
533
  {
526
534
  // We need to call both "cancel" and "reset" here because RN's gesture recognizer
@@ -60,7 +60,7 @@ namespace react = facebook::react;
60
60
 
61
61
  - (instancetype)init
62
62
  {
63
- if (self = [super init]) {
63
+ if (self = [super initWithFrame:CGRectZero]) {
64
64
  #ifdef RCT_NEW_ARCH_ENABLED
65
65
  static const auto defaultProps = std::make_shared<const react::RNSScreenContainerProps>();
66
66
  _props = defaultProps;
@@ -1,12 +1,15 @@
1
1
  #ifdef RCT_NEW_ARCH_ENABLED
2
2
  #import <React/RCTFabricComponentsPlugins.h>
3
+ #import <React/RCTFabricSurface.h>
3
4
  #import <React/RCTMountingTransactionObserving.h>
4
5
  #import <React/RCTSurfaceTouchHandler.h>
6
+ #import <React/RCTSurfaceView.h>
5
7
  #import <React/UIView+React.h>
6
8
  #import <react/renderer/components/rnscreens/ComponentDescriptors.h>
7
9
  #import <react/renderer/components/rnscreens/EventEmitters.h>
8
10
  #import <react/renderer/components/rnscreens/Props.h>
9
11
  #import <react/renderer/components/rnscreens/RCTComponentViewHelpers.h>
12
+ #import "RCTSurfaceTouchHandler+RNSUtility.h"
10
13
  #else
11
14
  #import <React/RCTBridge.h>
12
15
  #import <React/RCTRootContentView.h>
@@ -14,6 +17,7 @@
14
17
  #import <React/RCTTouchHandler.h>
15
18
  #import <React/RCTUIManager.h>
16
19
  #import <React/RCTUIManagerUtils.h>
20
+ #import "RCTTouchHandler+RNSUtility.h"
17
21
  #endif // RCT_NEW_ARCH_ENABLED
18
22
 
19
23
  #import "RNSScreen.h"
@@ -382,9 +386,12 @@ namespace react = facebook::react;
382
386
  [newControllers removeObjectsInArray:_presentedModals];
383
387
 
384
388
  // We need to find bottom-most view controller that should stay on the stack
385
- // for the duration of transition. There are couple of scenarios:
386
- // (1) No modals are presented or all modals were presented by this RNSNavigationController,
387
- // (2) There are modals presented by other RNSNavigationControllers (nested/outer)
389
+ // for the duration of transition.
390
+
391
+ // There are couple of scenarios:
392
+ // (1) no modals are presented or all modals were presented by this RNSNavigationController,
393
+ // (2) there are modals presented by other RNSNavigationControllers (nested/outer),
394
+ // (3) there are modals presented by other controllers (e.g. React Native's Modal view).
388
395
 
389
396
  // Last controller that is common for both _presentedModals & controllers
390
397
  __block UIViewController *changeRootController = _controller;
@@ -479,16 +486,35 @@ namespace react = facebook::react;
479
486
  }
480
487
  };
481
488
 
489
+ // changeRootController is the last controller that *is owned by this stack*, and should stay unchanged after this
490
+ // batch of transitions. Therefore changeRootController.presentedViewController is the first constroller to be
491
+ // dismissed (implying also all controllers above). Notice here, that firstModalToBeDismissed could have been
492
+ // RNSScreen modal presented from *this* stack, another stack, or any other view controller with modal presentation
493
+ // provided by third-party libraries (e.g. React Native's Modal view). In case of presence of other (not managed by
494
+ // us) modal controllers, weird interactions might arise. The code below, besides handling our presentation /
495
+ // dismissal logic also attempts to handle possible wide gamut of cases of interactions with third-party modal
496
+ // controllers, however it's not perfect.
497
+ // TODO: Find general way to manage owned and foreign modal view controllers and refactor this code. Consider building
498
+ // model first (data structue, attempting to be aware of all modals in presentation and some text-like algorithm for
499
+ // computing required operations).
500
+
482
501
  UIViewController *firstModalToBeDismissed = changeRootController.presentedViewController;
502
+
483
503
  if (firstModalToBeDismissed != nil) {
484
504
  BOOL shouldAnimate = changeRootIndex == controllers.count &&
485
505
  [firstModalToBeDismissed isKindOfClass:[RNSScreen class]] &&
486
506
  ((RNSScreen *)firstModalToBeDismissed).screenView.stackAnimation != RNSScreenStackAnimationNone;
487
507
 
488
- if ([_presentedModals containsObject:firstModalToBeDismissed]) {
508
+ if ([_presentedModals containsObject:firstModalToBeDismissed] ||
509
+ ![firstModalToBeDismissed isKindOfClass:RNSScreen.class]) {
489
510
  // We dismiss every VC that was presented by changeRootController VC or its descendant.
490
511
  // After the series of dismissals is completed we run completion block in which
491
512
  // we present modals on top of changeRootController (which may be the this stack VC)
513
+ //
514
+ // There also might the second case, where the firstModalToBeDismissed is foreign.
515
+ // See: https://github.com/software-mansion/react-native-screens/issues/2048
516
+ // For now, to mitigate the issue, we also decide to trigger its dismissal before
517
+ // starting the presentation chain down below in finish() callback.
492
518
  [changeRootController dismissViewControllerAnimated:shouldAnimate completion:finish];
493
519
  return;
494
520
  }
@@ -709,19 +735,43 @@ namespace react = facebook::react;
709
735
  // item is close to an edge and we start pulling from edge we want the Touchable to be cancelled.
710
736
  // Without the below code the Touchable will remain active (highlighted) for the duration of back
711
737
  // gesture and onPress may fire when we release the finger.
738
+ #ifdef RCT_NEW_ARCH_ENABLED
739
+ // On Fabric there is no view that exposes touchHandler above us in the view hierarchy, however it is still
740
+ // utilised. `RCTSurfaceView` should be present above us, which hosts `RCTFabricSurface` instance, which in turn
741
+ // hosts `RCTSurfaceTouchHandler` as a private field. When initialised, `RCTSurfaceTouchHandler` is attached to the
742
+ // surface view as a gestureRecognizer <- and this is where we can lay our hands on it.
712
743
  UIView *parent = _controller.view;
713
- while (parent != nil && ![parent respondsToSelector:@selector(touchHandler)])
744
+ while (parent != nil && ![parent isKindOfClass:RCTSurfaceView.class]) {
714
745
  parent = parent.superview;
715
- if (parent != nil) {
716
- #ifdef RCT_NEW_ARCH_ENABLED
717
- RCTSurfaceTouchHandler *touchHandler = [parent performSelector:@selector(touchHandler)];
746
+ }
747
+
748
+ // This could be possible in modal context
749
+ if (parent == nil) {
750
+ return;
751
+ }
752
+
753
+ RCTSurfaceTouchHandler *touchHandler = nil;
754
+ // Experimentation shows that RCTSurfaceTouchHandler is the only gestureRecognizer registered here,
755
+ // so we should not be afraid of any performance hit here.
756
+ for (UIGestureRecognizer *recognizer in parent.gestureRecognizers) {
757
+ if ([recognizer isKindOfClass:RCTSurfaceTouchHandler.class]) {
758
+ touchHandler = static_cast<RCTSurfaceTouchHandler *>(recognizer);
759
+ }
760
+ }
761
+
762
+ [touchHandler rnscreens_cancelTouches];
718
763
  #else
764
+ // On Paper we can access touchHandler hosted by `RCTRootContentView` which should be above ScreenStack
765
+ // in view hierarchy.
766
+ UIView *parent = _controller.view;
767
+ while (parent != nil && ![parent respondsToSelector:@selector(touchHandler)]) {
768
+ parent = parent.superview;
769
+ }
770
+ if (parent != nil) {
719
771
  RCTTouchHandler *touchHandler = [parent performSelector:@selector(touchHandler)];
720
- #endif
721
- [touchHandler setEnabled:NO];
722
- [touchHandler setEnabled:YES];
723
- [touchHandler reset];
772
+ [touchHandler rnscreens_cancelTouches];
724
773
  }
774
+ #endif // RCT_NEW_ARCH_ENABLED
725
775
  }
726
776
 
727
777
  - (BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer
@@ -901,6 +951,10 @@ namespace react = facebook::react;
901
951
  {
902
952
  [self emitOnFinishTransitioningEvent];
903
953
  [RNSScreenWindowTraits updateWindowTraits];
954
+ // Because of the bug that caused view to have incorrect dimensions while changing the orientation,
955
+ // we need to signalize that it needs to be layouted.
956
+ // see https://github.com/software-mansion/react-native-screens/pull/1970
957
+ [_controller.view setNeedsLayout];
904
958
  }
905
959
  #endif
906
960
 
@@ -1149,7 +1203,11 @@ namespace react = facebook::react;
1149
1203
 
1150
1204
  - (void)takeSnapshot
1151
1205
  {
1152
- _snapshot = [_controller.visibleViewController.view snapshotViewAfterScreenUpdates:NO];
1206
+ if (_presentedModals.count < 2) {
1207
+ _snapshot = [_controller.visibleViewController.view snapshotViewAfterScreenUpdates:NO];
1208
+ } else {
1209
+ _snapshot = [[_presentedModals.lastObject view] snapshotViewAfterScreenUpdates:NO];
1210
+ }
1153
1211
  }
1154
1212
 
1155
1213
  - (void)mountingTransactionWillMount:(react::MountingTransaction const &)transaction
@@ -55,6 +55,7 @@
55
55
  @property (nonatomic) BOOL translucent;
56
56
  @property (nonatomic) BOOL backButtonInCustomView;
57
57
  @property (nonatomic) UISemanticContentAttribute direction;
58
+ @property (nonatomic) UINavigationItemBackButtonDisplayMode backButtonDisplayMode;
58
59
 
59
60
  + (void)willShowViewController:(UIViewController *)vc
60
61
  animated:(BOOL)animated
@@ -70,5 +71,6 @@
70
71
 
71
72
  + (UIBlurEffectStyle)UIBlurEffectStyle:(id)json;
72
73
  + (UISemanticContentAttribute)UISemanticContentAttribute:(id)json;
74
+ + (UINavigationItemBackButtonDisplayMode)UINavigationItemBackButtonDisplayMode:(id)json;
73
75
 
74
76
  @end
@@ -19,6 +19,7 @@
19
19
  #import <React/RCTFont.h>
20
20
  #import <React/RCTImageLoader.h>
21
21
  #import <React/RCTImageSource.h>
22
+ #import "RNSConvert.h"
22
23
  #import "RNSScreen.h"
23
24
  #import "RNSScreenStackHeaderConfig.h"
24
25
  #import "RNSSearchBar.h"
@@ -511,8 +512,24 @@ namespace react = facebook::react;
511
512
  action:nil];
512
513
  [backBarButtonItem setMenuHidden:config.disableBackButtonMenu];
513
514
 
515
+ auto isBackButtonCustomized = !isBackTitleBlank || config.disableBackButtonMenu;
516
+
517
+ #if defined(__IPHONE_OS_VERSION_MAX_ALLOWED) && defined(__IPHONE_14_0) && \
518
+ __IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_14_0
519
+ if (@available(iOS 14.0, *)) {
520
+ prevItem.backButtonDisplayMode = config.backButtonDisplayMode;
521
+ }
522
+ #endif
523
+
514
524
  if (config.isBackTitleVisible) {
515
- if (config.backTitleFontFamily || config.backTitleFontSize) {
525
+ if ((config.backTitleFontFamily &&
526
+ // While being used by react-navigation, the `backTitleFontFamily` will
527
+ // be set to "System" by default - which is the system default font.
528
+ // To avoid always considering the font as customized, we need to have an additional check.
529
+ // See: https://github.com/software-mansion/react-native-screens/pull/2105#discussion_r1565222738
530
+ ![config.backTitleFontFamily isEqual:@"System"]) ||
531
+ config.backTitleFontSize) {
532
+ isBackButtonCustomized = YES;
516
533
  NSMutableDictionary *attrs = [NSMutableDictionary new];
517
534
  NSNumber *size = config.backTitleFontSize ?: @17;
518
535
  if (config.backTitleFontFamily) {
@@ -535,9 +552,17 @@ namespace react = facebook::react;
535
552
  // When backBarButtonItem's title is null, back menu will use value
536
553
  // of backButtonTitle
537
554
  [backBarButtonItem setTitle:nil];
555
+ isBackButtonCustomized = YES;
538
556
  prevItem.backButtonTitle = resolvedBackTitle;
539
557
  }
540
- prevItem.backBarButtonItem = backBarButtonItem;
558
+
559
+ // Prevent unnecessary assignment of backBarButtonItem if it is not customized,
560
+ // as assigning one will override the native behavior of automatically shortening
561
+ // the title to "Back" or hide the back title if there's not enough space.
562
+ // See: https://github.com/software-mansion/react-native-screens/issues/1589
563
+ if (isBackButtonCustomized) {
564
+ prevItem.backBarButtonItem = backBarButtonItem;
565
+ }
541
566
 
542
567
  if (@available(iOS 11.0, *)) {
543
568
  if (config.largeTitle) {
@@ -769,11 +794,6 @@ static RCTResizeMode resizeModeFromCppEquiv(react::ImageResizeMode resizeMode)
769
794
  _initialPropsSet = NO;
770
795
  }
771
796
 
772
- + (react::ComponentDescriptorProvider)componentDescriptorProvider
773
- {
774
- return react::concreteComponentDescriptorProvider<react::RNSScreenStackHeaderConfigComponentDescriptor>();
775
- }
776
-
777
797
  - (NSNumber *)getFontSizePropValue:(int)value
778
798
  {
779
799
  if (value > 0)
@@ -781,14 +801,9 @@ static RCTResizeMode resizeModeFromCppEquiv(react::ImageResizeMode resizeMode)
781
801
  return nil;
782
802
  }
783
803
 
784
- - (UISemanticContentAttribute)getDirectionPropValue:(react::RNSScreenStackHeaderConfigDirection)direction
804
+ + (react::ComponentDescriptorProvider)componentDescriptorProvider
785
805
  {
786
- switch (direction) {
787
- case react::RNSScreenStackHeaderConfigDirection::Rtl:
788
- return UISemanticContentAttributeForceRightToLeft;
789
- case react::RNSScreenStackHeaderConfigDirection::Ltr:
790
- return UISemanticContentAttributeForceLeftToRight;
791
- }
806
+ return react::concreteComponentDescriptorProvider<react::RNSScreenStackHeaderConfigComponentDescriptor>();
792
807
  }
793
808
 
794
809
  - (void)updateProps:(react::Props::Shared const &)props oldProps:(react::Props::Shared const &)oldProps
@@ -835,9 +850,11 @@ static RCTResizeMode resizeModeFromCppEquiv(react::ImageResizeMode resizeMode)
835
850
  _backTitleFontSize = [self getFontSizePropValue:newScreenProps.backTitleFontSize];
836
851
  _hideBackButton = newScreenProps.hideBackButton;
837
852
  _disableBackButtonMenu = newScreenProps.disableBackButtonMenu;
853
+ _backButtonDisplayMode =
854
+ [RNSConvert UINavigationItemBackButtonDisplayModeFromCppEquivalent:newScreenProps.backButtonDisplayMode];
838
855
 
839
856
  if (newScreenProps.direction != oldScreenProps.direction) {
840
- _direction = [self getDirectionPropValue:newScreenProps.direction];
857
+ _direction = [RNSConvert UISemanticContentAttributeFromCppEquivalent:newScreenProps.direction];
841
858
  }
842
859
 
843
860
  _backTitleVisible = newScreenProps.backTitleVisible;
@@ -928,8 +945,8 @@ RCT_EXPORT_VIEW_PROPERTY(hideBackButton, BOOL)
928
945
  RCT_EXPORT_VIEW_PROPERTY(hideShadow, BOOL)
929
946
  RCT_EXPORT_VIEW_PROPERTY(backButtonInCustomView, BOOL)
930
947
  RCT_EXPORT_VIEW_PROPERTY(disableBackButtonMenu, BOOL)
931
- // `hidden` is an UIView property, we need to use different name internally
932
- RCT_REMAP_VIEW_PROPERTY(hidden, hide, BOOL)
948
+ RCT_EXPORT_VIEW_PROPERTY(backButtonDisplayMode, UINavigationItemBackButtonDisplayMode)
949
+ RCT_REMAP_VIEW_PROPERTY(hidden, hide, BOOL) // `hidden` is an UIView property, we need to use different name internally
933
950
  RCT_EXPORT_VIEW_PROPERTY(translucent, BOOL)
934
951
 
935
952
  @end
@@ -985,6 +1002,16 @@ RCT_ENUM_CONVERTER(
985
1002
  UISemanticContentAttributeUnspecified,
986
1003
  integerValue)
987
1004
 
1005
+ RCT_ENUM_CONVERTER(
1006
+ UINavigationItemBackButtonDisplayMode,
1007
+ (@{
1008
+ @"default" : @(UINavigationItemBackButtonDisplayModeDefault),
1009
+ @"generic" : @(UINavigationItemBackButtonDisplayModeGeneric),
1010
+ @"minimal" : @(UINavigationItemBackButtonDisplayModeMinimal),
1011
+ }),
1012
+ UINavigationItemBackButtonDisplayModeDefault,
1013
+ integerValue)
1014
+
988
1015
  RCT_ENUM_CONVERTER(UIBlurEffectStyle, ([self blurEffectsForIOSVersion]), UIBlurEffectStyleExtraLight, integerValue)
989
1016
 
990
1017
  @end
@@ -29,11 +29,11 @@
29
29
 
30
30
  #ifdef RCT_NEW_ARCH_ENABLED
31
31
  #else
32
- @property (nonatomic, copy) RCTBubblingEventBlock onChangeText;
33
- @property (nonatomic, copy) RCTBubblingEventBlock onCancelButtonPress;
34
- @property (nonatomic, copy) RCTBubblingEventBlock onSearchButtonPress;
35
- @property (nonatomic, copy) RCTBubblingEventBlock onFocus;
36
- @property (nonatomic, copy) RCTBubblingEventBlock onBlur;
32
+ @property (nonatomic, copy) RCTDirectEventBlock onChangeText;
33
+ @property (nonatomic, copy) RCTDirectEventBlock onCancelButtonPress;
34
+ @property (nonatomic, copy) RCTDirectEventBlock onSearchButtonPress;
35
+ @property (nonatomic, copy) RCTDirectEventBlock onSearchFocus;
36
+ @property (nonatomic, copy) RCTDirectEventBlock onSearchBlur;
37
37
  #endif
38
38
 
39
39
  @end
@@ -67,11 +67,11 @@ namespace react = facebook::react;
67
67
  #ifdef RCT_NEW_ARCH_ENABLED
68
68
  if (_eventEmitter != nullptr) {
69
69
  std::dynamic_pointer_cast<const react::RNSSearchBarEventEmitter>(_eventEmitter)
70
- ->onFocus(react::RNSSearchBarEventEmitter::OnFocus{});
70
+ ->onSearchFocus(react::RNSSearchBarEventEmitter::OnSearchFocus{});
71
71
  }
72
72
  #else
73
- if (self.onFocus) {
74
- self.onFocus(@{});
73
+ if (self.onSearchFocus) {
74
+ self.onSearchFocus(@{});
75
75
  }
76
76
  #endif
77
77
  }
@@ -81,11 +81,11 @@ namespace react = facebook::react;
81
81
  #ifdef RCT_NEW_ARCH_ENABLED
82
82
  if (_eventEmitter != nullptr) {
83
83
  std::dynamic_pointer_cast<const react::RNSSearchBarEventEmitter>(_eventEmitter)
84
- ->onBlur(react::RNSSearchBarEventEmitter::OnBlur{});
84
+ ->onSearchBlur(react::RNSSearchBarEventEmitter::OnSearchBlur{});
85
85
  }
86
86
  #else
87
- if (self.onBlur) {
88
- self.onBlur(@{});
87
+ if (self.onSearchBlur) {
88
+ self.onSearchBlur(@{});
89
89
  }
90
90
  #endif
91
91
  }
@@ -414,11 +414,11 @@ RCT_EXPORT_VIEW_PROPERTY(textColor, UIColor)
414
414
  RCT_EXPORT_VIEW_PROPERTY(cancelButtonText, NSString)
415
415
  RCT_EXPORT_VIEW_PROPERTY(placement, RNSSearchBarPlacement)
416
416
 
417
- RCT_EXPORT_VIEW_PROPERTY(onChangeText, RCTBubblingEventBlock)
418
- RCT_EXPORT_VIEW_PROPERTY(onCancelButtonPress, RCTBubblingEventBlock)
419
- RCT_EXPORT_VIEW_PROPERTY(onSearchButtonPress, RCTBubblingEventBlock)
420
- RCT_EXPORT_VIEW_PROPERTY(onFocus, RCTBubblingEventBlock)
421
- RCT_EXPORT_VIEW_PROPERTY(onBlur, RCTBubblingEventBlock)
417
+ RCT_EXPORT_VIEW_PROPERTY(onChangeText, RCTDirectEventBlock)
418
+ RCT_EXPORT_VIEW_PROPERTY(onCancelButtonPress, RCTDirectEventBlock)
419
+ RCT_EXPORT_VIEW_PROPERTY(onSearchButtonPress, RCTDirectEventBlock)
420
+ RCT_EXPORT_VIEW_PROPERTY(onSearchFocus, RCTDirectEventBlock)
421
+ RCT_EXPORT_VIEW_PROPERTY(onSearchBlur, RCTDirectEventBlock)
422
422
 
423
423
  #ifndef RCT_NEW_ARCH_ENABLED
424
424
 
@@ -0,0 +1,15 @@
1
+ #ifdef RCT_NEW_ARCH_ENABLED
2
+
3
+ #import <React/RCTSurfaceTouchHandler.h>
4
+
5
+ NS_ASSUME_NONNULL_BEGIN
6
+
7
+ @interface RCTSurfaceTouchHandler (RNSUtility)
8
+
9
+ - (void)rnscreens_cancelTouches;
10
+
11
+ @end
12
+
13
+ NS_ASSUME_NONNULL_END
14
+
15
+ #endif // RCT_NEW_ARCH_ENABLED
@@ -0,0 +1,14 @@
1
+ #ifdef RCT_NEW_ARCH_ENABLED
2
+ #import "RCTSurfaceTouchHandler+RNSUtility.h"
3
+
4
+ @implementation RCTSurfaceTouchHandler (RNSUtility)
5
+
6
+ - (void)rnscreens_cancelTouches
7
+ {
8
+ [self setEnabled:NO];
9
+ [self setEnabled:YES];
10
+ [self reset];
11
+ }
12
+
13
+ @end
14
+ #endif // RCT_NEW_ARCH_ENABLED
@@ -0,0 +1,15 @@
1
+ #ifndef RCT_NEW_ARCH_ENABLED
2
+
3
+ #import <React/RCTTouchHandler.h>
4
+
5
+ NS_ASSUME_NONNULL_BEGIN
6
+
7
+ @interface RCTTouchHandler (RNSUtility)
8
+
9
+ - (void)rnscreens_cancelTouches;
10
+
11
+ @end
12
+
13
+ NS_ASSUME_NONNULL_END
14
+
15
+ #endif // !RCT_NEW_ARCH_ENABLED