Skip to content

Commit

Permalink
feat(iOS): working app in all modes
Browse files Browse the repository at this point in the history
  • Loading branch information
Vadzim Filipovich committed May 8, 2024
1 parent 391764e commit 8aad3f9
Show file tree
Hide file tree
Showing 16 changed files with 145 additions and 81 deletions.
67 changes: 41 additions & 26 deletions lib/ios/AppDelegate/RNNAppDelegate.mm
Original file line number Diff line number Diff line change
Expand Up @@ -21,58 +21,40 @@

static NSString *const kRNConcurrentRoot = @"concurrentRoot";

@interface RNNAppDelegate () <RCTTurboModuleManagerDelegate, RCTCxxBridgeDelegate> {
std::shared_ptr<const facebook::react::ReactNativeConfig> _reactNativeConfig;
facebook::react::ContextContainer::Shared _contextContainer;
facebook::react::RuntimeExecutor _runtimeExecutor;
std::shared_ptr<facebook::react::RuntimeScheduler> _runtimeScheduler;
}
@interface RNNAppDelegate () <RCTTurboModuleManagerDelegate, RCTCxxBridgeDelegate> {}
@end

#endif

@implementation RNNAppDelegate

#ifdef RCT_NEW_ARCH_ENABLED
- (instancetype)init {
if (self = [super init]) {
_contextContainer = std::make_shared<facebook::react::ContextContainer const>();
_reactNativeConfig = std::make_shared<facebook::react::EmptyReactNativeConfig const>();
_contextContainer->insert("ReactNativeConfig", _reactNativeConfig);
}
return self;
}
#endif

- (BOOL)application:(UIApplication *)application
didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {

#ifdef RCT_NEW_ARCH_ENABLED
// Copied from RCTAppDelegate, it private inside it
self.rootViewFactory = [self createRCTRootViewFactory];

#ifdef RCT_NEW_ARCH_ENABLED
RCTAppSetupPrepareApp(application, self.turboModuleEnabled);
RCTSetNewArchEnabled(TRUE);

if (self.bridgelessEnabled) {
// Creating host instead of bridge
self.rootViewFactory.reactHost = [self.rootViewFactory createReactHost:launchOptions];

[ReactNativeNavigation bootstrapWithHost:self.rootViewFactory.reactHost];

return YES;
}
#else
self.bridge = [[RCTBridge alloc] initWithDelegate:self launchOptions:launchOptions];
#endif
// Force RN to init all necessary modules instead of copy-pasting code (ex. bridge)
[self.rootViewFactory viewWithModuleName:@""];

[ReactNativeNavigation bootstrapWithBridge:self.bridge];

return YES;
}

- (NSArray<id<RCTBridgeModule>> *)extraModulesForBridge:(RCTBridge *)bridge {
return [ReactNativeNavigation extraModulesForBridge:bridge];
}

#ifdef RCT_NEW_ARCH_ENABLED
- (RCTRootViewFactory *)createRCTRootViewFactory
{
__weak __typeof(self) weakSelf = self;
Expand All @@ -87,18 +69,51 @@ - (RCTRootViewFactory *)createRCTRootViewFactory
turboModuleEnabled:self.turboModuleEnabled
bridgelessEnabled:self.bridgelessEnabled];

if (!self.bridgelessEnabled) {
configuration.extraModulesForBridge = ^NSArray<id<RCTBridgeModule>> * _Nonnull(RCTBridge * _Nonnull bridge) {
return [ReactNativeNavigation extraModulesForBridge:bridge];
};
}

configuration.createRootViewWithBridge = ^UIView *(RCTBridge *bridge, NSString *moduleName, NSDictionary *initProps)
{
return [weakSelf createRootViewWithBridge:bridge moduleName:moduleName initProps:initProps];
// Ignoring creation of default view, will initialize our custom UIViewController later
return nil;
};

configuration.createBridgeWithDelegate = ^RCTBridge *(id<RCTBridgeDelegate> delegate, NSDictionary *launchOptions)
{
return [weakSelf createBridgeWithDelegate:delegate launchOptions:launchOptions];
};

#ifndef RCT_NEW_ARCH_ENABLED
return [[RCTRootViewFactory alloc] initWithConfiguration:configuration];
}
#else
return [[RCTRootViewFactory alloc] initWithConfiguration:configuration andTurboModuleManagerDelegate:self];
}

#pragma mark RCTTurboModuleManagerDelegate

- (Class)getModuleClassFromName:(const char *)name {
return RCTCoreModulesClassProvider(name);
}

- (std::shared_ptr<facebook::react::TurboModule>)
getTurboModule:(const std::string &)name
jsInvoker:(std::shared_ptr<facebook::react::CallInvoker>)jsInvoker {
return nullptr;
}

- (std::shared_ptr<facebook::react::TurboModule>)
getTurboModule:(const std::string &)name
initParams:(const facebook::react::ObjCTurboModule::InitParams &)params {
return nullptr;
}

- (id<RCTTurboModule>)getModuleInstanceFromClass:(Class)moduleClass {
return RCTAppSetupDefaultModuleFromClass(moduleClass);
}
#endif

- (NSURL *)sourceURLForBridge:(RCTBridge *)bridge {
Expand Down
4 changes: 4 additions & 0 deletions lib/ios/Bridge/RNNBridgeEventEmitter.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
#import "RNNEventEmitter.h"

@interface RNNBridgeEventEmitter : RNNEventEmitter
@end
7 changes: 7 additions & 0 deletions lib/ios/Bridge/RNNBridgeEventEmitter.mm
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
#import "RNNBridgeEventEmitter.h"

@implementation RNNBridgeEventEmitter {}

RCT_EXPORT_MODULE()

@end
6 changes: 3 additions & 3 deletions lib/ios/Bridge/RNNBridgeManager.mm
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

#import "RNNBridgeModule.h"
#import "RNNComponentViewCreator.h"
#import "RNNEventEmitter.h"
#import "RNNBridgeEventEmitter.h"
#import "RNNLayoutManager.h"
#import "RNNModalHostViewManagerHandler.h"
#import "RNNReactComponentRegistry.h"
Expand Down Expand Up @@ -61,7 +61,7 @@ - (void)registerExternalComponent:(NSString *)name callback:(RNNExternalViewCrea
}

- (NSArray<id<RCTBridgeModule>> *)extraModulesForBridge:(RCTBridge *)bridge {
RNNEventEmitter *eventEmitter = [[RNNEventEmitter alloc] init];
RNNEventEmitter * eventEmitter = [[RNNBridgeEventEmitter alloc] init];

RNNModalManagerEventHandler *modalManagerEventHandler =
[[RNNModalManagerEventHandler alloc] initWithEventEmitter:eventEmitter];
Expand Down Expand Up @@ -109,7 +109,7 @@ - (void)onJavaScriptLoaded {
[_commandsHandler setReadyToReceiveCommands:true];
[_modalHostViewHandler
connectModalHostViewManager:[self.bridge moduleForClass:RCTModalHostViewManager.class]];
[[_bridge moduleForClass:[RNNEventEmitter class]] sendOnAppLaunched];
[[_bridge moduleForClass:[RNNBridgeEventEmitter class]] sendOnAppLaunched];
}

- (void)onBridgeWillReload {
Expand Down
13 changes: 0 additions & 13 deletions lib/ios/Events/RNNEventEmitter.h
Original file line number Diff line number Diff line change
@@ -1,20 +1,7 @@
#import <Foundation/Foundation.h>
#import <React/RCTEventEmitter.h>

#ifdef RCT_NEW_ARCH_ENABLED
#import <rnnavigation/rnnavigation.h>
#endif

@class RCTHost;

@interface RNNEventEmitter : RCTEventEmitter
#ifdef RCT_NEW_ARCH_ENABLED
<NativeRNNEventEmitterSpec>

- (void)setHost:(RCTHost *)host;

@property(nonatomic, strong, readonly) RCTHost *host;
#endif

- (void)sendOnAppLaunched;

Expand Down
17 changes: 0 additions & 17 deletions lib/ios/Events/RNNEventEmitter.mm
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,6 @@ @implementation RNNEventEmitter {
BOOL _appLaunchedEventDeferred;
}

RCT_EXPORT_MODULE()

static NSString *const AppLaunched = @"RNN.AppLaunched";
static NSString *const CommandCompleted = @"RNN.CommandCompleted";
static NSString *const BottomTabSelected = @"RNN.BottomTabSelected";
Expand Down Expand Up @@ -159,19 +157,4 @@ - (void)send:(NSString *)eventName body:(id)body {
[self sendEventWithName:eventName body:body];
}

#ifdef RCT_NEW_ARCH_ENABLED
- (std::shared_ptr<facebook::react::TurboModule>)getTurboModule:
(const facebook::react::ObjCTurboModule::InitParams &)params
{
return std::make_shared<facebook::react::NativeRNNEventEmitterSpecJSI>(params);
}

- (void)setHost:(RCTHost *)host {
if (_host != nil) {
return;
}
_host = host;
}
#endif

@end
14 changes: 14 additions & 0 deletions lib/ios/Turbomodules/RNNTurboEventEmitter.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
#ifdef RCT_NEW_ARCH_ENABLED
#import "RNNEventEmitter.h"
#import <rnnavigation/rnnavigation.h>

@class RCTHost;

@interface RNNTurboEventEmitter : RNNEventEmitter <NativeRNNTurboEventEmitterSpec>

- (void)setHost:(RCTHost *)host;

@property(nonatomic, strong, readonly) RCTHost *host;

@end
#endif
22 changes: 22 additions & 0 deletions lib/ios/Turbomodules/RNNTurboEventEmitter.mm
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
#ifdef RCT_NEW_ARCH_ENABLED
#import "RNNTurboEventEmitter.h"

@implementation RNNTurboEventEmitter {}

RCT_EXPORT_MODULE()

- (std::shared_ptr<facebook::react::TurboModule>)getTurboModule:
(const facebook::react::ObjCTurboModule::InitParams &)params
{
return std::make_shared<facebook::react::NativeRNNTurboEventEmitterSpecJSI>(params);
}

- (void)setHost:(RCTHost *)host {
if (_host != nil) {
return;
}
_host = host;
}

@end
#endif
8 changes: 4 additions & 4 deletions lib/ios/Turbomodules/RNNTurboManager.mm
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
#import "RNNTurboManager.h"
#import "RNNCommandsHandler.h"
#import "RNNComponentViewCreator.h"
#import "RNNEventEmitter.h"
#import "RNNTurboEventEmitter.h"
#import "RNNLayoutManager.h"
#import "RNNModalHostViewManagerHandler.h"
#import "RNNReactComponentRegistry.h"
Expand All @@ -20,7 +20,7 @@ @interface RNNTurboManager ()
@property(nonatomic, strong, readonly) RNNModalManager *modalManager;
@property(nonatomic, strong, readonly) RNNModalHostViewManagerHandler *modalHostViewHandler;
@property(nonatomic, strong, readonly) RNNCommandsHandler *commandsHandler;
@property(nonatomic, strong, readonly) RNNEventEmitter *eventEmitter;
@property(nonatomic, strong, readonly) RNNTurboEventEmitter *eventEmitter;

@end

Expand All @@ -46,7 +46,7 @@ - (instancetype)initWithHost:(RCTHost *)host mainWindow:(UIWindow *)mainWindow {
name:RCTJavaScriptWillStartLoadingNotification
object:nil];

_eventEmitter = [[_host moduleRegistry] moduleForName:"RNNEventEmitter"];
_eventEmitter = [[_host moduleRegistry] moduleForName:"RNNTurboEventEmitter"];
_eventEmitter.host = _host;

RNNModalManagerEventHandler *modalManagerEventHandler =
Expand Down Expand Up @@ -104,7 +104,7 @@ - (void)onJavaScriptLoaded {
// [_modalHostViewHandler
// connectModalHostViewManager:[[_host moduleRegistry] moduleForName:"RCTModalHostViewManager"]];
// TODO: Possibly will cause crashes in events with previous copy of emitter, need to test
_eventEmitter = [[_host moduleRegistry] moduleForName:"RNNEventEmitter"];
_eventEmitter = [[_host moduleRegistry] moduleForName:"RNNTurboEventEmitter"];
_eventEmitter.host = _host;

[_eventEmitter sendOnAppLaunched];
Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,20 @@
#ifdef RCT_NEW_ARCH_ENABLED
#import "RNNTurboEventEmitter.h"
#else
#import "RNNEventEmitter.h"
#endif
#import <Foundation/Foundation.h>
#import <UIKit/UIKit.h>

@class RCTHost;

@interface StackControllerDelegate : NSObject <UINavigationControllerDelegate>

#ifdef RCT_NEW_ARCH_ENABLED
- (instancetype)initWithEventEmitter:(RNNTurboEventEmitter *)eventEmitter;
#else
- (instancetype)initWithEventEmitter:(RNNEventEmitter *)eventEmitter;
#endif

- (BOOL)navigationController:(UINavigationController *)navigationController
shouldPopItem:(BOOL)shouldPopItem;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,20 @@
#import "UIViewController+LayoutProtocol.h"

@implementation StackControllerDelegate {
#ifdef RCT_NEW_ARCH_ENABLED
RNNTurboEventEmitter *_eventEmitter;
#else
RNNEventEmitter *_eventEmitter;
#endif
UIViewController *_presentedViewController;
BOOL _isPopping;
}

#ifdef RCT_NEW_ARCH_ENABLED
- (instancetype)initWithEventEmitter:(RNNTurboEventEmitter *)eventEmitter {
#else
- (instancetype)initWithEventEmitter:(RNNEventEmitter *)eventEmitter {
#endif
self = [super init];
_eventEmitter = eventEmitter;
return self;
Expand Down
4 changes: 2 additions & 2 deletions lib/ios/Views/RNNReactView.mm
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ - (instancetype)initWithBridge:(RCTBridge *)bridge
initialProperties:(NSDictionary *)initialProperties
eventEmitter:(RNNEventEmitter *)eventEmitter
sizeMeasureMode:(RCTSurfaceSizeMeasureMode)sizeMeasureMode
reactViewReadyBlock:(RNNReactViewReadyCompletionBlock)reactViewReadyBlock {
reactViewReadyBlock:(RNNReactViewReadyCompletionBlock)reactViewReadyBlock {
RCTFabricSurface *surface = [[RCTFabricSurface alloc] initWithSurfacePresenter:(RCTSurfacePresenter *)bridge.surfacePresenter
moduleName:moduleName
initialProperties:initialProperties];
Expand Down Expand Up @@ -79,7 +79,7 @@ - (void)surface:(__unused RCTSurface *)surface didChangeStage:(RCTSurfaceStage)s
{
RCTExecuteOnMainQueue(^{
[super surface:surface didChangeStage:stage];
//[self reactViewReady];
[self reactViewReady];
});
}
#else
Expand Down
2 changes: 1 addition & 1 deletion lib/src/adapters/NativeEventsReceiver.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ import {
BottomTabLongPressedEvent,
BottomTabPressedEvent,
} from '../interfaces/Events';
import RNNEventEmitter from './NativeRNNEventEmitter';
import RNNEventEmitter from './NativeRNNTurboEventEmitter';

export class NativeEventsReceiver {
private emitter: NativeEventEmitter;
Expand Down
10 changes: 0 additions & 10 deletions lib/src/adapters/NativeRNNEventEmitter.ts

This file was deleted.

18 changes: 18 additions & 0 deletions lib/src/adapters/NativeRNNTurboEventEmitter.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import { TurboModule, TurboModuleRegistry, NativeModules, NativeModule } from "react-native";

export interface Spec extends TurboModule {
addListener: (eventType: string) => void;
removeListeners: (count: number) => void;
}

let eventEmitter: Spec | null = null;

try {
// Running in bridge mode
eventEmitter = NativeModules.RNNBridgeEventEmitter;
} catch (e) {
// Running in bridgeless, access to NativeModules is prohibited
eventEmitter = TurboModuleRegistry.get<Spec>("RNNTurboEventEmitter");
}

export default eventEmitter as NativeModule;
Loading

0 comments on commit 8aad3f9

Please sign in to comment.