1 | #import <UIKit/UIKit.h>
|
2 |
|
3 | #import "RNSFullWindowOverlay.h"
|
4 |
|
5 | #ifdef RCT_NEW_ARCH_ENABLED
|
6 | #import <React/RCTConversions.h>
|
7 | #import <React/RCTFabricComponentsPlugins.h>
|
8 | #import <React/RCTSurfaceTouchHandler.h>
|
9 | #import <react/renderer/components/rnscreens/ComponentDescriptors.h>
|
10 | #import <react/renderer/components/rnscreens/Props.h>
|
11 | #import <react/renderer/components/rnscreens/RCTComponentViewHelpers.h>
|
12 | #else
|
13 | #import <React/RCTTouchHandler.h>
|
14 | #endif // RCT_NEW_ARCH_ENABLED
|
15 |
|
16 | @implementation RNSFullWindowOverlayContainer
|
17 |
|
18 | - (instancetype)initWithFrame:(CGRect)frame
|
19 | {
|
20 | if (self = [super initWithFrame:frame]) {
|
21 | self.accessibilityViewIsModal = YES;
|
22 | }
|
23 | return self;
|
24 | }
|
25 |
|
26 | - (BOOL)pointInside:(CGPoint)point withEvent:(UIEvent *)event
|
27 | {
|
28 | for (UIView *view in [self subviews]) {
|
29 | if (view.userInteractionEnabled && [view pointInside:[self convertPoint:point toView:view] withEvent:event]) {
|
30 | return YES;
|
31 | }
|
32 | }
|
33 | return NO;
|
34 | }
|
35 |
|
36 | - (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event
|
37 | {
|
38 | BOOL canReceiveTouchEvents = ([self isUserInteractionEnabled] && ![self isHidden]);
|
39 | if (!canReceiveTouchEvents) {
|
40 | return nil;
|
41 | }
|
42 |
|
43 |
|
44 |
|
45 | UIView *hitSubview = nil;
|
46 | BOOL isPointInside = [self pointInside:point withEvent:event];
|
47 | if (![self clipsToBounds] || isPointInside) {
|
48 |
|
49 | NSArray<UIView *> *sortedSubviews = [self reactZIndexSortedSubviews];
|
50 |
|
51 |
|
52 |
|
53 |
|
54 |
|
55 |
|
56 |
|
57 | for (UIView *subview in [sortedSubviews reverseObjectEnumerator]) {
|
58 | CGPoint convertedPoint = [subview convertPoint:point fromView:self];
|
59 | hitSubview = [subview hitTest:convertedPoint withEvent:event];
|
60 | if (hitSubview != nil) {
|
61 | break;
|
62 | }
|
63 | }
|
64 | }
|
65 | return hitSubview;
|
66 | }
|
67 |
|
68 | @end
|
69 |
|
70 | @implementation RNSFullWindowOverlay {
|
71 | __weak RCTBridge *_bridge;
|
72 | RNSFullWindowOverlayContainer *_container;
|
73 | CGRect _reactFrame;
|
74 | #ifdef RCT_NEW_ARCH_ENABLED
|
75 | RCTSurfaceTouchHandler *_touchHandler;
|
76 | #else
|
77 | RCTTouchHandler *_touchHandler;
|
78 | #endif // RCT_NEW_ARCH_ENABLED
|
79 | }
|
80 |
|
81 | #ifdef RCT_NEW_ARCH_ENABLED
|
82 | - (instancetype)init
|
83 | {
|
84 | if (self = [super init]) {
|
85 | static const auto defaultProps = std::make_shared<const react::RNSFullWindowOverlayProps>();
|
86 | _props = defaultProps;
|
87 | [self _initCommon];
|
88 | }
|
89 | return self;
|
90 | }
|
91 | #endif // RCT_NEW_ARCH_ENABLED
|
92 |
|
93 | - (instancetype)initWithBridge:(RCTBridge *)bridge
|
94 | {
|
95 | if (self = [super init]) {
|
96 | _bridge = bridge;
|
97 | [self _initCommon];
|
98 | }
|
99 |
|
100 | return self;
|
101 | }
|
102 |
|
103 | - (void)_initCommon
|
104 | {
|
105 | _reactFrame = CGRectNull;
|
106 | _container = self.container;
|
107 | [self show];
|
108 | }
|
109 |
|
110 | - (void)addSubview:(UIView *)view
|
111 | {
|
112 | [_container addSubview:view];
|
113 | }
|
114 |
|
115 | - (RNSFullWindowOverlayContainer *)container
|
116 | {
|
117 | if (_container == nil) {
|
118 | _container = [[RNSFullWindowOverlayContainer alloc] initWithFrame:_reactFrame];
|
119 | }
|
120 |
|
121 | return _container;
|
122 | }
|
123 |
|
124 | - (void)show
|
125 | {
|
126 | UIWindow *window = RCTKeyWindow();
|
127 | [window addSubview:_container];
|
128 | }
|
129 |
|
130 | - (void)didMoveToSuperview
|
131 | {
|
132 | if (self.superview == nil) {
|
133 | if (_container != nil) {
|
134 | [_container removeFromSuperview];
|
135 | [_touchHandler detachFromView:_container];
|
136 | }
|
137 | } else {
|
138 | if (_container != nil) {
|
139 | UIAccessibilityPostNotification(UIAccessibilityLayoutChangedNotification, _container);
|
140 | }
|
141 | if (_touchHandler == nil) {
|
142 | #ifdef RCT_NEW_ARCH_ENABLED
|
143 | _touchHandler = [RCTSurfaceTouchHandler new];
|
144 | #else
|
145 | _touchHandler = [[RCTTouchHandler alloc] initWithBridge:_bridge];
|
146 | #endif
|
147 | }
|
148 | [_touchHandler attachToView:_container];
|
149 | }
|
150 | }
|
151 |
|
152 | #ifdef RCT_NEW_ARCH_ENABLED
|
153 | #pragma mark - Fabric Specific
|
154 |
|
155 |
|
156 |
|
157 | - (void)maybeShow
|
158 | {
|
159 | UIWindow *window = RCTKeyWindow();
|
160 | if (![[window subviews] containsObject:self]) {
|
161 | [window addSubview:_container];
|
162 | }
|
163 | }
|
164 |
|
165 | + (react::ComponentDescriptorProvider)componentDescriptorProvider
|
166 | {
|
167 | return react::concreteComponentDescriptorProvider<react::RNSFullWindowOverlayComponentDescriptor>();
|
168 | }
|
169 |
|
170 | - (void)prepareForRecycle
|
171 | {
|
172 | [_container removeFromSuperview];
|
173 |
|
174 |
|
175 |
|
176 |
|
177 | [super prepareForRecycle];
|
178 | }
|
179 |
|
180 | - (void)mountChildComponentView:(UIView<RCTComponentViewProtocol> *)childComponentView index:(NSInteger)index
|
181 | {
|
182 |
|
183 |
|
184 |
|
185 |
|
186 | [self maybeShow];
|
187 | [self addSubview:childComponentView];
|
188 | }
|
189 |
|
190 | - (void)unmountChildComponentView:(UIView<RCTComponentViewProtocol> *)childComponentView index:(NSInteger)index
|
191 | {
|
192 | [childComponentView removeFromSuperview];
|
193 | }
|
194 |
|
195 | - (void)updateLayoutMetrics:(react::LayoutMetrics const &)layoutMetrics
|
196 | oldLayoutMetrics:(react::LayoutMetrics const &)oldLayoutMetrics
|
197 | {
|
198 | CGRect frame = RCTCGRectFromRect(layoutMetrics.frame);
|
199 | _reactFrame = frame;
|
200 | [_container setFrame:frame];
|
201 | }
|
202 |
|
203 | #else
|
204 | #pragma mark - Paper specific
|
205 |
|
206 | - (void)reactSetFrame:(CGRect)frame
|
207 | {
|
208 | _reactFrame = frame;
|
209 | [_container setFrame:frame];
|
210 | }
|
211 |
|
212 | - (void)invalidate
|
213 | {
|
214 | [_container removeFromSuperview];
|
215 | _container = nil;
|
216 | }
|
217 |
|
218 | #endif // RCT_NEW_ARCH_ENABLED
|
219 |
|
220 | @end
|
221 |
|
222 | #ifdef RCT_NEW_ARCH_ENABLED
|
223 | Class<RCTComponentViewProtocol> RNSFullWindowOverlayCls(void)
|
224 | {
|
225 | return RNSFullWindowOverlay.class;
|
226 | }
|
227 | #endif // RCT_NEW_ARCH_ENABLED
|
228 |
|
229 | @implementation RNSFullWindowOverlayManager
|
230 |
|
231 | RCT_EXPORT_MODULE()
|
232 |
|
233 | #ifdef RCT_NEW_ARCH_ENABLED
|
234 | #else
|
235 | - (UIView *)view
|
236 | {
|
237 | return [[RNSFullWindowOverlay alloc] initWithBridge:self.bridge];
|
238 | }
|
239 | #endif // RCT_NEW_ARCH_ENABLED
|
240 |
|
241 | @end
|