1// Copyright 2020-present 650 Industries. All rights reserved.
2
3#if __has_include(<EXUpdates/EXUpdatesService.h>)
4
5#import "EXUpdatesBinding.h"
6
7#import <objc/runtime.h>
8
9#import "ExpoModulesCore-Swift.h"
10#if __has_include(<EXUpdatesInterface/EXUpdatesInterface-Swift.h>)
11#import <EXUpdatesInterface/EXUpdatesInterface-Swift.h>
12#else
13#import "EXUpdatesInterface-Swift.h"
14#endif
15#import "EXUpdates-Swift.h"
16
17NS_ASSUME_NONNULL_BEGIN
18
19@interface EXUpdatesBinding ()
20
21@property (nonatomic, strong) NSString *scopeKey;
22@property (nonatomic, weak) id<EXUpdatesBindingDelegate> updatesKernelService;
23@property (nonatomic, weak) id<EXUpdatesDatabaseBindingDelegate> databaseKernelService;
24
25@end
26
27/**
28 * Scoped internal module which overrides EXUpdatesService at runtime in Expo Go, and gives
29 * EXUpdatesModule access to properties from the correct instance of EXAppLoaderExpoUpdates (through
30 * EXUpdatesKernelService) as well as the global database object (through
31 * EXUpdatesDatabaseKernelService).
32 */
33@implementation EXUpdatesBinding : EXUpdatesService
34
35- (instancetype)initWithScopeKey:(NSString *)scopeKey updatesKernelService:(id<EXUpdatesBindingDelegate>)updatesKernelService databaseKernelService:(id<EXUpdatesDatabaseBindingDelegate>)databaseKernelService
36{
37  if (self = [super init]) {
38    _scopeKey = scopeKey;
39    _updatesKernelService = updatesKernelService;
40    _databaseKernelService = databaseKernelService;
41  }
42  return self;
43}
44
45- (nullable EXUpdatesConfig *)config
46{
47  EXUpdatesConfig *config = [_updatesKernelService configForScopeKey:_scopeKey];
48  // Ensures the universal UpdatesConfig can cast to versioned UpdatesConfig without exception in Swift
49  object_setClass(config, [EXUpdatesConfig class]);
50  return config;
51}
52
53- (EXUpdatesDatabase *)database
54{
55  return _databaseKernelService.database;
56}
57
58- (nullable EXUpdatesSelectionPolicy *)selectionPolicy
59{
60  return [_updatesKernelService selectionPolicyForScopeKey:_scopeKey];
61}
62
63- (NSURL *)directory
64{
65  return _databaseKernelService.updatesDirectory;
66}
67
68- (nullable EXUpdatesUpdate *)embeddedUpdate
69{
70  return nil;
71}
72
73- (nullable EXUpdatesUpdate *)launchedUpdate
74{
75  EXUpdatesUpdate *update = [_updatesKernelService launchedUpdateForScopeKey:_scopeKey];
76  // Ensures the universal UpdatesUpdate can cast to versioned UpdatesUpdate without exception in Swift
77  object_setClass(update, [EXUpdatesUpdate class]);
78  return update;
79}
80
81- (nullable NSDictionary *)assetFilesMap
82{
83  return [_updatesKernelService assetFilesMapForScopeKey:_scopeKey];
84}
85
86- (BOOL)isUsingEmbeddedAssets
87{
88  return [_updatesKernelService isUsingEmbeddedAssetsForScopeKey:_scopeKey];
89}
90
91- (BOOL)isStarted
92{
93  return [_updatesKernelService isStartedForScopeKey:_scopeKey];
94}
95
96- (BOOL)isEmergencyLaunch
97{
98  return [_updatesKernelService isEmergencyLaunchForScopeKey:_scopeKey];
99}
100
101- (BOOL)canRelaunch
102{
103  return YES;
104}
105
106- (BOOL)canCheckForUpdateAndFetchUpdate
107{
108  // not allowed in managed
109  return NO;
110}
111
112- (void)requestRelaunchWithCompletion:(EXUpdatesAppRelaunchCompletionBlock)completion
113{
114  return [_updatesKernelService requestRelaunchForScopeKey:_scopeKey withCompletion:completion];
115}
116
117- (void)resetSelectionPolicy
118{
119  // no-op in managed
120}
121
122+ (const NSArray<Protocol *> *)exportedInterfaces {
123  return @[@protocol(EXUpdatesModuleInterface)];
124}
125
126@end
127
128NS_ASSUME_NONNULL_END
129
130#endif
131