[both] continued work on multi app support - storage now full supported and auth WIP
This commit is contained in:
parent
82a2afd59b
commit
282f953f52
|
@ -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);
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
|
||||
#import <React/RCTBridgeModule.h>
|
||||
|
||||
@interface RNFirebaseConfig : NSObject <RCTBridgeModule>
|
||||
@interface RNFirebaseRemoteConfig : NSObject <RCTBridgeModule>
|
||||
|
||||
@end
|
||||
|
|
@ -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];
|
|
@ -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);
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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: {
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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,
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
@ -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 {*}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
}
|
||||
},
|
||||
"rules": {
|
||||
"no-plusplus": 0,
|
||||
"class-methods-use-this": 0,
|
||||
"no-underscore-dangle": 0,
|
||||
"no-use-before-define": 0,
|
||||
|
|
|
@ -20,6 +20,7 @@ const instances = {
|
|||
}),
|
||||
};
|
||||
|
||||
|
||||
instances.web.database().ref('tests/types').set(DatabaseContents.DEFAULT);
|
||||
|
||||
instances.web.database().ref('tests/priority').setWithPriority({
|
||||
|
|
|
@ -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({
|
||||
|
|
Loading…
Reference in New Issue