1 // Copyright 2015-present 650 Industries. All rights reserved. 2 3 #import <Foundation/Foundation.h> 4 #import "EXAppFetcher.h" 5 #import "EXAppFetcherDevelopmentMode.h" 6 #import "EXAppFetcherWithTimeout.h" 7 #import "EXCachedResource.h" 8 #import <EXManifests/EXManifestsManifest.h> 9 10 @class EXKernelAppRecord; 11 @class EXAbstractLoader; 12 13 NS_ASSUME_NONNULL_BEGIN 14 15 FOUNDATION_EXPORT NSTimeInterval const kEXAppLoaderDefaultTimeout; 16 FOUNDATION_EXPORT NSTimeInterval const kEXJSBundleTimeout; 17 18 typedef enum EXAppLoaderStatus { 19 kEXAppLoaderStatusNew, 20 kEXAppLoaderStatusHasManifest, // possibly optimistic 21 kEXAppLoaderStatusHasManifestAndBundle, 22 kEXAppLoaderStatusError, 23 } EXAppLoaderStatus; 24 25 typedef enum EXAppLoaderRemoteUpdateStatus { 26 kEXAppLoaderRemoteUpdateStatusChecking, 27 kEXAppLoaderRemoteUpdateStatusDownloading 28 } EXAppLoaderRemoteUpdateStatus; 29 30 @protocol EXAppLoaderDelegate <NSObject> 31 32 - (void)appLoader:(EXAbstractLoader *)appLoader didLoadOptimisticManifest:(EXManifestsManifest *)manifest; 33 - (void)appLoader:(EXAbstractLoader *)appLoader didLoadBundleWithProgress:(EXLoadingProgress *)progress; 34 - (void)appLoader:(EXAbstractLoader *)appLoader didFinishLoadingManifest:(EXManifestsManifest *)manifest bundle:(NSData *)data; 35 - (void)appLoader:(EXAbstractLoader *)appLoader didFailWithError:(NSError *)error; 36 - (void)appLoader:(EXAbstractLoader *)appLoader didResolveUpdatedBundleWithManifest:(EXManifestsManifest * _Nullable)manifest isFromCache:(BOOL)isFromCache error:(NSError * _Nullable)error; 37 38 @end 39 40 /** 41 Class with stub methods to load apps. 42 It has two subclasses: EXHomeLoader (for loading the home app), and 43 EXAppLoaderExpoUpdates (for loading and displaying apps in the home UI) 44 */ 45 @interface EXAbstractLoader : NSObject <EXAppFetcherDelegate, EXAppFetcherDevelopmentModeDelegate, EXAppFetcherWithTimeoutDelegate, EXAppFetcherCacheDataSource> 46 47 @property (nonatomic, readonly) NSURL *manifestUrl; 48 @property (nonatomic, readonly) EXManifestsManifest * _Nullable manifest; // possibly optimistic 49 @property (nonatomic, readonly) EXManifestsManifest * _Nullable cachedManifest; // we definitely have this manifest and its bundle on the device 50 @property (nonatomic, readonly) NSData * _Nullable bundle; 51 @property (nonatomic, readonly) EXAppLoaderStatus status; 52 @property (nonatomic, readonly) EXAppLoaderRemoteUpdateStatus remoteUpdateStatus; 53 @property (nonatomic, readonly) BOOL shouldShowRemoteUpdateStatus; 54 @property (nonatomic, readonly) BOOL isUpToDate; 55 56 @property (nonatomic, weak) id<EXAppLoaderDelegate> delegate; 57 @property (nonatomic, weak) id<EXAppFetcherDataSource> dataSource; 58 59 - (instancetype)initWithManifestUrl:(NSURL *)url; 60 - (instancetype)initWithLocalManifest:(EXManifestsManifest * _Nonnull)manifest; 61 62 /** 63 * Begin a new request. 64 * In production, this will fetch a manifest and a bundle using the caching behavior specified by the Updates API. 65 * If the manifest enables developer tools, this will stop after it gets a manifest, and wait for `forceBundleReload`. 66 */ 67 - (void)request; 68 69 /** 70 * Begin a new request, but only use the most recently cached manifest. 71 * In production, this will fetch a manifest and a bundle using the caching behavior specified by the Updates API. 72 * If the manifest enables developer tools, this will stop after it gets a manifest, and wait for `forceBundleReload`. 73 */ 74 - (void)requestFromCache; 75 76 /** 77 * Tell this AppLoader that everything has finished successfully and its manifest resource can be cached. 78 */ 79 - (void)writeManifestToCache; 80 81 /** 82 * Reset status to `kEXAppLoaderStatusHasManifest` and fetch the bundle at the existing 83 * manifest. This is called when RN devtools reload an AppManager/RCTBridge directly 84 * via reload, live reload, etc. 85 * 86 * This will throw if not supported, i.e. if `supportsBundleReload` returns false. 87 */ 88 - (void)forceBundleReload; 89 90 /** 91 * Return whether this AppLoader supports directly reloading the bundle. Right now the only case 92 * where that's possible is if we're running an app in dev mode. 93 */ 94 - (BOOL)supportsBundleReload; 95 96 /** 97 * Fetch manifest without any side effects or interaction with the timer. 98 */ 99 - (void)fetchManifestWithCacheBehavior:(EXManifestCacheBehavior)cacheBehavior success:(void (^)(EXManifestsManifest *))success failure:(void (^)(NSError *))failure; 100 101 @end 102 103 NS_ASSUME_NONNULL_END 104