1// Copyright 2015-present 650 Industries. All rights reserved.
2
3#import <EXDevLauncher/EXDevLauncherRCTBridge.h>
4#import <EXDevLauncher/EXDevLauncherController.h>
5#import <EXDevLauncher/RCTCxxBridge+Private.h>
6
7#import <React/RCTPerformanceLogger.h>
8#import <React/RCTDevSettings.h>
9#import <React/RCTDevMenu.h>
10
11@import EXDevMenuInterface;
12
13@implementation EXDevLauncherRCTCxxBridge
14
15- (instancetype)initWithParentBridge:(RCTBridge *)bridge
16{
17  if ((self = [super initWithParentBridge:bridge])) {
18    RCTBridge *appBridge = [EXDevLauncherController sharedInstance].appBridge;
19    // reset the singleton `RCTBridge.currentBridge` to app bridge instance
20    RCTBridge.currentBridge = appBridge != nil ? appBridge.batchedBridge : nil;
21  }
22  return self;
23}
24
25/**
26 * Theoretically, we could overwrite the `RCTDevSettings` module by exporting our version through the bridge.
27 * However, this won't work with the js remote debugging. For some reason, the RN needs to initialized remote tools very early. So it always uses the default module to do it.
28 * When we export our module, it won't be used in the initialized phase. So the launcher will start with remote debug support.
29 */
30- (RCTDevSettings *)devSettings
31{
32#ifdef EX_DEV_LAUNCHER_URL
33 return super.devSettings;
34#endif
35 return nil;
36}
37
38- (RCTDevMenu *)devMenu
39{
40  return nil;
41}
42
43- (NSArray<Class> *)filterModuleList:(NSArray<Class> *)modules
44{
45  NSArray<NSString *> *allowedModules = @[@"RCT", @"DevMenu", @"ExpoBridgeModule", @"EXNativeModulesProxy", @"ViewManagerAdapter_", @"EXReactNativeEventEmitter"];
46  NSArray<Class> *filteredModuleList = [modules filteredArrayUsingPredicate:[NSPredicate predicateWithBlock:^BOOL(id  _Nullable clazz, NSDictionary<NSString *,id> * _Nullable bindings) {
47    if ([clazz conformsToProtocol:@protocol(DevMenuExtensionProtocol)]) {
48      return true;
49    }
50
51    if ([clazz conformsToProtocol:@protocol(EXDevExtensionProtocol)]) {
52      return true;
53    }
54
55    NSString* clazzName = NSStringFromClass(clazz);
56    for (NSString *allowedModule in allowedModules) {
57      if ([clazzName hasPrefix:allowedModule]) {
58        return true;
59      }
60    }
61    return false;
62  }]];
63
64  return filteredModuleList;
65}
66
67- (NSArray<RCTModuleData *> *)_initializeModules:(NSArray<Class> *)modules
68                               withDispatchGroup:(dispatch_group_t)dispatchGroup
69                                lazilyDiscovered:(BOOL)lazilyDiscovered
70{
71  return [super _initializeModules:[self filterModuleList:modules] withDispatchGroup:dispatchGroup lazilyDiscovered:lazilyDiscovered];
72}
73
74@end
75
76@implementation EXDevLauncherRCTBridge
77
78- (Class)bridgeClass
79{
80  return [EXDevLauncherRCTCxxBridge class];
81}
82
83#pragma clang diagnostic push
84#pragma clang diagnostic ignored "-Wdeprecated-implementations"
85// This method is still used so we need to override it even if it's deprecated
86- (void)reloadWithReason:(NSString *)reason {}
87#pragma clang diagnostic pop
88
89@end
90