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