216 lines
5.4 KiB
JavaScript
216 lines
5.4 KiB
JavaScript
/**
|
|
* @flow
|
|
* UploadTask representation wrapper
|
|
*/
|
|
import { statics as StorageStatics } from './';
|
|
import { isFunction } from './../../utils';
|
|
import type Storage from './';
|
|
import type StorageReference from './reference';
|
|
|
|
export const UPLOAD_TASK = 'upload';
|
|
export const DOWNLOAD_TASK = 'download';
|
|
|
|
declare type UploadTaskSnapshotType = {
|
|
bytesTransferred: number,
|
|
downloadURL: string | null,
|
|
metadata: Object, // TODO flow type def for https://firebase.google.com/docs/reference/js/firebase.storage.FullMetadata.html
|
|
ref: StorageReference,
|
|
state:
|
|
| typeof StorageStatics.TaskState.RUNNING
|
|
| typeof StorageStatics.TaskState.PAUSED
|
|
| typeof StorageStatics.TaskState.SUCCESS
|
|
| typeof StorageStatics.TaskState.CANCELLED
|
|
| typeof StorageStatics.TaskState.ERROR,
|
|
task: StorageTask,
|
|
totalBytes: number,
|
|
};
|
|
|
|
declare type FuncSnapshotType =
|
|
| null
|
|
| ((snapshot: UploadTaskSnapshotType) => any);
|
|
|
|
declare type FuncErrorType = null | ((error: Error) => any);
|
|
|
|
declare type NextOrObserverType =
|
|
| null
|
|
| {
|
|
next?: FuncSnapshotType,
|
|
error?: FuncErrorType,
|
|
complete?: FuncSnapshotType,
|
|
}
|
|
| FuncSnapshotType;
|
|
|
|
/**
|
|
* @url https://firebase.google.com/docs/reference/js/firebase.storage.UploadTask
|
|
*/
|
|
export default class StorageTask {
|
|
type: typeof UPLOAD_TASK | typeof DOWNLOAD_TASK;
|
|
ref: StorageReference;
|
|
storage: Storage;
|
|
path: string;
|
|
then: () => Promise<*>;
|
|
catch: () => Promise<*>;
|
|
|
|
constructor(
|
|
type: typeof UPLOAD_TASK | typeof DOWNLOAD_TASK,
|
|
promise: Promise<*>,
|
|
storageRef: StorageReference
|
|
) {
|
|
this.type = type;
|
|
this.ref = storageRef;
|
|
this.storage = storageRef._storage;
|
|
this.path = storageRef.path;
|
|
|
|
// 'proxy' original promise
|
|
this.then = promise.then.bind(promise);
|
|
this.catch = promise.catch.bind(promise);
|
|
}
|
|
|
|
/**
|
|
* Intercepts a native snapshot result object attaches ref / task instances
|
|
* and calls the original function
|
|
* @returns {Promise.<T>}
|
|
* @private
|
|
*/
|
|
_interceptSnapshotEvent(f: ?Function): null | (() => *) {
|
|
if (!isFunction(f)) return null;
|
|
return snapshot => {
|
|
const _snapshot = Object.assign({}, snapshot);
|
|
_snapshot.task = this;
|
|
_snapshot.ref = this.ref;
|
|
return f && f(_snapshot);
|
|
};
|
|
}
|
|
|
|
/**
|
|
* Intercepts a error object form native and converts to a JS Error
|
|
* @param f
|
|
* @returns {*}
|
|
* @private
|
|
*/
|
|
_interceptErrorEvent(f: ?Function): null | (Error => *) {
|
|
if (!isFunction(f)) return null;
|
|
return error => {
|
|
const _error = new Error(error.message);
|
|
// $FlowFixMe
|
|
_error.code = error.code;
|
|
return f && f(_error);
|
|
};
|
|
}
|
|
|
|
/**
|
|
*
|
|
* @param nextOrObserver
|
|
* @param error
|
|
* @param complete
|
|
* @returns {function()}
|
|
* @private
|
|
*/
|
|
_subscribe(
|
|
nextOrObserver: NextOrObserverType,
|
|
error: FuncErrorType,
|
|
complete: FuncSnapshotType
|
|
): Function {
|
|
let _error;
|
|
let _next;
|
|
let _complete;
|
|
|
|
if (typeof nextOrObserver === 'function') {
|
|
_error = this._interceptErrorEvent(error);
|
|
_next = this._interceptSnapshotEvent(nextOrObserver);
|
|
_complete = this._interceptSnapshotEvent(complete);
|
|
} else if (nextOrObserver) {
|
|
_error = this._interceptErrorEvent(nextOrObserver.error);
|
|
_next = this._interceptSnapshotEvent(nextOrObserver.next);
|
|
_complete = this._interceptSnapshotEvent(nextOrObserver.complete);
|
|
}
|
|
|
|
if (_next) {
|
|
this.storage._addListener(
|
|
this.path,
|
|
StorageStatics.TaskEvent.STATE_CHANGED,
|
|
_next
|
|
);
|
|
}
|
|
if (_error) {
|
|
this.storage._addListener(this.path, `${this.type}_failure`, _error);
|
|
}
|
|
if (_complete) {
|
|
this.storage._addListener(this.path, `${this.type}_success`, _complete);
|
|
}
|
|
|
|
return () => {
|
|
if (_next)
|
|
this.storage._removeListener(
|
|
this.path,
|
|
StorageStatics.TaskEvent.STATE_CHANGED,
|
|
_next
|
|
);
|
|
if (_error)
|
|
this.storage._removeListener(this.path, `${this.type}_failure`, _error);
|
|
if (_complete)
|
|
this.storage._removeListener(
|
|
this.path,
|
|
`${this.type}_success`,
|
|
_complete
|
|
);
|
|
};
|
|
}
|
|
|
|
/**
|
|
*
|
|
* @param event
|
|
* @param nextOrObserver
|
|
* @param error
|
|
* @param complete
|
|
* @returns {function()}
|
|
*/
|
|
on(
|
|
event: string = StorageStatics.TaskEvent.STATE_CHANGED,
|
|
nextOrObserver: NextOrObserverType,
|
|
error: FuncErrorType,
|
|
complete: FuncSnapshotType
|
|
): Function {
|
|
if (!event) {
|
|
throw new Error(
|
|
"StorageTask.on listener is missing required string argument 'event'."
|
|
);
|
|
}
|
|
|
|
if (event !== StorageStatics.TaskEvent.STATE_CHANGED) {
|
|
throw new Error(
|
|
`StorageTask.on event argument must be a string with a value of '${
|
|
StorageStatics.TaskEvent.STATE_CHANGED
|
|
}'`
|
|
);
|
|
}
|
|
|
|
// if only event provided return the subscriber function
|
|
if (!nextOrObserver && !error && !complete) {
|
|
return this._subscribe.bind(this);
|
|
}
|
|
|
|
return this._subscribe(nextOrObserver, error, complete);
|
|
}
|
|
|
|
pause() {
|
|
throw new Error(
|
|
'.pause() is not currently supported by react-native-firebase'
|
|
);
|
|
}
|
|
|
|
resume() {
|
|
// todo
|
|
throw new Error(
|
|
'.resume() is not currently supported by react-native-firebase'
|
|
);
|
|
}
|
|
|
|
cancel() {
|
|
// todo
|
|
throw new Error(
|
|
'.cancel() is not currently supported by react-native-firebase'
|
|
);
|
|
}
|
|
}
|