/* * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. */ #import "RCTSurfaceHostingProxyRootView.h" #import #import "RCTAssert.h" #import "RCTBridge+Private.h" #import "RCTBridge.h" #import "RCTLog.h" #import "RCTPerformanceLogger.h" #import "RCTProfile.h" #import "RCTRootContentView.h" #import "RCTRootViewDelegate.h" #import "RCTSurface.h" #import "UIView+React.h" static RCTSurfaceSizeMeasureMode convertToSurfaceSizeMeasureMode(RCTRootViewSizeFlexibility sizeFlexibility) { switch (sizeFlexibility) { case RCTRootViewSizeFlexibilityWidthAndHeight: return RCTSurfaceSizeMeasureModeWidthUndefined | RCTSurfaceSizeMeasureModeHeightUndefined; case RCTRootViewSizeFlexibilityWidth: return RCTSurfaceSizeMeasureModeWidthUndefined | RCTSurfaceSizeMeasureModeHeightExact; case RCTRootViewSizeFlexibilityHeight: return RCTSurfaceSizeMeasureModeWidthExact | RCTSurfaceSizeMeasureModeHeightUndefined; case RCTRootViewSizeFlexibilityNone: return RCTSurfaceSizeMeasureModeWidthExact | RCTSurfaceSizeMeasureModeHeightExact; } } static RCTRootViewSizeFlexibility convertToRootViewSizeFlexibility(RCTSurfaceSizeMeasureMode sizeMeasureMode) { switch (sizeMeasureMode) { case RCTSurfaceSizeMeasureModeWidthUndefined | RCTSurfaceSizeMeasureModeHeightUndefined: return RCTRootViewSizeFlexibilityWidthAndHeight; case RCTSurfaceSizeMeasureModeWidthUndefined | RCTSurfaceSizeMeasureModeHeightExact: return RCTRootViewSizeFlexibilityWidth; case RCTSurfaceSizeMeasureModeWidthExact | RCTSurfaceSizeMeasureModeHeightUndefined: return RCTRootViewSizeFlexibilityHeight; case RCTSurfaceSizeMeasureModeWidthExact | RCTSurfaceSizeMeasureModeHeightExact: default: return RCTRootViewSizeFlexibilityNone; } } @implementation RCTSurfaceHostingProxyRootView { RCTModuleRegistry *_moduleRegistry; } - (instancetype)initWithBridge:(RCTBridge *)bridge moduleName:(NSString *)moduleName initialProperties:(NSDictionary *)initialProperties { RCTAssertMainQueue(); RCTAssert(bridge, @"A bridge instance is required to create an RCTSurfaceHostingProxyRootView"); RCTAssert(moduleName, @"A moduleName is required to create an RCTSurfaceHostingProxyRootView"); RCT_PROFILE_BEGIN_EVENT(RCTProfileTagAlways, @"-[RCTSurfaceHostingProxyRootView init]", nil); _bridge = bridge; _minimumSize = CGSizeZero; if (!bridge.isLoading) { [bridge.performanceLogger markStartForTag:RCTPLTTI]; } // `RCTRootViewSizeFlexibilityNone` is the RCTRootView's default. RCTSurfaceSizeMeasureMode sizeMeasureMode = convertToSurfaceSizeMeasureMode(RCTRootViewSizeFlexibilityNone); self = [super initWithBridge:bridge moduleName:moduleName initialProperties:initialProperties sizeMeasureMode:sizeMeasureMode]; RCT_PROFILE_END_EVENT(RCTProfileTagAlways, @""); return self; } - (instancetype)initWithBundleURL:(NSURL *)bundleURL moduleName:(NSString *)moduleName initialProperties:(NSDictionary *)initialProperties launchOptions:(NSDictionary *)launchOptions { RCTBridge *bridge = [[RCTBridge alloc] initWithBundleURL:bundleURL moduleProvider:nil launchOptions:launchOptions]; return [self initWithBridge:bridge moduleName:moduleName initialProperties:initialProperties]; } - (instancetype)initWithSurface:(id)surface sizeMeasureMode:(RCTSurfaceSizeMeasureMode)sizeMeasureMode moduleRegistry:(RCTModuleRegistry *)moduleRegistry { if (self = [super initWithSurface:surface sizeMeasureMode:sizeMeasureMode]) { _moduleRegistry = moduleRegistry; } return self; } - (BOOL)hasBridge { return _bridge != nil; } - (RCTModuleRegistry *)moduleRegistry { // In bridgeless mode, RCTSurfaceHostingProxyRootView is created with an RCTModuleRegistry if (_moduleRegistry) { return _moduleRegistry; } return _bridge.moduleRegistry; } - (id)eventDispatcher { return [self.moduleRegistry moduleForName:"EventDispatcher"]; } RCT_NOT_IMPLEMENTED(-(instancetype)initWithFrame : (CGRect)frame) RCT_NOT_IMPLEMENTED(-(instancetype)initWithCoder : (NSCoder *)aDecoder) #pragma mark proxy methods to RCTSurfaceHostingView - (NSString *)moduleName { return super.surface.moduleName; } - (UIView *)contentView { return self; } - (NSNumber *)reactTag { return super.surface.rootViewTag; } - (RCTRootViewSizeFlexibility)sizeFlexibility { return convertToRootViewSizeFlexibility(super.sizeMeasureMode); } - (void)setSizeFlexibility:(RCTRootViewSizeFlexibility)sizeFlexibility { super.sizeMeasureMode = convertToSurfaceSizeMeasureMode(sizeFlexibility); } - (NSDictionary *)appProperties { return super.surface.properties; } - (void)setAppProperties:(NSDictionary *)appProperties { [super.surface setProperties:appProperties]; } - (UIView *)loadingView { return super.activityIndicatorViewFactory ? super.activityIndicatorViewFactory() : nil; } - (void)setLoadingView:(UIView *)loadingView { super.activityIndicatorViewFactory = ^UIView *(void) { return loadingView; }; } #pragma mark RCTSurfaceDelegate proxying - (void)surface:(RCTSurface *)surface didChangeStage:(RCTSurfaceStage)stage { [super surface:surface didChangeStage:stage]; if (RCTSurfaceStageIsRunning(stage)) { [_bridge.performanceLogger markStopForTag:RCTPLTTI]; dispatch_async(dispatch_get_main_queue(), ^{ [[NSNotificationCenter defaultCenter] postNotificationName:RCTContentDidAppearNotification object:self]; }); } } - (void)surface:(RCTSurface *)surface didChangeIntrinsicSize:(CGSize)intrinsicSize { [super surface:surface didChangeIntrinsicSize:intrinsicSize]; [_delegate rootViewDidChangeIntrinsicSize:(RCTRootView *)self]; } #pragma mark legacy - (UIViewController *)reactViewController { return _reactViewController ?: [super reactViewController]; } - (void)setMinimumSize:(CGSize)minimumSize { if (!CGSizeEqualToSize(minimumSize, CGSizeZero)) { // TODO (T93859532): Investigate implementation for this. RCTLogError(@"RCTSurfaceHostingProxyRootView does not support changing the deprecated minimumSize"); } _minimumSize = CGSizeZero; } #pragma mark unsupported - (void)cancelTouches { // Not supported. } @end