[both] continued work on multi app support - storage now full supported and auth WIP

This commit is contained in:
Salakar 2017-07-12 15:49:33 +01:00
parent 82a2afd59b
commit 282f953f52
18 changed files with 280 additions and 194 deletions

View File

@ -29,14 +29,15 @@ import com.google.android.gms.tasks.Task;
import com.google.android.gms.tasks.OnFailureListener;
import com.google.android.gms.tasks.OnSuccessListener;
import com.google.firebase.storage.StorageException;
import com.google.firebase.storage.StorageTask;
import com.google.firebase.storage.StreamDownloadTask;
import com.google.firebase.FirebaseApp;
import com.google.firebase.storage.UploadTask;
import com.google.firebase.storage.StorageTask;
import com.google.firebase.storage.FirebaseStorage;
import com.google.firebase.storage.StorageMetadata;
import com.google.firebase.storage.StorageException;
import com.google.firebase.storage.StorageReference;
import com.google.firebase.storage.OnPausedListener;
import com.google.firebase.storage.StreamDownloadTask;
import com.google.firebase.storage.OnProgressListener;
import io.invertase.firebase.Utils;
@ -109,8 +110,8 @@ public class RNFirebaseStorage extends ReactContextBaseJavaModule {
* @url https://firebase.google.com/docs/reference/js/firebase.storage.Reference#delete
*/
@ReactMethod
public void delete(final String path, final Promise promise) {
StorageReference reference = this.getReference(path);
public void delete(String appName, final String path, final Promise promise) {
StorageReference reference = this.getReference(path, appName);
reference.delete().addOnSuccessListener(new OnSuccessListener<Void>() {
@Override
public void onSuccess(Void aVoid) {
@ -132,9 +133,9 @@ public class RNFirebaseStorage extends ReactContextBaseJavaModule {
* @url https://firebase.google.com/docs/reference/js/firebase.storage.Reference#getDownloadURL
*/
@ReactMethod
public void getDownloadURL(final String path, final Promise promise) {
public void getDownloadURL(String appName, final String path, final Promise promise) {
Log.d(TAG, "getDownloadURL path " + path);
final StorageReference reference = this.getReference(path);
final StorageReference reference = this.getReference(path, appName);
Task<Uri> downloadTask = reference.getDownloadUrl();
downloadTask
@ -160,8 +161,8 @@ public class RNFirebaseStorage extends ReactContextBaseJavaModule {
* @url https://firebase.google.com/docs/reference/js/firebase.storage.Reference#getMetadata
*/
@ReactMethod
public void getMetadata(final String path, final Promise promise) {
StorageReference reference = this.getReference(path);
public void getMetadata(String appName, final String path, final Promise promise) {
StorageReference reference = this.getReference(path, appName);
reference.getMetadata().addOnSuccessListener(new OnSuccessListener<StorageMetadata>() {
@Override
public void onSuccess(StorageMetadata storageMetadata) {
@ -184,8 +185,8 @@ public class RNFirebaseStorage extends ReactContextBaseJavaModule {
* @url https://firebase.google.com/docs/reference/js/firebase.storage.Reference#updateMetadata
*/
@ReactMethod
public void updateMetadata(final String path, final ReadableMap metadata, final Promise promise) {
StorageReference reference = this.getReference(path);
public void updateMetadata(String appName, final String path, final ReadableMap metadata, final Promise promise) {
StorageReference reference = this.getReference(path, appName);
StorageMetadata md = buildMetadataFromMap(metadata);
reference.updateMetadata(md).addOnSuccessListener(new OnSuccessListener<StorageMetadata>() {
@ -212,7 +213,7 @@ public class RNFirebaseStorage extends ReactContextBaseJavaModule {
* @url https://firebase.google.com/docs/reference/js/firebase.storage.Reference#downloadFile
*/
@ReactMethod
public void downloadFile(final String path, final String localPath, final Promise promise) {
public void downloadFile(final String appName, final String path, final String localPath, final Promise promise) {
if (!isExternalStorageWritable()) {
promise.reject(
"storage/invalid-device-file-path",
@ -223,7 +224,7 @@ public class RNFirebaseStorage extends ReactContextBaseJavaModule {
}
Log.d(TAG, "downloadFile path: " + path);
StorageReference reference = this.getReference(path);
StorageReference reference = this.getReference(path, appName);
reference.getStream(new StreamDownloadTask.StreamProcessor() {
@Override
@ -252,21 +253,21 @@ public class RNFirebaseStorage extends ReactContextBaseJavaModule {
public void onProgress(StreamDownloadTask.TaskSnapshot taskSnapshot) {
Log.d(TAG, "downloadFile progress " + taskSnapshot);
WritableMap event = getDownloadTaskAsMap(taskSnapshot);
sendJSEvent(STORAGE_STATE_CHANGED, path, event);
sendJSEvent(appName, STORAGE_STATE_CHANGED, path, event);
}
}).addOnPausedListener(new OnPausedListener<StreamDownloadTask.TaskSnapshot>() {
@Override
public void onPaused(StreamDownloadTask.TaskSnapshot taskSnapshot) {
Log.d(TAG, "downloadFile paused " + taskSnapshot);
WritableMap event = getDownloadTaskAsMap(taskSnapshot);
sendJSEvent(STORAGE_STATE_CHANGED, path, event);
sendJSEvent(appName, STORAGE_STATE_CHANGED, path, event);
}
}).addOnSuccessListener(new OnSuccessListener<StreamDownloadTask.TaskSnapshot>() {
@Override
public void onSuccess(StreamDownloadTask.TaskSnapshot taskSnapshot) {
Log.d(TAG, "downloadFile success" + taskSnapshot);
WritableMap resp = getDownloadTaskAsMap(taskSnapshot);
sendJSEvent(STORAGE_DOWNLOAD_SUCCESS, path, resp);
sendJSEvent(appName, STORAGE_DOWNLOAD_SUCCESS, path, resp);
resp = getDownloadTaskAsMap(taskSnapshot);
promise.resolve(resp);
}
@ -287,8 +288,11 @@ public class RNFirebaseStorage extends ReactContextBaseJavaModule {
* @url https://firebase.google.com/docs/reference/js/firebase.storage.Storage#setMaxDownloadRetryTime
*/
@ReactMethod
public void setMaxDownloadRetryTime(final double milliseconds) {
FirebaseStorage.getInstance().setMaxDownloadRetryTimeMillis((long) milliseconds);
public void setMaxDownloadRetryTime(String appName, final double milliseconds) {
FirebaseApp firebaseApp = FirebaseApp.getInstance(appName);
FirebaseStorage firebaseStorage = FirebaseStorage.getInstance(firebaseApp);
firebaseStorage.setMaxDownloadRetryTimeMillis((long) milliseconds);
}
/**
@ -298,8 +302,11 @@ public class RNFirebaseStorage extends ReactContextBaseJavaModule {
* @url https://firebase.google.com/docs/reference/js/firebase.storage.Storage#setMaxOperationRetryTime
*/
@ReactMethod
public void setMaxOperationRetryTime(final double milliseconds) {
FirebaseStorage.getInstance().setMaxOperationRetryTimeMillis((long) milliseconds);
public void setMaxOperationRetryTime(String appName, final double milliseconds) {
FirebaseApp firebaseApp = FirebaseApp.getInstance(appName);
FirebaseStorage firebaseStorage = FirebaseStorage.getInstance(firebaseApp);
firebaseStorage.setMaxOperationRetryTimeMillis((long) milliseconds);
}
/**
@ -309,8 +316,11 @@ public class RNFirebaseStorage extends ReactContextBaseJavaModule {
* @url https://firebase.google.com/docs/reference/js/firebase.storage.Storage#setMaxUploadRetryTime
*/
@ReactMethod
public void setMaxUploadRetryTime(final double milliseconds) {
FirebaseStorage.getInstance().setMaxUploadRetryTimeMillis((long) milliseconds);
public void setMaxUploadRetryTime(String appName, final double milliseconds) {
FirebaseApp firebaseApp = FirebaseApp.getInstance(appName);
FirebaseStorage firebaseStorage = FirebaseStorage.getInstance(firebaseApp);
firebaseStorage.setMaxUploadRetryTimeMillis((long) milliseconds);
}
/**
@ -323,8 +333,8 @@ public class RNFirebaseStorage extends ReactContextBaseJavaModule {
* @url https://firebase.google.com/docs/reference/js/firebase.storage.Reference#putFile
*/
@ReactMethod
public void putFile(final String path, final String localPath, final ReadableMap metadata, final Promise promise) {
StorageReference reference = this.getReference(path);
public void putFile(final String appName, final String path, final String localPath, final ReadableMap metadata, final Promise promise) {
StorageReference reference = this.getReference(path, appName);
Log.i(TAG, "putFile: " + localPath + " to " + path);
@ -356,11 +366,11 @@ public class RNFirebaseStorage extends ReactContextBaseJavaModule {
public void onSuccess(UploadTask.TaskSnapshot taskSnapshot) {
Log.d(TAG, "putFile success " + taskSnapshot);
WritableMap resp = getUploadTaskAsMap(taskSnapshot);
sendJSEvent(STORAGE_STATE_CHANGED, path, resp);
sendJSEvent(appName, STORAGE_STATE_CHANGED, path, resp);
// to avoid readable map already consumed errors
resp = getUploadTaskAsMap(taskSnapshot);
sendJSEvent(STORAGE_UPLOAD_SUCCESS, path, resp);
sendJSEvent(appName, STORAGE_UPLOAD_SUCCESS, path, resp);
resp = getUploadTaskAsMap(taskSnapshot);
promise.resolve(resp);
@ -370,7 +380,7 @@ public class RNFirebaseStorage extends ReactContextBaseJavaModule {
@Override
public void onProgress(UploadTask.TaskSnapshot taskSnapshot) {
Log.d(TAG, "putFile progress " + taskSnapshot);
sendJSEvent(STORAGE_STATE_CHANGED, path, getUploadTaskAsMap(taskSnapshot));
sendJSEvent(appName, STORAGE_STATE_CHANGED, path, getUploadTaskAsMap(taskSnapshot));
}
})
.addOnPausedListener(new OnPausedListener<UploadTask.TaskSnapshot>() {
@ -378,7 +388,7 @@ public class RNFirebaseStorage extends ReactContextBaseJavaModule {
public void onPaused(UploadTask.TaskSnapshot taskSnapshot) {
Log.d(TAG, "putFile paused " + taskSnapshot);
WritableMap event = getUploadTaskAsMap(taskSnapshot);
sendJSEvent(STORAGE_STATE_CHANGED, path, event);
sendJSEvent(appName, STORAGE_STATE_CHANGED, path, event);
}
});
} catch (Exception exception) {
@ -388,20 +398,25 @@ public class RNFirebaseStorage extends ReactContextBaseJavaModule {
/**
* Internal helper to detect if ref is from url or a path.
*
* @param path
* @return
*/
private StorageReference getReference(String path) {
private StorageReference getReference(String path, String appName) {
FirebaseApp firebaseApp = FirebaseApp.getInstance(appName);
FirebaseStorage firebaseStorage = FirebaseStorage.getInstance(firebaseApp);
if (path.startsWith("url::")) {
String url = path.substring(5);
return FirebaseStorage.getInstance().getReferenceFromUrl(url);
return firebaseStorage.getReferenceFromUrl(url);
} else {
return FirebaseStorage.getInstance().getReference(path);
return firebaseStorage.getReference(path);
}
}
/**
* Internal helper to convert content:// uri's to a real path
*
* @param uri
* @return
*/
@ -477,8 +492,8 @@ public class RNFirebaseStorage extends ReactContextBaseJavaModule {
* @return
*/
private WritableMap getUploadTaskAsMap(UploadTask.TaskSnapshot taskSnapshot) {
WritableMap resp = Arguments.createMap();
if (taskSnapshot != null) {
resp.putDouble("bytesTransferred", taskSnapshot.getBytesTransferred());
resp.putString("downloadUrl", taskSnapshot.getDownloadUrl() != null ? taskSnapshot.getDownloadUrl().toString() : null);
@ -566,9 +581,10 @@ public class RNFirebaseStorage extends ReactContextBaseJavaModule {
* @param path
* @param body
*/
private void sendJSEvent(final String name, final String path, WritableMap body) {
private void sendJSEvent(String appName, final String name, final String path, WritableMap body) {
WritableMap event = Arguments.createMap();
event.putString("appName", appName);
event.putString("eventName", name);
event.putString("path", path);
event.putMap("body", body);

View File

@ -3,7 +3,7 @@
#import <React/RCTBridgeModule.h>
@interface RNFirebaseConfig : NSObject <RCTBridgeModule>
@interface RNFirebaseRemoteConfig : NSObject <RCTBridgeModule>
@end

View File

@ -1,4 +1,4 @@
#import "RNFirebaseConfig.h"
#import "RNFirebaseRemoteConfig.h"
#if __has_include(<FirebaseRemoteConfig/FirebaseRemoteConfig.h>)
@ -33,15 +33,15 @@ NSDictionary *convertFIRRemoteConfigValueToNSDictionary(FIRRemoteConfigValue *va
return @{@"stringValue": value.stringValue ?: [NSNull null], @"numberValue": value.numberValue ?: [NSNull null], @"dataValue": value.dataValue ? [value.dataValue base64EncodedStringWithOptions:0] : [NSNull null], @"boolValue": @(value.boolValue), @"source": convertFIRRemoteConfigSourceToNSString(value.source)};
}
@interface RNFirebaseConfig ()
@interface RNFirebaseRemoteConfig ()
@property(nonatomic, readwrite, weak) FIRRemoteConfig *remoteConfig;
@end
@implementation RNFirebaseConfig
@implementation RNFirebaseRemoteConfig
RCT_EXPORT_MODULE(RNFirebaseConfig);
RCT_EXPORT_MODULE(RNFirebaseRemoteConfig);
RCT_EXPORT_METHOD(enableDeveloperMode) {
FIRRemoteConfigSettings *remoteConfigSettings = [[FIRRemoteConfigSettings alloc] initWithDeveloperModeEnabled:YES];

View File

@ -1,6 +1,7 @@
#import "RNFirebaseStorage.h"
#if __has_include(<FirebaseStorage/FIRStorage.h>)
#import "RNFirebaseEvents.h"
#import <Photos/Photos.h>
#import "Firebase.h"
@ -20,7 +21,7 @@ RCT_EXPORT_MODULE(RNFirebaseStorage);
@param reject RCTPromiseRejectBlock
@param error NSError
*/
- (void) promiseRejectStorageException:(RCTPromiseRejectBlock) reject error:(NSError *)error {
- (void)promiseRejectStorageException:(RCTPromiseRejectBlock)reject error:(NSError *)error {
NSString *code = @"storage/unknown";
NSString *message = [error localizedDescription];
@ -97,12 +98,17 @@ RCT_EXPORT_MODULE(RNFirebaseStorage);
@url https://firebase.google.com/docs/reference/js/firebase.storage.Reference#delete
@param NSString path
*/
RCT_EXPORT_METHOD(delete: (NSString *) path resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject) {
RCT_EXPORT_METHOD(delete:
(NSString *) path
resolver:
(RCTPromiseResolveBlock) resolve
rejecter:
(RCTPromiseRejectBlock) reject) {
FIRStorageReference *fileRef = [self getReference:path];
[fileRef deleteWithCompletion:^(NSError * _Nullable error) {
[fileRef deleteWithCompletion:^(NSError *_Nullable error) {
if (error != nil) {
[self promiseRejectStorageException:reject error: error];
[self promiseRejectStorageException:reject error:error];
} else {
resolve([NSNull null]);
}
@ -115,12 +121,17 @@ RCT_EXPORT_METHOD(delete: (NSString *) path resolver:(RCTPromiseResolveBlock)res
@url https://firebase.google.com/docs/reference/js/firebase.storage.Reference#getDownloadURL
@param NSString path
*/
RCT_EXPORT_METHOD(getDownloadURL: (NSString *) path resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject) {
RCT_EXPORT_METHOD(getDownloadURL:
(NSString *) path
resolver:
(RCTPromiseResolveBlock) resolve
rejecter:
(RCTPromiseRejectBlock) reject) {
FIRStorageReference *fileRef = [self getReference:path];
[fileRef downloadURLWithCompletion:^(NSURL * _Nullable URL, NSError * _Nullable error) {
[fileRef downloadURLWithCompletion:^(NSURL *_Nullable URL, NSError *_Nullable error) {
if (error != nil) {
[self promiseRejectStorageException:reject error: error];
[self promiseRejectStorageException:reject error:error];
} else {
resolve([URL absoluteString]);
}
@ -133,12 +144,17 @@ RCT_EXPORT_METHOD(getDownloadURL: (NSString *) path resolver:(RCTPromiseResolveB
@url https://firebase.google.com/docs/reference/js/firebase.storage.Reference#getMetadata
@param NSString path
*/
RCT_EXPORT_METHOD(getMetadata: (NSString *) path resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject) {
RCT_EXPORT_METHOD(getMetadata:
(NSString *) path
resolver:
(RCTPromiseResolveBlock) resolve
rejecter:
(RCTPromiseRejectBlock) reject) {
FIRStorageReference *fileRef = [self getReference:path];
[fileRef metadataWithCompletion:^(FIRStorageMetadata * _Nullable metadata, NSError * _Nullable error) {
[fileRef metadataWithCompletion:^(FIRStorageMetadata *_Nullable metadata, NSError *_Nullable error) {
if (error != nil) {
[self promiseRejectStorageException:reject error: error];
[self promiseRejectStorageException:reject error:error];
} else {
resolve([metadata dictionaryRepresentation]);
}
@ -152,13 +168,20 @@ RCT_EXPORT_METHOD(getMetadata: (NSString *) path resolver:(RCTPromiseResolveBloc
@param NSString path
@param NSDictionary metadata
*/
RCT_EXPORT_METHOD(updateMetadata: (NSString *) path metadata:(NSDictionary *) metadata resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject) {
RCT_EXPORT_METHOD(updateMetadata:
(NSString *) path
metadata:
(NSDictionary *) metadata
resolver:
(RCTPromiseResolveBlock) resolve
rejecter:
(RCTPromiseRejectBlock) reject) {
FIRStorageReference *fileRef = [self getReference:path];
FIRStorageMetadata *firmetadata = [self buildMetadataFromMap:metadata];
[fileRef updateMetadata:firmetadata completion:^(FIRStorageMetadata * _Nullable metadata, NSError * _Nullable error) {
[fileRef updateMetadata:firmetadata completion:^(FIRStorageMetadata *_Nullable metadata, NSError *_Nullable error) {
if (error != nil) {
[self promiseRejectStorageException:reject error: error];
[self promiseRejectStorageException:reject error:error];
} else {
resolve([metadata dictionaryRepresentation]);
}
@ -172,7 +195,15 @@ RCT_EXPORT_METHOD(updateMetadata: (NSString *) path metadata:(NSDictionary *) me
@param NSString path
@param NSString localPath
*/
RCT_EXPORT_METHOD(downloadFile: (NSString *) path localPath:(NSString *) localPath resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject) {
RCT_EXPORT_METHOD(downloadFile:
(NSString *) appName
path:(NSString *) path
localPath:
(NSString *) localPath
resolver:
(RCTPromiseResolveBlock) resolve
rejecter:
(RCTPromiseRejectBlock) reject) {
FIRStorageReference *fileRef = [self getReference:path];
NSURL *localFile = [NSURL fileURLWithPath:localPath];
FIRStorageDownloadTask *downloadTask = [fileRef writeToFile:localFile];
@ -181,25 +212,25 @@ RCT_EXPORT_METHOD(downloadFile: (NSString *) path localPath:(NSString *) localPa
[downloadTask observeStatus:FIRStorageTaskStatusResume handler:^(FIRStorageTaskSnapshot *snapshot) {
// download resumed, also fires when the upload starts
NSDictionary *event = [self getDownloadTaskAsDictionary:snapshot];
[self sendJSEvent:STORAGE_EVENT path:path title:STORAGE_STATE_CHANGED props:event];
[self sendJSEvent:appName type:STORAGE_EVENT path:path title:STORAGE_STATE_CHANGED props:event];
}];
[downloadTask observeStatus:FIRStorageTaskStatusPause handler:^(FIRStorageTaskSnapshot *snapshot) {
// download paused
NSDictionary *event = [self getDownloadTaskAsDictionary:snapshot];
[self sendJSEvent:STORAGE_EVENT path:path title:STORAGE_STATE_CHANGED props:event];
[self sendJSEvent:appName type:STORAGE_EVENT path:path title:STORAGE_STATE_CHANGED props:event];
}];
[downloadTask observeStatus:FIRStorageTaskStatusProgress handler:^(FIRStorageTaskSnapshot *snapshot) {
// download reported progress
NSDictionary *event = [self getDownloadTaskAsDictionary:snapshot];
[self sendJSEvent:STORAGE_EVENT path:path title:STORAGE_STATE_CHANGED props:event];
[self sendJSEvent:appName type:STORAGE_EVENT path:path title:STORAGE_STATE_CHANGED props:event];
}];
[downloadTask observeStatus:FIRStorageTaskStatusSuccess handler:^(FIRStorageTaskSnapshot *snapshot) {
// download completed successfully
NSDictionary *resp = [self getDownloadTaskAsDictionary:snapshot];
[self sendJSEvent:STORAGE_EVENT path:path title:STORAGE_DOWNLOAD_SUCCESS props:resp];
[self sendJSEvent:appName type:STORAGE_EVENT path:path title:STORAGE_DOWNLOAD_SUCCESS props:resp];
resolve(resp);
}];
@ -218,7 +249,8 @@ RCT_EXPORT_METHOD(downloadFile: (NSString *) path localPath:(NSString *) localPa
@url https://firebase.google.com/docs/reference/js/firebase.storage.Storage#setMaxDownloadRetryTime
@param NSNumber milliseconds
*/
RCT_EXPORT_METHOD(setMaxDownloadRetryTime:(NSNumber *) milliseconds) {
RCT_EXPORT_METHOD(setMaxDownloadRetryTime:
(NSNumber *) milliseconds) {
[[FIRStorage storage] setMaxDownloadRetryTime:[milliseconds doubleValue]];
}
@ -228,7 +260,8 @@ RCT_EXPORT_METHOD(setMaxDownloadRetryTime:(NSNumber *) milliseconds) {
@url https://firebase.google.com/docs/reference/js/firebase.storage.Storage#setMaxOperationRetryTime
@param NSNumber milliseconds
*/
RCT_EXPORT_METHOD(setMaxOperationRetryTime:(NSNumber *) milliseconds) {
RCT_EXPORT_METHOD(setMaxOperationRetryTime:
(NSNumber *) milliseconds) {
[[FIRStorage storage] setMaxOperationRetryTime:[milliseconds doubleValue]];
}
@ -237,7 +270,8 @@ RCT_EXPORT_METHOD(setMaxOperationRetryTime:(NSNumber *) milliseconds) {
@url https://firebase.google.com/docs/reference/js/firebase.storage.Storage#setMaxUploadRetryTime
*/
RCT_EXPORT_METHOD(setMaxUploadRetryTime:(NSNumber *) milliseconds) {
RCT_EXPORT_METHOD(setMaxUploadRetryTime:
(NSNumber *) milliseconds) {
[[FIRStorage storage] setMaxUploadRetryTime:[milliseconds doubleValue]];
}
@ -249,9 +283,19 @@ RCT_EXPORT_METHOD(setMaxUploadRetryTime:(NSNumber *) milliseconds) {
@param NSString localPath
@param NSDictionary metadata
*/
RCT_EXPORT_METHOD(putFile:(NSString *) path localPath:(NSString *)localPath metadata:(NSDictionary *)metadata resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject) {
RCT_EXPORT_METHOD(putFile:
(NSString *) appName
path:(NSString *) path
localPath:
(NSString *) localPath
metadata:
(NSDictionary *) metadata
resolver:
(RCTPromiseResolveBlock) resolve
rejecter:
(RCTPromiseRejectBlock) reject) {
if ([localPath hasPrefix:@"assets-library://"] || [localPath hasPrefix:@"ph://"]) {
PHFetchResult* assets;
PHFetchResult *assets;
if ([localPath hasPrefix:@"assets-library://"]) {
NSURL *localFile = [[NSURL alloc] initWithString:localPath];
@ -268,9 +312,9 @@ RCT_EXPORT_METHOD(putFile:(NSString *) path localPath:(NSString *)localPath meta
// images
PHImageRequestOptions *options = [PHImageRequestOptions new];
options.networkAccessAllowed = true;
[[PHImageManager defaultManager] requestImageDataForAsset:asset options:options resultHandler:^(NSData * imageData, NSString * dataUTI, UIImageOrientation orientation, NSDictionary * info) {
[[PHImageManager defaultManager] requestImageDataForAsset:asset options:options resultHandler:^(NSData *imageData, NSString *dataUTI, UIImageOrientation orientation, NSDictionary *info) {
if (info[PHImageErrorKey] == nil) {
[self uploadData:imageData metadata:metadata path:path resolver:resolve rejecter:reject];
[self uploadData:appName data:imageData metadata:metadata path:path resolver:resolve rejecter:reject];
} else {
reject(@"storage/request-image-data-failed", @"Could not obtain image data for the specified file.", nil);
}
@ -279,7 +323,7 @@ RCT_EXPORT_METHOD(putFile:(NSString *) path localPath:(NSString *)localPath meta
// video
PHVideoRequestOptions *options = [PHVideoRequestOptions new];
options.networkAccessAllowed = true;
[[PHImageManager defaultManager] requestExportSessionForVideo:asset options:options exportPreset:AVAssetExportPresetHighestQuality resultHandler:^(AVAssetExportSession * _Nullable exportSession, NSDictionary * _Nullable info) {
[[PHImageManager defaultManager] requestExportSessionForVideo:asset options:options exportPreset:AVAssetExportPresetHighestQuality resultHandler:^(AVAssetExportSession *_Nullable exportSession, NSDictionary *_Nullable info) {
if (info[PHImageErrorKey] == nil) {
NSURL *tempUrl = [self temporaryFileUrl];
exportSession.outputURL = tempUrl;
@ -292,7 +336,7 @@ RCT_EXPORT_METHOD(putFile:(NSString *) path localPath:(NSString *)localPath meta
[exportSession exportAsynchronouslyWithCompletionHandler:^{
if (exportSession.status == AVAssetExportSessionStatusCompleted) {
[self uploadFile:tempUrl metadata:metadata path:path resolver:resolve rejecter:reject];
[self uploadFile:appName url:tempUrl metadata:metadata path:path resolver:resolve rejecter:reject];
// we're not cleaning up the temporary file at the moment, just relying on the OS to do that in it's own time - todo?
} else {
reject(@"storage/temporary-file-failure", @"Unable to create temporary file for upload.", nil);
@ -305,54 +349,54 @@ RCT_EXPORT_METHOD(putFile:(NSString *) path localPath:(NSString *)localPath meta
}
} else {
NSData *data = [[NSFileManager defaultManager] contentsAtPath:localPath];
[self uploadData:data metadata:metadata path:path resolver:resolve rejecter:reject];
[self uploadData:appName data:data metadata:metadata path:path resolver:resolve rejecter:reject];
}
}
- (NSURL *) temporaryFileUrl {
- (NSURL *)temporaryFileUrl {
NSString *filename = [NSString stringWithFormat:@"%@.tmp", [[NSProcessInfo processInfo] globallyUniqueString]];
return [[NSURL fileURLWithPath:NSTemporaryDirectory()] URLByAppendingPathComponent:filename];
}
- (void) uploadFile:(NSURL *) url metadata:(NSDictionary *) metadata path:(NSString *) path resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject {
- (void)uploadFile:(NSString *) appName url:(NSURL *)url metadata:(NSDictionary *)metadata path:(NSString *)path resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject {
FIRStorageReference *fileRef = [self getReference:path];
FIRStorageMetadata *firmetadata = [self buildMetadataFromMap:metadata];
FIRStorageUploadTask *uploadTask = [fileRef putFile:url metadata:firmetadata];
[self addUploadObservers:uploadTask path:path resolver:resolve rejecter:reject];
[self addUploadObservers:appName uploadTask:uploadTask path:path resolver:resolve rejecter:reject];
}
- (void) uploadData:(NSData *) data metadata:(NSDictionary *) metadata path:(NSString *) path resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject{
- (void)uploadData:(NSString *)appName data:(NSData *)data metadata:(NSDictionary *)metadata path:(NSString *)path resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject {
FIRStorageReference *fileRef = [self getReference:path];
FIRStorageMetadata *firmetadata = [self buildMetadataFromMap:metadata];
FIRStorageUploadTask *uploadTask = [fileRef putData:data metadata:firmetadata];
[self addUploadObservers:uploadTask path:path resolver:resolve rejecter:reject];
[self addUploadObservers:appName uploadTask:uploadTask path:path resolver:resolve rejecter:reject];
}
- (void) addUploadObservers:(FIRStorageUploadTask *) uploadTask path:(NSString *) path resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject{
- (void)addUploadObservers:(NSString *) appName uploadTask:(FIRStorageUploadTask *)uploadTask path:(NSString *)path resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject {
// listen for state changes, errors, and completion of the upload.
[uploadTask observeStatus:FIRStorageTaskStatusResume handler:^(FIRStorageTaskSnapshot *snapshot) {
// upload resumed, also fires when the upload starts
NSDictionary *event = [self getUploadTaskAsDictionary:snapshot];
[self sendJSEvent:STORAGE_EVENT path:path title:STORAGE_STATE_CHANGED props:event];
[self sendJSEvent:appName type:STORAGE_EVENT path:path title:STORAGE_STATE_CHANGED props:event];
}];
[uploadTask observeStatus:FIRStorageTaskStatusPause handler:^(FIRStorageTaskSnapshot *snapshot) {
// upload paused
NSDictionary *event = [self getUploadTaskAsDictionary:snapshot];
[self sendJSEvent:STORAGE_EVENT path:path title:STORAGE_STATE_CHANGED props:event];
[self sendJSEvent:appName type:STORAGE_EVENT path:path title:STORAGE_STATE_CHANGED props:event];
}];
[uploadTask observeStatus:FIRStorageTaskStatusProgress handler:^(FIRStorageTaskSnapshot *snapshot) {
// upload reported progress
NSDictionary *event = [self getUploadTaskAsDictionary:snapshot];
[self sendJSEvent:STORAGE_EVENT path:path title:STORAGE_STATE_CHANGED props:event];
[self sendJSEvent:appName type:STORAGE_EVENT path:path title:STORAGE_STATE_CHANGED props:event];
}];
[uploadTask observeStatus:FIRStorageTaskStatusSuccess handler:^(FIRStorageTaskSnapshot *snapshot) {
// upload completed successfully
NSDictionary *resp = [self getUploadTaskAsDictionary:snapshot];
[self sendJSEvent:STORAGE_EVENT path:path title:STORAGE_STATE_CHANGED props:resp];
[self sendJSEvent:STORAGE_EVENT path:path title:STORAGE_UPLOAD_SUCCESS props:resp];
[self sendJSEvent:appName type:STORAGE_EVENT path:path title:STORAGE_STATE_CHANGED props:resp];
[self sendJSEvent:appName type:STORAGE_EVENT path:path title:STORAGE_UPLOAD_SUCCESS props:resp];
resolve(resp);
}];
@ -373,25 +417,13 @@ RCT_EXPORT_METHOD(putFile:(NSString *) path localPath:(NSString *)localPath meta
}
- (NSDictionary *)getDownloadTaskAsDictionary:(FIRStorageTaskSnapshot *)task {
return @{
@"bytesTransferred": @(task.progress.completedUnitCount),
@"ref": task.reference.fullPath,
@"state": [self getTaskStatus:task.status],
@"totalBytes": @(task.progress.totalUnitCount)
};
return @{@"bytesTransferred": @(task.progress.completedUnitCount), @"ref": task.reference.fullPath, @"state": [self getTaskStatus:task.status], @"totalBytes": @(task.progress.totalUnitCount)};
}
- (NSDictionary *)getUploadTaskAsDictionary:(FIRStorageTaskSnapshot *)task {
NSString *downloadUrl = [task.metadata.downloadURL absoluteString];
FIRStorageMetadata *metadata = [task.metadata dictionaryRepresentation];
return @{
@"bytesTransferred": @(task.progress.completedUnitCount),
@"downloadUrl": downloadUrl != nil ? downloadUrl : [NSNull null],
@"metadata": metadata != nil ? metadata : [NSNull null],
@"ref": task.reference.fullPath,
@"state": [self getTaskStatus:task.status],
@"totalBytes": @(task.progress.totalUnitCount)
};
return @{@"bytesTransferred": @(task.progress.completedUnitCount), @"downloadUrl": downloadUrl != nil ? downloadUrl : [NSNull null], @"metadata": metadata != nil ? metadata : [NSNull null], @"ref": task.reference.fullPath, @"state": [self getTaskStatus:task.status], @"totalBytes": @(task.progress.totalUnitCount)};
}
- (FIRStorageMetadata *)buildMetadataFromMap:(NSDictionary *)metadata {
@ -421,31 +453,21 @@ RCT_EXPORT_METHOD(putFile:(NSString *) path localPath:(NSString *)localPath meta
}
- (NSDictionary *)constantsToExport {
return @{
@"MAIN_BUNDLE_PATH": [[NSBundle mainBundle] bundlePath],
@"CACHES_DIRECTORY_PATH": [self getPathForDirectory:NSCachesDirectory],
@"DOCUMENT_DIRECTORY_PATH": [self getPathForDirectory:NSDocumentDirectory],
@"EXTERNAL_DIRECTORY_PATH": [NSNull null],
@"EXTERNAL_STORAGE_DIRECTORY_PATH": [NSNull null],
@"TEMP_DIRECTORY_PATH": NSTemporaryDirectory(),
@"LIBRARY_DIRECTORY_PATH": [self getPathForDirectory:NSLibraryDirectory],
@"FILETYPE_REGULAR": NSFileTypeRegular,
@"FILETYPE_DIRECTORY": NSFileTypeDirectory
};
return @{@"MAIN_BUNDLE_PATH": [[NSBundle mainBundle] bundlePath], @"CACHES_DIRECTORY_PATH": [self getPathForDirectory:NSCachesDirectory], @"DOCUMENT_DIRECTORY_PATH": [self getPathForDirectory:NSDocumentDirectory], @"EXTERNAL_DIRECTORY_PATH": [NSNull null], @"EXTERNAL_STORAGE_DIRECTORY_PATH": [NSNull null], @"TEMP_DIRECTORY_PATH": NSTemporaryDirectory(), @"LIBRARY_DIRECTORY_PATH": [self getPathForDirectory:NSLibraryDirectory], @"FILETYPE_REGULAR": NSFileTypeRegular, @"FILETYPE_DIRECTORY": NSFileTypeDirectory};
}
- (NSArray<NSString *> *)supportedEvents {
return @[STORAGE_EVENT, STORAGE_ERROR];
}
- (void) sendJSError:(NSError *) error withPath:(NSString *) path {
NSDictionary *evt = @{ @"path": path, @"message": [error debugDescription] };
[self sendJSEvent:STORAGE_ERROR path:path title:STORAGE_ERROR props: evt];
- (void)sendJSError:(NSString *)appName error:(NSError *)error path:(NSString *)path {
NSDictionary *evt = @{@"path": path, @"message": [error debugDescription]};
[self sendJSEvent:appName type:STORAGE_ERROR path:path title:STORAGE_ERROR props:evt];
}
- (void) sendJSEvent:(NSString *)type path:(NSString *)path title:(NSString *)title props:(NSDictionary *)props {
- (void)sendJSEvent:(NSString *)appName type:(NSString *)type path:(NSString *)path title:(NSString *)title props:(NSDictionary *)props {
@try {
[self sendEventWithName:type body:@{ @"eventName": title, @"path": path, @"body": props }];
[self sendEventWithName:type body:@{@"eventName": title, @"appName": appName, @"path": path, @"body": props}];
} @catch (NSException *err) {
NSLog(@"An error occurred in sendJSEvent: %@", [err debugDescription]);
NSLog(@"Tried to send: %@ with %@", title, props);

View File

@ -22,14 +22,7 @@ const FirebaseCoreModule = NativeModules.RNFirebase;
class FirebaseCore {
constructor() {
this._nativeEmitters = {};
// todo init other modules if available on native
// todo generalise this so adding other modules isn't so repetitive:
if (NativeModules.RNFirebaseAuth) {
this._nativeEmitters.auth = new NativeEventEmitter(NativeModules.RNFirebaseAuth);
this._subscribeForDistribution('onAuthStateChanged', this._nativeEmitters.auth);
}
// ...
this._nativeSubscriptions = {};
}
/**
@ -158,15 +151,19 @@ class FirebaseCore {
* @private
*/
_subscribeForDistribution(eventName, nativeEmitter) {
nativeEmitter.addListener(eventName, (event) => {
if (event.appName) {
// native event has an appName property - auto prefix and internally emit
INTERNALS.SharedEventEmitter.emit(`${event.appName}-${eventName}`, event);
} else {
// standard event - no need to prefix
INTERNALS.SharedEventEmitter.emit(eventName, event);
}
});
if (!this._nativeSubscriptions[eventName]) {
nativeEmitter.addListener(eventName, (event) => {
if (event.appName) {
// native event has an appName property - auto prefix and internally emit
INTERNALS.SharedEventEmitter.emit(`${event.appName}-${eventName}`, event);
} else {
// standard event - no need to prefix
INTERNALS.SharedEventEmitter.emit(eventName, event);
}
});
this._nativeSubscriptions[eventName] = true;
}
}
/**
@ -181,6 +178,7 @@ class FirebaseCore {
let _app = app;
// throw an error if it's not a valid app instance
if (_app && !(_app instanceof FirebaseApp)) throw new Error(INTERNALS.STRINGS.ERROR_NOT_APP(namespace));
// default to the 'DEFAULT' app if no arg provided - will throw an error
// if default app not initialized
else if (!_app) _app = this.app(INTERNALS.STRINGS.DEFAULT_APP_NAME);
@ -191,6 +189,21 @@ class FirebaseCore {
return getNamespace;
}
/**
*
* @param name
* @param nativeModule
* @return {*}
* @private
*/
_getOrSetNativeEmitter(name, nativeModule) {
if (this._nativeEmitters[name]) {
return this._nativeEmitters[name];
}
return this._nativeEmitters[name] = new NativeEventEmitter(nativeModule);
}
}
export default new FirebaseCore();

View File

@ -1,9 +1,8 @@
import EventEmitter from 'EventEmitter';
import { Platform } from 'react-native';
const DEFAULT_APP_NAME = Platform.OS === 'ios' ? '__FIRAPP_DEFAULT' : '[DEFAULT]';
const DEFAULT_APP_NAME = Platform.OS === 'ios' ? '__FIRAPP_DEFAULT' : '[DEFAULT]';
// am still thinking ;p
export default {
// default options
OPTIONS: {

View File

@ -19,7 +19,12 @@ export default class Auth extends ModuleBase {
this._user = null;
this._authResult = null;
this.authenticated = false;
this.addListener('onAuthStateChanged', this._onAuthStateChanged.bind(this));
this.addListener(
// sub to internal native event - this fans out to
// public event name: onAuthStateChangedPublic
this._getAppEventName('onAuthStateChanged'),
this._onAuthStateChanged.bind(this),
);
this._native.addAuthStateListener(); // this is the native function on ios/android:
}
@ -35,7 +40,7 @@ export default class Auth extends ModuleBase {
if (auth && auth.user && !this._user) this._user = new User(this, auth);
else if ((!auth || !auth.user) && this._user) this._user = null;
else if (this._user) this._user._updateValues(auth);
if (emit) this.emit(`${this._appName}-onAuthStateChanged`, this._user);
if (emit) this.emit(this._getAppEventName('onAuthStateChangedPublic'), this._user);
return auth ? this._user : null;
}
@ -46,7 +51,7 @@ export default class Auth extends ModuleBase {
*/
_offAuthStateChanged(listener: Function) {
this.log.info('Removing onAuthStateChanged listener');
this.removeListener('onAuthStateChanged', listener);
this.removeListener(this._getAppEventName('onAuthStateChangedPublic'), listener);
}
/**
@ -75,7 +80,7 @@ export default class Auth extends ModuleBase {
*/
onAuthStateChanged(listener: Function) {
this.log.info('Creating onAuthStateChanged listener');
this.on('onAuthStateChanged', listener);
this.on(this._getAppEventName('onAuthStateChangedPublic'), listener);
if (this._authResult) listener(this._user || null);
return this._offAuthStateChanged.bind(this, listener);
}

View File

@ -8,7 +8,7 @@ import ModuleBase from './../../utils/ModuleBase';
*/
export default class RemoteConfig extends ModuleBase {
constructor(firebaseApp: Object, options: Object = {}) {
super(firebaseApp, options, 'Config');
super(firebaseApp, options, 'RemoteConfig');
this.developerModeEnabled = false;
}

View File

@ -2,18 +2,16 @@
* @flow
*/
import ReferenceBase from './../../utils/ModuleBase';
import Reference from './reference.js';
/**
* @class Query
*/
export default class Query extends ReferenceBase {
export default class Query {
modifiers: Array<DatabaseModifier>;
constructor(ref: Reference, path: string, existingModifiers?: Array<DatabaseModifier>) {
super(path);
this.log.debug('creating Query ', path, existingModifiers);
ref.log.debug('creating Query ', path, existingModifiers);
this.modifiers = existingModifiers ? [...existingModifiers] : [];
}
@ -33,7 +31,7 @@ export default class Query extends ReferenceBase {
});
}
filter(name: string, value: any, key?:string) {
filter(name: string, value: any, key?: string) {
this.modifiers.push({
type: 'filter',
name,

View File

@ -59,7 +59,7 @@ export default class Reference extends ReferenceBase {
// todo logger missing as reference base no longer extends module base
constructor(database: Object, path: string, existingModifiers?: Array<DatabaseModifier>) {
super(path);
super(path, database);
this.refId = refId++;
this.refListeners = {};
this.database = database;

View File

@ -3,6 +3,7 @@ import { NativeModules } from 'react-native';
import StorageRef from './reference';
import ModuleBase from './../../utils/ModuleBase';
import INTERNALS from './../../internals';
const FirebaseStorage = NativeModules.RNFirebaseStorage;
@ -16,14 +17,14 @@ export default class Storage extends ModuleBase {
super(firebaseApp, options, 'Storage', true);
this._subscriptions = {};
this._successListener = this._eventEmitter.addListener(
'storage_event',
event => this._handleStorageEvent(event),
this.addListener(
this._getAppEventName('storage_event'),
this._handleStorageEvent.bind(this),
);
this._errorListener = this._eventEmitter.addListener(
'storage_error',
err => this._handleStorageError(err),
this.addListener(
this._getAppEventName('storage_error'),
this._handleStorageEvent.bind(this),
);
}
@ -78,48 +79,32 @@ export default class Storage extends ModuleBase {
/** **********
* INTERNALS
********** **/
_getSubEventName(path, eventName) {
return this._getAppEventName(`${path}-${eventName}`);
}
_handleStorageEvent(event: Object) {
const { path, eventName } = event;
const body = event.body || {};
this.log.debug('_handleStorageEvent: ', path, eventName, body);
if (this._subscriptions[path] && this._subscriptions[path][eventName]) {
this._subscriptions[path][eventName].forEach((cb) => {
cb(body);
});
}
this.emit(this._getSubEventName(path, eventName), body);
}
_handleStorageError(err: Object) {
const { path, eventName } = event;
const body = event.body || {};
this.log.debug('_handleStorageError ->', err);
this.emit(this._getSubEventName(path, eventName), body);
}
_addListener(path: string, eventName: string, cb: (evt: Object) => Object) {
if (!this._subscriptions[path]) this._subscriptions[path] = {};
if (!this._subscriptions[path][eventName]) this._subscriptions[path][eventName] = [];
this._subscriptions[path][eventName].push(cb);
this.on(this._getSubEventName(path, eventName), cb);
}
_removeListener(path: string, eventName: string, origCB: (evt: Object) => Object) {
if (!this._subscriptions[path] || (eventName && !this._subscriptions[path][eventName])) {
this.log.warn('_removeListener() called, but not currently listening at that location (bad path)', path, eventName);
return;
}
if (eventName && origCB) {
const i = this._subscriptions[path][eventName].indexOf(origCB);
if (i === -1) {
this.log.warn('_removeListener() called, but the callback specified is not listening at this location (bad path)', path, eventName);
} else {
this._subscriptions[path][eventName].splice(i, 1);
}
} else if (eventName) {
this._subscriptions[path][eventName] = [];
} else {
this._subscriptions[path] = {};
}
this.removeListener(this._getSubEventName(path, eventName), origCB);
}
}

View File

@ -10,8 +10,7 @@ import Storage from './';
*/
export default class StorageReference extends ReferenceBase {
constructor(storage: Storage, path: string) {
super(path);
this.storage = storage;
super(path, storage);
}
get fullPath(): string {
@ -29,7 +28,7 @@ export default class StorageReference extends ReferenceBase {
* @returns {StorageReference}
*/
child(path: string) {
return new StorageReference(this.storage, `${this.path}/${path}`);
return new StorageReference(this._module, `${this.path}/${path}`);
}
/**
@ -37,7 +36,7 @@ export default class StorageReference extends ReferenceBase {
* @returns {Promise.<T>|*}
*/
delete(): Promise<*> {
return this.storate._native.delete(this.path);
return this._module._native.delete(this.path);
}
/**
@ -45,7 +44,7 @@ export default class StorageReference extends ReferenceBase {
* @returns {Promise.<T>|*}
*/
getDownloadURL(): Promise<String> {
return this.storate._native.getDownloadURL(this.path);
return this._module._native.getDownloadURL(this.path);
}
/**
@ -53,7 +52,7 @@ export default class StorageReference extends ReferenceBase {
* @returns {Promise.<T>|*}
*/
getMetadata(): Promise<Object> {
return this.storate._native.getMetadata(this.path);
return this._module._native.getMetadata(this.path);
}
/**
@ -62,7 +61,7 @@ export default class StorageReference extends ReferenceBase {
* @returns {Promise.<T>|*}
*/
updateMetadata(metadata: Object = {}): Promise<Object> {
return this.storate._native.updateMetadata(this.path, metadata);
return this._module._native.updateMetadata(this.path, metadata);
}
/**
@ -71,7 +70,7 @@ export default class StorageReference extends ReferenceBase {
* @return {Promise}
*/
downloadFile(filePath: string): Promise<Object> {
return new StorageTask(DOWNLOAD_TASK, this.storate._native.downloadFile(this.path, filePath), this);
return new StorageTask(DOWNLOAD_TASK, this._module._native.downloadFile(this.path, filePath), this);
}
/**
@ -90,6 +89,6 @@ export default class StorageReference extends ReferenceBase {
*/
putFile(filePath: Object, metadata: Object = {}): Promise<Object> {
const _filePath = filePath.replace('file://', '');
return new StorageTask(UPLOAD_TASK, this.storate._native.putFile(this.path, _filePath, metadata), this);
return new StorageTask(UPLOAD_TASK, this._module._native.putFile(this.path, _filePath, metadata), this);
}
}

View File

@ -1,6 +1,6 @@
/* @flow */
import { statics as StorageStatics } from './';
import { isObject, isFunction } from './../../utils';
import { isFunction } from './../../utils';
import StorageReference from './reference';
export const UPLOAD_TASK = 'upload';
@ -38,17 +38,17 @@ declare type NextOrObserverType = null |
* @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: StorageReference.storage
path: StorageReference.path
then: () => Promise<*>
catch: () => Promise<*>
type: typeof UPLOAD_TASK | typeof DOWNLOAD_TASK;
ref: StorageReference;
storage: StorageReference.storage;
path: StorageReference.path;
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.storage = storageRef._module;
this.path = storageRef.path;
// 'proxy' original promise
@ -115,21 +115,21 @@ export default class StorageTask {
this.storage._addListener(
this.path,
StorageStatics.TaskEvent.STATE_CHANGED,
_next
_next,
);
}
if (_error) {
this.storage._addListener(
this.path,
`${this.type}_failure`,
_error
_error,
);
}
if (_complete) {
this.storage._addListener(
this.path,
`${this.type}_success`,
_complete
_complete,
);
}

View File

@ -1,10 +1,11 @@
/**
* @flow
*/
import { NativeModules, NativeEventEmitter } from 'react-native';
import { NativeModules } from 'react-native';
import Log from '../utils/log';
import { nativeWithApp } from './../utils';
import INTERNALS from './../internals';
import FirebaseCore from './../firebase';
const logs = {};
@ -15,6 +16,16 @@ const MULTI_APP_MODULES = [
'storage',
];
const NATIVE_MODULE_EVENTS = {
Storage: [
'storage_event',
'storage_error',
],
Auth: [
'onAuthStateChanged',
],
};
export default class ModuleBase {
constructor(firebaseApp, options, moduleName, withEventEmitter = false) {
this._options = Object.assign({}, options);
@ -23,14 +34,16 @@ export default class ModuleBase {
this._appName = firebaseApp.name;
this._namespace = `${this._appName}:${this._module}`;
// check if native module exists as all native modules are now optionally part of build
// check if native module exists as all native
// modules are now optionally part of build
const nativeModule = NativeModules[`RNFirebase${moduleName}`];
if (!nativeModule) {
throw new Error(INTERNALS.STRINGS.ERROR_MISSING_MODULE(moduleName));
}
// used by the modules that extend ModuleBase to access their native module counterpart
// used by the modules that extend ModuleBase
// to access their native module counterpart
if (!MULTI_APP_MODULES.includes(moduleName.toLowerCase())) {
this._native = nativeModule;
} else {
@ -38,10 +51,37 @@ export default class ModuleBase {
}
if (withEventEmitter) {
this._eventEmitter = new NativeEventEmitter(this._native);
this._setupEventEmitter(nativeModule, moduleName);
}
}
/**
*
* @param nativeModule
* @param moduleName
* @private
*/
_setupEventEmitter(nativeModule, moduleName) {
this._eventEmitter = FirebaseCore._getOrSetNativeEmitter(this._appName, nativeModule);
const events = NATIVE_MODULE_EVENTS[moduleName];
if (events && events.length) {
for (let i = 0, len = events.length; i < len; i++) {
FirebaseCore._subscribeForDistribution(events[i], this._eventEmitter);
}
}
}
/**
*
* @param eventName
* @return {string}
* @private
*/
_getAppEventName(eventName) {
return `${this._appName}-${eventName}`;
}
/**
* Returns the FirebaseApp instance for current module
* @return {*}

View File

@ -2,7 +2,8 @@
* @flow
*/
export default class ReferenceBase {
constructor(path: string) {
constructor(path: string, module) {
this._module = module;
this.path = path || '/';
}
@ -17,4 +18,8 @@ export default class ReferenceBase {
get key(): string | null {
return this.path === '/' ? null : this.path.substring(this.path.lastIndexOf('/') + 1);
}
get log() {
return this._module.log;
}
}

View File

@ -17,6 +17,7 @@
}
},
"rules": {
"no-plusplus": 0,
"class-methods-use-this": 0,
"no-underscore-dangle": 0,
"no-use-before-define": 0,

View File

@ -20,6 +20,7 @@ const instances = {
}),
};
instances.web.database().ref('tests/types').set(DatabaseContents.DEFAULT);
instances.web.database().ref('tests/priority').setWithPriority({

View File

@ -3,6 +3,7 @@ import { Provider } from 'react-redux';
import CoreContainer from './containers/CoreContainer';
import setupStore from './store/setup';
import { setupSuites } from './tests/index';
import { NativeModules } from 'react-native';
global.Promise = require('bluebird');
@ -35,6 +36,7 @@ function bootstrap() {
state: State;
componentDidMount() {
console.warn(JSON.stringify(Object.keys(NativeModules)));
setupStore((store) => {
setupSuites(store);
this.setState({