1// Copyright 2018-present 650 Industries. All rights reserved.
2
3#import <ExpoModulesCore/EXNativeModulesProxy.h>
4#import <ExpoModulesCore/EXReactNativeEventEmitter.h>
5#import <ExpoModulesCore/EXViewManagerAdapter.h>
6#import <ExpoModulesCore/EXModuleRegistryAdapter.h>
7#import <ExpoModulesCore/EXViewManagerAdapterClassesRegistry.h>
8#import <ExpoModulesCore/EXModuleRegistryHolderReactModule.h>
9#if __has_include(<ExpoModulesCore/ExpoModulesCore-Swift.h>)
10// For prebuilding xcframework, do not use quote notation.
11#import <ExpoModulesCore/ExpoModulesCore-Swift.h>
12#elif __has_include("ExpoModulesCore-Swift.h")
13#import "ExpoModulesCore-Swift.h"
14#endif
15
16@interface EXModuleRegistryAdapter ()
17
18@property (nonatomic, strong) EXModuleRegistryProvider *moduleRegistryProvider;
19@property (nonatomic, strong) EXViewManagerAdapterClassesRegistry *viewManagersClassesRegistry;
20@property (nonatomic, strong, nullable) id<ModulesProviderObjCProtocol> swiftModulesProvider;
21
22@end
23
24@implementation EXModuleRegistryAdapter
25
26- (instancetype)initWithModuleRegistryProvider:(EXModuleRegistryProvider *)moduleRegistryProvider
27{
28  if (self = [super init]) {
29    _moduleRegistryProvider = moduleRegistryProvider;
30    _viewManagersClassesRegistry = [[EXViewManagerAdapterClassesRegistry alloc] init];
31  }
32  return self;
33}
34
35- (instancetype)initWithModuleRegistryProvider:(EXModuleRegistryProvider *)moduleRegistryProvider swiftModulesProviderClass:(nullable Class)swiftModulesProviderClass
36{
37  if (self = [self initWithModuleRegistryProvider:moduleRegistryProvider]) {
38    if ([swiftModulesProviderClass conformsToProtocol:@protocol(ModulesProviderObjCProtocol)]) {
39      _swiftModulesProvider = [swiftModulesProviderClass new];
40    }
41  }
42  return self;
43}
44
45- (NSArray<id<RCTBridgeModule>> *)extraModulesForBridge:(RCTBridge *)bridge
46{
47  return [self extraModulesForModuleRegistry:[_moduleRegistryProvider moduleRegistry]];
48}
49
50- (NSArray<id<RCTBridgeModule>> *)extraModulesForModuleRegistry:(EXModuleRegistry *)moduleRegistry
51{
52  NSMutableArray<id<RCTBridgeModule>> *extraModules = [NSMutableArray array];
53
54  EXNativeModulesProxy *nativeModulesProxy = [[EXNativeModulesProxy alloc] initWithModuleRegistry:moduleRegistry];
55  [extraModules addObject:nativeModulesProxy];
56
57  // Event emitter is not automatically registered — we add it to the module registry here.
58  // It will be added to the bridge later in this method, as it conforms to `RCTBridgeModule`.
59  EXReactNativeEventEmitter *eventEmitter = [EXReactNativeEventEmitter new];
60  [moduleRegistry registerInternalModule:eventEmitter];
61
62  NSMutableSet *exportedSwiftViewModuleNames = [NSMutableSet new];
63
64  for (ViewModuleWrapper *swiftViewModule in [nativeModulesProxy.swiftInteropBridge getViewManagers]) {
65    Class wrappedViewModuleClass = [ViewModuleWrapper createViewModuleWrapperClassWithModule:swiftViewModule];
66    [extraModules addObject:[[wrappedViewModuleClass alloc] init]];
67    [exportedSwiftViewModuleNames addObject:swiftViewModule.name];
68  }
69  for (EXViewManager *viewManager in [moduleRegistry getAllViewManagers]) {
70    if (![exportedSwiftViewModuleNames containsObject:viewManager.viewName]) {
71      Class viewManagerAdapterClass = [EXViewManagerAdapterClassesRegistry createViewManagerAdapterClassForViewManager:viewManager];
72      [extraModules addObject:[[viewManagerAdapterClass alloc] init]];
73    }
74  }
75
76  // Silence React Native warning `Base module "%s" does not exist`
77  // occurring when view manager class is subclassing another class
78  // that is not RCTViewManager (in our case all the view manager adapters
79  // subclass EXViewManagerAdapter, so RN expects to find EXViewManagerAdapter
80  // exported.
81  [extraModules addObject:[[EXViewManagerAdapter alloc] init]];
82  [extraModules addObject:[[ViewModuleWrapper alloc] initWithDummy:nil]];
83
84  // It is possible that among internal modules there are some RCTBridgeModules --
85  // let's add them to extraModules here.
86  for (id<EXInternalModule> module in [moduleRegistry getAllInternalModules]) {
87    if ([module conformsToProtocol:@protocol(RCTBridgeModule)]) {
88      id<RCTBridgeModule> reactBridgeModule = (id<RCTBridgeModule>)module;
89      [extraModules addObject:reactBridgeModule];
90    }
91  }
92
93  // Adding the way to access the module registry from RCTBridgeModules.
94  [extraModules addObject:[[EXModuleRegistryHolderReactModule alloc] initWithModuleRegistry:moduleRegistry]];
95
96  // One could add some modules to the Module Registry after creating it.
97  // Here is our last call for finalizing initialization.
98  [moduleRegistry initialize];
99  return extraModules;
100}
101
102- (nullable SwiftInteropBridge *)swiftInteropBridgeModulesRegistry:(EXModuleRegistry *)moduleRegistry
103{
104  if (_swiftModulesProvider) {
105    return [[SwiftInteropBridge alloc] initWithModulesProvider:_swiftModulesProvider legacyModuleRegistry:moduleRegistry];
106  } else {
107    return nil;
108  }
109}
110
111@end
112