@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.
- package/CHANGELOG.md +6 -0
- package/RNFBStorage.podspec +9 -1
- package/dist/module/version.js +1 -1
- package/dist/typescript/lib/index.d.ts +1 -1
- package/dist/typescript/lib/version.d.ts +1 -1
- package/ios/RNFBStorage/RNFBStorageCommon.m +11 -0
- package/ios/RNFBStorage/RNFBStorageHelper.h +113 -0
- package/ios/RNFBStorage/RNFBStorageHelper.m +728 -0
- package/ios/RNFBStorage/RNFBStorageModule.mm +62 -596
- package/lib/version.ts +1 -1
- package/package.json +4 -4
|
@@ -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
|