1b987b50fSBen Roth// Copyright 2015-present 650 Industries. All rights reserved. 2b987b50fSBen Roth 39a7f140aSEric Samelson#import "EXEnvironment.h" 4b987b50fSBen Roth#import "EXHomeModule.h" 58a20a963SEric Samelson#import "EXSession.h" 6b987b50fSBen Roth#import "EXUnversioned.h" 7ec45106eSQuinlan Jung#import "EXProvisioningProfile.h" 8b987b50fSBen Roth 9b987b50fSBen Roth#import <React/RCTEventDispatcher.h> 10b987b50fSBen Roth 11b987b50fSBen Roth@interface EXHomeModule () 12b987b50fSBen Roth 13b987b50fSBen Roth@property (nonatomic, assign) BOOL hasListeners; 14b987b50fSBen Roth@property (nonatomic, strong) NSMutableDictionary *eventSuccessBlocks; 15b987b50fSBen Roth@property (nonatomic, strong) NSMutableDictionary *eventFailureBlocks; 16b987b50fSBen Roth@property (nonatomic, strong) NSArray * _Nonnull sdkVersions; 17b987b50fSBen Roth@property (nonatomic, weak) id<EXHomeModuleDelegate> delegate; 18b987b50fSBen Roth 19b987b50fSBen Roth@end 20b987b50fSBen Roth 21b987b50fSBen Roth@implementation EXHomeModule 22b987b50fSBen Roth 23b987b50fSBen Roth+ (NSString *)moduleName { return @"ExponentKernel"; } 24b987b50fSBen Roth 25b987b50fSBen Roth- (instancetype)initWithExperienceId:(NSString *)experienceId kernelServiceDelegate:(id)kernelServiceInstance params:(NSDictionary *)params 26b987b50fSBen Roth{ 27b987b50fSBen Roth if (self = [super initWithExperienceId:experienceId kernelServiceDelegate:kernelServiceInstance params:params]) { 28b987b50fSBen Roth _eventSuccessBlocks = [NSMutableDictionary dictionary]; 29b987b50fSBen Roth _eventFailureBlocks = [NSMutableDictionary dictionary]; 30*c350fdbbSTomasz Sapeta _sdkVersions = params[@"constants"][@"supportedExpoSdks"]; 31b987b50fSBen Roth _delegate = kernelServiceInstance; 32b987b50fSBen Roth } 33b987b50fSBen Roth return self; 34b987b50fSBen Roth} 35b987b50fSBen Roth 36b987b50fSBen Roth+ (BOOL)requiresMainQueueSetup 37b987b50fSBen Roth{ 38b987b50fSBen Roth return NO; 39b987b50fSBen Roth} 40b987b50fSBen Roth 41b987b50fSBen Roth- (NSDictionary *)constantsToExport 42b987b50fSBen Roth{ 43ec45106eSQuinlan Jung return @{ @"sdkVersions": _sdkVersions, 44ec45106eSQuinlan Jung @"IOSClientReleaseType": [EXProvisioningProfile clientReleaseTypeToString: [EXProvisioningProfile clientReleaseType]] }; 45b987b50fSBen Roth} 46b987b50fSBen Roth 47b987b50fSBen Roth#pragma mark - RCTEventEmitter methods 48b987b50fSBen Roth 49b987b50fSBen Roth- (NSArray<NSString *> *)supportedEvents 50b987b50fSBen Roth{ 51b987b50fSBen Roth return @[]; 52b987b50fSBen Roth} 53b987b50fSBen Roth 54b987b50fSBen Roth/** 55b987b50fSBen Roth * Override this method to avoid the [self supportedEvents] validation 56b987b50fSBen Roth */ 57b987b50fSBen Roth- (void)sendEventWithName:(NSString *)eventName body:(id)body 58b987b50fSBen Roth{ 59b987b50fSBen Roth // Note that this could be a versioned bridge! 60b987b50fSBen Roth [self.bridge enqueueJSCall:@"RCTDeviceEventEmitter.emit" 61b987b50fSBen Roth args:body ? @[eventName, body] : @[eventName]]; 62b987b50fSBen Roth} 63b987b50fSBen Roth 64b987b50fSBen Roth#pragma mark - 65b987b50fSBen Roth 66b987b50fSBen Roth- (void)dispatchJSEvent:(NSString *)eventName body:(NSDictionary *)eventBody onSuccess:(void (^)(NSDictionary *))success onFailure:(void (^)(NSString *))failure 67b987b50fSBen Roth{ 68b987b50fSBen Roth NSString *qualifiedEventName = [NSString stringWithFormat:@"ExponentKernel.%@", eventName]; 69b987b50fSBen Roth NSMutableDictionary *qualifiedEventBody = (eventBody) ? [eventBody mutableCopy] : [NSMutableDictionary dictionary]; 70b987b50fSBen Roth 71b987b50fSBen Roth if (success && failure) { 72b987b50fSBen Roth NSString *eventId = [[NSUUID UUID] UUIDString]; 73b987b50fSBen Roth [_eventSuccessBlocks setObject:success forKey:eventId]; 74b987b50fSBen Roth [_eventFailureBlocks setObject:failure forKey:eventId]; 75b987b50fSBen Roth [qualifiedEventBody setObject:eventId forKey:@"eventId"]; 76b987b50fSBen Roth } 77b987b50fSBen Roth 78b987b50fSBen Roth [self sendEventWithName:qualifiedEventName body:qualifiedEventBody]; 79b987b50fSBen Roth} 80b987b50fSBen Roth 81b987b50fSBen Roth/** 82b987b50fSBen Roth * Duplicates Linking.openURL but does not validate that this is an exponent URL; 83b987b50fSBen Roth * in other words, we just take your word for it and never hand it off to iOS. 84b987b50fSBen Roth * Used by the home screen URL bar. 85b987b50fSBen Roth */ 86b987b50fSBen RothRCT_EXPORT_METHOD(openURL:(NSURL *)URL 87b987b50fSBen Roth resolve:(RCTPromiseResolveBlock)resolve 88b987b50fSBen Roth reject:(__unused RCTPromiseRejectBlock)reject) 89b987b50fSBen Roth{ 90b987b50fSBen Roth if (URL) { 91b987b50fSBen Roth [_delegate homeModule:self didOpenUrl:URL.absoluteString]; 92b987b50fSBen Roth resolve(@YES); 93b987b50fSBen Roth } else { 94b987b50fSBen Roth NSError *err = [NSError errorWithDomain:EX_UNVERSIONED(@"EXKernelErrorDomain") code:-1 userInfo:@{ NSLocalizedDescriptionKey: @"Cannot open a nil url" }]; 95b987b50fSBen Roth reject(@"E_INVALID_URL", err.localizedDescription, err); 96b987b50fSBen Roth } 97b987b50fSBen Roth} 98b987b50fSBen Roth 99b987b50fSBen RothRCT_REMAP_METHOD(doesCurrentTaskEnableDevtools, 100b987b50fSBen Roth doesCurrentTaskEnableDevtoolsWithResolver:(RCTPromiseResolveBlock)resolve 101b987b50fSBen Roth reject:(RCTPromiseRejectBlock)reject) 102b987b50fSBen Roth{ 103b987b50fSBen Roth if (_delegate) { 104b987b50fSBen Roth resolve(@([_delegate homeModuleShouldEnableDevtools:self])); 105b987b50fSBen Roth } else { 106b987b50fSBen Roth // don't reject, just disable devtools 107b987b50fSBen Roth resolve(@NO); 108b987b50fSBen Roth } 109b987b50fSBen Roth} 110b987b50fSBen Roth 111b987b50fSBen RothRCT_REMAP_METHOD(isLegacyMenuBehaviorEnabledAsync, 112b987b50fSBen Roth isLegacyMenuBehaviorEnabledWithResolver:(RCTPromiseResolveBlock)resolve 113b987b50fSBen Roth rejecter:(RCTPromiseRejectBlock)reject) 114b987b50fSBen Roth{ 115b987b50fSBen Roth if (_delegate) { 116b987b50fSBen Roth resolve(@([_delegate homeModuleShouldEnableLegacyMenuBehavior:self])); 117b987b50fSBen Roth } else { 118b987b50fSBen Roth resolve(@(NO)); 119b987b50fSBen Roth } 120b987b50fSBen Roth} 121b987b50fSBen Roth 122b987b50fSBen RothRCT_EXPORT_METHOD(setIsLegacyMenuBehaviorEnabledAsync:(BOOL)isEnabled) 123b987b50fSBen Roth{ 124b987b50fSBen Roth if (_delegate) { 125b987b50fSBen Roth [_delegate homeModule:self didSelectEnableLegacyMenuBehavior:isEnabled]; 126b987b50fSBen Roth } 127b987b50fSBen Roth} 128b987b50fSBen Roth 129b987b50fSBen RothRCT_REMAP_METHOD(getDevMenuItemsToShow, 130b987b50fSBen Roth getDevMenuItemsToShowWithResolver:(RCTPromiseResolveBlock)resolve 131b987b50fSBen Roth reject:(RCTPromiseRejectBlock)reject) 132b987b50fSBen Roth{ 133b987b50fSBen Roth if (_delegate && [_delegate homeModuleShouldEnableDevtools:self]) { 134b987b50fSBen Roth resolve([_delegate devMenuItemsForHomeModule:self]); 135b987b50fSBen Roth } else { 136b987b50fSBen Roth // don't reject, just show no devtools 137b987b50fSBen Roth resolve(@{}); 138b987b50fSBen Roth } 139b987b50fSBen Roth} 140b987b50fSBen Roth 141b987b50fSBen RothRCT_EXPORT_METHOD(selectDevMenuItemWithKey:(NSString *)key) 142b987b50fSBen Roth{ 143b987b50fSBen Roth if (_delegate) { 144b987b50fSBen Roth [_delegate homeModule:self didSelectDevMenuItemWithKey:key]; 145b987b50fSBen Roth } 146b987b50fSBen Roth} 147b987b50fSBen Roth 148b987b50fSBen RothRCT_EXPORT_METHOD(selectRefresh) 149b987b50fSBen Roth{ 150b987b50fSBen Roth if (_delegate) { 151b987b50fSBen Roth [_delegate homeModuleDidSelectRefresh:self]; 152b987b50fSBen Roth } 153b987b50fSBen Roth} 154b987b50fSBen Roth 155b987b50fSBen RothRCT_EXPORT_METHOD(selectCloseMenu) 156b987b50fSBen Roth{ 157b987b50fSBen Roth if (_delegate) { 158b987b50fSBen Roth [_delegate homeModuleDidSelectCloseMenu:self]; 159b987b50fSBen Roth } 160b987b50fSBen Roth} 161b987b50fSBen Roth 162b987b50fSBen RothRCT_EXPORT_METHOD(selectGoToHome) 163b987b50fSBen Roth{ 164b987b50fSBen Roth if (_delegate) { 165b987b50fSBen Roth [_delegate homeModuleDidSelectGoToHome:self]; 166b987b50fSBen Roth } 167b987b50fSBen Roth} 168b987b50fSBen Roth 1692fcba380SBen RothRCT_EXPORT_METHOD(selectQRReader) 1702fcba380SBen Roth{ 1712fcba380SBen Roth if (_delegate) { 1722fcba380SBen Roth [_delegate homeModuleDidSelectQRReader:self]; 1732fcba380SBen Roth } 1742fcba380SBen Roth} 1752fcba380SBen Roth 1768a20a963SEric SamelsonRCT_REMAP_METHOD(getSessionAsync, 1778a20a963SEric Samelson getSessionAsync:(RCTPromiseResolveBlock)resolve 1788a20a963SEric Samelson rejecter:(RCTPromiseRejectBlock)reject) 1799a7f140aSEric Samelson{ 1808a20a963SEric Samelson NSDictionary *session = [[EXSession sharedInstance] session]; 1818a20a963SEric Samelson resolve(session); 1829a7f140aSEric Samelson} 1839a7f140aSEric Samelson 1848a20a963SEric SamelsonRCT_REMAP_METHOD(setSessionAsync, 1858a20a963SEric Samelson setSessionAsync:(NSDictionary *)session 1868a20a963SEric Samelson resolver:(RCTPromiseResolveBlock)resolve 1878a20a963SEric Samelson rejecter:(RCTPromiseRejectBlock)reject) 1889a7f140aSEric Samelson{ 1898a20a963SEric Samelson NSError *error; 1908a20a963SEric Samelson BOOL success = [[EXSession sharedInstance] saveSessionToKeychain:session error:&error]; 1918a20a963SEric Samelson if (success) { 1928a20a963SEric Samelson resolve(nil); 1938a20a963SEric Samelson } else { 1948a20a963SEric Samelson reject(@"ERR_SESSION_NOT_SAVED", @"Could not save session", error); 1958a20a963SEric Samelson } 1968a20a963SEric Samelson} 1978a20a963SEric Samelson 1988a20a963SEric SamelsonRCT_REMAP_METHOD(removeSessionAsync, 1998a20a963SEric Samelson removeSessionAsync:(RCTPromiseResolveBlock)resolve 2008a20a963SEric Samelson rejecter:(RCTPromiseRejectBlock)reject) 2018a20a963SEric Samelson{ 2028a20a963SEric Samelson NSError *error; 2038a20a963SEric Samelson BOOL success = [[EXSession sharedInstance] deleteSessionFromKeychainWithError:&error]; 2048a20a963SEric Samelson if (success) { 2058a20a963SEric Samelson resolve(nil); 2068a20a963SEric Samelson } else { 2078a20a963SEric Samelson reject(@"ERR_SESSION_NOT_REMOVED", @"Could not remove session", error); 2088a20a963SEric Samelson } 2099a7f140aSEric Samelson} 2109a7f140aSEric Samelson 211b987b50fSBen RothRCT_EXPORT_METHOD(addDevMenu) 212b987b50fSBen Roth{ 213b987b50fSBen Roth __weak typeof(self) weakSelf = self; 214b987b50fSBen Roth dispatch_async(dispatch_get_main_queue(), ^{ 215b987b50fSBen Roth if (weakSelf.delegate) { 216b987b50fSBen Roth [weakSelf.delegate homeModuleDidSelectHomeDiagnostics:self]; 217b987b50fSBen Roth } 218b987b50fSBen Roth }); 219b987b50fSBen Roth} 220b987b50fSBen Roth 22166169681SBen RothRCT_REMAP_METHOD(getIsNuxFinishedAsync, 22266169681SBen Roth getIsNuxFinishedWithResolver:(RCTPromiseResolveBlock)resolve 22366169681SBen Roth rejecter:(RCTPromiseRejectBlock)reject) 224b987b50fSBen Roth{ 22566169681SBen Roth if (_delegate) { 22666169681SBen Roth BOOL isFinished = [_delegate homeModuleShouldFinishNux:self]; 22766169681SBen Roth resolve(@(isFinished)); 22866169681SBen Roth } else { 22966169681SBen Roth resolve(@(NO)); 23066169681SBen Roth } 23166169681SBen Roth} 23266169681SBen Roth 23366169681SBen RothRCT_REMAP_METHOD(setIsNuxFinishedAsync, 23466169681SBen Roth setIsNuxFinished:(BOOL)isNuxFinished) 23566169681SBen Roth{ 23666169681SBen Roth if (_delegate) { 23766169681SBen Roth [_delegate homeModule:self didFinishNux:isNuxFinished]; 23866169681SBen Roth } 239b987b50fSBen Roth} 240b987b50fSBen Roth 241b987b50fSBen RothRCT_REMAP_METHOD(onEventSuccess, 242b987b50fSBen Roth eventId:(NSString *)eventId 243b987b50fSBen Roth body:(NSDictionary *)body) 244b987b50fSBen Roth{ 245b987b50fSBen Roth void (^success)(NSDictionary *) = [_eventSuccessBlocks objectForKey:eventId]; 246b987b50fSBen Roth if (success) { 247b987b50fSBen Roth success(body); 248b987b50fSBen Roth [_eventSuccessBlocks removeObjectForKey:eventId]; 249b987b50fSBen Roth [_eventFailureBlocks removeObjectForKey:eventId]; 250b987b50fSBen Roth } 251b987b50fSBen Roth} 252b987b50fSBen Roth 253b987b50fSBen RothRCT_REMAP_METHOD(onEventFailure, 254b987b50fSBen Roth eventId:(NSString *)eventId 255b987b50fSBen Roth message:(NSString *)message) 256b987b50fSBen Roth{ 257b987b50fSBen Roth void (^failure)(NSString *) = [_eventFailureBlocks objectForKey:eventId]; 258b987b50fSBen Roth if (failure) { 259b987b50fSBen Roth failure(message); 260b987b50fSBen Roth [_eventSuccessBlocks removeObjectForKey:eventId]; 261b987b50fSBen Roth [_eventFailureBlocks removeObjectForKey:eventId]; 262b987b50fSBen Roth } 263b987b50fSBen Roth} 264b987b50fSBen Roth 265b987b50fSBen Roth@end 266