react-native-screens 3.13.0 → 3.14.1
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.
- package/README.md +2 -2
- package/RNScreens.podspec +5 -4
- package/android/build.gradle +18 -1
- package/android/src/main/java/com/swmansion/rnscreens/ScreenStack.kt +8 -4
- package/android/src/main/java/com/swmansion/rnscreens/ScreenViewManager.kt +24 -6
- package/android/src/main/java/com/swmansion/rnscreens/ScreenWindowTraits.kt +14 -18
- package/android/src/main/jni/Android.mk +1 -2
- package/android/src/paper/java/com/facebook/react/viewmanagers/RNSScreenManagerDelegate.java +39 -14
- package/android/src/paper/java/com/facebook/react/viewmanagers/RNSScreenManagerInterface.java +15 -6
- package/android/src/paper/java/com/facebook/react/viewmanagers/RNSScreenStackHeaderConfigManagerDelegate.java +3 -3
- package/android/src/paper/java/com/facebook/react/viewmanagers/RNSScreenStackHeaderConfigManagerInterface.java +1 -1
- package/common/cpp/Android.mk +1 -2
- package/createNativeStackNavigator/README.md +4 -0
- package/ios/RNSConvert.h +30 -0
- package/ios/RNSConvert.mm +120 -0
- package/ios/RNSEnums.h +59 -0
- package/ios/RNSFullWindowOverlay.h +17 -2
- package/ios/RNSFullWindowOverlay.mm +199 -0
- package/ios/RNSScreen.h +70 -79
- package/ios/{RNSScreen.m → RNSScreen.mm} +679 -302
- package/ios/RNSScreenContainer.h +15 -1
- package/ios/{RNSScreenContainer.m → RNSScreenContainer.mm} +99 -8
- package/ios/{RNSScreenNavigationContainer.m → RNSScreenNavigationContainer.mm} +22 -0
- package/ios/RNSScreenStack.h +19 -3
- package/ios/{RNSScreenStack.m → RNSScreenStack.mm} +377 -126
- package/ios/{RNSScreenStackAnimator.m → RNSScreenStackAnimator.mm} +19 -14
- package/ios/RNSScreenStackHeaderConfig.h +20 -21
- package/ios/{RNSScreenStackHeaderConfig.m → RNSScreenStackHeaderConfig.mm} +232 -117
- package/ios/RNSScreenStackHeaderSubview.h +45 -0
- package/ios/RNSScreenStackHeaderSubview.mm +137 -0
- package/ios/RNSScreenViewEvent.h +12 -0
- package/ios/RNSScreenViewEvent.mm +59 -0
- package/ios/{RNSScreenWindowTraits.m → RNSScreenWindowTraits.mm} +3 -2
- package/ios/RNSSearchBar.h +14 -1
- package/ios/RNSSearchBar.mm +351 -0
- package/ios/{UIViewController+RNScreens.m → UIViewController+RNScreens.mm} +0 -0
- package/ios/{UIWindow+RNScreens.m → UIWindow+RNScreens.mm} +0 -0
- package/lib/commonjs/fabric/FullWindowOverlay.js +26 -0
- package/lib/commonjs/fabric/FullWindowOverlay.js.map +1 -0
- package/lib/commonjs/fabric/FullWindowOverlayNativeComponent.js +21 -0
- package/lib/commonjs/fabric/FullWindowOverlayNativeComponent.js.map +1 -0
- package/lib/commonjs/fabric/Screen.js +10 -8
- package/lib/commonjs/fabric/Screen.js.map +1 -1
- package/lib/commonjs/fabric/ScreenContainer.js +28 -0
- package/lib/commonjs/fabric/ScreenContainer.js.map +1 -0
- package/lib/commonjs/fabric/ScreenContainerNativeComponent.js +21 -0
- package/lib/commonjs/fabric/ScreenContainerNativeComponent.js.map +1 -0
- package/lib/commonjs/fabric/ScreenNativeComponent.js.map +1 -1
- package/lib/commonjs/fabric/ScreenNavigationContainer.js +28 -0
- package/lib/commonjs/fabric/ScreenNavigationContainer.js.map +1 -0
- package/lib/commonjs/fabric/ScreenNavigationContainerNativeComponent.js +21 -0
- package/lib/commonjs/fabric/ScreenNavigationContainerNativeComponent.js.map +1 -0
- package/lib/commonjs/fabric/ScreenStack.js +6 -7
- package/lib/commonjs/fabric/ScreenStack.js.map +1 -1
- package/lib/commonjs/fabric/ScreenStackHeaderConfigNativeComponent.js.map +1 -1
- package/lib/commonjs/fabric/ScreenStackHeaderSubview.js +4 -1
- package/lib/commonjs/fabric/ScreenStackHeaderSubview.js.map +1 -1
- package/lib/commonjs/fabric/ScreenStackNativeComponent.js.map +1 -1
- package/lib/commonjs/fabric/SearchBar.js +37 -0
- package/lib/commonjs/fabric/SearchBar.js.map +1 -0
- package/lib/commonjs/fabric/SearchBarNativeComponent.js +25 -0
- package/lib/commonjs/fabric/SearchBarNativeComponent.js.map +1 -0
- package/lib/commonjs/fabric/index.js +32 -0
- package/lib/commonjs/fabric/index.js.map +1 -1
- package/lib/commonjs/index.native.js +14 -18
- package/lib/commonjs/index.native.js.map +1 -1
- package/lib/commonjs/native-stack/views/NativeStackView.js +4 -0
- package/lib/commonjs/native-stack/views/NativeStackView.js.map +1 -1
- package/lib/commonjs/reanimated/ReanimatedNativeStackScreen.js +8 -2
- package/lib/commonjs/reanimated/ReanimatedNativeStackScreen.js.map +1 -1
- package/lib/module/fabric/FullWindowOverlay.js +15 -0
- package/lib/module/fabric/FullWindowOverlay.js.map +1 -0
- package/lib/module/fabric/FullWindowOverlayNativeComponent.js +9 -0
- package/lib/module/fabric/FullWindowOverlayNativeComponent.js.map +1 -0
- package/lib/module/fabric/Screen.js +8 -3
- package/lib/module/fabric/Screen.js.map +1 -1
- package/lib/module/fabric/ScreenContainer.js +17 -0
- package/lib/module/fabric/ScreenContainer.js.map +1 -0
- package/lib/module/fabric/ScreenContainerNativeComponent.js +9 -0
- package/lib/module/fabric/ScreenContainerNativeComponent.js.map +1 -0
- package/lib/module/fabric/ScreenNativeComponent.js.map +1 -1
- package/lib/module/fabric/ScreenNavigationContainer.js +17 -0
- package/lib/module/fabric/ScreenNavigationContainer.js.map +1 -0
- package/lib/module/fabric/ScreenNavigationContainerNativeComponent.js +9 -0
- package/lib/module/fabric/ScreenNavigationContainerNativeComponent.js.map +1 -0
- package/lib/module/fabric/ScreenStack.js +5 -2
- package/lib/module/fabric/ScreenStack.js.map +1 -1
- package/lib/module/fabric/ScreenStackHeaderConfigNativeComponent.js.map +1 -1
- package/lib/module/fabric/ScreenStackHeaderSubview.js +4 -1
- package/lib/module/fabric/ScreenStackHeaderSubview.js.map +1 -1
- package/lib/module/fabric/ScreenStackNativeComponent.js.map +1 -1
- package/lib/module/fabric/SearchBar.js +24 -0
- package/lib/module/fabric/SearchBar.js.map +1 -0
- package/lib/module/fabric/SearchBarNativeComponent.js +11 -0
- package/lib/module/fabric/SearchBarNativeComponent.js.map +1 -0
- package/lib/module/fabric/index.js +5 -1
- package/lib/module/fabric/index.js.map +1 -1
- package/lib/module/index.native.js +15 -20
- package/lib/module/index.native.js.map +1 -1
- package/lib/module/native-stack/views/NativeStackView.js +4 -0
- package/lib/module/native-stack/views/NativeStackView.js.map +1 -1
- package/lib/module/reanimated/ReanimatedNativeStackScreen.js +7 -2
- package/lib/module/reanimated/ReanimatedNativeStackScreen.js.map +1 -1
- package/lib/typescript/native-stack/types.d.ts +12 -0
- package/lib/typescript/reanimated/ReanimatedNativeStackScreen.d.ts +1 -1
- package/lib/typescript/reanimated/ReanimatedScreen.d.ts +1 -1
- package/lib/typescript/types.d.ts +24 -0
- package/native-stack/README.md +21 -0
- package/package.json +2 -2
- package/src/fabric/FullWindowOverlay.js +13 -0
- package/src/fabric/FullWindowOverlayNativeComponent.js +19 -0
- package/src/fabric/Screen.js +5 -2
- package/src/fabric/ScreenContainer.js +16 -0
- package/src/fabric/ScreenContainerNativeComponent.js +19 -0
- package/src/fabric/ScreenNativeComponent.js +41 -8
- package/src/fabric/ScreenNavigationContainer.js +16 -0
- package/src/fabric/ScreenNavigationContainerNativeComponent.js +19 -0
- package/src/fabric/ScreenStack.js +4 -2
- package/src/fabric/ScreenStackHeaderConfigNativeComponent.js +1 -1
- package/src/fabric/ScreenStackHeaderSubview.js +3 -1
- package/src/fabric/ScreenStackNativeComponent.js +4 -0
- package/src/fabric/SearchBar.js +20 -0
- package/src/fabric/SearchBarNativeComponent.js +62 -0
- package/src/fabric/index.js +8 -0
- package/src/index.native.tsx +20 -19
- package/src/native-stack/types.tsx +12 -0
- package/src/native-stack/views/NativeStackView.tsx +4 -0
- package/src/reanimated/ReanimatedNativeStackScreen.tsx +6 -0
- package/src/types.tsx +25 -0
- package/ios/RNSFullWindowOverlay.m +0 -105
- package/ios/RNSScreenComponentView.h +0 -23
- package/ios/RNSScreenComponentView.mm +0 -159
- package/ios/RNSScreenController.h +0 -10
- package/ios/RNSScreenController.mm +0 -79
- package/ios/RNSScreenStackComponentView.h +0 -15
- package/ios/RNSScreenStackComponentView.mm +0 -295
- package/ios/RNSScreenStackHeaderConfigComponentView.h +0 -42
- package/ios/RNSScreenStackHeaderConfigComponentView.mm +0 -662
- package/ios/RNSScreenStackHeaderSubviewComponentView.h +0 -14
- package/ios/RNSScreenStackHeaderSubviewComponentView.mm +0 -77
- package/ios/RNSSearchBar.m +0 -198
|
@@ -2,57 +2,86 @@
|
|
|
2
2
|
|
|
3
3
|
#import "RNSScreen.h"
|
|
4
4
|
#import "RNSScreenContainer.h"
|
|
5
|
-
#import "RNSScreenStack.h"
|
|
6
|
-
#import "RNSScreenStackHeaderConfig.h"
|
|
7
5
|
#import "RNSScreenWindowTraits.h"
|
|
8
6
|
|
|
9
|
-
#
|
|
7
|
+
#ifdef RN_FABRIC_ENABLED
|
|
8
|
+
#import <React/RCTConversions.h>
|
|
9
|
+
#import <React/RCTRootComponentView.h>
|
|
10
|
+
#import <React/RCTSurfaceTouchHandler.h>
|
|
11
|
+
#import <react/renderer/components/rnscreens/EventEmitters.h>
|
|
12
|
+
#import <react/renderer/components/rnscreens/Props.h>
|
|
13
|
+
#import <react/renderer/components/rnscreens/RCTComponentViewHelpers.h>
|
|
14
|
+
#import <rnscreens/RNSScreenComponentDescriptor.h>
|
|
15
|
+
#import "RCTFabricComponentsPlugins.h"
|
|
16
|
+
#import "RNSConvert.h"
|
|
17
|
+
#import "RNSScreenViewEvent.h"
|
|
18
|
+
#else
|
|
10
19
|
#import <React/RCTTouchHandler.h>
|
|
20
|
+
#endif
|
|
21
|
+
|
|
22
|
+
#import <React/RCTShadowView.h>
|
|
11
23
|
#import <React/RCTUIManager.h>
|
|
24
|
+
#import "RNSScreenStack.h"
|
|
25
|
+
#import "RNSScreenStackHeaderConfig.h"
|
|
12
26
|
|
|
13
|
-
@interface RNSScreenView ()
|
|
27
|
+
@interface RNSScreenView ()
|
|
28
|
+
#ifdef RN_FABRIC_ENABLED
|
|
29
|
+
<RCTRNSScreenViewProtocol, UIAdaptivePresentationControllerDelegate>
|
|
30
|
+
#else
|
|
31
|
+
<UIAdaptivePresentationControllerDelegate, RCTInvalidating>
|
|
32
|
+
#endif
|
|
14
33
|
@end
|
|
15
34
|
|
|
16
35
|
@implementation RNSScreenView {
|
|
17
36
|
__weak RCTBridge *_bridge;
|
|
18
|
-
|
|
37
|
+
#ifdef RN_FABRIC_ENABLED
|
|
38
|
+
RCTSurfaceTouchHandler *_touchHandler;
|
|
39
|
+
facebook::react::RNSScreenShadowNode::ConcreteState::Shared _state;
|
|
40
|
+
// on fabric, they are not available by default so we need them exposed here too
|
|
41
|
+
NSMutableArray<UIView *> *_reactSubviews;
|
|
42
|
+
#else
|
|
19
43
|
RCTTouchHandler *_touchHandler;
|
|
20
44
|
CGRect _reactFrame;
|
|
45
|
+
#endif
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
#ifdef RN_FABRIC_ENABLED
|
|
49
|
+
- (instancetype)initWithFrame:(CGRect)frame
|
|
50
|
+
{
|
|
51
|
+
if (self = [super initWithFrame:frame]) {
|
|
52
|
+
static const auto defaultProps = std::make_shared<const facebook::react::RNSScreenProps>();
|
|
53
|
+
_props = defaultProps;
|
|
54
|
+
_reactSubviews = [NSMutableArray new];
|
|
55
|
+
[self initCommonProps];
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
return self;
|
|
21
59
|
}
|
|
60
|
+
#endif
|
|
22
61
|
|
|
23
62
|
- (instancetype)initWithBridge:(RCTBridge *)bridge
|
|
24
63
|
{
|
|
25
64
|
if (self = [super init]) {
|
|
26
65
|
_bridge = bridge;
|
|
27
|
-
|
|
28
|
-
_stackPresentation = RNSScreenStackPresentationPush;
|
|
29
|
-
_stackAnimation = RNSScreenStackAnimationDefault;
|
|
30
|
-
_gestureEnabled = YES;
|
|
31
|
-
_replaceAnimation = RNSScreenReplaceAnimationPop;
|
|
32
|
-
_dismissed = NO;
|
|
33
|
-
_hasStatusBarStyleSet = NO;
|
|
34
|
-
_hasStatusBarAnimationSet = NO;
|
|
35
|
-
_hasStatusBarHiddenSet = NO;
|
|
36
|
-
_hasOrientationSet = NO;
|
|
37
|
-
_hasHomeIndicatorHiddenSet = NO;
|
|
66
|
+
[self initCommonProps];
|
|
38
67
|
}
|
|
39
68
|
|
|
40
69
|
return self;
|
|
41
70
|
}
|
|
42
71
|
|
|
43
|
-
- (void)
|
|
72
|
+
- (void)initCommonProps
|
|
44
73
|
{
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
74
|
+
_controller = [[RNSScreen alloc] initWithView:self];
|
|
75
|
+
_stackPresentation = RNSScreenStackPresentationPush;
|
|
76
|
+
_stackAnimation = RNSScreenStackAnimationDefault;
|
|
77
|
+
_gestureEnabled = YES;
|
|
78
|
+
_replaceAnimation = RNSScreenReplaceAnimationPop;
|
|
79
|
+
_dismissed = NO;
|
|
80
|
+
_hasStatusBarStyleSet = NO;
|
|
81
|
+
_hasStatusBarAnimationSet = NO;
|
|
82
|
+
_hasStatusBarHiddenSet = NO;
|
|
83
|
+
_hasOrientationSet = NO;
|
|
84
|
+
_hasHomeIndicatorHiddenSet = NO;
|
|
56
85
|
}
|
|
57
86
|
|
|
58
87
|
- (UIViewController *)reactViewController
|
|
@@ -60,28 +89,25 @@
|
|
|
60
89
|
return _controller;
|
|
61
90
|
}
|
|
62
91
|
|
|
63
|
-
|
|
92
|
+
#ifdef RN_FABRIC_ENABLED
|
|
93
|
+
- (NSArray<UIView *> *)reactSubviews
|
|
64
94
|
{
|
|
65
|
-
|
|
95
|
+
return _reactSubviews;
|
|
66
96
|
}
|
|
97
|
+
#endif
|
|
67
98
|
|
|
68
|
-
|
|
69
|
-
// it from JS to be a plain value (non animated).
|
|
70
|
-
// In case when nil is received, we want to ignore such value and not make
|
|
71
|
-
// any updates as the actual non-nil value will follow immediately.
|
|
72
|
-
- (void)setActivityStateOrNil:(NSNumber *)activityStateOrNil
|
|
99
|
+
- (void)updateBounds
|
|
73
100
|
{
|
|
74
|
-
|
|
75
|
-
if (
|
|
76
|
-
|
|
77
|
-
|
|
101
|
+
#ifdef RN_FABRIC_ENABLED
|
|
102
|
+
if (_state != nullptr) {
|
|
103
|
+
auto newState = facebook::react::RNSScreenState{RCTSizeFromCGSize(self.bounds.size)};
|
|
104
|
+
_state->updateState(std::move(newState));
|
|
105
|
+
UINavigationController *navctr = _controller.navigationController;
|
|
106
|
+
[navctr.view setNeedsLayout];
|
|
78
107
|
}
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
{
|
|
83
|
-
// pointer events settings are managed by the parent screen container, we ignore
|
|
84
|
-
// any attempt of setting that via React props
|
|
108
|
+
#else
|
|
109
|
+
[_bridge.uiManager setSize:self.bounds.size forView:self];
|
|
110
|
+
#endif
|
|
85
111
|
}
|
|
86
112
|
|
|
87
113
|
- (void)setStackPresentation:(RNSScreenStackPresentation)stackPresentation
|
|
@@ -131,8 +157,13 @@
|
|
|
131
157
|
// https://developer.apple.com/documentation/uikit/uiviewcontroller/1621426-presentationcontroller?language=objc
|
|
132
158
|
_controller.presentationController.delegate = self;
|
|
133
159
|
} else if (_stackPresentation != RNSScreenStackPresentationPush) {
|
|
160
|
+
#ifdef RN_FABRIC_ENABLED
|
|
161
|
+
// TODO: on Fabric, same controllers can be used as modals and then recycled and used a push which would result in
|
|
162
|
+
// this error. It would be good to check if it doesn't leak in such case.
|
|
163
|
+
#else
|
|
134
164
|
RCTLogError(
|
|
135
165
|
@"Screen presentation updated from modal to push, this may likely result in a screen object leakage. If you need to change presentation style create a new screen object instead");
|
|
166
|
+
#endif
|
|
136
167
|
}
|
|
137
168
|
_stackPresentation = stackPresentation;
|
|
138
169
|
}
|
|
@@ -177,6 +208,19 @@
|
|
|
177
208
|
_replaceAnimation = replaceAnimation;
|
|
178
209
|
}
|
|
179
210
|
|
|
211
|
+
// Nil will be provided when activityState is set as an animated value and we change
|
|
212
|
+
// it from JS to be a plain value (non animated).
|
|
213
|
+
// In case when nil is received, we want to ignore such value and not make
|
|
214
|
+
// any updates as the actual non-nil value will follow immediately.
|
|
215
|
+
- (void)setActivityStateOrNil:(NSNumber *)activityStateOrNil
|
|
216
|
+
{
|
|
217
|
+
int activityState = [activityStateOrNil intValue];
|
|
218
|
+
if (activityStateOrNil != nil && activityState != -1 && activityState != _activityState) {
|
|
219
|
+
_activityState = activityState;
|
|
220
|
+
[_reactSuperview markChildUpdated];
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
|
|
180
224
|
#if !TARGET_OS_TV
|
|
181
225
|
- (void)setStatusBarStyle:(RNSStatusBarStyle)statusBarStyle
|
|
182
226
|
{
|
|
@@ -230,13 +274,17 @@
|
|
|
230
274
|
}
|
|
231
275
|
}
|
|
232
276
|
|
|
233
|
-
- (void)notifyFinishTransitioning
|
|
234
|
-
{
|
|
235
|
-
[_controller notifyFinishTransitioning];
|
|
236
|
-
}
|
|
237
|
-
|
|
238
277
|
- (void)notifyDismissedWithCount:(int)dismissCount
|
|
239
278
|
{
|
|
279
|
+
#ifdef RN_FABRIC_ENABLED
|
|
280
|
+
// If screen is already unmounted then there will be no event emitter
|
|
281
|
+
// it will be cleaned in prepareForRecycle
|
|
282
|
+
if (_eventEmitter != nullptr) {
|
|
283
|
+
std::dynamic_pointer_cast<const facebook::react::RNSScreenEventEmitter>(_eventEmitter)
|
|
284
|
+
->onDismissed(facebook::react::RNSScreenEventEmitter::OnDismissed{.dismissCount = dismissCount});
|
|
285
|
+
}
|
|
286
|
+
#else
|
|
287
|
+
// TODO: hopefully problems connected to dismissed prop are only the case on paper
|
|
240
288
|
_dismissed = YES;
|
|
241
289
|
if (self.onDismissed) {
|
|
242
290
|
dispatch_async(dispatch_get_main_queue(), ^{
|
|
@@ -245,27 +293,75 @@
|
|
|
245
293
|
}
|
|
246
294
|
});
|
|
247
295
|
}
|
|
296
|
+
#endif
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
- (void)notifyDismissCancelledWithDismissCount:(int)dismissCount
|
|
300
|
+
{
|
|
301
|
+
#ifdef RN_FABRIC_ENABLED
|
|
302
|
+
// If screen is already unmounted then there will be no event emitter
|
|
303
|
+
// it will be cleaned in prepareForRecycle
|
|
304
|
+
if (_eventEmitter != nullptr) {
|
|
305
|
+
std::dynamic_pointer_cast<const facebook::react::RNSScreenEventEmitter>(_eventEmitter)
|
|
306
|
+
->onNativeDismissCancelled(
|
|
307
|
+
facebook::react::RNSScreenEventEmitter::OnNativeDismissCancelled{.dismissCount = dismissCount});
|
|
308
|
+
}
|
|
309
|
+
#else
|
|
310
|
+
if (self.onNativeDismissCancelled) {
|
|
311
|
+
self.onNativeDismissCancelled(@{@"dismissCount" : @(dismissCount)});
|
|
312
|
+
}
|
|
313
|
+
#endif
|
|
248
314
|
}
|
|
249
315
|
|
|
250
316
|
- (void)notifyWillAppear
|
|
251
317
|
{
|
|
318
|
+
#ifdef RN_FABRIC_ENABLED
|
|
319
|
+
// If screen is already unmounted then there will be no event emitter
|
|
320
|
+
// it will be cleaned in prepareForRecycle
|
|
321
|
+
if (_eventEmitter != nullptr) {
|
|
322
|
+
std::dynamic_pointer_cast<const facebook::react::RNSScreenEventEmitter>(_eventEmitter)
|
|
323
|
+
->onWillAppear(facebook::react::RNSScreenEventEmitter::OnWillAppear{});
|
|
324
|
+
}
|
|
325
|
+
[self updateLayoutMetrics:_newLayoutMetrics oldLayoutMetrics:_oldLayoutMetrics];
|
|
326
|
+
#else
|
|
252
327
|
if (self.onWillAppear) {
|
|
253
328
|
self.onWillAppear(nil);
|
|
254
329
|
}
|
|
255
330
|
// we do it here too because at this moment the `parentViewController` is already not nil,
|
|
256
331
|
// so if the parent is not UINavCtr, the frame will be updated to the correct one.
|
|
257
332
|
[self reactSetFrame:_reactFrame];
|
|
333
|
+
#endif
|
|
258
334
|
}
|
|
259
335
|
|
|
260
336
|
- (void)notifyWillDisappear
|
|
261
337
|
{
|
|
338
|
+
if (_hideKeyboardOnSwipe) {
|
|
339
|
+
[self endEditing:YES];
|
|
340
|
+
}
|
|
341
|
+
#ifdef RN_FABRIC_ENABLED
|
|
342
|
+
// If screen is already unmounted then there will be no event emitter
|
|
343
|
+
// it will be cleaned in prepareForRecycle
|
|
344
|
+
if (_eventEmitter != nullptr) {
|
|
345
|
+
std::dynamic_pointer_cast<const facebook::react::RNSScreenEventEmitter>(_eventEmitter)
|
|
346
|
+
->onWillDisappear(facebook::react::RNSScreenEventEmitter::OnWillDisappear{});
|
|
347
|
+
}
|
|
348
|
+
#else
|
|
262
349
|
if (self.onWillDisappear) {
|
|
263
350
|
self.onWillDisappear(nil);
|
|
264
351
|
}
|
|
352
|
+
#endif
|
|
265
353
|
}
|
|
266
354
|
|
|
267
355
|
- (void)notifyAppear
|
|
268
356
|
{
|
|
357
|
+
#ifdef RN_FABRIC_ENABLED
|
|
358
|
+
// If screen is already unmounted then there will be no event emitter
|
|
359
|
+
// it will be cleaned in prepareForRecycle
|
|
360
|
+
if (_eventEmitter != nullptr) {
|
|
361
|
+
std::dynamic_pointer_cast<const facebook::react::RNSScreenEventEmitter>(_eventEmitter)
|
|
362
|
+
->onAppear(facebook::react::RNSScreenEventEmitter::OnAppear{});
|
|
363
|
+
}
|
|
364
|
+
#else
|
|
269
365
|
if (self.onAppear) {
|
|
270
366
|
dispatch_async(dispatch_get_main_queue(), ^{
|
|
271
367
|
if (self.onAppear) {
|
|
@@ -273,41 +369,39 @@
|
|
|
273
369
|
}
|
|
274
370
|
});
|
|
275
371
|
}
|
|
372
|
+
#endif
|
|
276
373
|
}
|
|
277
374
|
|
|
278
375
|
- (void)notifyDisappear
|
|
279
376
|
{
|
|
377
|
+
#ifdef RN_FABRIC_ENABLED
|
|
378
|
+
// If screen is already unmounted then there will be no event emitter
|
|
379
|
+
// it will be cleaned in prepareForRecycle
|
|
380
|
+
if (_eventEmitter != nullptr) {
|
|
381
|
+
std::dynamic_pointer_cast<const facebook::react::RNSScreenEventEmitter>(_eventEmitter)
|
|
382
|
+
->onDisappear(facebook::react::RNSScreenEventEmitter::OnDisappear{});
|
|
383
|
+
}
|
|
384
|
+
#else
|
|
280
385
|
if (self.onDisappear) {
|
|
281
386
|
self.onDisappear(nil);
|
|
282
387
|
}
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
- (void)notifyDismissCancelledWithDismissCount:(int)dismissCount
|
|
286
|
-
{
|
|
287
|
-
if (self.onNativeDismissCancelled) {
|
|
288
|
-
self.onNativeDismissCancelled(@{@"dismissCount" : @(dismissCount)});
|
|
289
|
-
}
|
|
290
|
-
}
|
|
291
|
-
|
|
292
|
-
- (void)notifyTransitionProgress:(double)progress closing:(BOOL)closing goingForward:(BOOL)goingForward
|
|
293
|
-
{
|
|
294
|
-
if (self.onTransitionProgress) {
|
|
295
|
-
self.onTransitionProgress(@{
|
|
296
|
-
@"progress" : @(progress),
|
|
297
|
-
@"closing" : @(closing ? 1 : 0),
|
|
298
|
-
@"goingForward" : @(goingForward ? 1 : 0),
|
|
299
|
-
});
|
|
300
|
-
}
|
|
388
|
+
#endif
|
|
301
389
|
}
|
|
302
390
|
|
|
303
391
|
- (BOOL)isMountedUnderScreenOrReactRoot
|
|
304
392
|
{
|
|
393
|
+
#ifdef RN_FABRIC_ENABLED
|
|
394
|
+
#define RNS_EXPECTED_VIEW RCTRootComponentView
|
|
395
|
+
#else
|
|
396
|
+
#define RNS_EXPECTED_VIEW RCTRootView
|
|
397
|
+
#endif
|
|
305
398
|
for (UIView *parent = self.superview; parent != nil; parent = parent.superview) {
|
|
306
|
-
if ([parent isKindOfClass:[
|
|
399
|
+
if ([parent isKindOfClass:[RNS_EXPECTED_VIEW class]] || [parent isKindOfClass:[RNSScreenView class]]) {
|
|
307
400
|
return YES;
|
|
308
401
|
}
|
|
309
402
|
}
|
|
310
403
|
return NO;
|
|
404
|
+
#undef RNS_EXPECTED_VIEW
|
|
311
405
|
}
|
|
312
406
|
|
|
313
407
|
- (void)didMoveToWindow
|
|
@@ -317,7 +411,11 @@
|
|
|
317
411
|
// root application window.
|
|
318
412
|
if (self.window != nil && ![self isMountedUnderScreenOrReactRoot]) {
|
|
319
413
|
if (_touchHandler == nil) {
|
|
414
|
+
#ifdef RN_FABRIC_ENABLED
|
|
415
|
+
_touchHandler = [RCTSurfaceTouchHandler new];
|
|
416
|
+
#else
|
|
320
417
|
_touchHandler = [[RCTTouchHandler alloc] initWithBridge:_bridge];
|
|
418
|
+
#endif
|
|
321
419
|
}
|
|
322
420
|
[_touchHandler attachToView:self];
|
|
323
421
|
} else {
|
|
@@ -325,6 +423,54 @@
|
|
|
325
423
|
}
|
|
326
424
|
}
|
|
327
425
|
|
|
426
|
+
#ifdef RN_FABRIC_ENABLED
|
|
427
|
+
- (RCTSurfaceTouchHandler *)touchHandler
|
|
428
|
+
#else
|
|
429
|
+
- (RCTTouchHandler *)touchHandler
|
|
430
|
+
#endif
|
|
431
|
+
{
|
|
432
|
+
if (_touchHandler != nil) {
|
|
433
|
+
return _touchHandler;
|
|
434
|
+
}
|
|
435
|
+
UIView *parent = [self superview];
|
|
436
|
+
while (parent != nil && ![parent respondsToSelector:@selector(touchHandler)])
|
|
437
|
+
parent = parent.superview;
|
|
438
|
+
if (parent != nil) {
|
|
439
|
+
return [parent performSelector:@selector(touchHandler)];
|
|
440
|
+
}
|
|
441
|
+
return nil;
|
|
442
|
+
}
|
|
443
|
+
|
|
444
|
+
- (void)notifyFinishTransitioning
|
|
445
|
+
{
|
|
446
|
+
[_controller notifyFinishTransitioning];
|
|
447
|
+
}
|
|
448
|
+
|
|
449
|
+
- (void)notifyTransitionProgress:(double)progress closing:(BOOL)closing goingForward:(BOOL)goingForward
|
|
450
|
+
{
|
|
451
|
+
#ifdef RN_FABRIC_ENABLED
|
|
452
|
+
if (_eventEmitter != nullptr) {
|
|
453
|
+
std::dynamic_pointer_cast<const facebook::react::RNSScreenEventEmitter>(_eventEmitter)
|
|
454
|
+
->onTransitionProgress(facebook::react::RNSScreenEventEmitter::OnTransitionProgress{
|
|
455
|
+
.progress = progress, .closing = closing ? 1 : 0, .goingForward = goingForward ? 1 : 0});
|
|
456
|
+
}
|
|
457
|
+
RNSScreenViewEvent *event = [[RNSScreenViewEvent alloc] initWithEventName:@"onTransitionProgress"
|
|
458
|
+
reactTag:[NSNumber numberWithInt:self.tag]
|
|
459
|
+
progress:progress
|
|
460
|
+
closing:closing
|
|
461
|
+
goingForward:goingForward];
|
|
462
|
+
[[RCTBridge currentBridge].eventDispatcher sendEvent:event];
|
|
463
|
+
#else
|
|
464
|
+
if (self.onTransitionProgress) {
|
|
465
|
+
self.onTransitionProgress(@{
|
|
466
|
+
@"progress" : @(progress),
|
|
467
|
+
@"closing" : @(closing ? 1 : 0),
|
|
468
|
+
@"goingForward" : @(goingForward ? 1 : 0),
|
|
469
|
+
});
|
|
470
|
+
}
|
|
471
|
+
#endif
|
|
472
|
+
}
|
|
473
|
+
|
|
328
474
|
- (void)presentationControllerWillDismiss:(UIPresentationController *)presentationController
|
|
329
475
|
{
|
|
330
476
|
// We need to call both "cancel" and "reset" here because RN's gesture recognizer
|
|
@@ -337,24 +483,15 @@
|
|
|
337
483
|
// pulling down starting at some touchable item. Without "reset" the touchable
|
|
338
484
|
// will never go back from highlighted state even when the modal start sliding
|
|
339
485
|
// down.
|
|
486
|
+
#ifdef RN_FABRIC_ENABLED
|
|
487
|
+
[_touchHandler setEnabled:NO];
|
|
488
|
+
[_touchHandler setEnabled:YES];
|
|
489
|
+
#else
|
|
340
490
|
[_touchHandler cancel];
|
|
491
|
+
#endif
|
|
341
492
|
[_touchHandler reset];
|
|
342
493
|
}
|
|
343
494
|
|
|
344
|
-
- (RCTTouchHandler *)touchHandler
|
|
345
|
-
{
|
|
346
|
-
if (_touchHandler != nil) {
|
|
347
|
-
return _touchHandler;
|
|
348
|
-
}
|
|
349
|
-
UIView *parent = [self superview];
|
|
350
|
-
while (parent != nil && ![parent respondsToSelector:@selector(touchHandler)])
|
|
351
|
-
parent = parent.superview;
|
|
352
|
-
if (parent != nil) {
|
|
353
|
-
return [parent performSelector:@selector(touchHandler)];
|
|
354
|
-
}
|
|
355
|
-
return nil;
|
|
356
|
-
}
|
|
357
|
-
|
|
358
495
|
- (BOOL)presentationControllerShouldDismiss:(UIPresentationController *)presentationController
|
|
359
496
|
{
|
|
360
497
|
if (_preventNativeDismiss) {
|
|
@@ -371,211 +508,212 @@
|
|
|
371
508
|
}
|
|
372
509
|
}
|
|
373
510
|
|
|
374
|
-
-
|
|
375
|
-
|
|
376
|
-
_controller = nil;
|
|
377
|
-
}
|
|
378
|
-
|
|
379
|
-
@end
|
|
511
|
+
#pragma mark - Fabric specific
|
|
512
|
+
#ifdef RN_FABRIC_ENABLED
|
|
380
513
|
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
UIView *_fakeView;
|
|
385
|
-
CADisplayLink *_animationTimer;
|
|
386
|
-
CGFloat _currentAlpha;
|
|
387
|
-
BOOL _closing;
|
|
388
|
-
BOOL _goingForward;
|
|
389
|
-
int _dismissCount;
|
|
390
|
-
BOOL _isSwiping;
|
|
391
|
-
BOOL _shouldNotify;
|
|
514
|
+
+ (facebook::react::ComponentDescriptorProvider)componentDescriptorProvider
|
|
515
|
+
{
|
|
516
|
+
return facebook::react::concreteComponentDescriptorProvider<facebook::react::RNSScreenComponentDescriptor>();
|
|
392
517
|
}
|
|
393
518
|
|
|
394
|
-
- (
|
|
519
|
+
- (void)mountChildComponentView:(UIView<RCTComponentViewProtocol> *)childComponentView index:(NSInteger)index
|
|
395
520
|
{
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
521
|
+
[super mountChildComponentView:childComponentView index:index];
|
|
522
|
+
if ([childComponentView isKindOfClass:[RNSScreenStackHeaderConfig class]]) {
|
|
523
|
+
_config = childComponentView;
|
|
524
|
+
((RNSScreenStackHeaderConfig *)childComponentView).screenView = self;
|
|
400
525
|
}
|
|
401
|
-
|
|
526
|
+
[_reactSubviews insertObject:childComponentView atIndex:index];
|
|
402
527
|
}
|
|
403
528
|
|
|
404
|
-
|
|
405
|
-
- (UIViewController *)childViewControllerForStatusBarStyle
|
|
529
|
+
- (void)unmountChildComponentView:(UIView<RCTComponentViewProtocol> *)childComponentView index:(NSInteger)index
|
|
406
530
|
{
|
|
407
|
-
|
|
408
|
-
|
|
531
|
+
if ([childComponentView isKindOfClass:[RNSScreenStackHeaderConfig class]]) {
|
|
532
|
+
_config = nil;
|
|
533
|
+
}
|
|
534
|
+
[_reactSubviews removeObject:childComponentView];
|
|
535
|
+
[super unmountChildComponentView:childComponentView index:index];
|
|
409
536
|
}
|
|
410
537
|
|
|
411
|
-
-
|
|
412
|
-
{
|
|
413
|
-
return [RNSScreenWindowTraits statusBarStyleForRNSStatusBarStyle:((RNSScreenView *)self.view).statusBarStyle];
|
|
414
|
-
}
|
|
538
|
+
#pragma mark - RCTComponentViewProtocol
|
|
415
539
|
|
|
416
|
-
- (
|
|
540
|
+
- (void)prepareForRecycle
|
|
417
541
|
{
|
|
418
|
-
|
|
419
|
-
|
|
542
|
+
[super prepareForRecycle];
|
|
543
|
+
// TODO: Make sure that there is no edge case when this should be uncommented
|
|
544
|
+
// _controller=nil;
|
|
545
|
+
_dismissed = NO;
|
|
546
|
+
_state.reset();
|
|
547
|
+
_touchHandler = nil;
|
|
420
548
|
}
|
|
421
549
|
|
|
422
|
-
- (
|
|
550
|
+
- (void)updateProps:(facebook::react::Props::Shared const &)props
|
|
551
|
+
oldProps:(facebook::react::Props::Shared const &)oldProps
|
|
423
552
|
{
|
|
424
|
-
|
|
425
|
-
|
|
553
|
+
const auto &oldScreenProps = *std::static_pointer_cast<const facebook::react::RNSScreenProps>(_props);
|
|
554
|
+
const auto &newScreenProps = *std::static_pointer_cast<const facebook::react::RNSScreenProps>(props);
|
|
426
555
|
|
|
427
|
-
|
|
428
|
-
{
|
|
429
|
-
UIViewController *vc = [self findChildVCForConfigAndTrait:RNSWindowTraitAnimation includingModals:NO];
|
|
556
|
+
[self setFullScreenSwipeEnabled:newScreenProps.fullScreenSwipeEnabled];
|
|
430
557
|
|
|
431
|
-
|
|
432
|
-
|
|
558
|
+
[self setGestureEnabled:newScreenProps.gestureEnabled];
|
|
559
|
+
|
|
560
|
+
[self setTransitionDuration:[NSNumber numberWithInt:newScreenProps.transitionDuration]];
|
|
561
|
+
|
|
562
|
+
[self setHideKeyboardOnSwipe:newScreenProps.hideKeyboardOnSwipe];
|
|
563
|
+
|
|
564
|
+
[self setCustomAnimationOnSwipe:newScreenProps.customAnimationOnSwipe];
|
|
565
|
+
|
|
566
|
+
[self
|
|
567
|
+
setGestureResponseDistance:[RNSConvert
|
|
568
|
+
gestureResponseDistanceDictFromCppStruct:newScreenProps.gestureResponseDistance]];
|
|
569
|
+
|
|
570
|
+
[self setPreventNativeDismiss:newScreenProps.preventNativeDismiss];
|
|
571
|
+
|
|
572
|
+
[self setActivityStateOrNil:[NSNumber numberWithFloat:newScreenProps.activityState]];
|
|
573
|
+
|
|
574
|
+
[self setSwipeDirection:[RNSConvert RNSScreenSwipeDirectionFromCppEquivalent:newScreenProps.swipeDirection]];
|
|
575
|
+
|
|
576
|
+
#if !TARGET_OS_TV
|
|
577
|
+
if (newScreenProps.statusBarHidden != oldScreenProps.statusBarHidden) {
|
|
578
|
+
[self setStatusBarHidden:newScreenProps.statusBarHidden];
|
|
433
579
|
}
|
|
434
|
-
return UIStatusBarAnimationFade;
|
|
435
|
-
}
|
|
436
580
|
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
581
|
+
if (newScreenProps.statusBarStyle != oldScreenProps.statusBarStyle) {
|
|
582
|
+
[self setStatusBarStyle:[RCTConvert
|
|
583
|
+
RNSStatusBarStyle:RCTNSStringFromStringNilIfEmpty(newScreenProps.statusBarStyle)]];
|
|
584
|
+
}
|
|
440
585
|
|
|
441
|
-
if (
|
|
442
|
-
|
|
586
|
+
if (newScreenProps.statusBarAnimation != oldScreenProps.statusBarAnimation) {
|
|
587
|
+
[self setStatusBarAnimation:[RCTConvert UIStatusBarAnimation:RCTNSStringFromStringNilIfEmpty(
|
|
588
|
+
newScreenProps.statusBarAnimation)]];
|
|
443
589
|
}
|
|
444
|
-
|
|
590
|
+
|
|
591
|
+
if (newScreenProps.screenOrientation != oldScreenProps.screenOrientation) {
|
|
592
|
+
[self setScreenOrientation:[RCTConvert UIInterfaceOrientationMask:RCTNSStringFromStringNilIfEmpty(
|
|
593
|
+
newScreenProps.screenOrientation)]];
|
|
594
|
+
}
|
|
595
|
+
|
|
596
|
+
if (newScreenProps.homeIndicatorHidden != oldScreenProps.homeIndicatorHidden) {
|
|
597
|
+
[self setHomeIndicatorHidden:newScreenProps.homeIndicatorHidden];
|
|
598
|
+
}
|
|
599
|
+
#endif
|
|
600
|
+
|
|
601
|
+
if (newScreenProps.stackPresentation != oldScreenProps.stackPresentation) {
|
|
602
|
+
[self
|
|
603
|
+
setStackPresentation:[RNSConvert RNSScreenStackPresentationFromCppEquivalent:newScreenProps.stackPresentation]];
|
|
604
|
+
}
|
|
605
|
+
|
|
606
|
+
if (newScreenProps.stackAnimation != oldScreenProps.stackAnimation) {
|
|
607
|
+
[self setStackAnimation:[RNSConvert RNSScreenStackAnimationFromCppEquivalent:newScreenProps.stackAnimation]];
|
|
608
|
+
}
|
|
609
|
+
|
|
610
|
+
if (newScreenProps.replaceAnimation != oldScreenProps.replaceAnimation) {
|
|
611
|
+
[self setReplaceAnimation:[RNSConvert RNSScreenReplaceAnimationFromCppEquivalent:newScreenProps.replaceAnimation]];
|
|
612
|
+
}
|
|
613
|
+
|
|
614
|
+
[super updateProps:props oldProps:oldProps];
|
|
445
615
|
}
|
|
446
616
|
|
|
447
|
-
- (
|
|
617
|
+
- (void)updateState:(facebook::react::State::Shared const &)state
|
|
618
|
+
oldState:(facebook::react::State::Shared const &)oldState
|
|
448
619
|
{
|
|
449
|
-
|
|
450
|
-
return vc == self ? nil : vc;
|
|
620
|
+
_state = std::static_pointer_cast<const facebook::react::RNSScreenShadowNode::ConcreteState>(state);
|
|
451
621
|
}
|
|
452
622
|
|
|
453
|
-
- (
|
|
623
|
+
- (void)updateLayoutMetrics:(const facebook::react::LayoutMetrics &)layoutMetrics
|
|
624
|
+
oldLayoutMetrics:(const facebook::react::LayoutMetrics &)oldLayoutMetrics
|
|
454
625
|
{
|
|
455
|
-
|
|
626
|
+
_newLayoutMetrics = layoutMetrics;
|
|
627
|
+
_oldLayoutMetrics = oldLayoutMetrics;
|
|
628
|
+
UIViewController *parentVC = self.reactViewController.parentViewController;
|
|
629
|
+
if (parentVC != nil && ![parentVC isKindOfClass:[RNScreensNavigationController class]]) {
|
|
630
|
+
[super updateLayoutMetrics:layoutMetrics oldLayoutMetrics:oldLayoutMetrics];
|
|
631
|
+
}
|
|
632
|
+
// when screen is mounted under RNScreensNavigationController it's size is controller
|
|
633
|
+
// by the navigation controller itself. That is, it is set to fill space of
|
|
634
|
+
// the controller. In that case we ignore react layout system from managing
|
|
635
|
+
// the screen dimensions and we wait for the screen VC to update and then we
|
|
636
|
+
// pass the dimensions to ui view manager to take into account when laying out
|
|
637
|
+
// subviews
|
|
638
|
+
// Explanation taken from `reactSetFrame`, which is old arch equivalent of this code.
|
|
456
639
|
}
|
|
457
640
|
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
// so we return self which results in asking self for preferredStatusBarStyle/Animation etc.;
|
|
461
|
-
// if the returned vc is nil, it means none of children could provide config and self does not have config either,
|
|
462
|
-
// so if it was asked by parent, it will fallback to parent's option, or use default option if it is the top Screen
|
|
463
|
-
- (UIViewController *)findChildVCForConfigAndTrait:(RNSWindowTrait)trait includingModals:(BOOL)includingModals
|
|
464
|
-
{
|
|
465
|
-
UIViewController *lastViewController = [[self childViewControllers] lastObject];
|
|
466
|
-
if ([self.presentedViewController isKindOfClass:[RNSScreen class]]) {
|
|
467
|
-
lastViewController = self.presentedViewController;
|
|
468
|
-
// we don't want to allow controlling of status bar appearance when we present non-fullScreen modal
|
|
469
|
-
// and it is not possible if `modalPresentationCapturesStatusBarAppearance` is not set to YES, so even
|
|
470
|
-
// if we went into a modal here and ask it, it wouldn't take any effect. For fullScreen modals, the system
|
|
471
|
-
// asks them by itself, so we can stop traversing here.
|
|
472
|
-
// for screen orientation, we need to start the search again from that modal
|
|
473
|
-
return !includingModals
|
|
474
|
-
? nil
|
|
475
|
-
: [(RNSScreen *)lastViewController findChildVCForConfigAndTrait:trait includingModals:includingModals]
|
|
476
|
-
?: lastViewController;
|
|
477
|
-
}
|
|
641
|
+
#pragma mark - Paper specific
|
|
642
|
+
#else
|
|
478
643
|
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
if ([lastViewController conformsToProtocol:@protocol(RNScreensViewControllerDelegate)]) {
|
|
484
|
-
// If there is a child (should be VC of ScreenContainer or ScreenStack), that has a child that could provide the
|
|
485
|
-
// trait, we recursively go into its findChildVCForConfig, and if one of the children has the trait set, we return
|
|
486
|
-
// it, otherwise we return self if this VC has config, and nil if it doesn't we use
|
|
487
|
-
// `childViewControllerForStatusBarStyle` for all options since the behavior is the same for all of them
|
|
488
|
-
UIViewController *childScreen = [lastViewController childViewControllerForStatusBarStyle];
|
|
489
|
-
if ([childScreen isKindOfClass:[RNSScreen class]]) {
|
|
490
|
-
return [(RNSScreen *)childScreen findChildVCForConfigAndTrait:trait includingModals:includingModals]
|
|
491
|
-
?: selfOrNil;
|
|
492
|
-
} else {
|
|
493
|
-
return selfOrNil;
|
|
494
|
-
}
|
|
495
|
-
} else {
|
|
496
|
-
// child vc is not from this library, so we don't ask it
|
|
497
|
-
return selfOrNil;
|
|
498
|
-
}
|
|
499
|
-
}
|
|
644
|
+
- (void)setPointerEvents:(RCTPointerEvents)pointerEvents
|
|
645
|
+
{
|
|
646
|
+
// pointer events settings are managed by the parent screen container, we ignore
|
|
647
|
+
// any attempt of setting that via React props
|
|
500
648
|
}
|
|
501
649
|
|
|
502
|
-
- (
|
|
650
|
+
- (void)reactSetFrame:(CGRect)frame
|
|
503
651
|
{
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
case RNSWindowTraitAnimation: {
|
|
509
|
-
return ((RNSScreenView *)self.view).hasStatusBarAnimationSet;
|
|
510
|
-
}
|
|
511
|
-
case RNSWindowTraitHidden: {
|
|
512
|
-
return ((RNSScreenView *)self.view).hasStatusBarHiddenSet;
|
|
513
|
-
}
|
|
514
|
-
case RNSWindowTraitOrientation: {
|
|
515
|
-
return ((RNSScreenView *)self.view).hasOrientationSet;
|
|
516
|
-
}
|
|
517
|
-
case RNSWindowTraitHomeIndicatorHidden: {
|
|
518
|
-
return ((RNSScreenView *)self.view).hasHomeIndicatorHiddenSet;
|
|
519
|
-
}
|
|
520
|
-
default: {
|
|
521
|
-
RCTLogError(@"Unknown trait passed: %d", (int)trait);
|
|
522
|
-
}
|
|
652
|
+
_reactFrame = frame;
|
|
653
|
+
UIViewController *parentVC = self.reactViewController.parentViewController;
|
|
654
|
+
if (parentVC != nil && ![parentVC isKindOfClass:[RNScreensNavigationController class]]) {
|
|
655
|
+
[super reactSetFrame:frame];
|
|
523
656
|
}
|
|
524
|
-
|
|
657
|
+
// when screen is mounted under RNScreensNavigationController it's size is controller
|
|
658
|
+
// by the navigation controller itself. That is, it is set to fill space of
|
|
659
|
+
// the controller. In that case we ignore react layout system from managing
|
|
660
|
+
// the screen dimensions and we wait for the screen VC to update and then we
|
|
661
|
+
// pass the dimensions to ui view manager to take into account when laying out
|
|
662
|
+
// subviews
|
|
525
663
|
}
|
|
526
664
|
|
|
665
|
+
- (void)invalidate
|
|
666
|
+
{
|
|
667
|
+
_controller = nil;
|
|
668
|
+
}
|
|
527
669
|
#endif
|
|
528
670
|
|
|
529
|
-
|
|
530
|
-
{
|
|
531
|
-
[super viewDidLayoutSubviews];
|
|
671
|
+
@end
|
|
532
672
|
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
// screen size
|
|
538
|
-
BOOL isDisplayedWithinUINavController =
|
|
539
|
-
[self.parentViewController isKindOfClass:[RNScreensNavigationController class]];
|
|
540
|
-
BOOL isPresentedAsNativeModal = self.parentViewController == nil && self.presentingViewController != nil;
|
|
541
|
-
if ((isDisplayedWithinUINavController || isPresentedAsNativeModal) &&
|
|
542
|
-
!CGRectEqualToRect(_lastViewFrame, self.view.frame)) {
|
|
543
|
-
_lastViewFrame = self.view.frame;
|
|
544
|
-
[((RNSScreenView *)self.viewIfLoaded) updateBounds];
|
|
545
|
-
}
|
|
673
|
+
#ifdef RN_FABRIC_ENABLED
|
|
674
|
+
Class<RCTComponentViewProtocol> RNSScreenCls(void)
|
|
675
|
+
{
|
|
676
|
+
return RNSScreenView.class;
|
|
546
677
|
}
|
|
678
|
+
#endif
|
|
547
679
|
|
|
548
|
-
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
680
|
+
#pragma mark - RNSScreen
|
|
681
|
+
|
|
682
|
+
@implementation RNSScreen {
|
|
683
|
+
__weak id _previousFirstResponder;
|
|
684
|
+
CGRect _lastViewFrame;
|
|
685
|
+
RNSScreenView *_initialView;
|
|
686
|
+
UIView *_fakeView;
|
|
687
|
+
CADisplayLink *_animationTimer;
|
|
688
|
+
CGFloat _currentAlpha;
|
|
689
|
+
BOOL _closing;
|
|
690
|
+
BOOL _goingForward;
|
|
691
|
+
int _dismissCount;
|
|
692
|
+
BOOL _isSwiping;
|
|
693
|
+
BOOL _shouldNotify;
|
|
560
694
|
}
|
|
561
695
|
|
|
562
|
-
-
|
|
696
|
+
#pragma mark - Common
|
|
697
|
+
|
|
698
|
+
- (instancetype)initWithView:(UIView *)view
|
|
563
699
|
{
|
|
564
|
-
[super
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
700
|
+
if (self = [super init]) {
|
|
701
|
+
self.view = view;
|
|
702
|
+
_fakeView = [UIView new];
|
|
703
|
+
_shouldNotify = YES;
|
|
704
|
+
#ifdef RN_FABRIC_ENABLED
|
|
705
|
+
_initialView = (RNSScreenView *)view;
|
|
706
|
+
#endif
|
|
570
707
|
}
|
|
708
|
+
return self;
|
|
571
709
|
}
|
|
572
710
|
|
|
711
|
+
// TODO: Find out why this is executed when screen is going out
|
|
573
712
|
- (void)viewWillAppear:(BOOL)animated
|
|
574
713
|
{
|
|
575
714
|
[super viewWillAppear:animated];
|
|
576
|
-
|
|
577
715
|
if (!_isSwiping) {
|
|
578
|
-
[
|
|
716
|
+
[self.screenView notifyWillAppear];
|
|
579
717
|
if (self.transitionCoordinator.isInteractive) {
|
|
580
718
|
// we started dismissing with swipe gesture
|
|
581
719
|
_isSwiping = YES;
|
|
@@ -587,7 +725,6 @@
|
|
|
587
725
|
}
|
|
588
726
|
|
|
589
727
|
[self hideHeaderIfNecessary];
|
|
590
|
-
|
|
591
728
|
// as per documentation of these methods
|
|
592
729
|
_goingForward = [self isBeingPresented] || [self isMovingToParentViewController];
|
|
593
730
|
|
|
@@ -599,46 +736,16 @@
|
|
|
599
736
|
}
|
|
600
737
|
}
|
|
601
738
|
|
|
602
|
-
- (void)hideHeaderIfNecessary
|
|
603
|
-
{
|
|
604
|
-
#if !TARGET_OS_TV
|
|
605
|
-
// On iOS >=13, there is a bug when user transitions from screen with active search bar to screen without header
|
|
606
|
-
// In that case default iOS header will be shown. To fix this we hide header when the screens that appears has header
|
|
607
|
-
// hidden and search bar was active on previous screen. We need to do it asynchronously, because default header is
|
|
608
|
-
// added after viewWillAppear.
|
|
609
|
-
if (@available(iOS 13.0, *)) {
|
|
610
|
-
NSUInteger currentIndex = [self.navigationController.viewControllers indexOfObject:self];
|
|
611
|
-
|
|
612
|
-
if (currentIndex > 0 && [self.view.reactSubviews[0] isKindOfClass:[RNSScreenStackHeaderConfig class]]) {
|
|
613
|
-
UINavigationItem *prevNavigationItem =
|
|
614
|
-
[self.navigationController.viewControllers objectAtIndex:currentIndex - 1].navigationItem;
|
|
615
|
-
RNSScreenStackHeaderConfig *config = ((RNSScreenStackHeaderConfig *)self.view.reactSubviews[0]);
|
|
616
|
-
|
|
617
|
-
BOOL wasSearchBarActive = prevNavigationItem.searchController.active;
|
|
618
|
-
BOOL shouldHideHeader = config.hide;
|
|
619
|
-
|
|
620
|
-
if (wasSearchBarActive && shouldHideHeader) {
|
|
621
|
-
dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, 0);
|
|
622
|
-
dispatch_after(popTime, dispatch_get_main_queue(), ^(void) {
|
|
623
|
-
[self.navigationController setNavigationBarHidden:YES animated:NO];
|
|
624
|
-
});
|
|
625
|
-
}
|
|
626
|
-
}
|
|
627
|
-
}
|
|
628
|
-
#endif
|
|
629
|
-
}
|
|
630
|
-
|
|
631
739
|
- (void)viewWillDisappear:(BOOL)animated
|
|
632
740
|
{
|
|
633
741
|
[super viewWillDisappear:animated];
|
|
634
|
-
|
|
635
742
|
if (!self.transitionCoordinator.isInteractive) {
|
|
636
743
|
// user might have long pressed ios 14 back button item,
|
|
637
744
|
// so he can go back more than one screen and we need to dismiss more screens in JS stack then.
|
|
638
745
|
// We check it by calculating the difference between the index of currently displayed screen
|
|
639
746
|
// and the index of the target screen, which is the view of topViewController at this point.
|
|
640
747
|
// If the value is lower than 1, it means we are dismissing a modal, or navigating forward, or going back with JS.
|
|
641
|
-
int selfIndex = [self getIndexOfView:self.
|
|
748
|
+
int selfIndex = [self getIndexOfView:self.screenView];
|
|
642
749
|
int targetIndex = [self getIndexOfView:self.navigationController.topViewController.view];
|
|
643
750
|
_dismissCount = selfIndex - targetIndex > 0 ? selfIndex - targetIndex : 1;
|
|
644
751
|
} else {
|
|
@@ -647,7 +754,7 @@
|
|
|
647
754
|
|
|
648
755
|
// same flow as in viewWillAppear
|
|
649
756
|
if (!_isSwiping) {
|
|
650
|
-
[
|
|
757
|
+
[self.screenView notifyWillDisappear];
|
|
651
758
|
if (self.transitionCoordinator.isInteractive) {
|
|
652
759
|
_isSwiping = YES;
|
|
653
760
|
}
|
|
@@ -668,11 +775,10 @@
|
|
|
668
775
|
- (void)viewDidAppear:(BOOL)animated
|
|
669
776
|
{
|
|
670
777
|
[super viewDidAppear:animated];
|
|
671
|
-
|
|
672
778
|
if (!_isSwiping || _shouldNotify) {
|
|
673
779
|
// we are going forward or dismissing without swipe
|
|
674
780
|
// or successfully swiped back
|
|
675
|
-
[
|
|
781
|
+
[self.screenView notifyAppear];
|
|
676
782
|
[self notifyTransitionProgress:1.0 closing:NO goingForward:_goingForward];
|
|
677
783
|
}
|
|
678
784
|
|
|
@@ -683,54 +789,57 @@
|
|
|
683
789
|
- (void)viewDidDisappear:(BOOL)animated
|
|
684
790
|
{
|
|
685
791
|
[super viewDidDisappear:animated];
|
|
686
|
-
|
|
792
|
+
#ifdef RN_FABRIC_ENABLED
|
|
793
|
+
[self resetViewToScreen];
|
|
794
|
+
#endif
|
|
687
795
|
if (self.parentViewController == nil && self.presentingViewController == nil) {
|
|
688
|
-
if (
|
|
796
|
+
if (self.screenView.preventNativeDismiss) {
|
|
689
797
|
// if we want to prevent the native dismiss, we do not send dismissal event,
|
|
690
798
|
// but instead call `updateContainer`, which restores the JS navigation stack
|
|
691
|
-
[
|
|
692
|
-
[
|
|
799
|
+
[self.screenView.reactSuperview updateContainer];
|
|
800
|
+
[self.screenView notifyDismissCancelledWithDismissCount:_dismissCount];
|
|
693
801
|
} else {
|
|
694
802
|
// screen dismissed, send event
|
|
695
|
-
[
|
|
803
|
+
[self.screenView notifyDismissedWithCount:_dismissCount];
|
|
696
804
|
}
|
|
697
805
|
}
|
|
698
|
-
|
|
699
806
|
// same flow as in viewDidAppear
|
|
700
807
|
if (!_isSwiping || _shouldNotify) {
|
|
701
|
-
[
|
|
808
|
+
[self.screenView notifyDisappear];
|
|
702
809
|
[self notifyTransitionProgress:1.0 closing:YES goingForward:_goingForward];
|
|
703
810
|
}
|
|
704
811
|
|
|
705
812
|
_isSwiping = NO;
|
|
706
813
|
_shouldNotify = YES;
|
|
707
|
-
|
|
708
|
-
|
|
814
|
+
#ifdef RN_FABRIC_ENABLED
|
|
815
|
+
#else
|
|
816
|
+
[self traverseForScrollView:self.screenView];
|
|
817
|
+
#endif
|
|
709
818
|
}
|
|
710
819
|
|
|
711
|
-
- (void)
|
|
820
|
+
- (void)viewDidLayoutSubviews
|
|
712
821
|
{
|
|
713
|
-
|
|
714
|
-
// we don't want to send `scrollViewDidEndDecelerating` event to JS before the JS thread is ready
|
|
715
|
-
return;
|
|
716
|
-
}
|
|
717
|
-
if ([view isKindOfClass:[UIScrollView class]] &&
|
|
718
|
-
([[(UIScrollView *)view delegate] respondsToSelector:@selector(scrollViewDidEndDecelerating:)])) {
|
|
719
|
-
[[(UIScrollView *)view delegate] scrollViewDidEndDecelerating:(id)view];
|
|
720
|
-
}
|
|
721
|
-
[view.subviews enumerateObjectsUsingBlock:^(__kindof UIView *_Nonnull obj, NSUInteger idx, BOOL *_Nonnull stop) {
|
|
722
|
-
[self traverseForScrollView:obj];
|
|
723
|
-
}];
|
|
724
|
-
}
|
|
822
|
+
[super viewDidLayoutSubviews];
|
|
725
823
|
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
824
|
+
// The below code makes the screen view adapt dimensions provided by the system. We take these
|
|
825
|
+
// into account only when the view is mounted under RNScreensNavigationController in which case system
|
|
826
|
+
// provides additional padding to account for possible header, and in the case when screen is
|
|
827
|
+
// shown as a native modal, as the final dimensions of the modal on iOS 12+ are shorter than the
|
|
828
|
+
// screen size
|
|
829
|
+
BOOL isDisplayedWithinUINavController =
|
|
830
|
+
[self.parentViewController isKindOfClass:[RNScreensNavigationController class]];
|
|
831
|
+
BOOL isPresentedAsNativeModal = self.parentViewController == nil && self.presentingViewController != nil;
|
|
730
832
|
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
|
|
833
|
+
if (isDisplayedWithinUINavController || isPresentedAsNativeModal) {
|
|
834
|
+
#ifdef RN_FABRIC_ENABLED
|
|
835
|
+
[self.screenView updateBounds];
|
|
836
|
+
#else
|
|
837
|
+
if (!CGRectEqualToRect(_lastViewFrame, self.screenView.frame)) {
|
|
838
|
+
_lastViewFrame = self.screenView.frame;
|
|
839
|
+
[((RNSScreenView *)self.viewIfLoaded) updateBounds];
|
|
840
|
+
}
|
|
841
|
+
#endif
|
|
842
|
+
}
|
|
734
843
|
}
|
|
735
844
|
|
|
736
845
|
- (void)notifyFinishTransitioning
|
|
@@ -741,6 +850,31 @@
|
|
|
741
850
|
[RNSScreenWindowTraits updateWindowTraits];
|
|
742
851
|
}
|
|
743
852
|
|
|
853
|
+
- (void)willMoveToParentViewController:(UIViewController *)parent
|
|
854
|
+
{
|
|
855
|
+
[super willMoveToParentViewController:parent];
|
|
856
|
+
if (parent == nil) {
|
|
857
|
+
id responder = [self findFirstResponder:self.screenView];
|
|
858
|
+
if (responder != nil) {
|
|
859
|
+
_previousFirstResponder = responder;
|
|
860
|
+
}
|
|
861
|
+
}
|
|
862
|
+
}
|
|
863
|
+
|
|
864
|
+
- (id)findFirstResponder:(UIView *)parent
|
|
865
|
+
{
|
|
866
|
+
if (parent.isFirstResponder) {
|
|
867
|
+
return parent;
|
|
868
|
+
}
|
|
869
|
+
for (UIView *subView in parent.subviews) {
|
|
870
|
+
id responder = [self findFirstResponder:subView];
|
|
871
|
+
if (responder != nil) {
|
|
872
|
+
return responder;
|
|
873
|
+
}
|
|
874
|
+
}
|
|
875
|
+
return nil;
|
|
876
|
+
}
|
|
877
|
+
|
|
744
878
|
#pragma mark - transition progress related methods
|
|
745
879
|
|
|
746
880
|
- (void)setupProgressNotification
|
|
@@ -775,9 +909,240 @@
|
|
|
775
909
|
|
|
776
910
|
- (void)notifyTransitionProgress:(double)progress closing:(BOOL)closing goingForward:(BOOL)goingForward
|
|
777
911
|
{
|
|
778
|
-
[
|
|
912
|
+
if ([self.view isKindOfClass:[RNSScreenView class]]) {
|
|
913
|
+
// if the view is already snapshot, there is not sense in sending progress since on JS side
|
|
914
|
+
// the component is already not present
|
|
915
|
+
[(RNSScreenView *)self.view notifyTransitionProgress:progress closing:closing goingForward:goingForward];
|
|
916
|
+
}
|
|
917
|
+
}
|
|
918
|
+
|
|
919
|
+
#if !TARGET_OS_TV
|
|
920
|
+
// if the returned vc is a child, it means that it can provide config;
|
|
921
|
+
// if the returned vc is self, it means that there is no child for config and self has config to provide,
|
|
922
|
+
// so we return self which results in asking self for preferredStatusBarStyle/Animation etc.;
|
|
923
|
+
// if the returned vc is nil, it means none of children could provide config and self does not have config either,
|
|
924
|
+
// so if it was asked by parent, it will fallback to parent's option, or use default option if it is the top Screen
|
|
925
|
+
- (UIViewController *)findChildVCForConfigAndTrait:(RNSWindowTrait)trait includingModals:(BOOL)includingModals
|
|
926
|
+
{
|
|
927
|
+
UIViewController *lastViewController = [[self childViewControllers] lastObject];
|
|
928
|
+
if ([self.presentedViewController isKindOfClass:[RNSScreen class]]) {
|
|
929
|
+
lastViewController = self.presentedViewController;
|
|
930
|
+
// we don't want to allow controlling of status bar appearance when we present non-fullScreen modal
|
|
931
|
+
// and it is not possible if `modalPresentationCapturesStatusBarAppearance` is not set to YES, so even
|
|
932
|
+
// if we went into a modal here and ask it, it wouldn't take any effect. For fullScreen modals, the system
|
|
933
|
+
// asks them by itself, so we can stop traversing here.
|
|
934
|
+
// for screen orientation, we need to start the search again from that modal
|
|
935
|
+
return !includingModals
|
|
936
|
+
? nil
|
|
937
|
+
: [(RNSScreen *)lastViewController findChildVCForConfigAndTrait:trait includingModals:includingModals]
|
|
938
|
+
?: lastViewController;
|
|
939
|
+
}
|
|
940
|
+
|
|
941
|
+
UIViewController *selfOrNil = [self hasTraitSet:trait] ? self : nil;
|
|
942
|
+
if (lastViewController == nil) {
|
|
943
|
+
return selfOrNil;
|
|
944
|
+
} else {
|
|
945
|
+
if ([lastViewController conformsToProtocol:@protocol(RNScreensViewControllerDelegate)]) {
|
|
946
|
+
// If there is a child (should be VC of ScreenContainer or ScreenStack), that has a child that could provide the
|
|
947
|
+
// trait, we recursively go into its findChildVCForConfig, and if one of the children has the trait set, we return
|
|
948
|
+
// it, otherwise we return self if this VC has config, and nil if it doesn't we use
|
|
949
|
+
// `childViewControllerForStatusBarStyle` for all options since the behavior is the same for all of them
|
|
950
|
+
UIViewController *childScreen = [lastViewController childViewControllerForStatusBarStyle];
|
|
951
|
+
if ([childScreen isKindOfClass:[RNSScreen class]]) {
|
|
952
|
+
return [(RNSScreen *)childScreen findChildVCForConfigAndTrait:trait includingModals:includingModals]
|
|
953
|
+
?: selfOrNil;
|
|
954
|
+
} else {
|
|
955
|
+
return selfOrNil;
|
|
956
|
+
}
|
|
957
|
+
} else {
|
|
958
|
+
// child vc is not from this library, so we don't ask it
|
|
959
|
+
return selfOrNil;
|
|
960
|
+
}
|
|
961
|
+
}
|
|
962
|
+
}
|
|
963
|
+
|
|
964
|
+
- (BOOL)hasTraitSet:(RNSWindowTrait)trait
|
|
965
|
+
{
|
|
966
|
+
switch (trait) {
|
|
967
|
+
case RNSWindowTraitStyle: {
|
|
968
|
+
return self.screenView.hasStatusBarStyleSet;
|
|
969
|
+
}
|
|
970
|
+
case RNSWindowTraitAnimation: {
|
|
971
|
+
return self.screenView.hasStatusBarAnimationSet;
|
|
972
|
+
}
|
|
973
|
+
case RNSWindowTraitHidden: {
|
|
974
|
+
return self.screenView.hasStatusBarHiddenSet;
|
|
975
|
+
}
|
|
976
|
+
case RNSWindowTraitOrientation: {
|
|
977
|
+
return self.screenView.hasOrientationSet;
|
|
978
|
+
}
|
|
979
|
+
case RNSWindowTraitHomeIndicatorHidden: {
|
|
980
|
+
return self.screenView.hasHomeIndicatorHiddenSet;
|
|
981
|
+
}
|
|
982
|
+
default: {
|
|
983
|
+
RCTLogError(@"Unknown trait passed: %d", (int)trait);
|
|
984
|
+
}
|
|
985
|
+
}
|
|
986
|
+
return NO;
|
|
987
|
+
}
|
|
988
|
+
|
|
989
|
+
- (UIViewController *)childViewControllerForStatusBarHidden
|
|
990
|
+
{
|
|
991
|
+
UIViewController *vc = [self findChildVCForConfigAndTrait:RNSWindowTraitHidden includingModals:NO];
|
|
992
|
+
return vc == self ? nil : vc;
|
|
993
|
+
}
|
|
994
|
+
|
|
995
|
+
- (BOOL)prefersStatusBarHidden
|
|
996
|
+
{
|
|
997
|
+
return self.screenView.statusBarHidden;
|
|
998
|
+
}
|
|
999
|
+
|
|
1000
|
+
- (UIViewController *)childViewControllerForStatusBarStyle
|
|
1001
|
+
{
|
|
1002
|
+
UIViewController *vc = [self findChildVCForConfigAndTrait:RNSWindowTraitStyle includingModals:NO];
|
|
1003
|
+
return vc == self ? nil : vc;
|
|
1004
|
+
}
|
|
1005
|
+
|
|
1006
|
+
- (UIStatusBarStyle)preferredStatusBarStyle
|
|
1007
|
+
{
|
|
1008
|
+
return [RNSScreenWindowTraits statusBarStyleForRNSStatusBarStyle:self.screenView.statusBarStyle];
|
|
1009
|
+
}
|
|
1010
|
+
|
|
1011
|
+
- (UIStatusBarAnimation)preferredStatusBarUpdateAnimation
|
|
1012
|
+
{
|
|
1013
|
+
UIViewController *vc = [self findChildVCForConfigAndTrait:RNSWindowTraitAnimation includingModals:NO];
|
|
1014
|
+
|
|
1015
|
+
if ([vc isKindOfClass:[RNSScreen class]]) {
|
|
1016
|
+
return ((RNSScreen *)vc).screenView.statusBarAnimation;
|
|
1017
|
+
}
|
|
1018
|
+
return UIStatusBarAnimationFade;
|
|
1019
|
+
}
|
|
1020
|
+
|
|
1021
|
+
- (UIInterfaceOrientationMask)supportedInterfaceOrientations
|
|
1022
|
+
{
|
|
1023
|
+
UIViewController *vc = [self findChildVCForConfigAndTrait:RNSWindowTraitOrientation includingModals:YES];
|
|
1024
|
+
|
|
1025
|
+
if ([vc isKindOfClass:[RNSScreen class]]) {
|
|
1026
|
+
return ((RNSScreen *)vc).screenView.screenOrientation;
|
|
1027
|
+
}
|
|
1028
|
+
return UIInterfaceOrientationMaskAllButUpsideDown;
|
|
1029
|
+
}
|
|
1030
|
+
|
|
1031
|
+
- (UIViewController *)childViewControllerForHomeIndicatorAutoHidden
|
|
1032
|
+
{
|
|
1033
|
+
UIViewController *vc = [self findChildVCForConfigAndTrait:RNSWindowTraitHomeIndicatorHidden includingModals:YES];
|
|
1034
|
+
return vc == self ? nil : vc;
|
|
1035
|
+
}
|
|
1036
|
+
|
|
1037
|
+
- (BOOL)prefersHomeIndicatorAutoHidden
|
|
1038
|
+
{
|
|
1039
|
+
return self.screenView.homeIndicatorHidden;
|
|
779
1040
|
}
|
|
780
1041
|
|
|
1042
|
+
- (int)getIndexOfView:(UIView *)view
|
|
1043
|
+
{
|
|
1044
|
+
return (int)[[self.screenView.reactSuperview reactSubviews] indexOfObject:view];
|
|
1045
|
+
}
|
|
1046
|
+
|
|
1047
|
+
- (int)getParentChildrenCount
|
|
1048
|
+
{
|
|
1049
|
+
return (int)[[self.screenView.reactSuperview reactSubviews] count];
|
|
1050
|
+
}
|
|
1051
|
+
#endif
|
|
1052
|
+
|
|
1053
|
+
// since on Fabric the view of controller can be a snapshot of type `UIView`,
|
|
1054
|
+
// when we want to check props of ScreenView, we need to get them from _initialView
|
|
1055
|
+
- (RNSScreenView *)screenView
|
|
1056
|
+
{
|
|
1057
|
+
#ifdef RN_FABRIC_ENABLED
|
|
1058
|
+
return _initialView;
|
|
1059
|
+
#else
|
|
1060
|
+
return (RNSScreenView *)self.view;
|
|
1061
|
+
#endif
|
|
1062
|
+
}
|
|
1063
|
+
|
|
1064
|
+
- (void)hideHeaderIfNecessary
|
|
1065
|
+
{
|
|
1066
|
+
#if !TARGET_OS_TV
|
|
1067
|
+
// On iOS >=13, there is a bug when user transitions from screen with active search bar to screen without header
|
|
1068
|
+
// In that case default iOS header will be shown. To fix this we hide header when the screens that appears has header
|
|
1069
|
+
// hidden and search bar was active on previous screen. We need to do it asynchronously, because default header is
|
|
1070
|
+
// added after viewWillAppear.
|
|
1071
|
+
if (@available(iOS 13.0, *)) {
|
|
1072
|
+
NSUInteger currentIndex = [self.navigationController.viewControllers indexOfObject:self];
|
|
1073
|
+
|
|
1074
|
+
// we need to check whether reactSubviews array is empty, because on Fabric child nodes are unmounted first ->
|
|
1075
|
+
// reactSubviews array may be empty
|
|
1076
|
+
if (currentIndex > 0 && [self.screenView.reactSubviews count] > 0 &&
|
|
1077
|
+
[self.screenView.reactSubviews[0] isKindOfClass:[RNSScreenStackHeaderConfig class]]) {
|
|
1078
|
+
UINavigationItem *prevNavigationItem =
|
|
1079
|
+
[self.navigationController.viewControllers objectAtIndex:currentIndex - 1].navigationItem;
|
|
1080
|
+
RNSScreenStackHeaderConfig *config = ((RNSScreenStackHeaderConfig *)self.screenView.reactSubviews[0]);
|
|
1081
|
+
|
|
1082
|
+
BOOL wasSearchBarActive = prevNavigationItem.searchController.active;
|
|
1083
|
+
|
|
1084
|
+
#ifdef RN_FABRIC_ENABLED
|
|
1085
|
+
BOOL shouldHideHeader = !config.show;
|
|
1086
|
+
#else
|
|
1087
|
+
BOOL shouldHideHeader = config.hide;
|
|
1088
|
+
#endif
|
|
1089
|
+
|
|
1090
|
+
if (wasSearchBarActive && shouldHideHeader) {
|
|
1091
|
+
dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, 0);
|
|
1092
|
+
dispatch_after(popTime, dispatch_get_main_queue(), ^(void) {
|
|
1093
|
+
[self.navigationController setNavigationBarHidden:YES animated:NO];
|
|
1094
|
+
});
|
|
1095
|
+
}
|
|
1096
|
+
}
|
|
1097
|
+
}
|
|
1098
|
+
#endif
|
|
1099
|
+
}
|
|
1100
|
+
|
|
1101
|
+
#ifdef RN_FABRIC_ENABLED
|
|
1102
|
+
#pragma mark - Fabric specific
|
|
1103
|
+
|
|
1104
|
+
- (void)setViewToSnapshot:(UIView *)snapshot
|
|
1105
|
+
{
|
|
1106
|
+
// modals of native stack seem not to support
|
|
1107
|
+
// changing their view by just setting the view
|
|
1108
|
+
if (_initialView.stackPresentation != RNSScreenStackPresentationPush) {
|
|
1109
|
+
UIView *superView = self.view.superview;
|
|
1110
|
+
[self.view removeFromSuperview];
|
|
1111
|
+
self.view = snapshot;
|
|
1112
|
+
[superView addSubview:self.view];
|
|
1113
|
+
} else {
|
|
1114
|
+
[self.view removeFromSuperview];
|
|
1115
|
+
self.view = snapshot;
|
|
1116
|
+
}
|
|
1117
|
+
}
|
|
1118
|
+
|
|
1119
|
+
- (void)resetViewToScreen
|
|
1120
|
+
{
|
|
1121
|
+
if (self.view != _initialView) {
|
|
1122
|
+
[self.view removeFromSuperview];
|
|
1123
|
+
self.view = _initialView;
|
|
1124
|
+
}
|
|
1125
|
+
}
|
|
1126
|
+
|
|
1127
|
+
#else
|
|
1128
|
+
#pragma mark - Paper specific
|
|
1129
|
+
|
|
1130
|
+
- (void)traverseForScrollView:(UIView *)view
|
|
1131
|
+
{
|
|
1132
|
+
if (![[self.view valueForKey:@"_bridge"] valueForKey:@"_jsThread"]) {
|
|
1133
|
+
// we don't want to send `scrollViewDidEndDecelerating` event to JS before the JS thread is ready
|
|
1134
|
+
return;
|
|
1135
|
+
}
|
|
1136
|
+
if ([view isKindOfClass:[UIScrollView class]] &&
|
|
1137
|
+
([[(UIScrollView *)view delegate] respondsToSelector:@selector(scrollViewDidEndDecelerating:)])) {
|
|
1138
|
+
[[(UIScrollView *)view delegate] scrollViewDidEndDecelerating:(id)view];
|
|
1139
|
+
}
|
|
1140
|
+
[view.subviews enumerateObjectsUsingBlock:^(__kindof UIView *_Nonnull obj, NSUInteger idx, BOOL *_Nonnull stop) {
|
|
1141
|
+
[self traverseForScrollView:obj];
|
|
1142
|
+
}];
|
|
1143
|
+
}
|
|
1144
|
+
#endif
|
|
1145
|
+
|
|
781
1146
|
@end
|
|
782
1147
|
|
|
783
1148
|
@implementation RNSScreenManager
|
|
@@ -789,6 +1154,8 @@ RCT_REMAP_VIEW_PROPERTY(activityState, activityStateOrNil, NSNumber)
|
|
|
789
1154
|
RCT_EXPORT_VIEW_PROPERTY(customAnimationOnSwipe, BOOL);
|
|
790
1155
|
RCT_EXPORT_VIEW_PROPERTY(fullScreenSwipeEnabled, BOOL);
|
|
791
1156
|
RCT_EXPORT_VIEW_PROPERTY(gestureEnabled, BOOL)
|
|
1157
|
+
RCT_EXPORT_VIEW_PROPERTY(gestureResponseDistance, NSDictionary)
|
|
1158
|
+
RCT_EXPORT_VIEW_PROPERTY(hideKeyboardOnSwipe, BOOL)
|
|
792
1159
|
RCT_EXPORT_VIEW_PROPERTY(preventNativeDismiss, BOOL)
|
|
793
1160
|
RCT_EXPORT_VIEW_PROPERTY(replaceAnimation, RNSScreenReplaceAnimation)
|
|
794
1161
|
RCT_EXPORT_VIEW_PROPERTY(stackPresentation, RNSScreenStackPresentation)
|
|
@@ -870,6 +1237,16 @@ RCT_ENUM_CONVERTER(
|
|
|
870
1237
|
integerValue)
|
|
871
1238
|
|
|
872
1239
|
#if !TARGET_OS_TV
|
|
1240
|
+
RCT_ENUM_CONVERTER(
|
|
1241
|
+
UIStatusBarAnimation,
|
|
1242
|
+
(@{
|
|
1243
|
+
@"none" : @(UIStatusBarAnimationNone),
|
|
1244
|
+
@"fade" : @(UIStatusBarAnimationFade),
|
|
1245
|
+
@"slide" : @(UIStatusBarAnimationSlide)
|
|
1246
|
+
}),
|
|
1247
|
+
UIStatusBarAnimationNone,
|
|
1248
|
+
integerValue)
|
|
1249
|
+
|
|
873
1250
|
RCT_ENUM_CONVERTER(
|
|
874
1251
|
RNSStatusBarStyle,
|
|
875
1252
|
(@{
|