react-native-screens 3.11.1 → 3.12.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (88) hide show
  1. package/README.md +4 -0
  2. package/RNScreens.podspec +36 -6
  3. package/android/build.gradle +73 -1
  4. package/android/src/fabric/java/com/swmansion/rnscreens/FabricEnabledViewGroup.kt +49 -0
  5. package/android/src/fabric/java/com/swmansion/rnscreens/RNScreensComponentsRegistry.java +28 -0
  6. package/android/src/main/java/com/swmansion/rnscreens/RNScreensPackage.kt +11 -2
  7. package/android/src/main/java/com/swmansion/rnscreens/Screen.kt +24 -10
  8. package/android/src/main/java/com/swmansion/rnscreens/ScreenStackHeaderConfigViewManager.kt +83 -18
  9. package/android/src/main/java/com/swmansion/rnscreens/ScreenStackHeaderSubviewManager.kt +17 -5
  10. package/android/src/main/java/com/swmansion/rnscreens/ScreenStackViewManager.kt +14 -1
  11. package/android/src/main/java/com/swmansion/rnscreens/ScreenViewManager.kt +33 -16
  12. package/android/src/main/jni/Android.mk +45 -0
  13. package/android/src/main/jni/OnLoad.cpp +9 -0
  14. package/android/src/main/jni/RNScreensComponentsRegistry.cpp +66 -0
  15. package/android/src/main/jni/RNScreensComponentsRegistry.h +34 -0
  16. package/android/src/paper/java/com/facebook/react/viewmanagers/RNSScreenManagerDelegate.java +71 -0
  17. package/android/src/paper/java/com/facebook/react/viewmanagers/RNSScreenManagerInterface.java +30 -0
  18. package/android/src/paper/java/com/facebook/react/viewmanagers/RNSScreenStackHeaderConfigManagerDelegate.java +104 -0
  19. package/android/src/paper/java/com/facebook/react/viewmanagers/RNSScreenStackHeaderConfigManagerInterface.java +41 -0
  20. package/android/src/paper/java/com/facebook/react/viewmanagers/RNSScreenStackHeaderSubviewManagerDelegate.java +31 -0
  21. package/android/src/paper/java/com/facebook/react/viewmanagers/RNSScreenStackHeaderSubviewManagerInterface.java +17 -0
  22. package/android/src/paper/java/com/facebook/react/viewmanagers/RNSScreenStackManagerDelegate.java +25 -0
  23. package/android/src/paper/java/com/facebook/react/viewmanagers/RNSScreenStackManagerInterface.java +16 -0
  24. package/android/src/paper/java/com/swmansion/rnscreens/FabricEnabledViewGroup.kt +16 -0
  25. package/common/cpp/Android.mk +38 -0
  26. package/common/cpp/rnscreens/RNSScreenComponentDescriptor.h +41 -0
  27. package/common/cpp/rnscreens/RNSScreenShadowNode.cpp +9 -0
  28. package/common/cpp/rnscreens/RNSScreenShadowNode.h +29 -0
  29. package/common/cpp/rnscreens/RNSScreenState.cpp +14 -0
  30. package/common/cpp/rnscreens/RNSScreenState.h +46 -0
  31. package/ios/RNSScreenComponentView.h +23 -0
  32. package/ios/RNSScreenComponentView.mm +159 -0
  33. package/ios/RNSScreenController.h +10 -0
  34. package/ios/RNSScreenController.mm +79 -0
  35. package/ios/RNSScreenStackComponentView.h +15 -0
  36. package/ios/RNSScreenStackComponentView.mm +295 -0
  37. package/ios/RNSScreenStackHeaderConfigComponentView.h +42 -0
  38. package/ios/RNSScreenStackHeaderConfigComponentView.mm +662 -0
  39. package/ios/RNSScreenStackHeaderSubviewComponentView.h +14 -0
  40. package/ios/RNSScreenStackHeaderSubviewComponentView.mm +77 -0
  41. package/ios/utils/RNSUIBarButtonItem.h +5 -0
  42. package/ios/utils/RNSUIBarButtonItem.mm +22 -0
  43. package/lib/commonjs/fabric/Screen.js +27 -0
  44. package/lib/commonjs/fabric/Screen.js.map +1 -0
  45. package/lib/commonjs/fabric/ScreenNativeComponent.js +23 -0
  46. package/lib/commonjs/fabric/ScreenNativeComponent.js.map +1 -0
  47. package/lib/commonjs/fabric/ScreenStack.js +27 -0
  48. package/lib/commonjs/fabric/ScreenStack.js.map +1 -0
  49. package/lib/commonjs/fabric/ScreenStackHeaderConfigNativeComponent.js +27 -0
  50. package/lib/commonjs/fabric/ScreenStackHeaderConfigNativeComponent.js.map +1 -0
  51. package/lib/commonjs/fabric/ScreenStackHeaderSubview.js +34 -0
  52. package/lib/commonjs/fabric/ScreenStackHeaderSubview.js.map +1 -0
  53. package/lib/commonjs/fabric/ScreenStackHeaderSubviewNativeComponent.js +27 -0
  54. package/lib/commonjs/fabric/ScreenStackHeaderSubviewNativeComponent.js.map +1 -0
  55. package/lib/commonjs/fabric/ScreenStackNativeComponent.js +21 -0
  56. package/lib/commonjs/fabric/ScreenStackNativeComponent.js.map +1 -0
  57. package/lib/commonjs/fabric/index.js +40 -0
  58. package/lib/commonjs/fabric/index.js.map +1 -0
  59. package/lib/commonjs/index.native.js +32 -15
  60. package/lib/commonjs/index.native.js.map +1 -1
  61. package/lib/module/fabric/Screen.js +11 -0
  62. package/lib/module/fabric/Screen.js.map +1 -0
  63. package/lib/module/fabric/ScreenNativeComponent.js +11 -0
  64. package/lib/module/fabric/ScreenNativeComponent.js.map +1 -0
  65. package/lib/module/fabric/ScreenStack.js +12 -0
  66. package/lib/module/fabric/ScreenStack.js.map +1 -0
  67. package/lib/module/fabric/ScreenStackHeaderConfigNativeComponent.js +10 -0
  68. package/lib/module/fabric/ScreenStackHeaderConfigNativeComponent.js.map +1 -0
  69. package/lib/module/fabric/ScreenStackHeaderSubview.js +21 -0
  70. package/lib/module/fabric/ScreenStackHeaderSubview.js.map +1 -0
  71. package/lib/module/fabric/ScreenStackHeaderSubviewNativeComponent.js +10 -0
  72. package/lib/module/fabric/ScreenStackHeaderSubviewNativeComponent.js.map +1 -0
  73. package/lib/module/fabric/ScreenStackNativeComponent.js +9 -0
  74. package/lib/module/fabric/ScreenStackNativeComponent.js.map +1 -0
  75. package/lib/module/fabric/index.js +6 -0
  76. package/lib/module/fabric/index.js.map +1 -0
  77. package/lib/module/index.native.js +32 -15
  78. package/lib/module/index.native.js.map +1 -1
  79. package/package.json +17 -3
  80. package/src/fabric/Screen.js +12 -0
  81. package/src/fabric/ScreenNativeComponent.js +64 -0
  82. package/src/fabric/ScreenStack.js +8 -0
  83. package/src/fabric/ScreenStackHeaderConfigNativeComponent.js +54 -0
  84. package/src/fabric/ScreenStackHeaderSubview.js +20 -0
  85. package/src/fabric/ScreenStackHeaderSubviewNativeComponent.js +31 -0
  86. package/src/fabric/ScreenStackNativeComponent.js +19 -0
  87. package/src/fabric/index.js +11 -0
  88. package/src/index.native.tsx +35 -14
@@ -0,0 +1,295 @@
1
+ #import "RNSScreenStackComponentView.h"
2
+ #import "RNSScreenComponentView.h"
3
+ #import "RNSScreenStackHeaderConfigComponentView.h"
4
+
5
+ #import <React/UIView+React.h>
6
+ #import <react/renderer/components/rnscreens/ComponentDescriptors.h>
7
+ #import <react/renderer/components/rnscreens/EventEmitters.h>
8
+ #import <react/renderer/components/rnscreens/Props.h>
9
+ #import <react/renderer/components/rnscreens/RCTComponentViewHelpers.h>
10
+
11
+ #import "RCTFabricComponentsPlugins.h"
12
+
13
+ using namespace facebook::react;
14
+
15
+ @interface RNSScreenStackComponentView () <
16
+ UINavigationControllerDelegate,
17
+ UIAdaptivePresentationControllerDelegate,
18
+ UIGestureRecognizerDelegate,
19
+ UIViewControllerTransitioningDelegate>
20
+ @end
21
+
22
+ @implementation RNSScreenStackComponentView {
23
+ UINavigationController *_controller;
24
+ NSMutableArray<RNSScreenComponentView *> *_reactSubviews;
25
+ BOOL _invalidated;
26
+ }
27
+
28
+ - (instancetype)initWithFrame:(CGRect)frame
29
+ {
30
+ if (self = [super initWithFrame:frame]) {
31
+ static const auto defaultProps = std::make_shared<const RNSScreenStackProps>();
32
+ _props = defaultProps;
33
+ _reactSubviews = [NSMutableArray new];
34
+ _controller = [[UINavigationController alloc] init];
35
+ _controller.delegate = self;
36
+ [_controller setViewControllers:@[ [UIViewController new] ]];
37
+ _invalidated = NO;
38
+ }
39
+
40
+ return self;
41
+ }
42
+
43
+ - (void)markChildUpdated
44
+ {
45
+ // do nothing
46
+ }
47
+
48
+ - (void)didUpdateChildren
49
+ {
50
+ // do nothing
51
+ }
52
+
53
+ - (void)mountChildComponentView:(UIView<RCTComponentViewProtocol> *)childComponentView index:(NSInteger)index
54
+ {
55
+ if (![childComponentView isKindOfClass:[RNSScreenComponentView class]]) {
56
+ RCTLogError(@"ScreenStack only accepts children of type Screen");
57
+ return;
58
+ }
59
+
60
+ RCTAssert(
61
+ childComponentView.reactSuperview == nil,
62
+ @"Attempt to mount already mounted component view. (parent: %@, child: %@, index: %@, existing parent: %@)",
63
+ self,
64
+ childComponentView,
65
+ @(index),
66
+ @([childComponentView.superview tag]));
67
+
68
+ [_reactSubviews insertObject:(RNSScreenComponentView *)childComponentView atIndex:index];
69
+ ((RNSScreenComponentView *)childComponentView).reactSuperview = self;
70
+ dispatch_async(dispatch_get_main_queue(), ^{
71
+ [self maybeAddToParentAndUpdateContainer];
72
+ });
73
+ }
74
+
75
+ - (void)unmountChildComponentView:(UIView<RCTComponentViewProtocol> *)childComponentView index:(NSInteger)index
76
+ {
77
+ RNSScreenComponentView *screenChildComponent = (RNSScreenComponentView *)childComponentView;
78
+ RCTAssert(
79
+ screenChildComponent.reactSuperview == self,
80
+ @"Attempt to unmount a view which is mounted inside different view. (parent: %@, child: %@, index: %@)",
81
+ self,
82
+ screenChildComponent,
83
+ @(index));
84
+ RCTAssert(
85
+ (_reactSubviews.count > index) && [_reactSubviews objectAtIndex:index] == childComponentView,
86
+ @"Attempt to unmount a view which has a different index. (parent: %@, child: %@, index: %@, actual index: %@, tag at index: %@)",
87
+ self,
88
+ screenChildComponent,
89
+ @(index),
90
+ @([_reactSubviews indexOfObject:screenChildComponent]),
91
+ @([[_reactSubviews objectAtIndex:index] tag]));
92
+ screenChildComponent.reactSuperview = nil;
93
+ [_reactSubviews removeObject:screenChildComponent];
94
+ [screenChildComponent removeFromSuperview];
95
+ dispatch_async(dispatch_get_main_queue(), ^{
96
+ [self maybeAddToParentAndUpdateContainer];
97
+ });
98
+ }
99
+
100
+ - (NSArray<UIView *> *)reactSubviews
101
+ {
102
+ return _reactSubviews;
103
+ }
104
+
105
+ - (void)didMoveToWindow
106
+ {
107
+ [super didMoveToWindow];
108
+ if (!_invalidated) {
109
+ [self maybeAddToParentAndUpdateContainer];
110
+ }
111
+ }
112
+
113
+ - (void)navigationController:(UINavigationController *)navigationController
114
+ willShowViewController:(UIViewController *)viewController
115
+ animated:(BOOL)animated
116
+ {
117
+ UIView *view = viewController.view;
118
+ if ([view isKindOfClass:RNSScreenComponentView.class]) {
119
+ RNSScreenStackHeaderConfigComponentView *config =
120
+ (RNSScreenStackHeaderConfigComponentView *)((RNSScreenComponentView *)view).config;
121
+ [RNSScreenStackHeaderConfigComponentView willShowViewController:viewController animated:animated withConfig:config];
122
+ }
123
+ }
124
+
125
+ - (void)maybeAddToParentAndUpdateContainer
126
+ {
127
+ BOOL wasScreenMounted = _controller.parentViewController != nil;
128
+ BOOL isScreenReadyForShowing = self.window;
129
+ if (!isScreenReadyForShowing && !wasScreenMounted) {
130
+ return;
131
+ }
132
+ [self updateContainer];
133
+ if (!wasScreenMounted) {
134
+ // when stack hasn't been added to parent VC yet we do two things:
135
+ // 1) we run updateContainer (the one above) – we do this because we want push view controllers to
136
+ // be installed before the VC is mounted. If we do that after it is added to parent the push
137
+ // updates operations are going to be blocked by UIKit.
138
+ // 2) we add navigation VS to parent – this is needed for the VC lifecycle events to be dispatched
139
+ // properly
140
+ // 3) we again call updateContainer – this time we do this to open modal controllers. Modals
141
+ // won't open in (1) because they require navigator to be added to parent. We handle that case
142
+ // gracefully in setModalViewControllers and can retry opening at any point.
143
+ [self reactAddControllerToClosestParent:_controller];
144
+ [self updateContainer];
145
+ }
146
+ }
147
+
148
+ - (void)reactAddControllerToClosestParent:(UIViewController *)controller
149
+ {
150
+ if (!controller.parentViewController) {
151
+ UIView *parentView = (UIView *)self.reactSuperview;
152
+ while (parentView) {
153
+ if ([parentView reactViewController]) {
154
+ [parentView.reactViewController addChildViewController:controller];
155
+ [self addSubview:controller.view];
156
+ #if !TARGET_OS_TV
157
+ _controller.interactivePopGestureRecognizer.delegate = self;
158
+ #endif
159
+ [self navigationController:_controller willShowViewController:_controller.topViewController animated:NO];
160
+ }
161
+ parentView = (UIView *)parentView.reactSuperview;
162
+ }
163
+ return;
164
+ }
165
+ }
166
+
167
+ - (void)setPushViewControllers:(NSArray<UIViewController *> *)controllers
168
+ {
169
+ // when there is no change we return immediately
170
+ if ([_controller.viewControllers isEqualToArray:controllers]) {
171
+ return;
172
+ }
173
+
174
+ // if view controller is not yet attached to window we skip updates now and run them when view
175
+ // is attached
176
+ if (self.window == nil) {
177
+ return;
178
+ }
179
+
180
+ UIViewController *top = controllers.lastObject;
181
+ UIViewController *lastTop = _controller.viewControllers.lastObject;
182
+
183
+ // at the start we set viewControllers to contain a single UIVIewController
184
+ // instance. This is a workaround for header height adjustment bug (see comment
185
+ // in the init function). Here, we need to detect if the initial empty
186
+ // controller is still there
187
+ BOOL firstTimePush = ![lastTop isKindOfClass:[RNSScreenController class]];
188
+
189
+ BOOL shouldAnimate = YES;
190
+
191
+ if (firstTimePush) {
192
+ // nothing pushed yet
193
+ [_controller setViewControllers:controllers animated:NO];
194
+ } else if (top != lastTop) {
195
+ if (![controllers containsObject:lastTop]) {
196
+ // if the previous top screen does not exist anymore and the new top was not on the stack before, probably replace
197
+ // was called, so we check the animation
198
+ if (![_controller.viewControllers containsObject:top]) {
199
+ // setting new controllers with animation does `push` animation by default
200
+ auto screenController = (RNSScreenController *)top;
201
+ [screenController resetViewToScreen];
202
+ [_controller setViewControllers:controllers animated:YES];
203
+ } else {
204
+ // last top controller is no longer on stack
205
+ // in this case we set the controllers stack to the new list with
206
+ // added the last top element to it and perform (animated) pop
207
+ NSMutableArray *newControllers = [NSMutableArray arrayWithArray:controllers];
208
+ [newControllers addObject:lastTop];
209
+ [_controller setViewControllers:newControllers animated:NO];
210
+ [_controller popViewControllerAnimated:shouldAnimate];
211
+ }
212
+ } else if (![_controller.viewControllers containsObject:top]) {
213
+ // new top controller is not on the stack
214
+ // in such case we update the stack except from the last element with
215
+ // no animation and do animated push of the last item
216
+ NSMutableArray *newControllers = [NSMutableArray arrayWithArray:controllers];
217
+ [newControllers removeLastObject];
218
+ [_controller setViewControllers:newControllers animated:NO];
219
+ auto screenController = (RNSScreenController *)top;
220
+ [screenController resetViewToScreen];
221
+ [_controller pushViewController:top animated:shouldAnimate];
222
+ } else {
223
+ // don't really know what this case could be, but may need to handle it
224
+ // somehow
225
+ [_controller setViewControllers:controllers animated:shouldAnimate];
226
+ }
227
+ } else {
228
+ // change wasn't on the top of the stack. We don't need animation.
229
+ [_controller setViewControllers:controllers animated:NO];
230
+ }
231
+ }
232
+
233
+ - (void)updateContainer
234
+ {
235
+ NSMutableArray<UIViewController *> *pushControllers = [NSMutableArray new];
236
+ for (RNSScreenComponentView *screen in _reactSubviews) {
237
+ if (screen.controller != nil) {
238
+ if (pushControllers.count == 0) {
239
+ // first screen on the list needs to be places as "push controller"
240
+ [pushControllers addObject:screen.controller];
241
+ } else {
242
+ [pushControllers addObject:screen.controller];
243
+ }
244
+ }
245
+ }
246
+
247
+ [self setPushViewControllers:pushControllers];
248
+ }
249
+
250
+ - (void)layoutSubviews
251
+ {
252
+ [super layoutSubviews];
253
+ _controller.view.frame = self.bounds;
254
+ }
255
+
256
+ - (void)invalidate
257
+ {
258
+ _invalidated = YES;
259
+ [_controller willMoveToParentViewController:nil];
260
+ [_controller removeFromParentViewController];
261
+ }
262
+
263
+ - (void)dismissOnReload
264
+ {
265
+ dispatch_async(dispatch_get_main_queue(), ^{
266
+ [self invalidate];
267
+ });
268
+ }
269
+
270
+ #pragma mark methods connected to transitioning
271
+
272
+ - (BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer
273
+ {
274
+ return YES;
275
+ }
276
+
277
+ #pragma mark - RCTComponentViewProtocol
278
+
279
+ - (void)prepareForRecycle
280
+ {
281
+ [super prepareForRecycle];
282
+ _reactSubviews = [NSMutableArray new];
283
+ }
284
+
285
+ + (ComponentDescriptorProvider)componentDescriptorProvider
286
+ {
287
+ return concreteComponentDescriptorProvider<RNSScreenStackComponentDescriptor>();
288
+ }
289
+
290
+ @end
291
+
292
+ Class<RCTComponentViewProtocol> RNSScreenStackCls(void)
293
+ {
294
+ return RNSScreenStackComponentView.class;
295
+ }
@@ -0,0 +1,42 @@
1
+ #import <UIKit/UIKit.h>
2
+
3
+ #import <React/RCTViewComponentView.h>
4
+
5
+ #import "RNSScreenComponentView.h"
6
+ #import "RNSScreenStackHeaderSubviewComponentView.h"
7
+
8
+ @interface RNSScreenStackHeaderConfigComponentView : RCTViewComponentView
9
+
10
+ @property (nonatomic, weak) RNSScreenComponentView *screenView;
11
+ @property (nonatomic) NSMutableArray<RNSScreenStackHeaderSubviewComponentView *> *reactSubviews;
12
+
13
+ // Properties from props
14
+ @property (nonatomic) BOOL show;
15
+ @property (nonatomic) BOOL translucent;
16
+ @property (nonatomic) BOOL hideShadow;
17
+ @property (nonatomic, retain) NSString *title;
18
+ @property (nonatomic, retain) NSString *titleFontFamily;
19
+ @property (nonatomic, retain) NSNumber *titleFontSize;
20
+ @property (nonatomic, retain) NSString *titleFontWeight;
21
+ @property (nonatomic, retain) UIColor *titleColor;
22
+ @property (nonatomic) BOOL largeTitle;
23
+ @property (nonatomic, retain) NSString *largeTitleFontFamily;
24
+ @property (nonatomic, retain) NSNumber *largeTitleFontSize;
25
+ @property (nonatomic, retain) NSString *largeTitleFontWeight;
26
+ @property (nonatomic, retain) UIColor *largeTitleBackgroundColor;
27
+ @property (nonatomic) BOOL largeTitleHideShadow;
28
+ @property (nonatomic, retain) UIColor *largeTitleColor;
29
+ @property (nonatomic, retain) UIColor *backgroundColor;
30
+ @property (nonatomic, retain) UIColor *color;
31
+ @property (nonatomic) UISemanticContentAttribute direction;
32
+ @property (nonatomic, retain) NSString *backTitle;
33
+ @property (nonatomic, retain) NSString *backTitleFontFamily;
34
+ @property (nonatomic, retain) NSNumber *backTitleFontSize;
35
+ @property (nonatomic) BOOL disableBackButtonMenu;
36
+ @property (nonatomic) BOOL hideBackButton;
37
+
38
+ + (void)willShowViewController:(UIViewController *)vc
39
+ animated:(BOOL)animated
40
+ withConfig:(RNSScreenStackHeaderConfigComponentView *)config;
41
+
42
+ @end