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