Skip to content

Commit

Permalink
feat: implement RCTReactController and RCTSwiftUIAppDelegate
Browse files Browse the repository at this point in the history
  • Loading branch information
okwasniewski committed Jan 10, 2024
1 parent e6c1b21 commit 5f9d777
Show file tree
Hide file tree
Showing 12 changed files with 457 additions and 53 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,8 @@ void RCTAppSetupPrepareApp(

RCT_EXTERN_C_BEGIN


// TODO: Rebase with this PR: https://github.com/facebook/react-native/pull/42172/files
//[[deprecated("Use the 3-argument overload of RCTAppSetupPrepareApp instead")]] void RCTAppSetupPrepareApp(
// UIApplication *application,
// BOOL turboModuleEnabled);
Expand Down
12 changes: 12 additions & 0 deletions packages/react-native/Libraries/AppDelegate/RCTReactController.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
#import <React/RCTBridgeDelegate.h>
#import <UIKit/UIKit.h>

@interface RCTReactController : UIViewController

@property (nonatomic, strong) NSString * _Nonnull moduleName;
@property (nonatomic, strong) NSDictionary * _Nullable initialProps;

- (instancetype _Nonnull)initWithModuleName:(NSString * _Nonnull)moduleName
initProps:(NSDictionary * _Nullable)initProps;

@end
120 changes: 120 additions & 0 deletions packages/react-native/Libraries/AppDelegate/RCTReactController.mm
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
#import "RCTReactController.h"
#import <React/RCTCxxBridgeDelegate.h>
#import <React/RCTLog.h>
#import <React/RCTRootView.h>
#import <React/RCTSurfacePresenterBridgeAdapter.h>
#import <React/RCTUtils.h>
#import <react/renderer/runtimescheduler/RuntimeScheduler.h>
#import "RCTAppSetupUtils.h"
#import <React/RCTUtils.h>

#if RN_DISABLE_OSS_PLUGIN_HEADER
#import <RCTTurboModulePlugin/RCTTurboModulePlugin.h>
#else
#import <React/CoreModulesPlugins.h>
#endif
#import <React/RCTBundleURLProvider.h>
#import <React/RCTComponentViewFactory.h>
#import <React/RCTComponentViewProtocol.h>
#import <React/RCTFabricSurface.h>
#import <React/RCTSurfaceHostingProxyRootView.h>
#import <React/RCTSurfacePresenter.h>
#import <ReactCommon/RCTContextContainerHandling.h>
#if USE_HERMES
#import <ReactCommon/RCTHermesInstance.h>
#else
#import <ReactCommon/RCTJscInstance.h>
#endif
#import <ReactCommon/RCTHost+Internal.h>
#import <ReactCommon/RCTHost.h>
#import <ReactCommon/RCTTurboModuleManager.h>
#import <react/config/ReactNativeConfig.h>
#import <react/renderer/runtimescheduler/RuntimeScheduler.h>
#import <react/renderer/runtimescheduler/RuntimeSchedulerCallInvoker.h>
#import <react/runtime/JSRuntimeFactory.h>

static NSString *const kRNConcurrentRoot = @"concurrentRoot";

static NSDictionary *updateInitialProps(NSDictionary *initialProps, BOOL isFabricEnabled)
{
NSMutableDictionary *mutableProps = [initialProps mutableCopy] ?: [NSMutableDictionary new];
// Hardcoding the Concurrent Root as it it not recommended to
// have the concurrentRoot turned off when Fabric is enabled.
mutableProps[kRNConcurrentRoot] = @(isFabricEnabled);
return mutableProps;
}


@implementation RCTReactController

- (instancetype)initWithModuleName:(NSString *)moduleName initProps:(NSDictionary *)initProps {
if (self = [super init]) {
_moduleName = moduleName;
_initialProps = initProps;
}
return self;
}

- (void)loadView {
BOOL fabricEnabled = self.fabricEnabled;
BOOL enableBridgeless = self.bridgelessEnabled;

NSDictionary *initProps = updateInitialProps([self prepareInitialProps], fabricEnabled);

UIView *rootView;
if (enableBridgeless) {
// TODO: Fix Bridgeless mode
// RCTFabricSurface *surface = [_reactHost createSurfaceWithModuleName:self.moduleName initialProperties:initProps];

// RCTSurfaceHostingProxyRootView *surfaceHostingProxyRootView = [[RCTSurfaceHostingProxyRootView alloc]
// initWithSurface:surface
// sizeMeasureMode:RCTSurfaceSizeMeasureModeWidthExact | RCTSurfaceSizeMeasureModeHeightExact];

// rootView = (RCTRootView *)surfaceHostingProxyRootView;
} else {
RCTBridge* bridge = [RCTSharedApplication().delegate performSelector:@selector(bridge)];
rootView = [self createRootViewWithBridge:bridge moduleName:self.moduleName initProps:initProps];
}

// Set rootView to the main of this view controller.
self.view = rootView;
}

- (UIView *)createRootViewWithBridge:(RCTBridge *)bridge
moduleName:(NSString *)moduleName
initProps:(NSDictionary *)initProps
{
BOOL enableFabric = self.fabricEnabled;
UIView *rootView = RCTAppSetupDefaultRootView(bridge, moduleName, initProps, enableFabric);

rootView.backgroundColor = [UIColor systemBackgroundColor];

return rootView;
}

- (NSDictionary *)prepareInitialProps
{
return self.initialProps;
}

- (BOOL)newArchEnabled
{
return [RCTSharedApplication().delegate performSelector:@selector(newArchEnabled)];
}

- (BOOL)turboModuleEnabled
{
return [self newArchEnabled];
}

- (BOOL)fabricEnabled
{
return [self newArchEnabled];
}

- (BOOL)bridgelessEnabled
{
return [RCTSharedApplication().delegate performSelector:@selector(bridgelessEnabled)];
}

@end
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
#import <React/RCTBridgeDelegate.h>
#import <UIKit/UIKit.h>

@class RCTBridge;
@protocol RCTBridgeDelegate;
@protocol RCTComponentViewProtocol;
@class RCTRootView;
@class RCTSurfacePresenterBridgeAdapter;

NS_ASSUME_NONNULL_BEGIN

@interface RCTSwiftUIAppDelegate : UIResponder <UIApplicationDelegate, RCTBridgeDelegate>

@property (nonatomic, strong, nonnull) UIWindow *window;
@property (nonatomic, strong, nullable) RCTBridge *bridge;
@property (nonatomic, strong, nullable) NSDictionary *initialProps;

@property (nonatomic, strong, nullable) RCTSurfacePresenterBridgeAdapter *bridgeAdapter;

/// This method returns a map of Component Descriptors and Components classes that needs to be registered in the
/// new renderer. The Component Descriptor is a string which represent the name used in JS to refer to the native
/// component. The default implementation returns an empty dictionary. Subclasses can override this method to register
/// the required components.
///
/// @return a dictionary that associate a component for the new renderer with his descriptor.
- (NSDictionary<NSString *, Class<RCTComponentViewProtocol>> *_Nullable)thirdPartyFabricComponents;

/// This method controls whether the `turboModules` feature of the New Architecture is turned on or off.
///
/// @note: This is required to be rendering on Fabric (i.e. on the New Architecture).
/// @return: `true` if the Turbo Native Module are enabled. Otherwise, it returns `false`.
- (BOOL)turboModuleEnabled;

/// This method controls whether the App will use the Fabric renderer of the New Architecture or not.
///
/// @return: `true` if the Fabric Renderer is enabled. Otherwise, it returns `false`.
- (BOOL)fabricEnabled;

/// This method controls whether React Native's new initialization layer is enabled.
///
/// @return: `true` if the new initialization layer is enabled. Otherwise returns `false`.
- (BOOL)bridgelessEnabled;

- (NSURL *)bundleURL;

@end

NS_ASSUME_NONNULL_END
Loading

0 comments on commit 5f9d777

Please sign in to comment.