1// Copyright 2015-present 650 Industries. All rights reserved. 2 3#if __has_include(<EXFacebook/EXFacebook.h>) 4#import "EXScopedFacebook.h" 5#import <FBSDKCoreKit/FBSDKSettings.h> 6#import <ExpoModulesCore/EXAppLifecycleService.h> 7#import <FBSDKCoreKit/FBSDKApplicationDelegate.h> 8 9@interface EXFacebook (ExportedMethods) 10 11- (void)initializeAsync:(NSDictionary *)options 12 resolver:(EXPromiseResolveBlock)resolve 13 rejecter:(EXPromiseRejectBlock)reject; 14 15- (void)logInWithReadPermissionsWithConfig:(NSDictionary *)config 16 resolver:(EXPromiseResolveBlock)resolve 17 rejecter:(EXPromiseRejectBlock)reject; 18 19- (void)logOutAsync:(EXPromiseResolveBlock)resolve 20 rejecter:(EXPromiseRejectBlock)reject; 21 22- (void)getAuthenticationCredentialAsync:(EXPromiseResolveBlock)resolve 23 rejecter:(EXPromiseRejectBlock)reject; 24 25- (void)setAutoInitEnabled:(BOOL)enabled 26 resolver:(EXPromiseResolveBlock)resolve 27 rejecter:(EXPromiseRejectBlock)reject; 28 29@end 30 31static NSString *AUTO_INIT_KEY = @"autoInitEnabled"; 32 33@interface EXScopedFacebook () 34 35@property (nonatomic, assign) BOOL isInitialized; 36@property (nonatomic, strong) NSString *appId; 37@property (nonatomic, strong) NSString *displayName; 38@property (nonatomic, strong) NSUserDefaults *settings; 39 40@end 41 42// Expo Go-only EXFacebook module, which ensures that Facebook SDK configurations 43// of different projects don't collide. 44 45@implementation EXScopedFacebook : EXFacebook 46 47- (instancetype)initWithScopeKey:(NSString *)scopeKey manifest:(EXManifestsManifest *)manifest 48{ 49 if (self = [super init]) { 50 NSString *suiteName = [NSString stringWithFormat:@"%@#%@", NSStringFromClass(self.class), scopeKey]; 51 _settings = [[NSUserDefaults alloc] initWithSuiteName:suiteName]; 52 53 BOOL hasPreviouslySetAutoInitEnabled = [_settings boolForKey:AUTO_INIT_KEY]; 54 BOOL manifestDefinesAutoInitEnabled = manifest.facebookAutoInitEnabled; 55 56 NSString *scopedFacebookAppId = [[NSBundle mainBundle] objectForInfoDictionaryKey:@"FacebookAppID"]; 57 NSString *manifestFacebookAppId = manifest.facebookAppId; 58 59 if (hasPreviouslySetAutoInitEnabled || manifestDefinesAutoInitEnabled) { 60 // This happens even before the app foregrounds, which mimics 61 // the mechanism behind EXFacebookAppDelegate. 62 // Check for FacebookAppId in case this is a custom client build 63 if (scopedFacebookAppId) { 64 [FBSDKApplicationDelegate initializeSDK:nil]; 65 _isInitialized = YES; 66 if (manifestFacebookAppId) { 67 EXLogInfo(@"Overriding Facebook App ID with Expo Go's. To test your own Facebook App ID, you'll need to build a standalone app. Refer to our documentation for more info- https://docs.expo.io/versions/latest/sdk/facebook/"); 68 } 69 } else { 70 EXLogWarn(@"FacebookAutoInit is enabled, but no FacebookAppId has been provided. Facebook SDK initialization aborted."); 71 } 72 } 73 } 74 return self; 75} 76 77- (void)initializeAsync:(NSDictionary *)options 78 resolver:(EXPromiseResolveBlock)resolve 79 rejecter:(EXPromiseRejectBlock)reject 80{ 81 _isInitialized = YES; 82 if (options[@"appId"]) { 83 EXLogInfo(@"Overriding Facebook App ID with Expo Go's. To test your own Facebook App ID, you'll need to build a standalone app. Refer to our documentation for more info- https://docs.expo.io/versions/latest/sdk/facebook/"); 84 } 85 86 NSString *scopedFacebookAppId = [[NSBundle mainBundle] objectForInfoDictionaryKey:@"FacebookAppID"]; 87 88 NSMutableDictionary *nativeOptions = [NSMutableDictionary dictionaryWithDictionary:options]; 89 // Overwrite the incoming app id with the Expo Facebook SDK app id. 90 nativeOptions[@"appId"] = scopedFacebookAppId; 91 92 [super initializeAsync:nativeOptions resolver:resolve rejecter:reject]; 93} 94 95- (void)setAutoInitEnabled:(BOOL)enabled resolver:(EXPromiseResolveBlock)resolve rejecter:(EXPromiseRejectBlock)reject 96{ 97 if (enabled) { 98 [_settings setBool:enabled forKey:AUTO_INIT_KEY]; 99 // Facebook SDK on iOS is initialized when `setAutoInitEnabled` is called with `YES`. 100 _isInitialized = YES; 101 } 102 [super setAutoInitEnabled:enabled resolver:resolve rejecter:reject]; 103} 104 105- (void)logInWithReadPermissionsWithConfig:(NSDictionary *)config resolver:(EXPromiseResolveBlock)resolve rejecter:(EXPromiseRejectBlock)reject 106{ 107 // If the developer didn't initialize the SDK, let them know. 108 if (!_isInitialized) { 109 reject(@"ERR_FACEBOOK_UNINITIALIZED", @"Facebook SDK has not been initialized yet.", nil); 110 return; 111 } 112 [super logInWithReadPermissionsWithConfig:config resolver:resolve rejecter:reject]; 113} 114 115- (void)getAuthenticationCredentialAsync:(EXPromiseResolveBlock)resolve rejecter:(EXPromiseRejectBlock)reject 116{ 117 // If the developer didn't initialize the SDK, let them know. 118 if (!_isInitialized) { 119 reject(@"ERR_FACEBOOK_UNINITIALIZED", @"Facebook SDK has not been initialized yet.", nil); 120 return; 121 } 122 [super getAuthenticationCredentialAsync:resolve rejecter:reject]; 123} 124 125- (void)logOutAsync:(EXPromiseResolveBlock)resolve rejecter:(EXPromiseRejectBlock)reject 126{ 127 // If the developer didn't initialize the SDK, let them know. 128 if (!_isInitialized) { 129 reject(@"ERR_FACEBOOK_UNINITIALIZED", @"Facebook SDK has not been initialized yet.", nil); 130 return; 131 } 132 [super logOutAsync:resolve rejecter:reject]; 133} 134 135# pragma mark - EXModuleRegistryConsumer 136 137- (void)setModuleRegistry:(EXModuleRegistry *)moduleRegistry 138{ 139 [super setModuleRegistry:moduleRegistry]; 140 141 id<EXAppLifecycleService> appLifecycleService = [moduleRegistry getModuleImplementingProtocol:@protocol(EXAppLifecycleService)]; 142 [appLifecycleService registerAppLifecycleListener:self]; 143} 144 145# pragma mark - EXAppLifecycleListener 146 147- (void)onAppBackgrounded { 148 // Save SDK settings state 149 _appId = [FBSDKSettings appID]; 150 _displayName = [FBSDKSettings displayName]; 151 [FBSDKSettings setAppID:nil]; 152 [FBSDKSettings setDisplayName:nil]; 153} 154 155- (void)onAppForegrounded { 156 // Restore SDK settings state 157 if (_appId) { 158 [FBSDKSettings setAppID:_appId]; 159 } 160 if (_displayName) { 161 [FBSDKSettings setDisplayName:_displayName]; 162 } 163} 164 165@end 166#endif 167