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