1// Copyright 2015-present 650 Industries. All rights reserved. 2 3#import "EXAbstractLoader+Updates.h" 4#import "EXKernel.h" 5#import "EXKernelAppRecord.h" 6#import "EXReactAppManager.h" 7#import "EXUpdatesDatabaseManager.h" 8#import "EXUpdatesManager.h" 9 10#import <React/RCTBridge.h> 11 12@import EXManifests; 13@import EXUpdates; 14 15NSString * const EXUpdatesEventName = @"Expo.nativeUpdatesEvent"; 16NSString * const EXUpdatesErrorEventType = @"error"; 17NSString * const EXUpdatesUpdateAvailableEventType = @"updateAvailable"; 18NSString * const EXUpdatesNotAvailableEventType = @"noUpdateAvailable"; 19 20@implementation EXUpdatesManager 21 22- (void)notifyApp:(EXKernelAppRecord *)appRecord 23ofDownloadWithManifest:(EXManifestsManifest * _Nullable)manifest 24 isNew:(BOOL)isBundleNew 25 error:(NSError * _Nullable)error; 26{ 27 NSDictionary *body; 28 if (error) { 29 body = @{ 30 @"type": EXUpdatesErrorEventType, 31 @"message": error.localizedDescription 32 }; 33 } else if (isBundleNew) { 34 // prevent a crash, but this shouldn't ever happen 35 NSDictionary *rawManifestJSON = manifest ? manifest.rawManifestJSON : @{}; 36 body = @{ 37 @"type": EXUpdatesUpdateAvailableEventType, 38 @"manifest": rawManifestJSON 39 }; 40 } else { 41 body = @{ 42 @"type": EXUpdatesNotAvailableEventType 43 }; 44 } 45 RCTBridge *bridge = appRecord.appManager.reactBridge; 46 if (appRecord.status == kEXKernelAppRecordStatusRunning) { 47 [bridge enqueueJSCall:@"RCTDeviceEventEmitter.emit" args:@[EXUpdatesEventName, body]]; 48 } 49} 50 51# pragma mark - internal 52 53- (EXAbstractLoader *)_appLoaderWithScopeKey:(NSString *)scopeKey 54{ 55 EXKernelAppRecord *appRecord = [[EXKernel sharedInstance].appRegistry newestRecordWithScopeKey:scopeKey]; 56 return appRecord.appLoader; 57} 58 59# pragma mark - EXUpdatesBindingDelegate 60 61- (nullable EXUpdatesConfig *)configForScopeKey:(NSString *)scopeKey 62{ 63 return [self _appLoaderWithScopeKey:scopeKey].config; 64} 65 66- (nullable EXUpdatesSelectionPolicy *)selectionPolicyForScopeKey:(NSString *)scopeKey 67{ 68 return [self _appLoaderWithScopeKey:scopeKey].selectionPolicy; 69} 70 71- (nullable nullable EXUpdatesUpdate *)launchedUpdateForScopeKey:(NSString *)scopeKey 72{ 73 return [self _appLoaderWithScopeKey:scopeKey].appLauncher.launchedUpdate; 74} 75 76- (nullable NSDictionary *)assetFilesMapForScopeKey:(NSString *)scopeKey 77{ 78 return [self _appLoaderWithScopeKey:scopeKey].appLauncher.assetFilesMap; 79} 80 81- (BOOL)isUsingEmbeddedAssetsForScopeKey:(NSString *)scopeKey 82{ 83 return NO; 84} 85 86- (BOOL)isStartedForScopeKey:(NSString *)scopeKey 87{ 88 return [self _appLoaderWithScopeKey:scopeKey].appLauncher != nil; 89} 90 91- (BOOL)isEmergencyLaunchForScopeKey:(NSString *)scopeKey 92{ 93 return [self _appLoaderWithScopeKey:scopeKey].isEmergencyLaunch; 94} 95 96- (void)requestRelaunchForScopeKey:(NSString *)scopeKey withCompletion:(EXUpdatesAppRelaunchCompletionBlock)completion 97{ 98 [[EXKernel sharedInstance] reloadAppFromCacheWithScopeKey:scopeKey]; 99 completion(YES); 100} 101 102@end 103