@react-native-firebase/storage 26.0.0 → 26.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,728 @@
1
+ /**
2
+ * Copyright (c) 2016-present Invertase Limited & Contributors
3
+ *
4
+ * Licensed under the Apache License, Version 2.0 (the "License");
5
+ * you may not use this library except in compliance with the License.
6
+ * You may obtain a copy of the License at
7
+ *
8
+ * http://www.apache.org/licenses/LICENSE-2.0
9
+ *
10
+ * Unless required by applicable law or agreed to in writing, software
11
+ * distributed under the License is distributed on an "AS IS" BASIS,
12
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ * See the License for the specific language governing permissions and
14
+ * limitations under the License.
15
+ *
16
+ */
17
+
18
+ #if __has_include(<Firebase/Firebase.h>)
19
+ #import <Firebase/Firebase.h>
20
+ #else
21
+ @import FirebaseCore;
22
+ @import FirebaseStorage;
23
+ #endif
24
+ #import <React/RCTUtils.h>
25
+
26
+ #import "RNFBApp/RCTConvert+FIRApp.h"
27
+ #import "RNFBApp/RNFBSharedUtils.h"
28
+ #import "RNFBRCTEventEmitter.h"
29
+ #import "RNFBStorageCommon.h"
30
+ #import "RNFBStorageHelper.h"
31
+
32
+ static NSString *const RNFB_STORAGE_EVENT = @"storage_event";
33
+ static NSString *const RNFB_STORAGE_STATE_CHANGED = @"state_changed";
34
+ static NSString *const RNFB_STORAGE_UPLOAD_SUCCESS = @"upload_success";
35
+ static NSString *const RNFB_STORAGE_UPLOAD_FAILURE = @"upload_failure";
36
+ static NSString *const RNFB_STORAGE_DOWNLOAD_SUCCESS = @"download_success";
37
+ static NSString *const RNFB_STORAGE_DOWNLOAD_FAILURE = @"download_failure";
38
+
39
+ static NSMutableDictionary *PENDING_TASKS;
40
+
41
+ // The iOS SDK has a short memory on settings, store these globally and set them in each time
42
+ static NSString *emulatorHost = nil;
43
+ static NSInteger emulatorPort = 0;
44
+ static NSMutableDictionary *emulatorConfigs;
45
+ static NSTimeInterval maxDownloadRetryTime = 600;
46
+ static NSTimeInterval maxUploadRetryTime = 600;
47
+ static NSTimeInterval maxOperationRetryTime = 120;
48
+
49
+ @implementation RNFBStorageHelper
50
+
51
+ #pragma mark -
52
+ #pragma mark Shared state
53
+
54
+ + (void)initializeSharedStateOnce {
55
+ static dispatch_once_t onceToken;
56
+ dispatch_once(&onceToken, ^{
57
+ PENDING_TASKS = [[NSMutableDictionary alloc] init];
58
+ emulatorConfigs = [[NSMutableDictionary alloc] init];
59
+ });
60
+ }
61
+
62
+ + (void)invalidate {
63
+ [self initializeSharedStateOnce];
64
+ for (NSString *key in [PENDING_TASKS allKeys]) {
65
+ [PENDING_TASKS removeObjectForKey:key];
66
+ }
67
+ }
68
+
69
+ #pragma mark -
70
+ #pragma mark Firebase Storage Methods
71
+
72
+ /**
73
+ * @url https://firebase.google.com/docs/reference/js/firebase.storage.Reference#delete
74
+ */
75
+ + (void)deleteObject:(NSString *)appName
76
+ url:(NSString *)url
77
+ resolve:(RCTPromiseResolveBlock)resolve
78
+ reject:(RCTPromiseRejectBlock)reject {
79
+ FIRApp *firebaseApp = [RCTConvert firAppFromString:appName];
80
+ FIRStorageReference *storageReference = [self getReferenceFromUrl:url app:firebaseApp];
81
+
82
+ [storageReference deleteWithCompletion:^(NSError *_Nullable error) {
83
+ if (error != nil) {
84
+ [self promiseRejectStorageException:reject error:error];
85
+ } else {
86
+ resolve([NSNull null]);
87
+ }
88
+ }];
89
+ }
90
+
91
+ /**
92
+ * @url https://firebase.google.com/docs/reference/js/firebase.storage.Reference#getDownloadURL
93
+ */
94
+ + (void)getDownloadURL:(NSString *)appName
95
+ url:(NSString *)url
96
+ resolve:(RCTPromiseResolveBlock)resolve
97
+ reject:(RCTPromiseRejectBlock)reject {
98
+ FIRApp *firebaseApp = [RCTConvert firAppFromString:appName];
99
+ FIRStorageReference *storageReference = [self getReferenceFromUrl:url app:firebaseApp];
100
+
101
+ [storageReference downloadURLWithCompletion:^(NSURL *_Nullable URL, NSError *_Nullable error) {
102
+ if (error != nil) {
103
+ [self promiseRejectStorageException:reject error:error];
104
+ } else {
105
+ NSString *url = URL.absoluteString;
106
+
107
+ if ([url rangeOfString:@":443"].location != NSNotFound) {
108
+ NSRange replaceRange = [url rangeOfString:@":443"];
109
+ url = [url stringByReplacingCharactersInRange:replaceRange withString:@""];
110
+ }
111
+
112
+ resolve(url);
113
+ }
114
+ }];
115
+ }
116
+
117
+ /**
118
+ * @url https://firebase.google.com/docs/reference/js/firebase.storage.Reference#getMetadata
119
+ */
120
+ + (void)getMetadata:(NSString *)appName
121
+ url:(NSString *)url
122
+ resolve:(RCTPromiseResolveBlock)resolve
123
+ reject:(RCTPromiseRejectBlock)reject {
124
+ FIRApp *firebaseApp = [RCTConvert firAppFromString:appName];
125
+ FIRStorageReference *storageReference = [self getReferenceFromUrl:url app:firebaseApp];
126
+
127
+ [storageReference
128
+ metadataWithCompletion:^(FIRStorageMetadata *_Nullable metadata, NSError *_Nullable error) {
129
+ if (error != nil) {
130
+ [self promiseRejectStorageException:reject error:error];
131
+ } else {
132
+ resolve([RNFBStorageCommon metadataToDict:metadata]);
133
+ }
134
+ }];
135
+ }
136
+
137
+ /**
138
+ * @url https://firebase.google.com/docs/reference/js/firebase.storage.Reference#updateMetadata
139
+ */
140
+ + (NSDictionary *)decodedMetadataMap:(NSDictionary *_Nullable)metadata {
141
+ if (metadata == nil) {
142
+ return @{};
143
+ }
144
+
145
+ return [RNFBSharedUtils decodeNullSentinels:metadata];
146
+ }
147
+
148
+ + (void)updateMetadata:(NSString *)appName
149
+ url:(NSString *)url
150
+ metadata:(NSDictionary *_Nullable)metadata
151
+ resolve:(RCTPromiseResolveBlock)resolve
152
+ reject:(RCTPromiseRejectBlock)reject {
153
+ FIRApp *firebaseApp = [RCTConvert firAppFromString:appName];
154
+ FIRStorageReference *storageReference = [self getReferenceFromUrl:url app:firebaseApp];
155
+ NSDictionary *metadataMap = [self decodedMetadataMap:metadata];
156
+
157
+ [storageReference metadataWithCompletion:^(FIRStorageMetadata *_Nullable fetchedMetadata,
158
+ NSError *_Nullable error) {
159
+ if (error != nil) {
160
+ [self promiseRejectStorageException:reject error:error];
161
+ } else {
162
+ FIRStorageMetadata *storageMetadata =
163
+ [RNFBStorageCommon buildMetadataFromMap:metadataMap
164
+ existingMetadata:fetchedMetadata
165
+ path:[storageReference fullPath]];
166
+
167
+ [storageReference updateMetadata:storageMetadata
168
+ completion:^(FIRStorageMetadata *_Nullable updatedMetadata,
169
+ NSError *_Nullable error) {
170
+ if (error != nil) {
171
+ [self promiseRejectStorageException:reject error:error];
172
+ } else {
173
+ resolve([RNFBStorageCommon metadataToDict:updatedMetadata]);
174
+ }
175
+ }];
176
+ }
177
+ }];
178
+ }
179
+
180
+ // list
181
+ + (void)list:(NSString *)appName
182
+ url:(NSString *)url
183
+ maxResults:(long)maxResults
184
+ pageToken:(NSString *_Nullable)pageToken
185
+ resolve:(RCTPromiseResolveBlock)resolve
186
+ reject:(RCTPromiseRejectBlock)reject {
187
+ FIRApp *firebaseApp = [RCTConvert firAppFromString:appName];
188
+ FIRStorageReference *storageReference = [self getReferenceFromUrl:url app:firebaseApp];
189
+
190
+ id completionBlock = ^(FIRStorageListResult *result, NSError *error) {
191
+ if (error != nil) {
192
+ [self promiseRejectStorageException:reject error:error];
193
+ } else {
194
+ resolve([RNFBStorageCommon listResultToDict:result]);
195
+ }
196
+ };
197
+
198
+ if (pageToken != nil) {
199
+ [storageReference listWithMaxResults:(int64_t)maxResults
200
+ pageToken:pageToken
201
+ completion:completionBlock];
202
+ } else {
203
+ [storageReference listWithMaxResults:(int64_t)maxResults completion:completionBlock];
204
+ }
205
+ }
206
+
207
+ // listAll
208
+ + (void)listAll:(NSString *)appName
209
+ url:(NSString *)url
210
+ resolve:(RCTPromiseResolveBlock)resolve
211
+ reject:(RCTPromiseRejectBlock)reject {
212
+ FIRApp *firebaseApp = [RCTConvert firAppFromString:appName];
213
+ FIRStorageReference *storageReference = [self getReferenceFromUrl:url app:firebaseApp];
214
+
215
+ __block bool alreadyCompleted = false;
216
+
217
+ id completionBlock = ^(FIRStorageListResult *result, NSError *error) {
218
+ // This may be called multiple times if an error occurs
219
+ // Make sure we won't try to resolve the promise twice in this case
220
+ // TODO - remove pending resolution of firebase-ios-sdk issue 7197
221
+ if (alreadyCompleted) {
222
+ return;
223
+ }
224
+ alreadyCompleted = true;
225
+ if (error != nil) {
226
+ [self promiseRejectStorageException:reject error:error];
227
+ } else {
228
+ resolve([RNFBStorageCommon listResultToDict:result]);
229
+ }
230
+ };
231
+
232
+ [storageReference listAllWithCompletion:completionBlock];
233
+ }
234
+
235
+ // setMaxDownloadRetryTime
236
+ + (void)setMaxDownloadRetryTime:(NSString *)appName
237
+ milliseconds:(double)milliseconds
238
+ resolve:(RCTPromiseResolveBlock)resolve
239
+ reject:(RCTPromiseRejectBlock)reject {
240
+ FIRApp *firebaseApp = [RCTConvert firAppFromString:appName];
241
+ maxDownloadRetryTime = milliseconds / 1000;
242
+ [[FIRStorage storageForApp:firebaseApp] setMaxDownloadRetryTime:milliseconds / 1000];
243
+ resolve([NSNull null]);
244
+ }
245
+
246
+ // setMaxOperationRetryTime
247
+ + (void)setMaxOperationRetryTime:(NSString *)appName
248
+ milliseconds:(double)milliseconds
249
+ resolve:(RCTPromiseResolveBlock)resolve
250
+ reject:(RCTPromiseRejectBlock)reject {
251
+ FIRApp *firebaseApp = [RCTConvert firAppFromString:appName];
252
+ maxOperationRetryTime = milliseconds / 1000;
253
+ [[FIRStorage storageForApp:firebaseApp] setMaxOperationRetryTime:milliseconds / 1000];
254
+ resolve([NSNull null]);
255
+ }
256
+
257
+ // setMaxUploadRetryTime
258
+ + (void)setMaxUploadRetryTime:(NSString *)appName
259
+ milliseconds:(double)milliseconds
260
+ resolve:(RCTPromiseResolveBlock)resolve
261
+ reject:(RCTPromiseRejectBlock)reject {
262
+ FIRApp *firebaseApp = [RCTConvert firAppFromString:appName];
263
+ maxUploadRetryTime = milliseconds / 1000;
264
+ [[FIRStorage storageForApp:firebaseApp] setMaxUploadRetryTime:milliseconds / 1000];
265
+ resolve([NSNull null]);
266
+ }
267
+
268
+ // writeToFile
269
+ + (void)writeToFile:(NSString *)appName
270
+ url:(NSString *)url
271
+ localFilePath:(NSString *)localFilePath
272
+ taskId:(double)taskId
273
+ resolve:(RCTPromiseResolveBlock)resolve
274
+ reject:(RCTPromiseRejectBlock)reject {
275
+ [self initializeSharedStateOnce];
276
+ FIRApp *firebaseApp = [RCTConvert firAppFromString:appName];
277
+ NSNumber *taskIdNumber = @(taskId);
278
+ FIRStorageReference *storageReference = [self getReferenceFromUrl:url app:firebaseApp];
279
+ NSURL *localFile = [NSURL fileURLWithPath:localFilePath];
280
+
281
+ __block FIRStorageDownloadTask *downloadTask;
282
+ RCTUnsafeExecuteOnMainQueueSync(^{
283
+ downloadTask = [storageReference writeToFile:localFile];
284
+ });
285
+
286
+ PENDING_TASKS[taskIdNumber] = downloadTask;
287
+
288
+ [downloadTask
289
+ observeStatus:FIRStorageTaskStatusResume
290
+ handler:^(FIRStorageTaskSnapshot *snapshot) {
291
+ NSDictionary *eventBody = [RNFBStorageCommon getDownloadTaskAsDictionary:snapshot];
292
+ NSDictionary *event =
293
+ [RNFBStorageCommon getStorageEventDictionary:eventBody
294
+ internalEventName:RNFB_STORAGE_STATE_CHANGED
295
+ appName:firebaseApp.name
296
+ taskId:taskIdNumber];
297
+ [[RNFBRCTEventEmitter shared] sendEventWithName:RNFB_STORAGE_EVENT body:event];
298
+ }];
299
+
300
+ [downloadTask
301
+ observeStatus:FIRStorageTaskStatusPause
302
+ handler:^(FIRStorageTaskSnapshot *snapshot) {
303
+ NSDictionary *eventBody = [RNFBStorageCommon getDownloadTaskAsDictionary:snapshot];
304
+ NSDictionary *event =
305
+ [RNFBStorageCommon getStorageEventDictionary:eventBody
306
+ internalEventName:RNFB_STORAGE_STATE_CHANGED
307
+ appName:firebaseApp.name
308
+ taskId:taskIdNumber];
309
+ [[RNFBRCTEventEmitter shared] sendEventWithName:RNFB_STORAGE_EVENT body:event];
310
+ }];
311
+
312
+ [downloadTask
313
+ observeStatus:FIRStorageTaskStatusProgress
314
+ handler:^(FIRStorageTaskSnapshot *snapshot) {
315
+ NSDictionary *eventBody = [RNFBStorageCommon getDownloadTaskAsDictionary:snapshot];
316
+ NSDictionary *event =
317
+ [RNFBStorageCommon getStorageEventDictionary:eventBody
318
+ internalEventName:RNFB_STORAGE_STATE_CHANGED
319
+ appName:firebaseApp.name
320
+ taskId:taskIdNumber];
321
+ [[RNFBRCTEventEmitter shared] sendEventWithName:RNFB_STORAGE_EVENT body:event];
322
+ }];
323
+
324
+ [downloadTask
325
+ observeStatus:FIRStorageTaskStatusSuccess
326
+ handler:^(FIRStorageTaskSnapshot *snapshot) {
327
+ [PENDING_TASKS removeObjectForKey:taskIdNumber];
328
+
329
+ NSDictionary *stateChangedEventBody =
330
+ [RNFBStorageCommon getDownloadTaskAsDictionary:snapshot];
331
+ NSDictionary *stateChangedEvent =
332
+ [RNFBStorageCommon getStorageEventDictionary:stateChangedEventBody
333
+ internalEventName:RNFB_STORAGE_STATE_CHANGED
334
+ appName:firebaseApp.name
335
+ taskId:taskIdNumber];
336
+ [[RNFBRCTEventEmitter shared] sendEventWithName:RNFB_STORAGE_EVENT
337
+ body:stateChangedEvent];
338
+
339
+ NSDictionary *eventBody = [RNFBStorageCommon getDownloadTaskAsDictionary:snapshot];
340
+ NSDictionary *event =
341
+ [RNFBStorageCommon getStorageEventDictionary:eventBody
342
+ internalEventName:RNFB_STORAGE_DOWNLOAD_SUCCESS
343
+ appName:firebaseApp.name
344
+ taskId:taskIdNumber];
345
+ [[RNFBRCTEventEmitter shared] sendEventWithName:RNFB_STORAGE_EVENT body:event];
346
+ resolve(eventBody);
347
+ }];
348
+
349
+ [downloadTask
350
+ observeStatus:FIRStorageTaskStatusFailure
351
+ handler:^(FIRStorageTaskSnapshot *snapshot) {
352
+ [PENDING_TASKS removeObjectForKey:taskIdNumber];
353
+
354
+ NSDictionary *stateChangedEventBody =
355
+ [RNFBStorageCommon getDownloadTaskAsDictionary:snapshot];
356
+ NSDictionary *stateChangedEvent =
357
+ [RNFBStorageCommon getStorageEventDictionary:stateChangedEventBody
358
+ internalEventName:RNFB_STORAGE_STATE_CHANGED
359
+ appName:firebaseApp.name
360
+ taskId:taskIdNumber];
361
+ [[RNFBRCTEventEmitter shared] sendEventWithName:RNFB_STORAGE_EVENT
362
+ body:stateChangedEvent];
363
+
364
+ NSMutableDictionary *taskSnapshotDict =
365
+ [RNFBStorageCommon getDownloadTaskAsDictionary:snapshot];
366
+ NSDictionary *eventBody = [RNFBStorageCommon buildErrorSnapshotDict:snapshot.error
367
+ taskSnapshotDict:taskSnapshotDict];
368
+ NSDictionary *event =
369
+ [RNFBStorageCommon getStorageEventDictionary:eventBody
370
+ internalEventName:RNFB_STORAGE_DOWNLOAD_FAILURE
371
+ appName:firebaseApp.name
372
+ taskId:taskIdNumber];
373
+ [[RNFBRCTEventEmitter shared] sendEventWithName:RNFB_STORAGE_EVENT body:event];
374
+
375
+ [self promiseRejectStorageException:reject error:snapshot.error];
376
+ }];
377
+ }
378
+
379
+ // putFile
380
+ + (void)putFile:(NSString *)appName
381
+ url:(NSString *)url
382
+ localFilePath:(NSString *)localFilePath
383
+ metadata:(NSDictionary *_Nullable)metadata
384
+ taskId:(double)taskId
385
+ resolve:(RCTPromiseResolveBlock)resolve
386
+ reject:(RCTPromiseRejectBlock)reject {
387
+ FIRApp *firebaseApp = [RCTConvert firAppFromString:appName];
388
+ NSNumber *taskIdNumber = @(taskId);
389
+ FIRStorageReference *storageReference = [self getReferenceFromUrl:url app:firebaseApp];
390
+ NSDictionary *metadataMap = [self decodedMetadataMap:metadata];
391
+ FIRStorageMetadata *storageMetadata =
392
+ [RNFBStorageCommon buildMetadataFromMap:metadataMap
393
+ existingMetadata:nil
394
+ path:[storageReference fullPath]];
395
+
396
+ [RNFBStorageCommon
397
+ NSURLForLocalFilePath:localFilePath
398
+ completion:^(NSArray *errorCodeMessageArray, NSURL *temporaryFileUrl,
399
+ NSString *contentType) {
400
+ if (errorCodeMessageArray != nil) {
401
+ NSMutableDictionary *taskSnapshotDict =
402
+ [RNFBStorageCommon getUploadTaskAsDictionary:nil];
403
+ NSDictionary *eventBody = [RNFBStorageCommon
404
+ buildErrorSnapshotDictFromCodeAndMessage:errorCodeMessageArray
405
+ taskSnapshotDict:taskSnapshotDict];
406
+ NSDictionary *stateChangedEvent = [RNFBStorageCommon
407
+ getStorageEventDictionary:eventBody
408
+ internalEventName:RNFB_STORAGE_STATE_CHANGED
409
+ appName:[[[storageReference storage] app] name]
410
+ taskId:taskIdNumber];
411
+ [[RNFBRCTEventEmitter shared] sendEventWithName:RNFB_STORAGE_EVENT
412
+ body:stateChangedEvent];
413
+
414
+ NSDictionary *event = [RNFBStorageCommon
415
+ getStorageEventDictionary:eventBody
416
+ internalEventName:RNFB_STORAGE_UPLOAD_FAILURE
417
+ appName:[[[storageReference storage] app] name]
418
+ taskId:taskIdNumber];
419
+ [[RNFBRCTEventEmitter shared] sendEventWithName:RNFB_STORAGE_EVENT body:event];
420
+
421
+ [RNFBSharedUtils rejectPromiseWithUserInfo:reject
422
+ userInfo:(NSMutableDictionary *)@{
423
+ @"code" : errorCodeMessageArray[0],
424
+ @"message" : errorCodeMessageArray[1],
425
+ }];
426
+ return;
427
+ }
428
+
429
+ storageMetadata.contentType = contentType;
430
+
431
+ if ([storageMetadata valueForKey:@"contentType"] == nil) {
432
+ storageMetadata.contentType =
433
+ [RNFBStorageCommon mimeTypeForPath:localFilePath];
434
+ }
435
+
436
+ __block FIRStorageUploadTask *uploadTask;
437
+ RCTUnsafeExecuteOnMainQueueSync(^{
438
+ uploadTask = [storageReference putFile:temporaryFileUrl
439
+ metadata:storageMetadata];
440
+ });
441
+
442
+ [self addUploadTaskObservers:uploadTask
443
+ appDisplayName:[[[storageReference storage] app] name]
444
+ taskId:taskIdNumber
445
+ resolver:resolve
446
+ rejecter:reject];
447
+ }];
448
+ }
449
+
450
+ // putString
451
+ + (void)putString:(NSString *)appName
452
+ url:(NSString *)url
453
+ string:(NSString *)string
454
+ format:(NSString *)format
455
+ metadata:(NSDictionary *_Nullable)metadata
456
+ taskId:(double)taskId
457
+ resolve:(RCTPromiseResolveBlock)resolve
458
+ reject:(RCTPromiseRejectBlock)reject {
459
+ FIRApp *firebaseApp = [RCTConvert firAppFromString:appName];
460
+ NSNumber *taskIdNumber = @(taskId);
461
+ FIRStorageReference *storageReference = [self getReferenceFromUrl:url app:firebaseApp];
462
+ NSDictionary *metadataMap = [self decodedMetadataMap:metadata];
463
+ FIRStorageMetadata *storageMetadata =
464
+ [RNFBStorageCommon buildMetadataFromMap:metadataMap
465
+ existingMetadata:nil
466
+ path:[storageReference fullPath]];
467
+
468
+ __block FIRStorageUploadTask *uploadTask;
469
+ RCTUnsafeExecuteOnMainQueueSync(^{
470
+ uploadTask = [storageReference putData:[RNFBStorageCommon NSDataFromUploadString:string
471
+ format:format]
472
+ metadata:storageMetadata];
473
+ });
474
+
475
+ [self addUploadTaskObservers:uploadTask
476
+ appDisplayName:[[[storageReference storage] app] name]
477
+ taskId:taskIdNumber
478
+ resolver:resolve
479
+ rejecter:reject];
480
+ }
481
+
482
+ // useEmulator
483
+ + (void)useEmulator:(NSString *)appName
484
+ host:(NSString *)host
485
+ port:(double)port
486
+ bucketUrl:(NSString *)bucketUrl {
487
+ [self initializeSharedStateOnce];
488
+ FIRApp *firebaseApp = [RCTConvert firAppFromString:appName];
489
+ emulatorHost = host;
490
+ emulatorPort = (NSInteger)port;
491
+ NSString *key = [self createEmulatorKey:bucketUrl appName:firebaseApp.name];
492
+
493
+ if (!emulatorConfigs[key]) {
494
+ [[FIRStorage storageForApp:firebaseApp URL:bucketUrl] useEmulatorWithHost:host
495
+ port:(NSInteger)port];
496
+ emulatorConfigs[key] = @YES;
497
+ }
498
+ }
499
+
500
+ // setTaskStatus
501
+ + (NSNumber *)setTaskStatus:(NSString *)appName taskId:(double)taskId status:(double)status {
502
+ [self initializeSharedStateOnce];
503
+ NSNumber *taskIdNumber = @(taskId);
504
+ id task = PENDING_TASKS[taskIdNumber];
505
+ if (task == nil) {
506
+ return @NO;
507
+ }
508
+
509
+ FIRStorageTaskSnapshot *snapshot = nil;
510
+ if ([task isKindOfClass:[FIRStorageUploadTask class]]) {
511
+ snapshot = [(FIRStorageUploadTask *)task snapshot];
512
+ } else if ([task isKindOfClass:[FIRStorageDownloadTask class]]) {
513
+ snapshot = [(FIRStorageDownloadTask *)task snapshot];
514
+ } else {
515
+ return @NO;
516
+ }
517
+
518
+ FIRStorageTaskStatus currentStatus = snapshot.status;
519
+
520
+ switch ((NSInteger)status) {
521
+ case 0:
522
+ if (currentStatus != FIRStorageTaskStatusPause &&
523
+ (currentStatus == FIRStorageTaskStatusResume ||
524
+ currentStatus == FIRStorageTaskStatusProgress)) {
525
+ if ([task isKindOfClass:[FIRStorageDownloadTask class]]) {
526
+ [(FIRStorageDownloadTask *)task pause];
527
+ } else {
528
+ [(FIRStorageUploadTask *)task pause];
529
+ }
530
+ return @YES;
531
+ }
532
+ return @NO;
533
+ case 1:
534
+ if (currentStatus == FIRStorageTaskStatusPause) {
535
+ if ([task isKindOfClass:[FIRStorageDownloadTask class]]) {
536
+ [(FIRStorageDownloadTask *)task resume];
537
+ } else {
538
+ [(FIRStorageUploadTask *)task resume];
539
+ }
540
+ return @YES;
541
+ }
542
+ return @NO;
543
+ case 2:
544
+ if (currentStatus != FIRStorageTaskStatusSuccess &&
545
+ currentStatus != FIRStorageTaskStatusFailure &&
546
+ (currentStatus == FIRStorageTaskStatusResume ||
547
+ currentStatus == FIRStorageTaskStatusProgress ||
548
+ currentStatus == FIRStorageTaskStatusPause)) {
549
+ [PENDING_TASKS removeObjectForKey:taskIdNumber];
550
+ if ([task isKindOfClass:[FIRStorageDownloadTask class]]) {
551
+ [(FIRStorageDownloadTask *)task cancel];
552
+ } else {
553
+ [(FIRStorageUploadTask *)task cancel];
554
+ }
555
+ return @YES;
556
+ }
557
+ return @NO;
558
+ default:
559
+ return @NO;
560
+ }
561
+ }
562
+
563
+ // storageConstantsDictionary
564
+ + (NSDictionary *)storageConstantsDictionary {
565
+ NSMutableDictionary *constants = [@{} mutableCopy];
566
+
567
+ if ([[[FIRApp allApps] allKeys] count] > 0) {
568
+ FIRStorage *storageInstance = [FIRStorage storage];
569
+ constants[@"maxDownloadRetryTime"] =
570
+ @((NSInteger)[storageInstance maxDownloadRetryTime] * 1000);
571
+ constants[@"maxOperationRetryTime"] =
572
+ @((NSInteger)[storageInstance maxOperationRetryTime] * 1000);
573
+ constants[@"maxUploadRetryTime"] = @((NSInteger)[storageInstance maxUploadRetryTime] * 1000);
574
+ } else {
575
+ constants[@"maxDownloadRetryTime"] = @0;
576
+ constants[@"maxOperationRetryTime"] = @0;
577
+ constants[@"maxUploadRetryTime"] = @0;
578
+ }
579
+
580
+ return constants;
581
+ }
582
+
583
+ #pragma mark -
584
+ #pragma mark Firebase Storage Internals
585
+
586
+ // createEmulatorKey
587
+ + (NSString *)createEmulatorKey:(NSString *)bucketUrl appName:(NSString *)appName {
588
+ return [NSString stringWithFormat:@"%@-%@", appName, bucketUrl];
589
+ }
590
+
591
+ // addUploadTaskObservers
592
+ + (void)addUploadTaskObservers:(FIRStorageUploadTask *)uploadTask
593
+ appDisplayName:(NSString *)appDisplayName
594
+ taskId:(NSNumber *)taskId
595
+ resolver:(RCTPromiseResolveBlock)resolve
596
+ rejecter:(RCTPromiseRejectBlock)reject {
597
+ [self initializeSharedStateOnce];
598
+ PENDING_TASKS[taskId] = uploadTask;
599
+
600
+ [uploadTask
601
+ observeStatus:FIRStorageTaskStatusResume
602
+ handler:^(FIRStorageTaskSnapshot *snapshot) {
603
+ NSDictionary *eventBody = [RNFBStorageCommon getUploadTaskAsDictionary:snapshot];
604
+ NSDictionary *event =
605
+ [RNFBStorageCommon getStorageEventDictionary:eventBody
606
+ internalEventName:RNFB_STORAGE_STATE_CHANGED
607
+ appName:appDisplayName
608
+ taskId:taskId];
609
+ [[RNFBRCTEventEmitter shared] sendEventWithName:RNFB_STORAGE_EVENT body:event];
610
+ }];
611
+
612
+ [uploadTask
613
+ observeStatus:FIRStorageTaskStatusPause
614
+ handler:^(FIRStorageTaskSnapshot *snapshot) {
615
+ NSDictionary *eventBody = [RNFBStorageCommon getUploadTaskAsDictionary:snapshot];
616
+ NSDictionary *event =
617
+ [RNFBStorageCommon getStorageEventDictionary:eventBody
618
+ internalEventName:RNFB_STORAGE_STATE_CHANGED
619
+ appName:appDisplayName
620
+ taskId:taskId];
621
+ [[RNFBRCTEventEmitter shared] sendEventWithName:RNFB_STORAGE_EVENT body:event];
622
+ }];
623
+
624
+ [uploadTask
625
+ observeStatus:FIRStorageTaskStatusProgress
626
+ handler:^(FIRStorageTaskSnapshot *snapshot) {
627
+ NSDictionary *eventBody = [RNFBStorageCommon getUploadTaskAsDictionary:snapshot];
628
+ NSDictionary *event =
629
+ [RNFBStorageCommon getStorageEventDictionary:eventBody
630
+ internalEventName:RNFB_STORAGE_STATE_CHANGED
631
+ appName:appDisplayName
632
+ taskId:taskId];
633
+ [[RNFBRCTEventEmitter shared] sendEventWithName:RNFB_STORAGE_EVENT body:event];
634
+ }];
635
+
636
+ [uploadTask observeStatus:FIRStorageTaskStatusSuccess
637
+ handler:^(FIRStorageTaskSnapshot *snapshot) {
638
+ [PENDING_TASKS removeObjectForKey:taskId];
639
+
640
+ NSDictionary *eventBody =
641
+ [RNFBStorageCommon getUploadTaskAsDictionary:snapshot];
642
+
643
+ NSDictionary *stateChangeEvent =
644
+ [RNFBStorageCommon getStorageEventDictionary:eventBody
645
+ internalEventName:RNFB_STORAGE_STATE_CHANGED
646
+ appName:appDisplayName
647
+ taskId:taskId];
648
+ [[RNFBRCTEventEmitter shared] sendEventWithName:RNFB_STORAGE_EVENT
649
+ body:stateChangeEvent];
650
+
651
+ NSDictionary *uploadSuccessEvent =
652
+ [RNFBStorageCommon getStorageEventDictionary:eventBody
653
+ internalEventName:RNFB_STORAGE_UPLOAD_SUCCESS
654
+ appName:appDisplayName
655
+ taskId:taskId];
656
+ [[RNFBRCTEventEmitter shared] sendEventWithName:RNFB_STORAGE_EVENT
657
+ body:uploadSuccessEvent];
658
+ resolve(eventBody);
659
+ }];
660
+
661
+ [uploadTask
662
+ observeStatus:FIRStorageTaskStatusFailure
663
+ handler:^(FIRStorageTaskSnapshot *snapshot) {
664
+ [PENDING_TASKS removeObjectForKey:taskId];
665
+
666
+ NSMutableDictionary *taskSnapshotDict =
667
+ [RNFBStorageCommon getUploadTaskAsDictionary:snapshot];
668
+ NSDictionary *stateChangedEvtBody =
669
+ [RNFBStorageCommon buildErrorSnapshotDict:snapshot.error
670
+ taskSnapshotDict:taskSnapshotDict];
671
+ NSDictionary *stateChangedEvent =
672
+ [RNFBStorageCommon getStorageEventDictionary:stateChangedEvtBody
673
+ internalEventName:RNFB_STORAGE_STATE_CHANGED
674
+ appName:appDisplayName
675
+ taskId:taskId];
676
+ [[RNFBRCTEventEmitter shared] sendEventWithName:RNFB_STORAGE_EVENT
677
+ body:stateChangedEvent];
678
+
679
+ NSDictionary *eventBody = [RNFBStorageCommon buildErrorSnapshotDict:snapshot.error
680
+ taskSnapshotDict:taskSnapshotDict];
681
+ NSDictionary *event =
682
+ [RNFBStorageCommon getStorageEventDictionary:eventBody
683
+ internalEventName:RNFB_STORAGE_UPLOAD_FAILURE
684
+ appName:appDisplayName
685
+ taskId:taskId];
686
+ [[RNFBRCTEventEmitter shared] sendEventWithName:RNFB_STORAGE_EVENT body:event];
687
+
688
+ [self promiseRejectStorageException:reject error:snapshot.error];
689
+ }];
690
+ }
691
+
692
+ // getReferenceFromUrl
693
+ + (FIRStorageReference *)getReferenceFromUrl:(NSString *)url app:(FIRApp *)firebaseApp {
694
+ [self initializeSharedStateOnce];
695
+ FIRStorage *storage;
696
+ NSString *pathWithBucketName = [url substringWithRange:NSMakeRange(5, [url length] - 5)];
697
+ NSString *bucket = url;
698
+ NSRange rangeOfSlash = [pathWithBucketName rangeOfString:@"/"];
699
+ if (rangeOfSlash.location != NSNotFound) {
700
+ bucket = [url substringWithRange:NSMakeRange(0, rangeOfSlash.location + 5)];
701
+ }
702
+ storage = [FIRStorage storageForApp:firebaseApp URL:bucket];
703
+
704
+ NSString *key = [self createEmulatorKey:bucket appName:firebaseApp.name];
705
+ if (![emulatorHost isEqual:[NSNull null]] && emulatorHost != nil && !emulatorConfigs[key]) {
706
+ @try {
707
+ [storage useEmulatorWithHost:emulatorHost port:emulatorPort];
708
+ emulatorConfigs[key] = @YES;
709
+ } @catch (NSException *e) {
710
+ NSLog(@"WARNING: Unable to set the Firebase Storage emulator settings. These must be set "
711
+ @"before any usages of Firebase Storage. If you see this log after a hot "
712
+ @"reload/restart you can safely ignore it.");
713
+ }
714
+ }
715
+ return [storage referenceForURL:url];
716
+ }
717
+
718
+ // promiseRejectStorageException
719
+ + (void)promiseRejectStorageException:(RCTPromiseRejectBlock)reject error:(NSError *)error {
720
+ NSArray *codeAndMessage = [RNFBStorageCommon getErrorCodeMessage:error];
721
+ [RNFBSharedUtils rejectPromiseWithUserInfo:reject
722
+ userInfo:(NSMutableDictionary *)@{
723
+ @"code" : (NSString *)codeAndMessage[0],
724
+ @"message" : (NSString *)codeAndMessage[1],
725
+ }];
726
+ }
727
+
728
+ @end