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
|
@@ -1,21 +1,39 @@
|
|
|
1
|
-
#
|
|
2
|
-
#import
|
|
3
|
-
#import
|
|
4
|
-
#import
|
|
5
|
-
#import
|
|
1
|
+
#ifdef RN_FABRIC_ENABLED
|
|
2
|
+
#import <React/RCTMountingTransactionObserving.h>
|
|
3
|
+
#import <React/RCTSurfaceTouchHandler.h>
|
|
4
|
+
#import <React/UIView+React.h>
|
|
5
|
+
#import <react/renderer/components/rnscreens/ComponentDescriptors.h>
|
|
6
|
+
#import <react/renderer/components/rnscreens/EventEmitters.h>
|
|
7
|
+
#import <react/renderer/components/rnscreens/Props.h>
|
|
8
|
+
#import <react/renderer/components/rnscreens/RCTComponentViewHelpers.h>
|
|
6
9
|
|
|
10
|
+
#import "RCTFabricComponentsPlugins.h"
|
|
11
|
+
|
|
12
|
+
#else
|
|
7
13
|
#import <React/RCTBridge.h>
|
|
8
14
|
#import <React/RCTRootContentView.h>
|
|
9
15
|
#import <React/RCTShadowView.h>
|
|
10
16
|
#import <React/RCTTouchHandler.h>
|
|
11
17
|
#import <React/RCTUIManager.h>
|
|
12
18
|
#import <React/RCTUIManagerUtils.h>
|
|
19
|
+
#endif // RN_FABRIC_ENABLED
|
|
20
|
+
|
|
21
|
+
#import "RNSScreen.h"
|
|
22
|
+
#import "RNSScreenStack.h"
|
|
23
|
+
#import "RNSScreenStackAnimator.h"
|
|
24
|
+
#import "RNSScreenStackHeaderConfig.h"
|
|
25
|
+
#import "RNSScreenWindowTraits.h"
|
|
13
26
|
|
|
14
27
|
@interface RNSScreenStackView () <
|
|
15
28
|
UINavigationControllerDelegate,
|
|
16
29
|
UIAdaptivePresentationControllerDelegate,
|
|
17
30
|
UIGestureRecognizerDelegate,
|
|
18
|
-
UIViewControllerTransitioningDelegate
|
|
31
|
+
UIViewControllerTransitioningDelegate
|
|
32
|
+
#ifdef RN_FABRIC_ENABLED
|
|
33
|
+
,
|
|
34
|
+
RCTMountingTransactionObserving
|
|
35
|
+
#endif
|
|
36
|
+
>
|
|
19
37
|
|
|
20
38
|
@property (nonatomic) NSMutableArray<UIViewController *> *presentedModals;
|
|
21
39
|
@property (nonatomic) BOOL updatingModals;
|
|
@@ -71,13 +89,29 @@
|
|
|
71
89
|
@implementation RNSScreenStackView {
|
|
72
90
|
UINavigationController *_controller;
|
|
73
91
|
NSMutableArray<RNSScreenView *> *_reactSubviews;
|
|
74
|
-
__weak RNSScreenStackManager *_manager;
|
|
75
|
-
BOOL _hasLayout;
|
|
76
92
|
BOOL _invalidated;
|
|
93
|
+
BOOL _isFullWidthSwiping;
|
|
77
94
|
UIPercentDrivenInteractiveTransition *_interactionController;
|
|
95
|
+
BOOL _hasLayout;
|
|
96
|
+
__weak RNSScreenStackManager *_manager;
|
|
78
97
|
BOOL _updateScheduled;
|
|
79
|
-
|
|
98
|
+
#ifdef RN_FABRIC_ENABLED
|
|
99
|
+
UIView *_snapshot;
|
|
100
|
+
#endif
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
#ifdef RN_FABRIC_ENABLED
|
|
104
|
+
- (instancetype)initWithFrame:(CGRect)frame
|
|
105
|
+
{
|
|
106
|
+
if (self = [super initWithFrame:frame]) {
|
|
107
|
+
static const auto defaultProps = std::make_shared<const facebook::react::RNSScreenStackProps>();
|
|
108
|
+
_props = defaultProps;
|
|
109
|
+
[self initCommonProps];
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
return self;
|
|
80
113
|
}
|
|
114
|
+
#endif // RN_FABRIC_ENABLED
|
|
81
115
|
|
|
82
116
|
- (instancetype)initWithManager:(RNSScreenStackManager *)manager
|
|
83
117
|
{
|
|
@@ -85,26 +119,41 @@
|
|
|
85
119
|
_hasLayout = NO;
|
|
86
120
|
_invalidated = NO;
|
|
87
121
|
_manager = manager;
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
122
|
+
[self initCommonProps];
|
|
123
|
+
}
|
|
124
|
+
return self;
|
|
125
|
+
}
|
|
92
126
|
|
|
127
|
+
- (void)initCommonProps
|
|
128
|
+
{
|
|
129
|
+
_reactSubviews = [NSMutableArray new];
|
|
130
|
+
_presentedModals = [NSMutableArray new];
|
|
131
|
+
_controller = [RNScreensNavigationController new];
|
|
132
|
+
_controller.delegate = self;
|
|
93
133
|
#if !TARGET_OS_TV
|
|
94
|
-
|
|
134
|
+
[self setupGestureHandlers];
|
|
95
135
|
#endif
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
}
|
|
102
|
-
return self;
|
|
136
|
+
// we have to initialize viewControllers with a non empty array for
|
|
137
|
+
// largeTitle header to render in the opened state. If it is empty
|
|
138
|
+
// the header will render in collapsed state which is perhaps a bug
|
|
139
|
+
// in UIKit but ¯\_(ツ)_/¯
|
|
140
|
+
[_controller setViewControllers:@[ [UIViewController new] ]];
|
|
103
141
|
}
|
|
104
142
|
|
|
105
|
-
-
|
|
143
|
+
#pragma mark - Common
|
|
144
|
+
|
|
145
|
+
- (void)emitOnFinishTransitioningEvent
|
|
106
146
|
{
|
|
107
|
-
|
|
147
|
+
#ifdef RN_FABRIC_ENABLED
|
|
148
|
+
if (_eventEmitter != nullptr) {
|
|
149
|
+
std::dynamic_pointer_cast<const facebook::react::RNSScreenStackEventEmitter>(_eventEmitter)
|
|
150
|
+
->onFinishTransitioning(facebook::react::RNSScreenStackEventEmitter::OnFinishTransitioning{});
|
|
151
|
+
}
|
|
152
|
+
#else
|
|
153
|
+
if (self.onFinishTransitioning) {
|
|
154
|
+
self.onFinishTransitioning(nil);
|
|
155
|
+
}
|
|
156
|
+
#endif
|
|
108
157
|
}
|
|
109
158
|
|
|
110
159
|
- (void)navigationController:(UINavigationController *)navigationController
|
|
@@ -112,6 +161,12 @@
|
|
|
112
161
|
animated:(BOOL)animated
|
|
113
162
|
{
|
|
114
163
|
UIView *view = viewController.view;
|
|
164
|
+
#ifdef RN_FABRIC_ENABLED
|
|
165
|
+
if (![view isKindOfClass:[RNSScreenView class]]) {
|
|
166
|
+
// if the current view is a snapshot, config was already removed so we don't trigger the method
|
|
167
|
+
return;
|
|
168
|
+
}
|
|
169
|
+
#endif
|
|
115
170
|
RNSScreenStackHeaderConfig *config = nil;
|
|
116
171
|
for (UIView *subview in view.reactSubviews) {
|
|
117
172
|
if ([subview isKindOfClass:[RNSScreenStackHeaderConfig class]]) {
|
|
@@ -122,100 +177,65 @@
|
|
|
122
177
|
[RNSScreenStackHeaderConfig willShowViewController:viewController animated:animated withConfig:config];
|
|
123
178
|
}
|
|
124
179
|
|
|
125
|
-
- (void)navigationController:(UINavigationController *)navigationController
|
|
126
|
-
didShowViewController:(UIViewController *)viewController
|
|
127
|
-
animated:(BOOL)animated
|
|
128
|
-
{
|
|
129
|
-
if (self.onFinishTransitioning) {
|
|
130
|
-
self.onFinishTransitioning(nil);
|
|
131
|
-
}
|
|
132
|
-
[RNSScreenWindowTraits updateWindowTraits];
|
|
133
|
-
}
|
|
134
|
-
|
|
135
180
|
- (void)presentationControllerDidDismiss:(UIPresentationController *)presentationController
|
|
136
181
|
{
|
|
137
182
|
// We don't directly set presentation delegate but instead rely on the ScreenView's delegate to
|
|
138
183
|
// forward certain calls to the container (Stack).
|
|
139
|
-
|
|
140
|
-
if ([screenView isKindOfClass:[RNSScreenView class]]) {
|
|
184
|
+
if ([presentationController.presentedViewController isKindOfClass:[RNSScreen class]]) {
|
|
141
185
|
// we trigger the update of status bar's appearance here because there is no other lifecycle method
|
|
142
186
|
// that can handle it when dismissing a modal, the same for orientation
|
|
143
187
|
[RNSScreenWindowTraits updateWindowTraits];
|
|
144
188
|
[_presentedModals removeObject:presentationController.presentedViewController];
|
|
145
|
-
|
|
146
|
-
// have tried to push another one during the transition
|
|
189
|
+
|
|
147
190
|
_updatingModals = NO;
|
|
191
|
+
#ifdef RN_FABRIC_ENABLED
|
|
192
|
+
[self emitOnFinishTransitioningEvent];
|
|
193
|
+
#else
|
|
194
|
+
// we double check if there are no new controllers pending to be presented since someone could
|
|
195
|
+
// have tried to push another one during the transition.
|
|
196
|
+
// We don't do it on Fabric since update of container will be triggered from "unmount" method afterwards
|
|
148
197
|
[self updateContainer];
|
|
149
198
|
if (self.onFinishTransitioning) {
|
|
150
199
|
// instead of directly triggering onFinishTransitioning this time we enqueue the event on the
|
|
151
200
|
// main queue. We do that because onDismiss event is also enqueued and we want for the transition
|
|
152
201
|
// finish event to arrive later than onDismiss (see RNSScreen#notifyDismiss)
|
|
153
202
|
dispatch_async(dispatch_get_main_queue(), ^{
|
|
154
|
-
|
|
155
|
-
self.onFinishTransitioning(nil);
|
|
156
|
-
}
|
|
203
|
+
[self emitOnFinishTransitioningEvent];
|
|
157
204
|
});
|
|
158
205
|
}
|
|
206
|
+
#endif
|
|
159
207
|
}
|
|
160
208
|
}
|
|
161
209
|
|
|
162
|
-
- (void)markChildUpdated
|
|
163
|
-
{
|
|
164
|
-
// do nothing
|
|
165
|
-
}
|
|
166
|
-
|
|
167
|
-
- (void)didUpdateChildren
|
|
168
|
-
{
|
|
169
|
-
// do nothing
|
|
170
|
-
}
|
|
171
|
-
|
|
172
|
-
- (void)insertReactSubview:(RNSScreenView *)subview atIndex:(NSInteger)atIndex
|
|
173
|
-
{
|
|
174
|
-
if (![subview isKindOfClass:[RNSScreenView class]]) {
|
|
175
|
-
RCTLogError(@"ScreenStack only accepts children of type Screen");
|
|
176
|
-
return;
|
|
177
|
-
}
|
|
178
|
-
subview.reactSuperview = self;
|
|
179
|
-
[_reactSubviews insertObject:subview atIndex:atIndex];
|
|
180
|
-
}
|
|
181
|
-
|
|
182
|
-
- (void)removeReactSubview:(RNSScreenView *)subview
|
|
183
|
-
{
|
|
184
|
-
subview.reactSuperview = nil;
|
|
185
|
-
[_reactSubviews removeObject:subview];
|
|
186
|
-
}
|
|
187
|
-
|
|
188
210
|
- (NSArray<UIView *> *)reactSubviews
|
|
189
211
|
{
|
|
190
212
|
return _reactSubviews;
|
|
191
213
|
}
|
|
192
214
|
|
|
193
|
-
- (void)didUpdateReactSubviews
|
|
194
|
-
{
|
|
195
|
-
// we need to wait until children have their layout set. At this point they don't have the layout
|
|
196
|
-
// set yet, however the layout call is already enqueued on ui thread. Enqueuing update call on the
|
|
197
|
-
// ui queue will guarantee that the update will run after layout.
|
|
198
|
-
dispatch_async(dispatch_get_main_queue(), ^{
|
|
199
|
-
self->_hasLayout = YES;
|
|
200
|
-
[self maybeAddToParentAndUpdateContainer];
|
|
201
|
-
});
|
|
202
|
-
}
|
|
203
|
-
|
|
204
215
|
- (void)didMoveToWindow
|
|
205
216
|
{
|
|
206
217
|
[super didMoveToWindow];
|
|
218
|
+
#ifdef RN_FABRIC_ENABLED
|
|
219
|
+
// for handling nested stacks
|
|
220
|
+
[self maybeAddToParentAndUpdateContainer];
|
|
221
|
+
#else
|
|
207
222
|
if (!_invalidated) {
|
|
208
223
|
// We check whether the view has been invalidated before running side-effects in didMoveToWindow
|
|
209
224
|
// This is needed because when LayoutAnimations are used it is possible for view to be re-attached
|
|
210
225
|
// to a window despite the fact it has been removed from the React Native view hierarchy.
|
|
211
226
|
[self maybeAddToParentAndUpdateContainer];
|
|
212
227
|
}
|
|
228
|
+
#endif
|
|
213
229
|
}
|
|
214
230
|
|
|
215
231
|
- (void)maybeAddToParentAndUpdateContainer
|
|
216
232
|
{
|
|
217
233
|
BOOL wasScreenMounted = _controller.parentViewController != nil;
|
|
234
|
+
#ifdef RN_FABRIC_ENABLED
|
|
235
|
+
BOOL isScreenReadyForShowing = self.window;
|
|
236
|
+
#else
|
|
218
237
|
BOOL isScreenReadyForShowing = self.window && _hasLayout;
|
|
238
|
+
#endif
|
|
219
239
|
if (!isScreenReadyForShowing && !wasScreenMounted) {
|
|
220
240
|
// We wait with adding to parent controller until the stack is mounted and has its initial
|
|
221
241
|
// layout done.
|
|
@@ -318,9 +338,7 @@
|
|
|
318
338
|
__weak RNSScreenStackView *weakSelf = self;
|
|
319
339
|
|
|
320
340
|
void (^afterTransitions)(void) = ^{
|
|
321
|
-
|
|
322
|
-
weakSelf.onFinishTransitioning(nil);
|
|
323
|
-
}
|
|
341
|
+
[weakSelf emitOnFinishTransitioningEvent];
|
|
324
342
|
weakSelf.updatingModals = NO;
|
|
325
343
|
if (weakSelf.scheduleModalsUpdate) {
|
|
326
344
|
// if modals update was requested during setModalViewControllers we set scheduleModalsUpdate
|
|
@@ -364,7 +382,7 @@
|
|
|
364
382
|
#endif
|
|
365
383
|
|
|
366
384
|
BOOL shouldAnimate = lastModal && [next isKindOfClass:[RNSScreen class]] &&
|
|
367
|
-
((
|
|
385
|
+
((RNSScreen *)next).screenView.stackAnimation != RNSScreenStackAnimationNone;
|
|
368
386
|
|
|
369
387
|
// if you want to present another modal quick enough after dismissing the previous one,
|
|
370
388
|
// it will result in wrong changeRootController, see repro in
|
|
@@ -391,7 +409,7 @@
|
|
|
391
409
|
[_presentedModals containsObject:changeRootController.presentedViewController]) {
|
|
392
410
|
BOOL shouldAnimate = changeRootIndex == controllers.count &&
|
|
393
411
|
[changeRootController.presentedViewController isKindOfClass:[RNSScreen class]] &&
|
|
394
|
-
((
|
|
412
|
+
((RNSScreen *)changeRootController.presentedViewController).screenView.stackAnimation !=
|
|
395
413
|
RNSScreenStackAnimationNone;
|
|
396
414
|
[changeRootController dismissViewControllerAnimated:shouldAnimate completion:finish];
|
|
397
415
|
} else {
|
|
@@ -434,33 +452,39 @@
|
|
|
434
452
|
}
|
|
435
453
|
|
|
436
454
|
UIViewController *top = controllers.lastObject;
|
|
437
|
-
|
|
455
|
+
#ifdef RN_FABRIC_ENABLED
|
|
456
|
+
UIViewController *previousTop = _controller.topViewController;
|
|
457
|
+
#else
|
|
458
|
+
UIViewController *previousTop = _controller.viewControllers.lastObject;
|
|
459
|
+
#endif
|
|
438
460
|
|
|
439
|
-
//
|
|
461
|
+
// At the start we set viewControllers to contain a single UIViewController
|
|
440
462
|
// instance. This is a workaround for header height adjustment bug (see comment
|
|
441
463
|
// in the init function). Here, we need to detect if the initial empty
|
|
442
464
|
// controller is still there
|
|
443
|
-
BOOL firstTimePush = ![
|
|
465
|
+
BOOL firstTimePush = ![previousTop isKindOfClass:[RNSScreen class]];
|
|
444
466
|
|
|
445
467
|
if (firstTimePush) {
|
|
446
468
|
// nothing pushed yet
|
|
447
469
|
[_controller setViewControllers:controllers animated:NO];
|
|
448
|
-
} else if (top !=
|
|
449
|
-
|
|
450
|
-
// `stackAnimation: 'none'`, which will resolve in no animation anyways.
|
|
451
|
-
if (![controllers containsObject:lastTop]) {
|
|
470
|
+
} else if (top != previousTop) {
|
|
471
|
+
if (![controllers containsObject:previousTop]) {
|
|
452
472
|
// if the previous top screen does not exist anymore and the new top was not on the stack before, probably replace
|
|
453
473
|
// was called, so we check the animation
|
|
454
474
|
if (![_controller.viewControllers containsObject:top] &&
|
|
455
475
|
((RNSScreenView *)top.view).replaceAnimation == RNSScreenReplaceAnimationPush) {
|
|
456
476
|
// setting new controllers with animation does `push` animation by default
|
|
477
|
+
#ifdef RN_FABRIC_ENABLED
|
|
478
|
+
auto screenController = (RNSScreen *)top;
|
|
479
|
+
[screenController resetViewToScreen];
|
|
480
|
+
#endif
|
|
457
481
|
[_controller setViewControllers:controllers animated:YES];
|
|
458
482
|
} else {
|
|
459
483
|
// last top controller is no longer on stack
|
|
460
484
|
// in this case we set the controllers stack to the new list with
|
|
461
485
|
// added the last top element to it and perform (animated) pop
|
|
462
486
|
NSMutableArray *newControllers = [NSMutableArray arrayWithArray:controllers];
|
|
463
|
-
[newControllers addObject:
|
|
487
|
+
[newControllers addObject:previousTop];
|
|
464
488
|
[_controller setViewControllers:newControllers animated:NO];
|
|
465
489
|
[_controller popViewControllerAnimated:YES];
|
|
466
490
|
}
|
|
@@ -471,6 +495,10 @@
|
|
|
471
495
|
NSMutableArray *newControllers = [NSMutableArray arrayWithArray:controllers];
|
|
472
496
|
[newControllers removeLastObject];
|
|
473
497
|
[_controller setViewControllers:newControllers animated:NO];
|
|
498
|
+
#ifdef RN_FABRIC_ENABLED
|
|
499
|
+
auto screenController = (RNSScreen *)top;
|
|
500
|
+
[screenController resetViewToScreen];
|
|
501
|
+
#endif
|
|
474
502
|
[_controller pushViewController:top animated:YES];
|
|
475
503
|
} else {
|
|
476
504
|
// don't really know what this case could be, but may need to handle it
|
|
@@ -506,45 +534,23 @@
|
|
|
506
534
|
[self setModalViewControllers:modalControllers];
|
|
507
535
|
}
|
|
508
536
|
|
|
509
|
-
// By default, the header buttons that are not inside the native hit area
|
|
510
|
-
// cannot be clicked, so we check it by ourselves
|
|
511
|
-
- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event
|
|
512
|
-
{
|
|
513
|
-
if (CGRectContainsPoint(_controller.navigationBar.frame, point)) {
|
|
514
|
-
// headerConfig should be the first subview of the topmost screen
|
|
515
|
-
UIView *headerConfig = [[_reactSubviews.lastObject reactSubviews] firstObject];
|
|
516
|
-
if ([headerConfig isKindOfClass:[RNSScreenStackHeaderConfig class]]) {
|
|
517
|
-
UIView *headerHitTestResult = [headerConfig hitTest:point withEvent:event];
|
|
518
|
-
if (headerHitTestResult != nil) {
|
|
519
|
-
return headerHitTestResult;
|
|
520
|
-
}
|
|
521
|
-
}
|
|
522
|
-
}
|
|
523
|
-
return [super hitTest:point withEvent:event];
|
|
524
|
-
}
|
|
525
|
-
|
|
526
537
|
- (void)layoutSubviews
|
|
527
538
|
{
|
|
528
539
|
[super layoutSubviews];
|
|
529
540
|
_controller.view.frame = self.bounds;
|
|
530
541
|
}
|
|
531
542
|
|
|
532
|
-
- (void)invalidate
|
|
533
|
-
{
|
|
534
|
-
_invalidated = YES;
|
|
535
|
-
for (UIViewController *controller in _presentedModals) {
|
|
536
|
-
[controller dismissViewControllerAnimated:NO completion:nil];
|
|
537
|
-
}
|
|
538
|
-
[_presentedModals removeAllObjects];
|
|
539
|
-
[_controller willMoveToParentViewController:nil];
|
|
540
|
-
[_controller removeFromParentViewController];
|
|
541
|
-
}
|
|
542
|
-
|
|
543
543
|
- (void)dismissOnReload
|
|
544
544
|
{
|
|
545
|
+
#ifdef RN_FABRIC_ENABLED
|
|
546
|
+
if ([_controller.visibleViewController isKindOfClass:[RNSScreen class]]) {
|
|
547
|
+
[(RNSScreen *)_controller.visibleViewController resetViewToScreen];
|
|
548
|
+
}
|
|
549
|
+
#else
|
|
545
550
|
dispatch_async(dispatch_get_main_queue(), ^{
|
|
546
551
|
[self invalidate];
|
|
547
552
|
});
|
|
553
|
+
#endif
|
|
548
554
|
}
|
|
549
555
|
|
|
550
556
|
#pragma mark methods connected to transitioning
|
|
@@ -556,9 +562,9 @@
|
|
|
556
562
|
{
|
|
557
563
|
RNSScreenView *screen;
|
|
558
564
|
if (operation == UINavigationControllerOperationPush) {
|
|
559
|
-
screen = (
|
|
565
|
+
screen = ((RNSScreen *)toVC).screenView;
|
|
560
566
|
} else if (operation == UINavigationControllerOperationPop) {
|
|
561
|
-
screen = (
|
|
567
|
+
screen = ((RNSScreen *)fromVC).screenView;
|
|
562
568
|
}
|
|
563
569
|
if (screen != nil &&
|
|
564
570
|
// we need to return the animator when full width swiping even if the animation is not custom,
|
|
@@ -579,8 +585,13 @@
|
|
|
579
585
|
while (parent != nil && ![parent respondsToSelector:@selector(touchHandler)])
|
|
580
586
|
parent = parent.superview;
|
|
581
587
|
if (parent != nil) {
|
|
588
|
+
#ifdef RN_FABRIC_ENABLED
|
|
589
|
+
RCTSurfaceTouchHandler *touchHandler = [parent performSelector:@selector(touchHandler)];
|
|
590
|
+
#else
|
|
582
591
|
RCTTouchHandler *touchHandler = [parent performSelector:@selector(touchHandler)];
|
|
583
|
-
|
|
592
|
+
#endif
|
|
593
|
+
[touchHandler setEnabled:NO];
|
|
594
|
+
[touchHandler setEnabled:YES];
|
|
584
595
|
[touchHandler reset];
|
|
585
596
|
}
|
|
586
597
|
}
|
|
@@ -600,8 +611,9 @@
|
|
|
600
611
|
#else
|
|
601
612
|
if (topScreen.fullScreenSwipeEnabled) {
|
|
602
613
|
// we want only `RNSPanGestureRecognizer` to be able to recognize when
|
|
603
|
-
// `fullScreenSwipeEnabled` is set
|
|
604
|
-
if ([gestureRecognizer isKindOfClass:[RNSPanGestureRecognizer class]]
|
|
614
|
+
// `fullScreenSwipeEnabled` is set, and we are in the bounds set by user
|
|
615
|
+
if ([gestureRecognizer isKindOfClass:[RNSPanGestureRecognizer class]] &&
|
|
616
|
+
[self isInGestureResponseDistance:gestureRecognizer topScreen:topScreen]) {
|
|
605
617
|
_isFullWidthSwiping = YES;
|
|
606
618
|
[self cancelTouchesInParent];
|
|
607
619
|
return YES;
|
|
@@ -634,7 +646,8 @@
|
|
|
634
646
|
[self cancelTouchesInParent];
|
|
635
647
|
return YES;
|
|
636
648
|
}
|
|
637
|
-
|
|
649
|
+
|
|
650
|
+
#endif // TARGET_OS_TV
|
|
638
651
|
}
|
|
639
652
|
|
|
640
653
|
#if !TARGET_OS_TV
|
|
@@ -662,7 +675,7 @@
|
|
|
662
675
|
|
|
663
676
|
- (void)handleSwipe:(UIPanGestureRecognizer *)gestureRecognizer
|
|
664
677
|
{
|
|
665
|
-
RNSScreenView *topScreen = (
|
|
678
|
+
RNSScreenView *topScreen = ((RNSScreen *)_controller.viewControllers.lastObject).screenView;
|
|
666
679
|
float translation;
|
|
667
680
|
float velocity;
|
|
668
681
|
float distance;
|
|
@@ -716,7 +729,6 @@
|
|
|
716
729
|
}
|
|
717
730
|
}
|
|
718
731
|
}
|
|
719
|
-
#endif
|
|
720
732
|
|
|
721
733
|
- (id<UIViewControllerInteractiveTransitioning>)navigationController:(UINavigationController *)navigationController
|
|
722
734
|
interactionControllerForAnimationController:
|
|
@@ -731,8 +743,244 @@
|
|
|
731
743
|
return _interactionController;
|
|
732
744
|
}
|
|
733
745
|
|
|
746
|
+
- (void)navigationController:(UINavigationController *)navigationController
|
|
747
|
+
didShowViewController:(UIViewController *)viewController
|
|
748
|
+
animated:(BOOL)animated
|
|
749
|
+
{
|
|
750
|
+
[self emitOnFinishTransitioningEvent];
|
|
751
|
+
[RNSScreenWindowTraits updateWindowTraits];
|
|
752
|
+
}
|
|
753
|
+
#endif
|
|
754
|
+
|
|
755
|
+
- (void)markChildUpdated
|
|
756
|
+
{
|
|
757
|
+
// do nothing
|
|
758
|
+
}
|
|
759
|
+
|
|
760
|
+
- (void)didUpdateChildren
|
|
761
|
+
{
|
|
762
|
+
// do nothing
|
|
763
|
+
}
|
|
764
|
+
|
|
765
|
+
- (UIViewController *)reactViewController
|
|
766
|
+
{
|
|
767
|
+
return _controller;
|
|
768
|
+
}
|
|
769
|
+
|
|
770
|
+
- (BOOL)isInGestureResponseDistance:(UIGestureRecognizer *)gestureRecognizer topScreen:(RNSScreenView *)topScreen
|
|
771
|
+
{
|
|
772
|
+
NSDictionary *gestureResponseDistanceValues = topScreen.gestureResponseDistance;
|
|
773
|
+
float x = [gestureRecognizer locationInView:gestureRecognizer.view].x;
|
|
774
|
+
float y = [gestureRecognizer locationInView:gestureRecognizer.view].y;
|
|
775
|
+
BOOL isRTL = _controller.view.semanticContentAttribute == UISemanticContentAttributeForceRightToLeft;
|
|
776
|
+
if (isRTL) {
|
|
777
|
+
x = _controller.view.frame.size.width - x;
|
|
778
|
+
}
|
|
779
|
+
|
|
780
|
+
// see:
|
|
781
|
+
// https://github.com/software-mansion/react-native-screens/pull/1442/commits/74d4bae321875d8305ad021b3d448ebf713e7d56
|
|
782
|
+
// this prop is always default initialized so we do not expect any nils
|
|
783
|
+
float start = [gestureResponseDistanceValues[@"start"] floatValue];
|
|
784
|
+
float end = [gestureResponseDistanceValues[@"end"] floatValue];
|
|
785
|
+
float top = [gestureResponseDistanceValues[@"top"] floatValue];
|
|
786
|
+
float bottom = [gestureResponseDistanceValues[@"bottom"] floatValue];
|
|
787
|
+
|
|
788
|
+
// we check if any of the constraints are violated and return NO if so
|
|
789
|
+
return !(
|
|
790
|
+
(start != -1 && x < start) || (end != -1 && x > end) || (top != -1 && y < top) || (bottom != -1 && y > bottom));
|
|
791
|
+
}
|
|
792
|
+
|
|
793
|
+
// By default, the header buttons that are not inside the native hit area
|
|
794
|
+
// cannot be clicked, so we check it by ourselves
|
|
795
|
+
- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event
|
|
796
|
+
{
|
|
797
|
+
if (CGRectContainsPoint(_controller.navigationBar.frame, point)) {
|
|
798
|
+
// headerConfig should be the first subview of the topmost screen
|
|
799
|
+
UIView *headerConfig = [[_reactSubviews.lastObject reactSubviews] firstObject];
|
|
800
|
+
if ([headerConfig isKindOfClass:[RNSScreenStackHeaderConfig class]]) {
|
|
801
|
+
UIView *headerHitTestResult = [headerConfig hitTest:point withEvent:event];
|
|
802
|
+
if (headerHitTestResult != nil) {
|
|
803
|
+
return headerHitTestResult;
|
|
804
|
+
}
|
|
805
|
+
}
|
|
806
|
+
}
|
|
807
|
+
return [super hitTest:point withEvent:event];
|
|
808
|
+
}
|
|
809
|
+
|
|
810
|
+
- (BOOL)isScrollViewPanGestureRecognizer:(UIGestureRecognizer *)gestureRecognizer
|
|
811
|
+
{
|
|
812
|
+
// NOTE: This hack is required to restore native behavior of edge swipe (interactive pop gesture)
|
|
813
|
+
// without this, on a screen with a scroll view, it's only possible to pop view by panning horizontally
|
|
814
|
+
// if even slightly diagonal (or if in motion), scroll view will scroll, and edge swipe will be cancelled
|
|
815
|
+
if (![[gestureRecognizer view] isKindOfClass:[UIScrollView class]]) {
|
|
816
|
+
return NO;
|
|
817
|
+
}
|
|
818
|
+
UIScrollView *scrollView = (UIScrollView *)gestureRecognizer.view;
|
|
819
|
+
return scrollView.panGestureRecognizer == gestureRecognizer;
|
|
820
|
+
}
|
|
821
|
+
|
|
822
|
+
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer
|
|
823
|
+
shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer
|
|
824
|
+
{
|
|
825
|
+
return [self isScrollViewPanGestureRecognizer:otherGestureRecognizer];
|
|
826
|
+
}
|
|
827
|
+
|
|
828
|
+
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer
|
|
829
|
+
shouldBeRequiredToFailByGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer
|
|
830
|
+
{
|
|
831
|
+
return [self isScrollViewPanGestureRecognizer:otherGestureRecognizer];
|
|
832
|
+
}
|
|
833
|
+
|
|
834
|
+
- (void)insertReactSubview:(RNSScreenView *)subview atIndex:(NSInteger)atIndex
|
|
835
|
+
{
|
|
836
|
+
if (![subview isKindOfClass:[RNSScreenView class]]) {
|
|
837
|
+
RCTLogError(@"ScreenStack only accepts children of type Screen");
|
|
838
|
+
return;
|
|
839
|
+
}
|
|
840
|
+
subview.reactSuperview = self;
|
|
841
|
+
[_reactSubviews insertObject:subview atIndex:atIndex];
|
|
842
|
+
}
|
|
843
|
+
|
|
844
|
+
- (void)removeReactSubview:(RNSScreenView *)subview
|
|
845
|
+
{
|
|
846
|
+
subview.reactSuperview = nil;
|
|
847
|
+
[_reactSubviews removeObject:subview];
|
|
848
|
+
}
|
|
849
|
+
|
|
850
|
+
- (void)didUpdateReactSubviews
|
|
851
|
+
{
|
|
852
|
+
// we need to wait until children have their layout set. At this point they don't have the layout
|
|
853
|
+
// set yet, however the layout call is already enqueued on ui thread. Enqueuing update call on the
|
|
854
|
+
// ui queue will guarantee that the update will run after layout.
|
|
855
|
+
dispatch_async(dispatch_get_main_queue(), ^{
|
|
856
|
+
self->_hasLayout = YES;
|
|
857
|
+
[self maybeAddToParentAndUpdateContainer];
|
|
858
|
+
});
|
|
859
|
+
}
|
|
860
|
+
|
|
861
|
+
#ifdef RN_FABRIC_ENABLED
|
|
862
|
+
#pragma mark - Fabric specific
|
|
863
|
+
|
|
864
|
+
- (void)mountChildComponentView:(UIView<RCTComponentViewProtocol> *)childComponentView index:(NSInteger)index
|
|
865
|
+
{
|
|
866
|
+
if (![childComponentView isKindOfClass:[RNSScreenView class]]) {
|
|
867
|
+
RCTLogError(@"ScreenStack only accepts children of type Screen");
|
|
868
|
+
return;
|
|
869
|
+
}
|
|
870
|
+
|
|
871
|
+
RCTAssert(
|
|
872
|
+
childComponentView.reactSuperview == nil,
|
|
873
|
+
@"Attempt to mount already mounted component view. (parent: %@, child: %@, index: %@, existing parent: %@)",
|
|
874
|
+
self,
|
|
875
|
+
childComponentView,
|
|
876
|
+
@(index),
|
|
877
|
+
@([childComponentView.superview tag]));
|
|
878
|
+
|
|
879
|
+
[_reactSubviews insertObject:(RNSScreenView *)childComponentView atIndex:index];
|
|
880
|
+
((RNSScreenView *)childComponentView).reactSuperview = self;
|
|
881
|
+
dispatch_async(dispatch_get_main_queue(), ^{
|
|
882
|
+
[self maybeAddToParentAndUpdateContainer];
|
|
883
|
+
});
|
|
884
|
+
}
|
|
885
|
+
|
|
886
|
+
- (void)unmountChildComponentView:(UIView<RCTComponentViewProtocol> *)childComponentView index:(NSInteger)index
|
|
887
|
+
{
|
|
888
|
+
RNSScreenView *screenChildComponent = (RNSScreenView *)childComponentView;
|
|
889
|
+
// We should only do a snapshot of a screen that is on the top.
|
|
890
|
+
// We also check `_presentedModals` since if you push 2 modals, second one is not a "child" of _controller.
|
|
891
|
+
// Also, when dissmised with a gesture, the screen already is not under the window, so we don't need to apply
|
|
892
|
+
// snapshot.
|
|
893
|
+
if (screenChildComponent.window != nil &&
|
|
894
|
+
((screenChildComponent == _controller.visibleViewController.view && _presentedModals.count < 2) ||
|
|
895
|
+
screenChildComponent == [_presentedModals.lastObject view])) {
|
|
896
|
+
[screenChildComponent.controller setViewToSnapshot:_snapshot];
|
|
897
|
+
}
|
|
898
|
+
|
|
899
|
+
RCTAssert(
|
|
900
|
+
screenChildComponent.reactSuperview == self,
|
|
901
|
+
@"Attempt to unmount a view which is mounted inside different view. (parent: %@, child: %@, index: %@)",
|
|
902
|
+
self,
|
|
903
|
+
screenChildComponent,
|
|
904
|
+
@(index));
|
|
905
|
+
RCTAssert(
|
|
906
|
+
(_reactSubviews.count > index) && [_reactSubviews objectAtIndex:index] == childComponentView,
|
|
907
|
+
@"Attempt to unmount a view which has a different index. (parent: %@, child: %@, index: %@, actual index: %@, tag at index: %@)",
|
|
908
|
+
self,
|
|
909
|
+
screenChildComponent,
|
|
910
|
+
@(index),
|
|
911
|
+
@([_reactSubviews indexOfObject:screenChildComponent]),
|
|
912
|
+
@([[_reactSubviews objectAtIndex:index] tag]));
|
|
913
|
+
screenChildComponent.reactSuperview = nil;
|
|
914
|
+
[_reactSubviews removeObject:screenChildComponent];
|
|
915
|
+
[screenChildComponent removeFromSuperview];
|
|
916
|
+
dispatch_async(dispatch_get_main_queue(), ^{
|
|
917
|
+
[self maybeAddToParentAndUpdateContainer];
|
|
918
|
+
});
|
|
919
|
+
}
|
|
920
|
+
|
|
921
|
+
- (void)takeSnapshot
|
|
922
|
+
{
|
|
923
|
+
_snapshot = [_controller.visibleViewController.view snapshotViewAfterScreenUpdates:NO];
|
|
924
|
+
}
|
|
925
|
+
|
|
926
|
+
- (void)mountingTransactionWillMount:(facebook::react::MountingTransaction const &)transaction
|
|
927
|
+
withSurfaceTelemetry:(facebook::react::SurfaceTelemetry const &)surfaceTelemetry
|
|
928
|
+
{
|
|
929
|
+
for (auto mutation : transaction.getMutations()) {
|
|
930
|
+
if (mutation.type == facebook::react::ShadowViewMutation::Type::Remove &&
|
|
931
|
+
mutation.parentShadowView.componentName != nil &&
|
|
932
|
+
strcmp(mutation.parentShadowView.componentName, "RNSScreenStack") == 0) {
|
|
933
|
+
[self takeSnapshot];
|
|
934
|
+
return;
|
|
935
|
+
}
|
|
936
|
+
}
|
|
937
|
+
}
|
|
938
|
+
|
|
939
|
+
- (void)prepareForRecycle
|
|
940
|
+
{
|
|
941
|
+
[super prepareForRecycle];
|
|
942
|
+
_reactSubviews = [NSMutableArray new];
|
|
943
|
+
|
|
944
|
+
for (UIViewController *controller in _presentedModals) {
|
|
945
|
+
[controller dismissViewControllerAnimated:NO completion:nil];
|
|
946
|
+
}
|
|
947
|
+
|
|
948
|
+
[_presentedModals removeAllObjects];
|
|
949
|
+
[self dismissOnReload];
|
|
950
|
+
[_controller willMoveToParentViewController:nil];
|
|
951
|
+
[_controller removeFromParentViewController];
|
|
952
|
+
[_controller setViewControllers:@[ [UIViewController new] ]];
|
|
953
|
+
}
|
|
954
|
+
|
|
955
|
+
+ (facebook::react::ComponentDescriptorProvider)componentDescriptorProvider
|
|
956
|
+
{
|
|
957
|
+
return facebook::react::concreteComponentDescriptorProvider<facebook::react::RNSScreenStackComponentDescriptor>();
|
|
958
|
+
}
|
|
959
|
+
#else
|
|
960
|
+
#pragma mark - Paper specific
|
|
961
|
+
|
|
962
|
+
- (void)invalidate
|
|
963
|
+
{
|
|
964
|
+
_invalidated = YES;
|
|
965
|
+
for (UIViewController *controller in _presentedModals) {
|
|
966
|
+
[controller dismissViewControllerAnimated:NO completion:nil];
|
|
967
|
+
}
|
|
968
|
+
[_presentedModals removeAllObjects];
|
|
969
|
+
[_controller willMoveToParentViewController:nil];
|
|
970
|
+
[_controller removeFromParentViewController];
|
|
971
|
+
}
|
|
972
|
+
|
|
973
|
+
#endif // RN_FABRIC_ENABLED
|
|
974
|
+
|
|
734
975
|
@end
|
|
735
976
|
|
|
977
|
+
#ifdef RN_FABRIC_ENABLED
|
|
978
|
+
Class<RCTComponentViewProtocol> RNSScreenStackCls(void)
|
|
979
|
+
{
|
|
980
|
+
return RNSScreenStackView.class;
|
|
981
|
+
}
|
|
982
|
+
#endif
|
|
983
|
+
|
|
736
984
|
@implementation RNSScreenStackManager {
|
|
737
985
|
NSPointerArray *_stacks;
|
|
738
986
|
}
|
|
@@ -741,6 +989,8 @@ RCT_EXPORT_MODULE()
|
|
|
741
989
|
|
|
742
990
|
RCT_EXPORT_VIEW_PROPERTY(onFinishTransitioning, RCTDirectEventBlock);
|
|
743
991
|
|
|
992
|
+
#ifdef RN_FABRIC_ENABLED
|
|
993
|
+
#else
|
|
744
994
|
- (UIView *)view
|
|
745
995
|
{
|
|
746
996
|
RNSScreenStackView *view = [[RNSScreenStackView alloc] initWithManager:self];
|
|
@@ -750,6 +1000,7 @@ RCT_EXPORT_VIEW_PROPERTY(onFinishTransitioning, RCTDirectEventBlock);
|
|
|
750
1000
|
[_stacks addPointer:(__bridge void *)view];
|
|
751
1001
|
return view;
|
|
752
1002
|
}
|
|
1003
|
+
#endif // RN_FABRIC_ENABLED
|
|
753
1004
|
|
|
754
1005
|
- (void)invalidate
|
|
755
1006
|
{
|