// Copyright 2015-present 650 Industries. All rights reserved. #import "EXLinkingManager.h" #import "EXScopedModuleRegistry.h" #import "EXUtil.h" #import #import #import NSString * const EXLinkingEventOpenUrl = @"url"; @interface EXLinkingManager () @property (nonatomic, weak) id kernelLinkingDelegate; @property (nonatomic, strong) NSURL *initialUrl; @property (nonatomic) BOOL hasListeners; @end @implementation EXLinkingManager EX_EXPORT_SCOPED_MODULE(RCTLinkingManager, KernelLinkingManager); - (instancetype)initWithExperienceStableLegacyId:(NSString *)experienceStableLegacyId scopeKey:(NSString *)scopeKey easProjectId:(NSString *)easProjectId kernelServiceDelegate:(id)kernelServiceInstance params:(NSDictionary *)params { if (self = [super initWithExperienceStableLegacyId:experienceStableLegacyId scopeKey:scopeKey easProjectId:easProjectId kernelServiceDelegate:kernelServiceInstance params:params]) { _kernelLinkingDelegate = kernelServiceInstance; _initialUrl = params[@"initialUri"]; if (_initialUrl == [NSNull null]) { _initialUrl = nil; } } return self; } #pragma mark - RCTEventEmitter methods - (NSArray *)supportedEvents { return @[EXLinkingEventOpenUrl]; } - (void)startObserving { _hasListeners = YES; } - (void)stopObserving { _hasListeners = NO; } #pragma mark - Linking methods - (void)dispatchOpenUrlEvent:(NSURL *)url { if (!url || !url.absoluteString) { RCTFatal(RCTErrorWithMessage([NSString stringWithFormat:@"Tried to open a deep link to an invalid url: %@", url])); return; } if (_hasListeners) { [self sendEventWithName:EXLinkingEventOpenUrl body:@{@"url": url.absoluteString}]; } } RCT_EXPORT_METHOD(openURL:(NSURL *)URL resolve:(RCTPromiseResolveBlock)resolve reject:(RCTPromiseRejectBlock)reject) { if ([_kernelLinkingDelegate linkingModule:self shouldOpenExpoUrl:URL]) { [_kernelLinkingDelegate linkingModule:self didOpenUrl:URL.absoluteString]; resolve(@YES); } else { [EXUtil performSynchronouslyOnMainThread:^{ [RCTSharedApplication() openURL:URL options:@{} completionHandler:^(BOOL success) { if (success) { resolve(nil); } else { reject(RCTErrorUnspecified, [NSString stringWithFormat:@"Unable to open URL: %@", URL], nil); } }]; }]; } } RCT_EXPORT_METHOD(canOpenURL:(NSURL *)URL resolve:(RCTPromiseResolveBlock)resolve reject:(__unused RCTPromiseRejectBlock)reject) { __block BOOL canOpen = [_kernelLinkingDelegate linkingModule:self shouldOpenExpoUrl:URL]; if (!canOpen) { [EXUtil performSynchronouslyOnMainThread:^{ canOpen = [RCTSharedApplication() canOpenURL:URL]; }]; } resolve(@(canOpen)); } RCT_EXPORT_METHOD(openSettings:(RCTPromiseResolveBlock)resolve reject:(RCTPromiseRejectBlock)reject) { [EXUtil performSynchronouslyOnMainThread:^{ NSURL *url = [NSURL URLWithString:UIApplicationOpenSettingsURLString]; [RCTSharedApplication() openURL:url options:@{} completionHandler:^(BOOL success) { if (success) { resolve(nil); } else { reject(RCTErrorUnspecified, @"Unable to open app settings", nil); } }]; }]; } RCT_EXPORT_METHOD(getInitialURL:(RCTPromiseResolveBlock)resolve reject:(__unused RCTPromiseRejectBlock)reject) { resolve(RCTNullIfNil(_initialUrl.absoluteString)); } @end