1 |
|
2 |
|
3 |
|
4 |
|
5 |
|
6 |
|
7 |
|
8 | #import "RCTSurfacePresenter.h"
|
9 |
|
10 | #import <mutex>
|
11 |
|
12 | #import <React/RCTAssert.h>
|
13 | #import <React/RCTComponentViewFactory.h>
|
14 | #import <React/RCTComponentViewRegistry.h>
|
15 | #import <React/RCTFabricSurface.h>
|
16 | #import <React/RCTFollyConvert.h>
|
17 | #import <React/RCTMountingManager.h>
|
18 | #import <React/RCTMountingManagerDelegate.h>
|
19 | #import <React/RCTScheduler.h>
|
20 | #import <React/RCTSurfaceRegistry.h>
|
21 | #import <React/RCTSurfaceView+Internal.h>
|
22 | #import <React/RCTSurfaceView.h>
|
23 | #import <React/RCTUtils.h>
|
24 |
|
25 | #import <react/components/root/RootShadowNode.h>
|
26 | #import <react/core/LayoutConstraints.h>
|
27 | #import <react/core/LayoutContext.h>
|
28 | #import <react/uimanager/ComponentDescriptorFactory.h>
|
29 | #import <react/uimanager/SchedulerToolbox.h>
|
30 | #import <react/utils/ContextContainer.h>
|
31 | #import <react/utils/ManagedObjectWrapper.h>
|
32 |
|
33 | #import "MainRunLoopEventBeat.h"
|
34 | #import "RCTConversions.h"
|
35 | #import "RuntimeEventBeat.h"
|
36 |
|
37 | using namespace facebook::react;
|
38 |
|
39 | @interface RCTSurfacePresenter () <RCTSchedulerDelegate, RCTMountingManagerDelegate>
|
40 | @end
|
41 |
|
42 | @implementation RCTSurfacePresenter {
|
43 | std::mutex _schedulerMutex;
|
44 | RCTScheduler
|
45 | *_Nullable _scheduler;
|
46 | ContextContainer::Shared _contextContainer;
|
47 | RuntimeExecutor _runtimeExecutor;
|
48 | RCTMountingManager *_mountingManager;
|
49 | RCTSurfaceRegistry *_surfaceRegistry;
|
50 | better::shared_mutex _observerListMutex;
|
51 | NSMutableArray<id<RCTSurfacePresenterObserver>> *_observers;
|
52 | }
|
53 |
|
54 | - (instancetype)initWithContextContainer:(ContextContainer::Shared)contextContainer
|
55 | runtimeExecutor:(RuntimeExecutor)runtimeExecutor
|
56 | {
|
57 | if (self = [super init]) {
|
58 | assert(contextContainer && "RuntimeExecutor must be not null.");
|
59 |
|
60 | _runtimeExecutor = runtimeExecutor;
|
61 | _contextContainer = contextContainer;
|
62 |
|
63 | _surfaceRegistry = [[RCTSurfaceRegistry alloc] init];
|
64 | _mountingManager = [[RCTMountingManager alloc] init];
|
65 | _mountingManager.delegate = self;
|
66 |
|
67 | _observers = [NSMutableArray array];
|
68 |
|
69 | _scheduler = [self _createScheduler];
|
70 | }
|
71 |
|
72 | return self;
|
73 | }
|
74 |
|
75 | - (RCTComponentViewFactory *)componentViewFactory
|
76 | {
|
77 | return _mountingManager.componentViewRegistry.componentViewFactory;
|
78 | }
|
79 |
|
80 | - (ContextContainer::Shared)contextContainer
|
81 | {
|
82 | std::lock_guard<std::mutex> lock(_schedulerMutex);
|
83 | return _contextContainer;
|
84 | }
|
85 |
|
86 | - (void)setContextContainer:(ContextContainer::Shared)contextContainer
|
87 | {
|
88 | std::lock_guard<std::mutex> lock(_schedulerMutex);
|
89 | _contextContainer = contextContainer;
|
90 | }
|
91 |
|
92 | - (void)setRuntimeExecutor:(RuntimeExecutor)runtimeExecutor
|
93 | {
|
94 | std::lock_guard<std::mutex> lock(_schedulerMutex);
|
95 | _runtimeExecutor = runtimeExecutor;
|
96 | }
|
97 |
|
98 | - (RuntimeExecutor)runtimeExecutor
|
99 | {
|
100 | std::lock_guard<std::mutex> lock(_schedulerMutex);
|
101 | return _runtimeExecutor;
|
102 | }
|
103 |
|
104 | #pragma mark - Internal Surface-dedicated Interface
|
105 |
|
106 | - (void)registerSurface:(RCTFabricSurface *)surface
|
107 | {
|
108 | std::lock_guard<std::mutex> lock(_schedulerMutex);
|
109 | [_surfaceRegistry registerSurface:surface];
|
110 | if (_scheduler) {
|
111 | [self _startSurface:surface];
|
112 | }
|
113 | }
|
114 |
|
115 | - (void)unregisterSurface:(RCTFabricSurface *)surface
|
116 | {
|
117 | std::lock_guard<std::mutex> lock(_schedulerMutex);
|
118 | if (_scheduler) {
|
119 | [self _stopSurface:surface];
|
120 | }
|
121 | [_surfaceRegistry unregisterSurface:surface];
|
122 | }
|
123 |
|
124 | - (void)setProps:(NSDictionary *)props surface:(RCTFabricSurface *)surface
|
125 | {
|
126 | std::lock_guard<std::mutex> lock(_schedulerMutex);
|
127 |
|
128 | [self _stopSurface:surface];
|
129 | [self _startSurface:surface];
|
130 | }
|
131 |
|
132 | - (RCTFabricSurface *)surfaceForRootTag:(ReactTag)rootTag
|
133 | {
|
134 | return [_surfaceRegistry surfaceForRootTag:rootTag];
|
135 | }
|
136 |
|
137 | - (CGSize)sizeThatFitsMinimumSize:(CGSize)minimumSize
|
138 | maximumSize:(CGSize)maximumSize
|
139 | surface:(RCTFabricSurface *)surface
|
140 | {
|
141 | std::lock_guard<std::mutex> lock(_schedulerMutex);
|
142 | LayoutContext layoutContext = {.pointScaleFactor = RCTScreenScale()};
|
143 | LayoutConstraints layoutConstraints = {.minimumSize = RCTSizeFromCGSize(minimumSize),
|
144 | .maximumSize = RCTSizeFromCGSize(maximumSize)};
|
145 | return [_scheduler measureSurfaceWithLayoutConstraints:layoutConstraints
|
146 | layoutContext:layoutContext
|
147 | surfaceId:surface.rootTag];
|
148 | }
|
149 |
|
150 | - (void)setMinimumSize:(CGSize)minimumSize maximumSize:(CGSize)maximumSize surface:(RCTFabricSurface *)surface
|
151 | {
|
152 | std::lock_guard<std::mutex> lock(_schedulerMutex);
|
153 | LayoutContext layoutContext = {.pointScaleFactor = RCTScreenScale()};
|
154 | LayoutConstraints layoutConstraints = {.minimumSize = RCTSizeFromCGSize(minimumSize),
|
155 | .maximumSize = RCTSizeFromCGSize(maximumSize)};
|
156 | [_scheduler constraintSurfaceLayoutWithLayoutConstraints:layoutConstraints
|
157 | layoutContext:layoutContext
|
158 | surfaceId:surface.rootTag];
|
159 | }
|
160 |
|
161 | - (BOOL)synchronouslyUpdateViewOnUIThread:(NSNumber *)reactTag props:(NSDictionary *)props
|
162 | {
|
163 | std::lock_guard<std::mutex> lock(_schedulerMutex);
|
164 | ReactTag tag = [reactTag integerValue];
|
165 | UIView<RCTComponentViewProtocol> *componentView =
|
166 | [_mountingManager.componentViewRegistry findComponentViewWithTag:tag];
|
167 | if (componentView == nil) {
|
168 | return NO;
|
169 | }
|
170 | ComponentHandle handle = [[componentView class] componentDescriptorProvider].handle;
|
171 | auto *componentDescriptor = [_scheduler findComponentDescriptorByHandle_DO_NOT_USE_THIS_IS_BROKEN:handle];
|
172 |
|
173 | if (!componentDescriptor) {
|
174 | return YES;
|
175 | }
|
176 |
|
177 | [_mountingManager synchronouslyUpdateViewOnUIThread:tag changedProps:props componentDescriptor:*componentDescriptor];
|
178 | return YES;
|
179 | }
|
180 |
|
181 | - (BOOL)suspend
|
182 | {
|
183 | std::lock_guard<std::mutex> lock(_schedulerMutex);
|
184 |
|
185 | if (!_scheduler) {
|
186 | return NO;
|
187 | }
|
188 |
|
189 | [self _stopAllSurfaces];
|
190 | _scheduler = nil;
|
191 |
|
192 | return YES;
|
193 | }
|
194 |
|
195 | - (BOOL)resume
|
196 | {
|
197 | std::lock_guard<std::mutex> lock(_schedulerMutex);
|
198 |
|
199 | if (_scheduler) {
|
200 | return NO;
|
201 | }
|
202 |
|
203 | _scheduler = [self _createScheduler];
|
204 | [self _startAllSurfaces];
|
205 |
|
206 | return YES;
|
207 | }
|
208 |
|
209 | #pragma mark - Private
|
210 |
|
211 | - (RCTScheduler *)_createScheduler
|
212 | {
|
213 | auto componentRegistryFactory = [factory = wrapManagedObject(self.componentViewFactory)](
|
214 | EventDispatcher::Weak const &eventDispatcher,
|
215 | ContextContainer::Shared const &contextContainer) {
|
216 | return [(RCTComponentViewFactory *)unwrapManagedObject(factory)
|
217 | createComponentDescriptorRegistryWithParameters:{eventDispatcher, contextContainer}];
|
218 | };
|
219 |
|
220 | auto runtimeExecutor = _runtimeExecutor;
|
221 |
|
222 | auto toolbox = SchedulerToolbox{};
|
223 | toolbox.contextContainer = _contextContainer;
|
224 | toolbox.componentRegistryFactory = componentRegistryFactory;
|
225 | toolbox.runtimeExecutor = runtimeExecutor;
|
226 |
|
227 | toolbox.synchronousEventBeatFactory = [runtimeExecutor](EventBeat::SharedOwnerBox const &ownerBox) {
|
228 | return std::make_unique<MainRunLoopEventBeat>(ownerBox, runtimeExecutor);
|
229 | };
|
230 |
|
231 | toolbox.asynchronousEventBeatFactory = [runtimeExecutor](EventBeat::SharedOwnerBox const &ownerBox) {
|
232 | return std::make_unique<RuntimeEventBeat>(ownerBox, runtimeExecutor);
|
233 | };
|
234 |
|
235 | RCTScheduler *scheduler = [[RCTScheduler alloc] initWithToolbox:toolbox];
|
236 | scheduler.delegate = self;
|
237 |
|
238 | return scheduler;
|
239 | }
|
240 |
|
241 | - (void)_startSurface:(RCTFabricSurface *)surface
|
242 | {
|
243 | RCTMountingManager *mountingManager = _mountingManager;
|
244 | RCTExecuteOnMainQueue(^{
|
245 | [mountingManager.componentViewRegistry dequeueComponentViewWithComponentHandle:RootShadowNode::Handle()
|
246 | tag:surface.rootTag];
|
247 | });
|
248 |
|
249 | LayoutContext layoutContext = {.pointScaleFactor = RCTScreenScale()};
|
250 |
|
251 | LayoutConstraints layoutConstraints = {.minimumSize = RCTSizeFromCGSize(surface.minimumSize),
|
252 | .maximumSize = RCTSizeFromCGSize(surface.maximumSize)};
|
253 |
|
254 | [_scheduler startSurfaceWithSurfaceId:surface.rootTag
|
255 | moduleName:surface.moduleName
|
256 | initialProps:surface.properties
|
257 | layoutConstraints:layoutConstraints
|
258 | layoutContext:layoutContext];
|
259 | }
|
260 |
|
261 | - (void)_stopSurface:(RCTFabricSurface *)surface
|
262 | {
|
263 | [_scheduler stopSurfaceWithSurfaceId:surface.rootTag];
|
264 |
|
265 | RCTMountingManager *mountingManager = _mountingManager;
|
266 | RCTExecuteOnMainQueue(^{
|
267 | RCTComponentViewDescriptor rootViewDescriptor =
|
268 | [mountingManager.componentViewRegistry componentViewDescriptorWithTag:surface.rootTag];
|
269 | [mountingManager.componentViewRegistry enqueueComponentViewWithComponentHandle:RootShadowNode::Handle()
|
270 | tag:surface.rootTag
|
271 | componentViewDescriptor:rootViewDescriptor];
|
272 | });
|
273 |
|
274 | [surface _unsetStage:(RCTSurfaceStagePrepared | RCTSurfaceStageMounted)];
|
275 | }
|
276 |
|
277 | - (void)_startAllSurfaces
|
278 | {
|
279 | [_surfaceRegistry enumerateWithBlock:^(NSEnumerator<RCTFabricSurface *> *enumerator) {
|
280 | for (RCTFabricSurface *surface in enumerator) {
|
281 | [self _startSurface:surface];
|
282 | }
|
283 | }];
|
284 | }
|
285 |
|
286 | - (void)_stopAllSurfaces
|
287 | {
|
288 | [_surfaceRegistry enumerateWithBlock:^(NSEnumerator<RCTFabricSurface *> *enumerator) {
|
289 | for (RCTFabricSurface *surface in enumerator) {
|
290 | [self _stopSurface:surface];
|
291 | }
|
292 | }];
|
293 | }
|
294 |
|
295 | #pragma mark - RCTSchedulerDelegate
|
296 |
|
297 | - (void)schedulerDidFinishTransaction:(MountingCoordinator::Shared const &)mountingCoordinator
|
298 | {
|
299 | RCTFabricSurface *surface = [_surfaceRegistry surfaceForRootTag:mountingCoordinator->getSurfaceId()];
|
300 |
|
301 | [surface _setStage:RCTSurfaceStagePrepared];
|
302 |
|
303 | [_mountingManager scheduleTransaction:mountingCoordinator];
|
304 | }
|
305 |
|
306 | - (void)schedulerDidDispatchCommand:(ShadowView const &)shadowView
|
307 | commandName:(std::string const &)commandName
|
308 | args:(folly::dynamic const)args
|
309 | {
|
310 | ReactTag tag = shadowView.tag;
|
311 | NSString *commandStr = [[NSString alloc] initWithUTF8String:commandName.c_str()];
|
312 | NSArray *argsArray = convertFollyDynamicToId(args);
|
313 |
|
314 | [self->_mountingManager dispatchCommand:tag commandName:commandStr args:argsArray];
|
315 | }
|
316 |
|
317 | - (void)addObserver:(id<RCTSurfacePresenterObserver>)observer
|
318 | {
|
319 | std::unique_lock<better::shared_mutex> lock(_observerListMutex);
|
320 | [self->_observers addObject:observer];
|
321 | }
|
322 |
|
323 | - (void)removeObserver:(id<RCTSurfacePresenterObserver>)observer
|
324 | {
|
325 | std::unique_lock<better::shared_mutex> lock(_observerListMutex);
|
326 | [self->_observers removeObject:observer];
|
327 | }
|
328 |
|
329 | #pragma mark - RCTMountingManagerDelegate
|
330 |
|
331 | - (void)mountingManager:(RCTMountingManager *)mountingManager willMountComponentsWithRootTag:(ReactTag)rootTag
|
332 | {
|
333 | RCTAssertMainQueue();
|
334 |
|
335 | std::shared_lock<better::shared_mutex> lock(_observerListMutex);
|
336 | for (id<RCTSurfacePresenterObserver> observer in _observers) {
|
337 | if ([observer respondsToSelector:@selector(willMountComponentsWithRootTag:)]) {
|
338 | [observer willMountComponentsWithRootTag:rootTag];
|
339 | }
|
340 | }
|
341 | }
|
342 |
|
343 | - (void)mountingManager:(RCTMountingManager *)mountingManager didMountComponentsWithRootTag:(ReactTag)rootTag
|
344 | {
|
345 | RCTAssertMainQueue();
|
346 |
|
347 | RCTFabricSurface *surface = [_surfaceRegistry surfaceForRootTag:rootTag];
|
348 | RCTSurfaceStage stage = surface.stage;
|
349 | if (stage & RCTSurfaceStagePrepared) {
|
350 |
|
351 | if ([surface _setStage:RCTSurfaceStageMounted]) {
|
352 | auto rootComponentViewDescriptor =
|
353 | [_mountingManager.componentViewRegistry componentViewDescriptorWithTag:rootTag];
|
354 | surface.view.rootView = (RCTSurfaceRootView *)rootComponentViewDescriptor.view;
|
355 | }
|
356 | }
|
357 |
|
358 | std::shared_lock<better::shared_mutex> lock(_observerListMutex);
|
359 | for (id<RCTSurfacePresenterObserver> observer in _observers) {
|
360 | if ([observer respondsToSelector:@selector(didMountComponentsWithRootTag:)]) {
|
361 | [observer didMountComponentsWithRootTag:rootTag];
|
362 | }
|
363 | }
|
364 | }
|
365 |
|
366 | @end
|