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.
Files changed (141) hide show
  1. package/README.md +2 -2
  2. package/RNScreens.podspec +5 -4
  3. package/android/build.gradle +18 -1
  4. package/android/src/main/java/com/swmansion/rnscreens/ScreenStack.kt +8 -4
  5. package/android/src/main/java/com/swmansion/rnscreens/ScreenViewManager.kt +24 -6
  6. package/android/src/main/java/com/swmansion/rnscreens/ScreenWindowTraits.kt +14 -18
  7. package/android/src/main/jni/Android.mk +1 -2
  8. package/android/src/paper/java/com/facebook/react/viewmanagers/RNSScreenManagerDelegate.java +39 -14
  9. package/android/src/paper/java/com/facebook/react/viewmanagers/RNSScreenManagerInterface.java +15 -6
  10. package/android/src/paper/java/com/facebook/react/viewmanagers/RNSScreenStackHeaderConfigManagerDelegate.java +3 -3
  11. package/android/src/paper/java/com/facebook/react/viewmanagers/RNSScreenStackHeaderConfigManagerInterface.java +1 -1
  12. package/common/cpp/Android.mk +1 -2
  13. package/createNativeStackNavigator/README.md +4 -0
  14. package/ios/RNSConvert.h +30 -0
  15. package/ios/RNSConvert.mm +120 -0
  16. package/ios/RNSEnums.h +59 -0
  17. package/ios/RNSFullWindowOverlay.h +17 -2
  18. package/ios/RNSFullWindowOverlay.mm +199 -0
  19. package/ios/RNSScreen.h +70 -79
  20. package/ios/{RNSScreen.m → RNSScreen.mm} +679 -302
  21. package/ios/RNSScreenContainer.h +15 -1
  22. package/ios/{RNSScreenContainer.m → RNSScreenContainer.mm} +99 -8
  23. package/ios/{RNSScreenNavigationContainer.m → RNSScreenNavigationContainer.mm} +22 -0
  24. package/ios/RNSScreenStack.h +19 -3
  25. package/ios/{RNSScreenStack.m → RNSScreenStack.mm} +377 -126
  26. package/ios/{RNSScreenStackAnimator.m → RNSScreenStackAnimator.mm} +19 -14
  27. package/ios/RNSScreenStackHeaderConfig.h +20 -21
  28. package/ios/{RNSScreenStackHeaderConfig.m → RNSScreenStackHeaderConfig.mm} +232 -117
  29. package/ios/RNSScreenStackHeaderSubview.h +45 -0
  30. package/ios/RNSScreenStackHeaderSubview.mm +137 -0
  31. package/ios/RNSScreenViewEvent.h +12 -0
  32. package/ios/RNSScreenViewEvent.mm +59 -0
  33. package/ios/{RNSScreenWindowTraits.m → RNSScreenWindowTraits.mm} +3 -2
  34. package/ios/RNSSearchBar.h +14 -1
  35. package/ios/RNSSearchBar.mm +351 -0
  36. package/ios/{UIViewController+RNScreens.m → UIViewController+RNScreens.mm} +0 -0
  37. package/ios/{UIWindow+RNScreens.m → UIWindow+RNScreens.mm} +0 -0
  38. package/lib/commonjs/fabric/FullWindowOverlay.js +26 -0
  39. package/lib/commonjs/fabric/FullWindowOverlay.js.map +1 -0
  40. package/lib/commonjs/fabric/FullWindowOverlayNativeComponent.js +21 -0
  41. package/lib/commonjs/fabric/FullWindowOverlayNativeComponent.js.map +1 -0
  42. package/lib/commonjs/fabric/Screen.js +10 -8
  43. package/lib/commonjs/fabric/Screen.js.map +1 -1
  44. package/lib/commonjs/fabric/ScreenContainer.js +28 -0
  45. package/lib/commonjs/fabric/ScreenContainer.js.map +1 -0
  46. package/lib/commonjs/fabric/ScreenContainerNativeComponent.js +21 -0
  47. package/lib/commonjs/fabric/ScreenContainerNativeComponent.js.map +1 -0
  48. package/lib/commonjs/fabric/ScreenNativeComponent.js.map +1 -1
  49. package/lib/commonjs/fabric/ScreenNavigationContainer.js +28 -0
  50. package/lib/commonjs/fabric/ScreenNavigationContainer.js.map +1 -0
  51. package/lib/commonjs/fabric/ScreenNavigationContainerNativeComponent.js +21 -0
  52. package/lib/commonjs/fabric/ScreenNavigationContainerNativeComponent.js.map +1 -0
  53. package/lib/commonjs/fabric/ScreenStack.js +6 -7
  54. package/lib/commonjs/fabric/ScreenStack.js.map +1 -1
  55. package/lib/commonjs/fabric/ScreenStackHeaderConfigNativeComponent.js.map +1 -1
  56. package/lib/commonjs/fabric/ScreenStackHeaderSubview.js +4 -1
  57. package/lib/commonjs/fabric/ScreenStackHeaderSubview.js.map +1 -1
  58. package/lib/commonjs/fabric/ScreenStackNativeComponent.js.map +1 -1
  59. package/lib/commonjs/fabric/SearchBar.js +37 -0
  60. package/lib/commonjs/fabric/SearchBar.js.map +1 -0
  61. package/lib/commonjs/fabric/SearchBarNativeComponent.js +25 -0
  62. package/lib/commonjs/fabric/SearchBarNativeComponent.js.map +1 -0
  63. package/lib/commonjs/fabric/index.js +32 -0
  64. package/lib/commonjs/fabric/index.js.map +1 -1
  65. package/lib/commonjs/index.native.js +14 -18
  66. package/lib/commonjs/index.native.js.map +1 -1
  67. package/lib/commonjs/native-stack/views/NativeStackView.js +4 -0
  68. package/lib/commonjs/native-stack/views/NativeStackView.js.map +1 -1
  69. package/lib/commonjs/reanimated/ReanimatedNativeStackScreen.js +8 -2
  70. package/lib/commonjs/reanimated/ReanimatedNativeStackScreen.js.map +1 -1
  71. package/lib/module/fabric/FullWindowOverlay.js +15 -0
  72. package/lib/module/fabric/FullWindowOverlay.js.map +1 -0
  73. package/lib/module/fabric/FullWindowOverlayNativeComponent.js +9 -0
  74. package/lib/module/fabric/FullWindowOverlayNativeComponent.js.map +1 -0
  75. package/lib/module/fabric/Screen.js +8 -3
  76. package/lib/module/fabric/Screen.js.map +1 -1
  77. package/lib/module/fabric/ScreenContainer.js +17 -0
  78. package/lib/module/fabric/ScreenContainer.js.map +1 -0
  79. package/lib/module/fabric/ScreenContainerNativeComponent.js +9 -0
  80. package/lib/module/fabric/ScreenContainerNativeComponent.js.map +1 -0
  81. package/lib/module/fabric/ScreenNativeComponent.js.map +1 -1
  82. package/lib/module/fabric/ScreenNavigationContainer.js +17 -0
  83. package/lib/module/fabric/ScreenNavigationContainer.js.map +1 -0
  84. package/lib/module/fabric/ScreenNavigationContainerNativeComponent.js +9 -0
  85. package/lib/module/fabric/ScreenNavigationContainerNativeComponent.js.map +1 -0
  86. package/lib/module/fabric/ScreenStack.js +5 -2
  87. package/lib/module/fabric/ScreenStack.js.map +1 -1
  88. package/lib/module/fabric/ScreenStackHeaderConfigNativeComponent.js.map +1 -1
  89. package/lib/module/fabric/ScreenStackHeaderSubview.js +4 -1
  90. package/lib/module/fabric/ScreenStackHeaderSubview.js.map +1 -1
  91. package/lib/module/fabric/ScreenStackNativeComponent.js.map +1 -1
  92. package/lib/module/fabric/SearchBar.js +24 -0
  93. package/lib/module/fabric/SearchBar.js.map +1 -0
  94. package/lib/module/fabric/SearchBarNativeComponent.js +11 -0
  95. package/lib/module/fabric/SearchBarNativeComponent.js.map +1 -0
  96. package/lib/module/fabric/index.js +5 -1
  97. package/lib/module/fabric/index.js.map +1 -1
  98. package/lib/module/index.native.js +15 -20
  99. package/lib/module/index.native.js.map +1 -1
  100. package/lib/module/native-stack/views/NativeStackView.js +4 -0
  101. package/lib/module/native-stack/views/NativeStackView.js.map +1 -1
  102. package/lib/module/reanimated/ReanimatedNativeStackScreen.js +7 -2
  103. package/lib/module/reanimated/ReanimatedNativeStackScreen.js.map +1 -1
  104. package/lib/typescript/native-stack/types.d.ts +12 -0
  105. package/lib/typescript/reanimated/ReanimatedNativeStackScreen.d.ts +1 -1
  106. package/lib/typescript/reanimated/ReanimatedScreen.d.ts +1 -1
  107. package/lib/typescript/types.d.ts +24 -0
  108. package/native-stack/README.md +21 -0
  109. package/package.json +2 -2
  110. package/src/fabric/FullWindowOverlay.js +13 -0
  111. package/src/fabric/FullWindowOverlayNativeComponent.js +19 -0
  112. package/src/fabric/Screen.js +5 -2
  113. package/src/fabric/ScreenContainer.js +16 -0
  114. package/src/fabric/ScreenContainerNativeComponent.js +19 -0
  115. package/src/fabric/ScreenNativeComponent.js +41 -8
  116. package/src/fabric/ScreenNavigationContainer.js +16 -0
  117. package/src/fabric/ScreenNavigationContainerNativeComponent.js +19 -0
  118. package/src/fabric/ScreenStack.js +4 -2
  119. package/src/fabric/ScreenStackHeaderConfigNativeComponent.js +1 -1
  120. package/src/fabric/ScreenStackHeaderSubview.js +3 -1
  121. package/src/fabric/ScreenStackNativeComponent.js +4 -0
  122. package/src/fabric/SearchBar.js +20 -0
  123. package/src/fabric/SearchBarNativeComponent.js +62 -0
  124. package/src/fabric/index.js +8 -0
  125. package/src/index.native.tsx +20 -19
  126. package/src/native-stack/types.tsx +12 -0
  127. package/src/native-stack/views/NativeStackView.tsx +4 -0
  128. package/src/reanimated/ReanimatedNativeStackScreen.tsx +6 -0
  129. package/src/types.tsx +25 -0
  130. package/ios/RNSFullWindowOverlay.m +0 -105
  131. package/ios/RNSScreenComponentView.h +0 -23
  132. package/ios/RNSScreenComponentView.mm +0 -159
  133. package/ios/RNSScreenController.h +0 -10
  134. package/ios/RNSScreenController.mm +0 -79
  135. package/ios/RNSScreenStackComponentView.h +0 -15
  136. package/ios/RNSScreenStackComponentView.mm +0 -295
  137. package/ios/RNSScreenStackHeaderConfigComponentView.h +0 -42
  138. package/ios/RNSScreenStackHeaderConfigComponentView.mm +0 -662
  139. package/ios/RNSScreenStackHeaderSubviewComponentView.h +0 -14
  140. package/ios/RNSScreenStackHeaderSubviewComponentView.mm +0 -77
  141. package/ios/RNSSearchBar.m +0 -198
@@ -1,105 +0,0 @@
1
- #import <UIKit/UIKit.h>
2
-
3
- #import "RNSFullWindowOverlay.h"
4
-
5
- #import <React/RCTTouchHandler.h>
6
-
7
- @implementation RNSFullWindowOverlayContainer
8
-
9
- - (BOOL)pointInside:(CGPoint)point withEvent:(UIEvent *)event
10
- {
11
- for (UIView *view in [self subviews]) {
12
- if (view.userInteractionEnabled && [view pointInside:[self convertPoint:point toView:view] withEvent:event]) {
13
- return YES;
14
- }
15
- }
16
- return NO;
17
- }
18
-
19
- @end
20
-
21
- @implementation RNSFullWindowOverlay {
22
- __weak RCTBridge *_bridge;
23
- RNSFullWindowOverlayContainer *_container;
24
- CGRect _reactFrame;
25
- RCTTouchHandler *_touchHandler;
26
- }
27
-
28
- - (instancetype)initWithBridge:(RCTBridge *)bridge
29
- {
30
- if (self = [super init]) {
31
- _bridge = bridge;
32
- _reactFrame = CGRectNull;
33
- _container = self.container;
34
- [self show];
35
- }
36
-
37
- return self;
38
- }
39
-
40
- - (void)reactSetFrame:(CGRect)frame
41
- {
42
- _reactFrame = frame;
43
- [_container setFrame:frame];
44
- }
45
-
46
- - (void)addSubview:(UIView *)view
47
- {
48
- [_container addSubview:view];
49
- }
50
-
51
- - (RNSFullWindowOverlayContainer *)container
52
- {
53
- if (_container == nil) {
54
- _container = [[RNSFullWindowOverlayContainer alloc] initWithFrame:_reactFrame];
55
- }
56
-
57
- return _container;
58
- }
59
-
60
- - (void)show
61
- {
62
- UIWindow *window = RCTSharedApplication().delegate.window;
63
- [window addSubview:_container];
64
- }
65
-
66
- - (void)hide
67
- {
68
- if (!_container) {
69
- return;
70
- }
71
-
72
- [_container removeFromSuperview];
73
- }
74
-
75
- - (void)didMoveToWindow
76
- {
77
- if (self.window == nil) {
78
- [self hide];
79
- [_touchHandler detachFromView:_container];
80
- } else {
81
- if (_touchHandler == nil) {
82
- _touchHandler = [[RCTTouchHandler alloc] initWithBridge:_bridge];
83
- }
84
- [_touchHandler attachToView:_container];
85
- }
86
- }
87
-
88
- - (void)invalidate
89
- {
90
- [self hide];
91
- _container = nil;
92
- }
93
-
94
- @end
95
-
96
- @implementation RNSFullWindowOverlayManager
97
-
98
- RCT_EXPORT_MODULE()
99
-
100
- - (UIView *)view
101
- {
102
- return [[RNSFullWindowOverlay alloc] initWithBridge:self.bridge];
103
- }
104
-
105
- @end
@@ -1,23 +0,0 @@
1
- #import <UIKit/UIKit.h>
2
-
3
- #import <React/RCTViewComponentView.h>
4
- #import "RNSScreenController.h"
5
-
6
- NS_ASSUME_NONNULL_BEGIN
7
-
8
- @interface RNSScreenComponentView : RCTViewComponentView
9
-
10
- @property (weak, nonatomic) UIView *reactSuperview;
11
- @property (weak, nonatomic) UIView *config;
12
- @property (nonatomic, retain) RNSScreenController *controller;
13
-
14
- - (void)notifyWillAppear;
15
- - (void)notifyWillDisappear;
16
- - (void)notifyAppear;
17
- - (void)notifyDisappear;
18
- - (void)updateBounds;
19
- - (void)notifyDismissedWithCount:(int)dismissCount;
20
-
21
- @end
22
-
23
- NS_ASSUME_NONNULL_END
@@ -1,159 +0,0 @@
1
- #import "RNSScreenComponentView.h"
2
- #import "RNSScreenStackHeaderConfigComponentView.h"
3
-
4
- #import <React/RCTConversions.h>
5
- #import <React/RCTMountingTransactionObserving.h>
6
-
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
- #import <rnscreens/RNSScreenComponentDescriptor.h>
11
-
12
- #import "RCTFabricComponentsPlugins.h"
13
-
14
- using namespace facebook::react;
15
-
16
- @interface RNSScreenComponentView () <RCTRNSScreenViewProtocol, RCTMountingTransactionObserving>
17
- @end
18
-
19
- @implementation RNSScreenComponentView {
20
- RNSScreenController *_controller;
21
- RNSScreenShadowNode::ConcreteState::Shared _state;
22
- }
23
-
24
- - (instancetype)initWithFrame:(CGRect)frame
25
- {
26
- if (self = [super initWithFrame:frame]) {
27
- static const auto defaultProps = std::make_shared<const RNSScreenProps>();
28
- _props = defaultProps;
29
- _controller = [[RNSScreenController alloc] initWithView:self];
30
- }
31
-
32
- return self;
33
- }
34
-
35
- - (void)mountChildComponentView:(UIView<RCTComponentViewProtocol> *)childComponentView index:(NSInteger)index
36
- {
37
- [super mountChildComponentView:childComponentView index:index];
38
- if ([childComponentView isKindOfClass:[RNSScreenStackHeaderConfigComponentView class]]) {
39
- _config = childComponentView;
40
- ((RNSScreenStackHeaderConfigComponentView *)childComponentView).screenView = self;
41
- }
42
- }
43
-
44
- - (void)unmountChildComponentView:(UIView<RCTComponentViewProtocol> *)childComponentView index:(NSInteger)index
45
- {
46
- [self.controller setViewToSnapshot];
47
- if ([childComponentView isKindOfClass:[RNSScreenStackHeaderConfigComponentView class]]) {
48
- _config = nil;
49
- }
50
- [super unmountChildComponentView:childComponentView index:index];
51
- }
52
-
53
- - (void)updateBounds
54
- {
55
- if (_state != nullptr) {
56
- auto boundsSize = self.bounds.size;
57
- auto newState = RNSScreenState{RCTSizeFromCGSize(boundsSize)};
58
- _state->updateState(std::move(newState));
59
- UINavigationController *navctr = _controller.navigationController;
60
- [navctr.view setNeedsLayout];
61
- }
62
- }
63
-
64
- - (UIView *)reactSuperview
65
- {
66
- return _reactSuperview;
67
- }
68
-
69
- - (void)notifyWillAppear
70
- {
71
- // If screen is already unmounted then there will be no event emitter
72
- // it will be cleaned in prepareForRecycle
73
- if (_eventEmitter != nullptr) {
74
- std::dynamic_pointer_cast<const RNSScreenEventEmitter>(_eventEmitter)
75
- ->onWillAppear(RNSScreenEventEmitter::OnWillAppear{});
76
- }
77
- }
78
-
79
- - (void)notifyWillDisappear
80
- {
81
- // If screen is already unmounted then there will be no event emitter
82
- // it will be cleaned in prepareForRecycle
83
- if (_eventEmitter != nullptr) {
84
- std::dynamic_pointer_cast<const RNSScreenEventEmitter>(_eventEmitter)
85
- ->onWillDisappear(RNSScreenEventEmitter::OnWillDisappear{});
86
- }
87
- }
88
-
89
- - (void)notifyAppear
90
- {
91
- // If screen is already unmounted then there will be no event emitter
92
- // it will be cleaned in prepareForRecycle
93
- if (_eventEmitter != nullptr) {
94
- std::dynamic_pointer_cast<const RNSScreenEventEmitter>(_eventEmitter)->onAppear(RNSScreenEventEmitter::OnAppear{});
95
- }
96
- }
97
-
98
- - (void)notifyDismissedWithCount:(int)dismissCount
99
- {
100
- // If screen is already unmounted then there will be no event emitter
101
- // it will be cleaned in prepareForRecycle
102
- if (_eventEmitter != nullptr) {
103
- std::dynamic_pointer_cast<const RNSScreenEventEmitter>(_eventEmitter)
104
- ->onDismissed(RNSScreenEventEmitter::OnDismissed{dismissCount : dismissCount});
105
- }
106
- }
107
-
108
- - (void)notifyDisappear
109
- {
110
- // If screen is already unmounted then there will be no event emitter
111
- // it will be cleaned in prepareForRecycle
112
- if (_eventEmitter != nullptr) {
113
- std::dynamic_pointer_cast<const RNSScreenEventEmitter>(_eventEmitter)
114
- ->onDisappear(RNSScreenEventEmitter::OnDisappear{});
115
- }
116
- }
117
-
118
- #pragma mark - RCTMountingTransactionObserving
119
-
120
- - (void)mountingTransactionWillMountWithMetadata:(MountingTransactionMetadata const &)metadata
121
- {
122
- [self.controller takeSnapshot];
123
- }
124
-
125
- #pragma mark - RCTComponentViewProtocol
126
-
127
- - (void)prepareForRecycle
128
- {
129
- [super prepareForRecycle];
130
- // TODO: Make sure that there is no edge case when this should be uncommented
131
- // _controller=nil;
132
- _state.reset();
133
- }
134
-
135
- + (ComponentDescriptorProvider)componentDescriptorProvider
136
- {
137
- return concreteComponentDescriptorProvider<RNSScreenComponentDescriptor>();
138
- }
139
-
140
- - (void)updateProps:(Props::Shared const &)props oldProps:(Props::Shared const &)oldProps
141
- {
142
- const auto &oldScreenProps = *std::static_pointer_cast<const RNSScreenProps>(_props);
143
- const auto &newScreenProps = *std::static_pointer_cast<const RNSScreenProps>(props);
144
-
145
- [super updateProps:props oldProps:oldProps];
146
- }
147
-
148
- - (void)updateState:(facebook::react::State::Shared const &)state
149
- oldState:(facebook::react::State::Shared const &)oldState
150
- {
151
- _state = std::static_pointer_cast<const RNSScreenShadowNode::ConcreteState>(state);
152
- }
153
-
154
- @end
155
-
156
- Class<RCTComponentViewProtocol> RNSScreenCls(void)
157
- {
158
- return RNSScreenComponentView.class;
159
- }
@@ -1,10 +0,0 @@
1
- #import <UIKit/UIKit.h>
2
-
3
- @interface RNSScreenController : UIViewController
4
-
5
- - (instancetype)initWithView:(UIView *)view;
6
- - (void)takeSnapshot;
7
- - (void)setViewToSnapshot;
8
- - (void)resetViewToScreen;
9
-
10
- @end
@@ -1,79 +0,0 @@
1
- #import <react/renderer/components/rnscreens/RCTComponentViewHelpers.h>
2
- #import "RNSScreenComponentView.h"
3
-
4
- @implementation RNSScreenController {
5
- CGRect _lastViewFrame;
6
- RNSScreenComponentView *_initialView;
7
- UIView *_snapshot;
8
- }
9
-
10
- - (instancetype)initWithView:(UIView *)view
11
- {
12
- if (self = [super init]) {
13
- self.view = view;
14
- if ([view isKindOfClass:[RNSScreenComponentView class]]) {
15
- _initialView = (RNSScreenComponentView *)view;
16
- } else {
17
- RCTLogError(@"ScreenController can only be initialized with ScreenComponentView");
18
- }
19
- }
20
- return self;
21
- }
22
-
23
- - (void)takeSnapshot
24
- {
25
- _snapshot = [self.view snapshotViewAfterScreenUpdates:NO];
26
- }
27
-
28
- - (void)setViewToSnapshot
29
- {
30
- [self.view removeFromSuperview];
31
- self.view = _snapshot;
32
- }
33
-
34
- - (void)resetViewToScreen
35
- {
36
- [self.view removeFromSuperview];
37
- self.view = _initialView;
38
- }
39
-
40
- // TODO: Find out why this is executed when screen is going out
41
- - (void)viewWillAppear:(BOOL)animated
42
- {
43
- [super viewWillAppear:animated];
44
- [_initialView notifyWillAppear];
45
- }
46
-
47
- - (void)viewWillDisappear:(BOOL)animated
48
- {
49
- [super viewWillDisappear:animated];
50
- [_initialView notifyWillDisappear];
51
- }
52
-
53
- - (void)viewDidAppear:(BOOL)animated
54
- {
55
- [super viewDidAppear:animated];
56
- [_initialView notifyAppear];
57
- }
58
-
59
- - (void)viewDidDisappear:(BOOL)animated
60
- {
61
- [super viewDidDisappear:animated];
62
- [_initialView notifyDisappear];
63
- if (self.parentViewController == nil && self.presentingViewController == nil) {
64
- // screen dismissed, send event
65
- [_initialView notifyDismissedWithCount:1];
66
- }
67
- }
68
-
69
- - (void)viewDidLayoutSubviews
70
- {
71
- [super viewDidLayoutSubviews];
72
- BOOL isDisplayedWithinUINavController = [self.parentViewController isKindOfClass:[UINavigationController class]];
73
- if (isDisplayedWithinUINavController && !CGRectEqualToRect(_lastViewFrame, self.view.frame)) {
74
- _lastViewFrame = self.view.frame;
75
- [_initialView updateBounds];
76
- }
77
- }
78
-
79
- @end
@@ -1,15 +0,0 @@
1
- #import <UIKit/UIKit.h>
2
-
3
- #import <React/RCTViewComponentView.h>
4
-
5
- NS_ASSUME_NONNULL_BEGIN
6
-
7
- @interface RNSScreenStackComponentView : RCTViewComponentView
8
-
9
- @end
10
-
11
- @interface RNSScreenStackView : UIView
12
- - (instancetype)initWithComponentView:(RNSScreenStackComponentView *)component;
13
- @end
14
-
15
- NS_ASSUME_NONNULL_END
@@ -1,295 +0,0 @@
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
- // We check whether the view has been invalidated before running side-effects in didMoveToWindow
110
- // This is needed because when LayoutAnimations are used it is possible for view to be re-attached
111
- // to a window despite the fact it has been removed from the React Native view hierarchy.
112
- // See https://github.com/software-mansion/react-native-screens/pull/700
113
- [self maybeAddToParentAndUpdateContainer];
114
- }
115
- }
116
-
117
- - (void)navigationController:(UINavigationController *)navigationController
118
- willShowViewController:(UIViewController *)viewController
119
- animated:(BOOL)animated
120
- {
121
- UIView *view = viewController.view;
122
- if ([view isKindOfClass:RNSScreenComponentView.class]) {
123
- RNSScreenStackHeaderConfigComponentView *config =
124
- (RNSScreenStackHeaderConfigComponentView *)((RNSScreenComponentView *)view).config;
125
- [RNSScreenStackHeaderConfigComponentView willShowViewController:viewController animated:animated withConfig:config];
126
- }
127
- }
128
-
129
- - (void)maybeAddToParentAndUpdateContainer
130
- {
131
- BOOL wasScreenMounted = _controller.parentViewController != nil;
132
- BOOL isScreenReadyForShowing = self.window;
133
- if (!isScreenReadyForShowing && !wasScreenMounted) {
134
- return;
135
- }
136
- [self updateContainer];
137
- if (!wasScreenMounted) {
138
- // when stack hasn't been added to parent VC yet we do two things:
139
- // 1) we run updateContainer (the one above) – we do this because we want push view controllers to
140
- // be installed before the VC is mounted. If we do that after it is added to parent the push
141
- // updates operations are going to be blocked by UIKit.
142
- // 2) we add navigation VS to parent – this is needed for the VC lifecycle events to be dispatched
143
- // properly
144
- // 3) we again call updateContainer – this time we do this to open modal controllers. Modals
145
- // won't open in (1) because they require navigator to be added to parent. We handle that case
146
- // gracefully in setModalViewControllers and can retry opening at any point.
147
- [self reactAddControllerToClosestParent:_controller];
148
- [self updateContainer];
149
- }
150
- }
151
-
152
- - (void)reactAddControllerToClosestParent:(UIViewController *)controller
153
- {
154
- if (!controller.parentViewController) {
155
- UIView *parentView = (UIView *)self.reactSuperview;
156
- while (parentView) {
157
- if ([parentView reactViewController]) {
158
- [parentView.reactViewController addChildViewController:controller];
159
- [self addSubview:controller.view];
160
- #if !TARGET_OS_TV
161
- _controller.interactivePopGestureRecognizer.delegate = self;
162
- #endif
163
- [self navigationController:_controller willShowViewController:_controller.topViewController animated:NO];
164
- }
165
- parentView = (UIView *)parentView.reactSuperview;
166
- }
167
- return;
168
- }
169
- }
170
-
171
- - (void)setPushViewControllers:(NSArray<UIViewController *> *)controllers
172
- {
173
- // when there is no change we return immediately
174
- if ([_controller.viewControllers isEqualToArray:controllers]) {
175
- return;
176
- }
177
-
178
- // if view controller is not yet attached to window we skip updates now and run them when view
179
- // is attached
180
- if (self.window == nil) {
181
- return;
182
- }
183
-
184
- UIViewController *top = controllers.lastObject;
185
- UIViewController *lastTop = _controller.viewControllers.lastObject;
186
-
187
- // at the start we set viewControllers to contain a single UIVIewController
188
- // instance. This is a workaround for header height adjustment bug (see comment
189
- // in the init function). Here, we need to detect if the initial empty
190
- // controller is still there
191
- BOOL firstTimePush = ![lastTop isKindOfClass:[RNSScreenController class]];
192
-
193
- BOOL shouldAnimate = YES;
194
-
195
- if (firstTimePush) {
196
- // nothing pushed yet
197
- [_controller setViewControllers:controllers animated:NO];
198
- } else if (top != lastTop) {
199
- if (![controllers containsObject:lastTop]) {
200
- // if the previous top screen does not exist anymore and the new top was not on the stack before, probably replace
201
- // was called, so we check the animation
202
- if (![_controller.viewControllers containsObject:top]) {
203
- // setting new controllers with animation does `push` animation by default
204
- auto screenController = (RNSScreenController *)top;
205
- [screenController resetViewToScreen];
206
- [_controller setViewControllers:controllers animated:YES];
207
- } else {
208
- // last top controller is no longer on stack
209
- // in this case we set the controllers stack to the new list with
210
- // added the last top element to it and perform (animated) pop
211
- NSMutableArray *newControllers = [NSMutableArray arrayWithArray:controllers];
212
- [newControllers addObject:lastTop];
213
- [_controller setViewControllers:newControllers animated:NO];
214
- [_controller popViewControllerAnimated:shouldAnimate];
215
- }
216
- } else if (![_controller.viewControllers containsObject:top]) {
217
- // new top controller is not on the stack
218
- // in such case we update the stack except from the last element with
219
- // no animation and do animated push of the last item
220
- NSMutableArray *newControllers = [NSMutableArray arrayWithArray:controllers];
221
- [newControllers removeLastObject];
222
- [_controller setViewControllers:newControllers animated:NO];
223
- auto screenController = (RNSScreenController *)top;
224
- [screenController resetViewToScreen];
225
- [_controller pushViewController:top animated:shouldAnimate];
226
- } else {
227
- // don't really know what this case could be, but may need to handle it
228
- // somehow
229
- [_controller setViewControllers:controllers animated:shouldAnimate];
230
- }
231
- } else {
232
- // change wasn't on the top of the stack. We don't need animation.
233
- [_controller setViewControllers:controllers animated:NO];
234
- }
235
- }
236
-
237
- - (void)updateContainer
238
- {
239
- NSMutableArray<UIViewController *> *pushControllers = [NSMutableArray new];
240
- for (RNSScreenComponentView *screen in _reactSubviews) {
241
- if (screen.controller != nil) {
242
- if (pushControllers.count == 0) {
243
- // first screen on the list needs to be places as "push controller"
244
- [pushControllers addObject:screen.controller];
245
- } else {
246
- [pushControllers addObject:screen.controller];
247
- }
248
- }
249
- }
250
-
251
- [self setPushViewControllers:pushControllers];
252
- }
253
-
254
- - (void)layoutSubviews
255
- {
256
- [super layoutSubviews];
257
- _controller.view.frame = self.bounds;
258
- }
259
-
260
- - (void)dismissOnReload
261
- {
262
- auto screenController = (RNSScreenController *)_controller.viewControllers.lastObject;
263
- [screenController resetViewToScreen];
264
- }
265
-
266
- #pragma mark methods connected to transitioning
267
-
268
- - (BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer
269
- {
270
- return YES;
271
- }
272
-
273
- #pragma mark - RCTComponentViewProtocol
274
-
275
- - (void)prepareForRecycle
276
- {
277
- [super prepareForRecycle];
278
- _reactSubviews = [NSMutableArray new];
279
- [self dismissOnReload];
280
- _invalidated = YES;
281
- [_controller willMoveToParentViewController:nil];
282
- [_controller removeFromParentViewController];
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
- }