1// Copyright 2015-present 650 Industries. All rights reserved. 2 3#import "EXLinkingManager.h" 4#import "EXScopedModuleRegistry.h" 5 6#import <React/RCTBridge.h> 7#import <React/RCTEventDispatcher.h> 8#import <React/RCTUtils.h> 9 10NSString * const EXLinkingEventOpenUrl = @"url"; 11 12@interface EXLinkingManager () 13 14@property (nonatomic, weak) id <EXLinkingManagerScopedModuleDelegate> kernelLinkingDelegate; 15@property (nonatomic, strong) NSURL *initialUrl; 16@property (nonatomic) BOOL hasListeners; 17 18@end 19 20@implementation EXLinkingManager 21 22EX_EXPORT_SCOPED_MODULE(RCTLinkingManager, KernelLinkingManager); 23 24- (instancetype)initWithExperienceId:(NSString *)experienceId kernelServiceDelegate:(id)kernelServiceInstance params:(NSDictionary *)params 25{ 26 if (self = [super initWithExperienceId:experienceId kernelServiceDelegate:kernelServiceInstance params:params]) { 27 _kernelLinkingDelegate = kernelServiceInstance; 28 _initialUrl = params[@"initialUri"]; 29 } 30 return self; 31} 32 33#pragma mark - RCTEventEmitter methods 34 35- (NSArray<NSString *> *)supportedEvents 36{ 37 return @[EXLinkingEventOpenUrl]; 38} 39 40- (void)startObserving 41{ 42 _hasListeners = YES; 43} 44 45- (void)stopObserving 46{ 47 _hasListeners = NO; 48} 49 50#pragma mark - Linking methods 51 52- (void)dispatchOpenUrlEvent:(NSURL *)url 53{ 54 if (!url || !url.absoluteString) { 55 RCTFatal(RCTErrorWithMessage([NSString stringWithFormat:@"Tried to open a deep link to an invalid url: %@", url])); 56 return; 57 } 58 if (_hasListeners) { 59 [self sendEventWithName:EXLinkingEventOpenUrl body:@{@"url": url.absoluteString}]; 60 } 61} 62 63RCT_EXPORT_METHOD(openURL:(NSURL *)URL 64 resolve:(RCTPromiseResolveBlock)resolve 65 reject:(RCTPromiseRejectBlock)reject) 66{ 67 if ([_kernelLinkingDelegate linkingModule:self shouldOpenExpoUrl:URL]) { 68 [_kernelLinkingDelegate linkingModule:self didOpenUrl:URL.absoluteString]; 69 resolve(@YES); 70 } else { 71 BOOL opened = [RCTSharedApplication() openURL:URL]; 72 if (opened) { 73 resolve(nil); 74 } else { 75 reject(RCTErrorUnspecified, [NSString stringWithFormat:@"Unable to open URL: %@", URL], nil); 76 } 77 } 78} 79 80RCT_EXPORT_METHOD(canOpenURL:(NSURL *)URL 81 resolve:(RCTPromiseResolveBlock)resolve 82 reject:(__unused RCTPromiseRejectBlock)reject) 83{ 84 BOOL canOpen = [_kernelLinkingDelegate linkingModule:self shouldOpenExpoUrl:URL]; 85 if (!canOpen) { 86 canOpen = [RCTSharedApplication() canOpenURL:URL]; 87 } 88 resolve(@(canOpen)); 89} 90 91RCT_EXPORT_METHOD(getInitialURL:(RCTPromiseResolveBlock)resolve 92 reject:(__unused RCTPromiseRejectBlock)reject) 93{ 94 resolve(RCTNullIfNil(_initialUrl.absoluteString)); 95} 96 97@end 98