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