diff --git a/React/Fabric/RCTSurfacePresenter.h b/React/Fabric/RCTSurfacePresenter.h new file mode 100644 index 000000000..d99133d59 --- /dev/null +++ b/React/Fabric/RCTSurfacePresenter.h @@ -0,0 +1,60 @@ +/** + * Copyright (c) 2015-present, Facebook, Inc. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +#import +#import + +#import +#import +#import + +NS_ASSUME_NONNULL_BEGIN + +@class RCTFabricSurface; +@class RCTMountingManager; + +/** + * Coordinates presenting of React Native Surfaces and represents application + * facing interface of running React Native core. + * SurfacePresenter incapsulates a bridge object inside and discourage direct + * access to it. + */ +@interface RCTSurfacePresenter : NSObject + +- (instancetype)initWithBridge:(RCTBridge *)bridge; + +@end + +@interface RCTSurfacePresenter (Internal) + +/** + * Surface uses those methods to register itself in the Presenter. + * Registering initiates running, rendering and mounting processes. + */ +- (void)registerSurface:(RCTFabricSurface *)surface; +- (void)unregisterSurface:(RCTFabricSurface *)surface; + +@end + +@interface RCTSurfacePresenter (Deprecated) + +/** + * We need to expose `exceptionManager` and `uiManager` for registration + * purposes. Eventually, we will move this down to C++ side. + */ +- (std::shared_ptr)exceptionManager_DO_NOT_USE; +- (std::shared_ptr)uiManager_DO_NOT_USE; + +@end + +@interface RCTBridge (RCTSurfacePresenter) + +- (RCTSurfacePresenter *)surfacePresenter; + +@end + +NS_ASSUME_NONNULL_END diff --git a/React/Fabric/RCTSurfacePresenter.mm b/React/Fabric/RCTSurfacePresenter.mm new file mode 100644 index 000000000..8e88548c8 --- /dev/null +++ b/React/Fabric/RCTSurfacePresenter.mm @@ -0,0 +1,154 @@ +/** + * Copyright (c) 2015-present, Facebook, Inc. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +#import "RCTSurfacePresenter.h" + +#import +#import +#import +#import +#import +#import +#import +#import +#import +#import +#import + +using namespace facebook::react; + +@interface RCTSurfacePresenter () +@end + +@implementation RCTSurfacePresenter { + std::shared_ptr _exceptionManager; + RCTScheduler *_scheduler; + RCTMountingManager *_mountingManager; + RCTBridge *_bridge; + RCTBridge *_batchedBridge; + RCTSurfaceRegistry *_surfaceRegistry; +} + +- (instancetype)initWithBridge:(RCTBridge *)bridge +{ + if (self = [super init]) { + _bridge = bridge; + _batchedBridge = [_bridge batchedBridge] ?: _bridge; + + _exceptionManager = std::make_shared(); + + _scheduler = [[RCTScheduler alloc] init]; + _scheduler.delegate = self; + + _surfaceRegistry = [[RCTSurfaceRegistry alloc] init]; + _mountingManager = [[RCTMountingManager alloc] init]; + _mountingManager.delegate = self; + } + + return self; +} + +- (std::shared_ptr)exceptionManager +{ + return _exceptionManager; +} + +- (void)schedulerDidComputeMutationInstructions:(facebook::react::TreeMutationInstructionList)instructions rootTag:(ReactTag)rootTag +{ + [_mountingManager mutateComponentViewTreeWithMutationInstructions:instructions + rootTag:rootTag]; +} + +- (void)schedulerDidRequestPreliminaryViewAllocationWithComponentName:(NSString *)componentName +{ + // TODO: To be implemeted. +} + +#pragma mark - Internal Surface-dedicated Interface + +- (void)registerSurface:(RCTFabricSurface *)surface +{ + [_surfaceRegistry registerSurface:surface]; + [_scheduler registerRootTag:surface.rootViewTag.integerValue]; + [self runSurface:surface]; + + // FIXME: Mutation instruction MUST produce instruction for root node. + [_mountingManager.componentViewRegistry dequeueComponentViewWithName:@"Root" tag:surface.rootViewTag.integerValue]; +} + +- (void)unregisterSurface:(RCTFabricSurface *)surface +{ + [self stopSurface:surface]; + [_scheduler unregisterRootTag:surface.rootViewTag.integerValue]; + [_surfaceRegistry unregisterSurface:surface]; +} + +- (void)runSurface:(RCTFabricSurface *)surface +{ + NSDictionary *applicationParameters = @{ + @"rootTag": surface.rootViewTag, + @"initialProps": surface.properties, + }; + + [_batchedBridge enqueueJSCall:@"AppRegistry" method:@"runApplication" args:@[surface.moduleName, applicationParameters] completion:NULL]; +} + +- (void)stopSurface:(RCTFabricSurface *)surface +{ + [_batchedBridge enqueueJSCall:@"AppRegistry" method:@"unmountApplicationComponentAtRootTag" args:@[surface.rootViewTag] completion:NULL]; +} + +#pragma mark - RCTMountingManagerDelegate + +- (void)mountingManager:(RCTMountingManager *)mountingManager willMountComponentsWithRootTag:(ReactTag)rootTag +{ + RCTIsMainQueue(); + // TODO: Propagate state change to Surface. +} + +- (void)mountingManager:(RCTMountingManager *)mountingManager didMountComponentsWithRootTag:(ReactTag)rootTag +{ + RCTIsMainQueue(); + RCTFabricSurface *surface = [_surfaceRegistry surfaceForRootTag:rootTag]; + + // FIXME: Implement proper state propagation mechanism. + [surface _setStage:RCTSurfaceStageSurfaceDidInitialRendering]; + [surface _setStage:RCTSurfaceStageSurfaceDidInitialLayout]; + [surface _setStage:RCTSurfaceStageSurfaceDidInitialMounting]; + + UIView *rootComponentView = [_mountingManager.componentViewRegistry componentViewByTag:rootTag]; + + // FIXME: Remove this. + rootComponentView.frame = CGRectMake(0, 0, 400, 400); + + surface.view.rootView = (RCTSurfaceRootView *)rootComponentView; +} + +@end + +@implementation RCTSurfacePresenter (Deprecated) + +- (std::shared_ptr)uiManager_DO_NOT_USE +{ + return _scheduler.uiManager_DO_NOT_USE; +} + +- (std::shared_ptr)exceptionManager_DO_NOT_USE +{ + return _exceptionManager; +} + +@end + +@implementation RCTBridge (RCTSurfacePresenter) + +- (RCTSurfacePresenter *)surfacePresenter +{ + return [self jsBoundExtraModuleForClass:[RCTSurfacePresenter class]]; +} + +@end