1 | // Copyright 2018-present 650 Industries. All rights reserved.
|
2 |
|
3 | #import <UMCore/UMDefines.h>
|
4 | #import <UMCore/UMUtilities.h>
|
5 | #import <UMCore/UMEventEmitterService.h>
|
6 |
|
7 | #import <UMConstantsInterface/UMConstantsInterface.h>
|
8 |
|
9 | #import <EXTaskManager/EXTaskManager.h>
|
10 | #import <EXTaskManager/EXTaskService.h>
|
11 | #import <UMTaskManagerInterface/UMTaskServiceInterface.h>
|
12 |
|
13 | NSString * const EXTaskManagerEventName = @"TaskManager.executeTask";
|
14 |
|
15 | @interface EXTaskManager ()
|
16 |
|
17 | @property (nonatomic, strong) NSString *appId;
|
18 | @property (nonatomic, strong) NSMutableArray<NSDictionary *> *eventsQueue;
|
19 | @property (nonatomic, weak) id<UMEventEmitterService> eventEmitter;
|
20 | @property (nonatomic, weak) id<UMConstantsInterface> constantsService;
|
21 | @property (nonatomic, weak) id<UMTaskServiceInterface> taskService;
|
22 |
|
23 | @end
|
24 |
|
25 | @implementation EXTaskManager
|
26 |
|
27 | UM_EXPORT_MODULE(ExpoTaskManager);
|
28 |
|
29 | + (const NSArray<Protocol *> *)exportedInterfaces
|
30 | {
|
31 | return @[@protocol(UMTaskManagerInterface)];
|
32 | }
|
33 |
|
34 | - (instancetype)init
|
35 | {
|
36 | return [self initWithExperienceId:@"mainApplication"];
|
37 | }
|
38 |
|
39 | // TODO: Remove when adding bare React Native support
|
40 | - (instancetype)initWithExperienceId:(NSString *)experienceId
|
41 | {
|
42 | if (self = [super init]) {
|
43 | _appId = experienceId;
|
44 | _eventsQueue = [NSMutableArray new];
|
45 | }
|
46 | return self;
|
47 | }
|
48 |
|
49 | - (void)setModuleRegistry:(UMModuleRegistry *)moduleRegistry
|
50 | {
|
51 | _eventEmitter = [moduleRegistry getModuleImplementingProtocol:@protocol(UMEventEmitterService)];
|
52 | _constantsService = [moduleRegistry getModuleImplementingProtocol:@protocol(UMConstantsInterface)];
|
53 | _taskService = [moduleRegistry getSingletonModuleForName:@"TaskService"];
|
54 |
|
55 | // Register task manager in task service.
|
56 | [_taskService setTaskManager:self forAppId:_appId withUrl:[self _findAppUrl]];
|
57 | }
|
58 |
|
59 | - (NSDictionary *)constantsToExport
|
60 | {
|
61 | return @{
|
62 | @"EVENT_NAME": EXTaskManagerEventName,
|
63 | };
|
64 | }
|
65 |
|
66 | # pragma mark - UMEventEmitter
|
67 |
|
68 | - (NSArray<NSString *> *)supportedEvents
|
69 | {
|
70 | return @[EXTaskManagerEventName];
|
71 | }
|
72 |
|
73 |
|
74 |
|
75 |
|
76 |
|
77 | - (void)startObserving
|
78 | {
|
79 | if (_eventsQueue && _eventsQueue.count > 0) {
|
80 | // Emit queued events
|
81 | for (NSDictionary *eventBody in _eventsQueue) {
|
82 | [_eventEmitter sendEventWithName:EXTaskManagerEventName body:eventBody];
|
83 | }
|
84 | }
|
85 | _eventsQueue = nil;
|
86 | }
|
87 |
|
88 | - (void)stopObserving {}
|
89 |
|
90 | # pragma mark - Exported methods
|
91 |
|
92 | UM_EXPORT_METHOD_AS(notifyTaskFinishedAsync,
|
93 | notifyTaskFinished:(nonnull NSString *)taskName
|
94 | withResponse:(nonnull NSDictionary *)response
|
95 | resolve:(UMPromiseResolveBlock)resolve
|
96 | reject:(UMPromiseRejectBlock)reject)
|
97 | {
|
98 | [_taskService notifyTaskWithName:taskName forAppId:_appId didFinishWithResponse:response];
|
99 | resolve(nil);
|
100 | }
|
101 |
|
102 | UM_EXPORT_METHOD_AS(isTaskRegisteredAsync,
|
103 | isTaskRegistered:(nonnull NSString *)taskName
|
104 | resolve:(UMPromiseResolveBlock)resolve
|
105 | reject:(UMPromiseRejectBlock)reject)
|
106 | {
|
107 | resolve(@([self hasRegisteredTaskWithName:taskName]));
|
108 | }
|
109 |
|
110 | UM_EXPORT_METHOD_AS(getRegisteredTasksAsync,
|
111 | getRegisteredTasks:(UMPromiseResolveBlock)resolve
|
112 | reject:(UMPromiseRejectBlock)reject)
|
113 | {
|
114 | resolve([_taskService getRegisteredTasksForAppId:_appId]);
|
115 | }
|
116 |
|
117 | UM_EXPORT_METHOD_AS(getTaskOptionsAsync,
|
118 | getConfigurationForTaskName:(nonnull NSString *)taskName
|
119 | resolve:(UMPromiseResolveBlock)resolve
|
120 | reject:(UMPromiseRejectBlock)reject)
|
121 | {
|
122 | resolve(UMNullIfNil([_taskService getOptionsForTaskName:taskName forAppId:_appId]));
|
123 | }
|
124 |
|
125 | UM_EXPORT_METHOD_AS(unregisterTaskAsync,
|
126 | unregisterTaskWithName:(nonnull NSString *)taskName
|
127 | resolve:(UMPromiseResolveBlock)resolve
|
128 | reject:(UMPromiseRejectBlock)reject)
|
129 | {
|
130 | @try {
|
131 | [self unregisterTaskWithName:taskName consumerClass:nil];
|
132 | } @catch (NSException *e) {
|
133 | return reject(e.name, e.reason, nil);
|
134 | }
|
135 | resolve(nil);
|
136 | }
|
137 |
|
138 | UM_EXPORT_METHOD_AS(unregisterAllTasksAsync,
|
139 | unregisterAllTasks:(UMPromiseResolveBlock)resolve
|
140 | reject:(UMPromiseRejectBlock)reject)
|
141 | {
|
142 | [_taskService unregisterAllTasksForAppId:_appId];
|
143 | resolve(nil);
|
144 | }
|
145 |
|
146 | # pragma mark - UMTaskManagerInterface
|
147 |
|
148 | - (BOOL)hasRegisteredTaskWithName:(nonnull NSString *)taskName
|
149 | {
|
150 | return [_taskService hasRegisteredTaskWithName:taskName forAppId:_appId];
|
151 | }
|
152 |
|
153 | - (BOOL)taskWithName:(nonnull NSString *)taskName hasConsumerOfClass:(Class)consumerClass
|
154 | {
|
155 | return [_taskService taskWithName:taskName forAppId:_appId hasConsumerOfClass:consumerClass];
|
156 | }
|
157 |
|
158 | - (void)registerTaskWithName:(nonnull NSString *)taskName
|
159 | consumer:(Class)consumerClass
|
160 | options:(nonnull NSDictionary *)options
|
161 | {
|
162 | NSString *appUrl = [self _findAppUrl];
|
163 |
|
164 | [_taskService registerTaskWithName:taskName
|
165 | appId:_appId
|
166 | appUrl:appUrl
|
167 | consumerClass:consumerClass
|
168 | options:options];
|
169 | }
|
170 |
|
171 | - (void)unregisterTaskWithName:(nonnull NSString *)taskName
|
172 | consumerClass:(Class)consumerClass
|
173 | {
|
174 | [_taskService unregisterTaskWithName:taskName forAppId:_appId consumerClass:consumerClass];
|
175 | }
|
176 |
|
177 | - (BOOL)hasBackgroundModeEnabled:(nonnull NSString *)backgroundMode
|
178 | {
|
179 | return [EXTaskService hasBackgroundModeEnabled:backgroundMode];
|
180 | }
|
181 |
|
182 | - (void)executeWithBody:(NSDictionary *)body
|
183 | {
|
184 | if (!_eventsQueue) {
|
185 | // Module's event emitter is already being observed, so we can send events.
|
186 | [_eventEmitter sendEventWithName:EXTaskManagerEventName body:body];
|
187 | } else {
|
188 | // Otherwise add event body to the queue (it will be send in `startObserving`).
|
189 | [_eventsQueue addObject:body];
|
190 | }
|
191 | }
|
192 |
|
193 | - (BOOL)isRunningInHeadlessMode
|
194 | {
|
195 | return [[_constantsService constants][@"isHeadless"] boolValue];
|
196 | }
|
197 |
|
198 | # pragma mark - internals
|
199 |
|
200 | - (NSString *)_findAppUrl
|
201 | {
|
202 | // TODO(@tsapeta): find app url for vanilla RN apps
|
203 | return [_constantsService constants][@"experienceUrl"];
|
204 | }
|
205 |
|
206 | @end
|