|
17 | 17 |
|
18 | 18 | import { getApp } from '@react-native-firebase/app'; |
19 | 19 | import { MODULAR_DEPRECATION_ARG } from '@react-native-firebase/app/dist/module/common'; |
| 20 | +import { NativeFirebaseError } from '@react-native-firebase/app/dist/module/internal'; |
20 | 21 | import type { FirebaseApp } from '@react-native-firebase/app'; |
21 | 22 | import type { |
22 | 23 | FirebaseStorage, |
23 | 24 | StorageReference, |
24 | 25 | FullMetadata, |
25 | 26 | ListResult, |
26 | 27 | ListOptions, |
27 | | - TaskResult, |
28 | 28 | Task, |
29 | 29 | SettableMetadata, |
30 | 30 | UploadMetadata, |
31 | 31 | EmulatorMockTokenOptions, |
| 32 | + UploadResult, |
32 | 33 | } from './types/storage'; |
33 | 34 | import { TaskEvent, TaskState } from './types/storage'; |
34 | 35 | import type { StorageReferenceInternal, StorageInternal } from './types/internal'; |
@@ -269,43 +270,67 @@ export function updateMetadata( |
269 | 270 |
|
270 | 271 | /** |
271 | 272 | * Uploads data to this object's location. The upload is not resumable. If the upload is canceled, |
272 | | - * the Promise will reject with the TaskSnapshot. If there is an error it will reject with the StorageError |
| 273 | + * the Promise rejects with a {@link NativeFirebaseError} (typically `storage/cancelled`), |
| 274 | + * matching other storage upload tasks. Other failures reject with the same error type as {@link uploadBytesResumable}. |
273 | 275 | * @param storageRef - Storage `Reference` instance. |
274 | 276 | * @param data - The data (Blob | Uint8Array | ArrayBuffer) to upload to the storage bucket at the reference location. |
275 | 277 | * @param metadata - A Storage `UploadMetadata` instance to update. Optional. |
276 | | - * @returns {Promise<TaskResult>} |
| 278 | + * @returns {Promise<UploadResult>} |
277 | 279 | */ |
278 | 280 | export async function uploadBytes( |
279 | 281 | storageRef: StorageReference, |
280 | 282 | data: Blob | Uint8Array | ArrayBuffer, |
281 | 283 | metadata?: UploadMetadata, |
282 | | -): Promise<TaskResult> { |
| 284 | +): Promise<UploadResult> { |
283 | 285 | const task = uploadBytesResumable(storageRef, data, metadata); |
284 | 286 | return new Promise((resolve, reject) => { |
285 | | - task.on( |
| 287 | + let completed = false; |
| 288 | + const subscription: { unsubscribe?: () => void } = {}; |
| 289 | + |
| 290 | + const settle = (fn: () => void) => { |
| 291 | + if (completed) { |
| 292 | + return; |
| 293 | + } |
| 294 | + completed = true; |
| 295 | + subscription.unsubscribe?.(); |
| 296 | + fn(); |
| 297 | + }; |
| 298 | + |
| 299 | + subscription.unsubscribe = task.on( |
286 | 300 | TaskEvent.STATE_CHANGED, |
287 | 301 | taskSnapshot => { |
288 | 302 | switch (taskSnapshot.state) { |
289 | 303 | case TaskState.RUNNING: |
290 | 304 | break; |
291 | 305 | case TaskState.PAUSED: |
| 306 | + // we are wrapping the resumable version, just resume if it pauses |
292 | 307 | task.resume(); |
293 | 308 | break; |
294 | 309 | case TaskState.SUCCESS: |
295 | | - resolve({ ref: taskSnapshot.ref, metadata: taskSnapshot.metadata }); |
| 310 | + settle(() => resolve({ ref: taskSnapshot.ref, metadata: taskSnapshot.metadata })); |
296 | 311 | break; |
297 | 312 | case TaskState.CANCELED: |
298 | | - // The TaskSnapshot may be useful to have if we reject due to cancel |
299 | | - reject(taskSnapshot); |
| 313 | + settle(() => |
| 314 | + reject( |
| 315 | + NativeFirebaseError.fromEvent( |
| 316 | + { code: 'cancelled', message: 'User cancelled the operation.' }, |
| 317 | + 'storage', |
| 318 | + ), |
| 319 | + ), |
| 320 | + ); |
300 | 321 | break; |
301 | 322 | case TaskState.ERROR: |
302 | | - // this will be handled in the dedicated error listener |
| 323 | + // this is handled in the dedicated error listener below |
303 | 324 | break; |
304 | 325 | default: |
305 | | - throw new Error(`Unhandled task state in uploadBytes: ${taskSnapshot.state}`); |
| 326 | + settle(() => |
| 327 | + reject(new Error(`Unhandled task state in uploadBytes: ${taskSnapshot.state}`)), |
| 328 | + ); |
306 | 329 | } |
307 | 330 | }, |
308 | | - error => reject(error), |
| 331 | + error => { |
| 332 | + settle(() => reject(error)); |
| 333 | + }, |
309 | 334 | ); |
310 | 335 | }); |
311 | 336 | } |
|
0 commit comments