Merge branch 'master' of https://github.com/invertase/react-native-firebase into multi-apps
This commit is contained in:
commit
33470419ed
|
@ -1,5 +1,5 @@
|
|||
|
||||
(Please write your issue here along with the environment details below)
|
||||
(Please write your issue here along with the environment details below. Include any key files which will help us to debug, such as your `Podfile` and/or `app/build.gradle` file).
|
||||
|
||||
### Environment
|
||||
|
||||
|
|
|
@ -16,4 +16,5 @@ Pod::Spec.new do |s|
|
|||
s.platform = :ios, "8.0"
|
||||
s.preserve_paths = 'README.md', 'package.json', '*.js'
|
||||
s.source_files = 'ios/RNFirebase/**/*.{h,m}'
|
||||
s.dependency 'React'
|
||||
end
|
||||
|
|
|
@ -88,7 +88,6 @@ public class RNFirebaseDatabase extends ReactContextBaseJavaModule {
|
|||
DatabaseReference ref = mFirebaseDatabase.getReference(path);
|
||||
Map<String, Object> m = Utils.recursivelyDeconstructReadableMap(props);
|
||||
|
||||
|
||||
DatabaseReference.CompletionListener listener = new DatabaseReference.CompletionListener() {
|
||||
@Override
|
||||
public void onComplete(DatabaseError error, DatabaseReference ref) {
|
||||
|
@ -99,6 +98,44 @@ public class RNFirebaseDatabase extends ReactContextBaseJavaModule {
|
|||
ref.setValue(m.get("value"), listener);
|
||||
}
|
||||
|
||||
@ReactMethod
|
||||
public void priority(
|
||||
final String path,
|
||||
final ReadableMap priority,
|
||||
final Callback callback) {
|
||||
DatabaseReference ref = mFirebaseDatabase.getReference(path);
|
||||
Map<String, Object> priorityMap = Utils.recursivelyDeconstructReadableMap(priority);
|
||||
|
||||
DatabaseReference.CompletionListener listener = new DatabaseReference.CompletionListener() {
|
||||
@Override
|
||||
public void onComplete(DatabaseError error, DatabaseReference ref) {
|
||||
handleCallback("priority", callback, error);
|
||||
}
|
||||
};
|
||||
|
||||
ref.setPriority(priorityMap.get("value"), listener);
|
||||
}
|
||||
|
||||
@ReactMethod
|
||||
public void withPriority(
|
||||
final String path,
|
||||
final ReadableMap data,
|
||||
final ReadableMap priority,
|
||||
final Callback callback) {
|
||||
DatabaseReference ref = mFirebaseDatabase.getReference(path);
|
||||
Map<String, Object> dataMap = Utils.recursivelyDeconstructReadableMap(data);
|
||||
Map<String, Object> priorityMap = Utils.recursivelyDeconstructReadableMap(priority);
|
||||
|
||||
DatabaseReference.CompletionListener listener = new DatabaseReference.CompletionListener() {
|
||||
@Override
|
||||
public void onComplete(DatabaseError error, DatabaseReference ref) {
|
||||
handleCallback("withPriority", callback, error);
|
||||
}
|
||||
};
|
||||
|
||||
ref.setValue(dataMap.get("value"), priorityMap.get("value"), listener);
|
||||
}
|
||||
|
||||
@ReactMethod
|
||||
public void update(final String path,
|
||||
final ReadableMap props,
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
# iOS Installation
|
||||
|
||||
Please note that there is a known issue when using Cocoapods with the `!use_frameworks` enabled. This is explained [here](https://github.com/invertase/react-native-firebase/issues/252#issuecomment-316340974). Unfortunately we don't currently have a workaround, but are engaging with Firebase directly to try and resolve the problem.
|
||||
|
||||
## 1) Setup GoogleService-Info.plist
|
||||
Setup the `GoogleService-Info.plist` file by following the instructions and adding it to the root of your project at `ios/[YOUR APP NAME]/GoogleService-Info.plist` [here](https://firebase.google.com/docs/ios/setup#add_firebase_to_your_app).
|
||||
|
||||
|
@ -141,6 +143,18 @@ Add the following methods:
|
|||
fetchCompletionHandler:(nonnull void (^)(UIBackgroundFetchResult))completionHandler{
|
||||
[RNFirebaseMessaging didReceiveRemoteNotification:userInfo fetchCompletionHandler:completionHandler];
|
||||
}
|
||||
|
||||
- (void)userNotificationCenter:(UNUserNotificationCenter *)center
|
||||
willPresentNotification:(UNNotification *)notification
|
||||
withCompletionHandler:(void (^)(UNNotificationPresentationOptions))completionHandler {
|
||||
[RNFirebaseMessaging willPresentNotification:notification withCompletionHandler:completionHandler];
|
||||
}
|
||||
|
||||
- (void)userNotificationCenter:(UNUserNotificationCenter *)center
|
||||
didReceiveNotificationResponse:(UNNotificationResponse *)response
|
||||
withCompletionHandler:(void (^)())completionHandler {
|
||||
[RNFirebaseMessaging didReceiveNotificationResponse:response withCompletionHandler:completionHandler];
|
||||
}
|
||||
```
|
||||
|
||||
### 3.5) Debugging
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
|
||||
#import "FirebaseRemoteConfig/FirebaseRemoteConfig.h"
|
||||
#import <React/RCTConvert.h>
|
||||
#import <React/RCTUtils.h>
|
||||
|
||||
NSString *convertFIRRemoteConfigFetchStatusToNSString(FIRRemoteConfigFetchStatus value) {
|
||||
switch (value) {
|
||||
|
|
|
@ -1,206 +1,9 @@
|
|||
#import "RNFirebaseDatabase.h"
|
||||
#import "RNFirebaseEvents.h"
|
||||
#import "Firebase.h"
|
||||
|
||||
#if __has_include(<FirebaseDatabase/FIRDatabase.h>)
|
||||
|
||||
@interface RNFirebaseDBReference : NSObject
|
||||
@property RCTEventEmitter *emitter;
|
||||
@property FIRDatabaseQuery *query;
|
||||
@property NSNumber *refId;
|
||||
@property NSString *path;
|
||||
@property NSMutableDictionary *listeners;
|
||||
|
||||
+ (NSDictionary *)snapshotToDict:(FIRDataSnapshot *)snapshot;
|
||||
@end
|
||||
|
||||
@implementation RNFirebaseDBReference
|
||||
|
||||
|
||||
- (id)initWithPathAndModifiers:(RCTEventEmitter *)emitter database:(FIRDatabase *)database refId:(NSNumber *)refId path:(NSString *)path modifiers:(NSArray *)modifiers {
|
||||
self = [super init];
|
||||
if (self) {
|
||||
_emitter = emitter;
|
||||
_refId = refId;
|
||||
_path = path;
|
||||
_query = [self buildQueryAtPathWithModifiers:database path:path modifiers:modifiers];
|
||||
_listeners = [[NSMutableDictionary alloc] init];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)addEventHandler:(NSNumber *)listenerId eventName:(NSString *)eventName {
|
||||
if (!_listeners[listenerId]) {
|
||||
id andPreviousSiblingKeyWithBlock = ^(FIRDataSnapshot *_Nonnull snapshot, NSString *_Nullable previousChildName) {
|
||||
NSDictionary *props = [RNFirebaseDBReference snapshotToDict:snapshot];
|
||||
[self sendJSEvent:DATABASE_DATA_EVENT title:eventName props:@{@"eventName": eventName, @"refId": _refId, @"listenerId": listenerId, @"path": _path, @"snapshot": props, @"previousChildName": previousChildName != nil ? previousChildName : [NSNull null]}];
|
||||
};
|
||||
id errorBlock = ^(NSError *_Nonnull error) {
|
||||
NSLog(@"Error onDBEvent: %@", [error debugDescription]);
|
||||
[self removeEventHandler:listenerId eventName:eventName];
|
||||
[self getAndSendDatabaseError:error listenerId:listenerId];
|
||||
};
|
||||
int eventType = [self eventTypeFromName:eventName];
|
||||
FIRDatabaseHandle handle = [_query observeEventType:eventType andPreviousSiblingKeyWithBlock:andPreviousSiblingKeyWithBlock withCancelBlock:errorBlock];
|
||||
_listeners[listenerId] = @(handle);
|
||||
} else {
|
||||
NSLog(@"Warning Trying to add duplicate listener for refId: %@ listenerId: %@", _refId, listenerId);
|
||||
}
|
||||
}
|
||||
|
||||
- (void)addSingleEventHandler:(NSString *)eventName callback:(RCTResponseSenderBlock)callback {
|
||||
FIRDataEventType firDataEventType = (FIRDataEventType)[self eventTypeFromName:eventName];
|
||||
|
||||
[_query observeSingleEventOfType:firDataEventType andPreviousSiblingKeyWithBlock:^(FIRDataSnapshot *_Nonnull snapshot, NSString *_Nullable previousChildName) {
|
||||
NSDictionary *props = [RNFirebaseDBReference snapshotToDict:snapshot];
|
||||
callback(@[[NSNull null], @{@"eventName": eventName, @"path": _path, @"refId": _refId, @"snapshot": props, @"previousChildName": previousChildName != nil ? previousChildName : [NSNull null]}]);
|
||||
} withCancelBlock:^(NSError *_Nonnull error) {
|
||||
NSLog(@"Error onDBEventOnce: %@", [error debugDescription]);
|
||||
callback(@[@{@"eventName": DATABASE_ERROR_EVENT, @"path": _path, @"refId": _refId, @"code": @([error code]), @"details": [error debugDescription], @"message": [error localizedDescription], @"description": [error description]}]);
|
||||
}];
|
||||
}
|
||||
|
||||
- (void)removeEventHandler:(NSNumber *)listenerId eventName:(NSString *)eventName {
|
||||
FIRDatabaseHandle handle = (FIRDatabaseHandle) [_listeners[listenerId] integerValue];
|
||||
if (handle) {
|
||||
[_listeners removeObjectForKey:listenerId];
|
||||
[_query removeObserverWithHandle:handle];
|
||||
}
|
||||
}
|
||||
|
||||
+ (NSDictionary *)snapshotToDict:(FIRDataSnapshot *)snapshot {
|
||||
NSMutableDictionary *dict = [[NSMutableDictionary alloc] init];
|
||||
[dict setValue:snapshot.key forKey:@"key"];
|
||||
NSDictionary *val = snapshot.value;
|
||||
dict[@"value"] = val;
|
||||
// Snapshot ordering
|
||||
NSMutableArray *childKeys = [NSMutableArray array];
|
||||
if (snapshot.childrenCount > 0) {
|
||||
// Since JS does not respect object ordering of keys
|
||||
// we keep a list of the keys and their ordering
|
||||
// in the snapshot event
|
||||
NSEnumerator *children = [snapshot children];
|
||||
FIRDataSnapshot *child;
|
||||
while (child = [children nextObject]) {
|
||||
[childKeys addObject:child.key];
|
||||
}
|
||||
}
|
||||
dict[@"childKeys"] = childKeys;
|
||||
[dict setValue:@(snapshot.hasChildren) forKey:@"hasChildren"];
|
||||
[dict setValue:@(snapshot.exists) forKey:@"exists"];
|
||||
[dict setValue:@(snapshot.childrenCount) forKey:@"childrenCount"];
|
||||
[dict setValue:snapshot.priority forKey:@"priority"];
|
||||
return dict;
|
||||
}
|
||||
|
||||
- (NSDictionary *)getAndSendDatabaseError:(NSError *)error listenerId:(NSNumber *)listenerId {
|
||||
NSDictionary *event = @{@"eventName": DATABASE_ERROR_EVENT, @"path": _path, @"refId": _refId, @"listenerId": listenerId, @"code": @([error code]), @"details": [error debugDescription], @"message": [error localizedDescription], @"description": [error description]};
|
||||
|
||||
@try {
|
||||
[_emitter sendEventWithName:DATABASE_ERROR_EVENT body:event];
|
||||
} @catch (NSException *err) {
|
||||
NSLog(@"An error occurred in getAndSendDatabaseError: %@", [err debugDescription]);
|
||||
NSLog(@"Tried to send: %@ with %@", DATABASE_ERROR_EVENT, event);
|
||||
}
|
||||
|
||||
return event;
|
||||
}
|
||||
|
||||
- (void)sendJSEvent:(NSString *)type title:(NSString *)title props:(NSDictionary *)props {
|
||||
@try {
|
||||
[_emitter sendEventWithName:type body:@{@"eventName": title, @"body": props}];
|
||||
} @catch (NSException *err) {
|
||||
NSLog(@"An error occurred in sendJSEvent: %@", [err debugDescription]);
|
||||
NSLog(@"Tried to send: %@ with %@", title, props);
|
||||
}
|
||||
}
|
||||
|
||||
- (FIRDatabaseQuery *)buildQueryAtPathWithModifiers:(FIRDatabase *)database path:(NSString *)path modifiers:(NSArray *)modifiers {
|
||||
FIRDatabaseQuery *query = [[database reference] child:path];
|
||||
|
||||
for (NSDictionary *modifier in modifiers) {
|
||||
NSString *type = [modifier valueForKey:@"type"];
|
||||
NSString *name = [modifier valueForKey:@"name"];
|
||||
if ([type isEqualToString:@"orderBy"]) {
|
||||
if ([name isEqualToString:@"orderByKey"]) {
|
||||
query = [query queryOrderedByKey];
|
||||
} else if ([name isEqualToString:@"orderByPriority"]) {
|
||||
query = [query queryOrderedByPriority];
|
||||
} else if ([name isEqualToString:@"orderByValue"]) {
|
||||
query = [query queryOrderedByValue];
|
||||
} else if ([name isEqualToString:@"orderByChild"]) {
|
||||
NSString *key = [modifier valueForKey:@"key"];
|
||||
query = [query queryOrderedByChild:key];
|
||||
}
|
||||
} else if ([type isEqualToString:@"limit"]) {
|
||||
int limit = [[modifier valueForKey:@"limit"] integerValue];
|
||||
if ([name isEqualToString:@"limitToLast"]) {
|
||||
query = [query queryLimitedToLast:limit];
|
||||
} else if ([name isEqualToString:@"limitToFirst"]) {
|
||||
query = [query queryLimitedToFirst:limit];
|
||||
}
|
||||
} else if ([type isEqualToString:@"filter"]) {
|
||||
NSString *valueType = [modifier valueForKey:@"valueType"];
|
||||
NSString *key = [modifier valueForKey:@"key"];
|
||||
id value = [self getIdValue:[modifier valueForKey:@"value"] type:valueType];
|
||||
if ([name isEqualToString:@"equalTo"]) {
|
||||
if (key != nil) {
|
||||
query = [query queryEqualToValue:value childKey:key];
|
||||
} else {
|
||||
query = [query queryEqualToValue:value];
|
||||
}
|
||||
} else if ([name isEqualToString:@"endAt"]) {
|
||||
if (key != nil) {
|
||||
query = [query queryEndingAtValue:value childKey:key];
|
||||
} else {
|
||||
query = [query queryEndingAtValue:value];
|
||||
}
|
||||
} else if ([name isEqualToString:@"startAt"]) {
|
||||
if (key != nil) {
|
||||
query = [query queryStartingAtValue:value childKey:key];
|
||||
} else {
|
||||
query = [query queryStartingAtValue:value];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return query;
|
||||
}
|
||||
|
||||
- (id)getIdValue:(NSString *)value type:(NSString *)type {
|
||||
if ([type isEqualToString:@"number"]) {
|
||||
return @(value.doubleValue);
|
||||
} else if ([type isEqualToString:@"boolean"]) {
|
||||
return @(value.boolValue);
|
||||
} else {
|
||||
return value;
|
||||
}
|
||||
}
|
||||
|
||||
- (BOOL)hasListeners {
|
||||
return [[_listeners allKeys] count] > 0;
|
||||
}
|
||||
|
||||
- (int)eventTypeFromName:(NSString *)name {
|
||||
int eventType = FIRDataEventTypeValue;
|
||||
|
||||
if ([name isEqualToString:DATABASE_VALUE_EVENT]) {
|
||||
eventType = FIRDataEventTypeValue;
|
||||
} else if ([name isEqualToString:DATABASE_CHILD_ADDED_EVENT]) {
|
||||
eventType = FIRDataEventTypeChildAdded;
|
||||
} else if ([name isEqualToString:DATABASE_CHILD_MODIFIED_EVENT]) {
|
||||
eventType = FIRDataEventTypeChildChanged;
|
||||
} else if ([name isEqualToString:DATABASE_CHILD_REMOVED_EVENT]) {
|
||||
eventType = FIRDataEventTypeChildRemoved;
|
||||
} else if ([name isEqualToString:DATABASE_CHILD_MOVED_EVENT]) {
|
||||
eventType = FIRDataEventTypeChildMoved;
|
||||
}
|
||||
return eventType;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
#import "RNFirebaseDatabaseReference.h"
|
||||
#import "RNFirebaseEvents.h"
|
||||
#import "Firebase.h"
|
||||
|
||||
@implementation RNFirebaseDatabase
|
||||
RCT_EXPORT_MODULE();
|
||||
|
@ -269,7 +72,7 @@ RCT_EXPORT_METHOD(startTransaction:
|
|||
if (databaseError != nil) {
|
||||
[self sendTransactionEvent:DATABASE_TRANSACTION_EVENT body:@{@"id": identifier, @"type": @"error", @"code": @([databaseError code]), @"message": [databaseError description]}];
|
||||
} else {
|
||||
[self sendTransactionEvent:DATABASE_TRANSACTION_EVENT body:@{@"id": identifier, @"type": @"complete", @"committed": @(committed), @"snapshot": [RNFirebaseDBReference snapshotToDict:snapshot],}];
|
||||
[self sendTransactionEvent:DATABASE_TRANSACTION_EVENT body:@{@"id": identifier, @"type": @"complete", @"committed": @(committed), @"snapshot": [RNFirebaseDatabaseReference snapshotToDict:snapshot],}];
|
||||
}
|
||||
}
|
||||
withLocalEvents:
|
||||
|
@ -345,6 +148,25 @@ RCT_EXPORT_METHOD(set:
|
|||
}];
|
||||
}
|
||||
|
||||
RCT_EXPORT_METHOD(priority:(NSString *) path
|
||||
priorityData:(NSDictionary *) priorityData
|
||||
callback:(RCTResponseSenderBlock) callback) {
|
||||
FIRDatabaseReference *ref = [self getPathRef:path];
|
||||
[ref setPriority:[priorityData valueForKey:@"value"] withCompletionBlock:^(NSError * _Nullable error, FIRDatabaseReference * _Nonnull ref) {
|
||||
[self handleCallback:@"priority" callback:callback databaseError:error];
|
||||
}];
|
||||
}
|
||||
|
||||
RCT_EXPORT_METHOD(withPriority:(NSString *) path
|
||||
data:(NSDictionary *) data
|
||||
priorityData:(NSDictionary *) priorityData
|
||||
callback:(RCTResponseSenderBlock) callback) {
|
||||
FIRDatabaseReference *ref = [self getPathRef:path];
|
||||
[ref setValue:[data valueForKey:@"value"] andPriority:[priorityData valueForKey:@"value"] withCompletionBlock:^(NSError * _Nullable error, FIRDatabaseReference * _Nonnull ref) {
|
||||
[self handleCallback:@"withPriority" callback:callback databaseError:error];
|
||||
}];
|
||||
}
|
||||
|
||||
RCT_EXPORT_METHOD(update:
|
||||
(NSString *) path
|
||||
value:
|
||||
|
@ -404,7 +226,7 @@ RCT_EXPORT_METHOD(on:
|
|||
listenerId:(nonnull NSNumber *) listenerId
|
||||
name:(NSString *) eventName
|
||||
callback:(RCTResponseSenderBlock) callback) {
|
||||
RNFirebaseDBReference *ref = [self getDBHandle:refId path:path modifiers:modifiers];
|
||||
RNFirebaseDatabaseReference *ref = [self getDBHandle:refId path:path modifiers:modifiers];
|
||||
[ref addEventHandler:listenerId eventName:eventName];
|
||||
callback(@[[NSNull null], @{@"status": @"success", @"refId": refId, @"handle": path}]);
|
||||
}
|
||||
|
@ -416,7 +238,7 @@ RCT_EXPORT_METHOD(once:
|
|||
modifiers:(NSArray *) modifiers
|
||||
eventName:(NSString *) eventName
|
||||
callback:(RCTResponseSenderBlock) callback) {
|
||||
RNFirebaseDBReference *ref = [self getDBHandle:refId path:path modifiers:modifiers];
|
||||
RNFirebaseDatabaseReference *ref = [self getDBHandle:refId path:path modifiers:modifiers];
|
||||
[ref addSingleEventHandler:eventName callback:callback];
|
||||
}
|
||||
|
||||
|
@ -425,7 +247,7 @@ RCT_EXPORT_METHOD(off:
|
|||
NSNumber *) refId
|
||||
listeners:(NSArray *) listeners
|
||||
callback:(RCTResponseSenderBlock) callback) {
|
||||
RNFirebaseDBReference *ref = _dbReferences[refId];
|
||||
RNFirebaseDatabaseReference *ref = _dbReferences[refId];
|
||||
if (ref != nil) {
|
||||
for (NSDictionary *listener in listeners) {
|
||||
NSNumber *listenerId = [listener valueForKey:@"listenerId"];
|
||||
|
@ -494,11 +316,11 @@ RCT_EXPORT_METHOD(goOnline) {
|
|||
}
|
||||
}
|
||||
|
||||
- (RNFirebaseDBReference *)getDBHandle:(NSNumber *)refId path:(NSString *)path modifiers:(NSArray *)modifiers {
|
||||
RNFirebaseDBReference *ref = _dbReferences[refId];
|
||||
- (RNFirebaseDatabaseReference *)getDBHandle:(NSNumber *)refId path:(NSString *)path modifiers:(NSArray *)modifiers {
|
||||
RNFirebaseDatabaseReference *ref = _dbReferences[refId];
|
||||
|
||||
if (ref == nil) {
|
||||
ref = [[RNFirebaseDBReference alloc] initWithPathAndModifiers:self database:[FIRDatabase database] refId:refId path:path modifiers:modifiers];
|
||||
ref = [[RNFirebaseDatabaseReference alloc] initWithPathAndModifiers:self database:[FIRDatabase database] refId:refId path:path modifiers:modifiers];
|
||||
_dbReferences[refId] = ref;
|
||||
}
|
||||
return ref;
|
||||
|
|
|
@ -0,0 +1,29 @@
|
|||
#ifndef RNFirebaseDatabaseReference_h
|
||||
#define RNFirebaseDatabaseReference_h
|
||||
|
||||
#if __has_include(<FirebaseDatabase/FIRDatabase.h>)
|
||||
#import <React/RCTEventEmitter.h>
|
||||
#import "Firebase.h"
|
||||
|
||||
@interface RNFirebaseDatabaseReference : NSObject
|
||||
@property RCTEventEmitter *emitter;
|
||||
@property FIRDatabaseQuery *query;
|
||||
@property NSNumber *refId;
|
||||
@property NSString *path;
|
||||
@property NSMutableDictionary *listeners;
|
||||
|
||||
- (id)initWithPathAndModifiers:(RCTEventEmitter *)emitter database:(FIRDatabase *)database refId:(NSNumber *)refId path:(NSString *)path modifiers:(NSArray *)modifiers;
|
||||
- (void)addEventHandler:(NSNumber *)listenerId eventName:(NSString *)eventName;
|
||||
- (void)addSingleEventHandler:(NSString *)eventName callback:(RCTResponseSenderBlock)callback;
|
||||
- (void)removeEventHandler:(NSNumber *)listenerId eventName:(NSString *)eventName;
|
||||
- (BOOL)hasListeners;
|
||||
+ (NSDictionary *)snapshotToDict:(FIRDataSnapshot *)snapshot;
|
||||
@end
|
||||
|
||||
#else
|
||||
|
||||
@interface RNFirebaseDatabaseReference : NSObject
|
||||
@end
|
||||
#endif
|
||||
|
||||
#endif
|
|
@ -0,0 +1,195 @@
|
|||
#import "RNFirebaseDatabaseReference.h"
|
||||
|
||||
#if __has_include(<FirebaseDatabase/FIRDatabase.h>)
|
||||
#import "RNFirebaseEvents.h"
|
||||
|
||||
@implementation RNFirebaseDatabaseReference
|
||||
|
||||
- (id)initWithPathAndModifiers:(RCTEventEmitter *)emitter database:(FIRDatabase *)database refId:(NSNumber *)refId path:(NSString *)path modifiers:(NSArray *)modifiers {
|
||||
self = [super init];
|
||||
if (self) {
|
||||
_emitter = emitter;
|
||||
_refId = refId;
|
||||
_path = path;
|
||||
_query = [self buildQueryAtPathWithModifiers:database path:path modifiers:modifiers];
|
||||
_listeners = [[NSMutableDictionary alloc] init];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)addEventHandler:(NSNumber *)listenerId eventName:(NSString *)eventName {
|
||||
if (!_listeners[listenerId]) {
|
||||
id andPreviousSiblingKeyWithBlock = ^(FIRDataSnapshot *_Nonnull snapshot, NSString *_Nullable previousChildName) {
|
||||
NSDictionary *props = [RNFirebaseDatabaseReference snapshotToDict:snapshot];
|
||||
[self sendJSEvent:DATABASE_DATA_EVENT title:eventName props:@{@"eventName": eventName, @"refId": _refId, @"listenerId": listenerId, @"path": _path, @"snapshot": props, @"previousChildName": previousChildName != nil ? previousChildName : [NSNull null]}];
|
||||
};
|
||||
id errorBlock = ^(NSError *_Nonnull error) {
|
||||
NSLog(@"Error onDBEvent: %@", [error debugDescription]);
|
||||
[self removeEventHandler:listenerId eventName:eventName];
|
||||
[self getAndSendDatabaseError:error listenerId:listenerId];
|
||||
};
|
||||
int eventType = [self eventTypeFromName:eventName];
|
||||
FIRDatabaseHandle handle = [_query observeEventType:eventType andPreviousSiblingKeyWithBlock:andPreviousSiblingKeyWithBlock withCancelBlock:errorBlock];
|
||||
_listeners[listenerId] = @(handle);
|
||||
} else {
|
||||
NSLog(@"Warning Trying to add duplicate listener for refId: %@ listenerId: %@", _refId, listenerId);
|
||||
}
|
||||
}
|
||||
|
||||
- (void)addSingleEventHandler:(NSString *)eventName callback:(RCTResponseSenderBlock)callback {
|
||||
FIRDataEventType firDataEventType = (FIRDataEventType)[self eventTypeFromName:eventName];
|
||||
|
||||
[_query observeSingleEventOfType:firDataEventType andPreviousSiblingKeyWithBlock:^(FIRDataSnapshot *_Nonnull snapshot, NSString *_Nullable previousChildName) {
|
||||
NSDictionary *props = [RNFirebaseDatabaseReference snapshotToDict:snapshot];
|
||||
callback(@[[NSNull null], @{@"eventName": eventName, @"path": _path, @"refId": _refId, @"snapshot": props, @"previousChildName": previousChildName != nil ? previousChildName : [NSNull null]}]);
|
||||
} withCancelBlock:^(NSError *_Nonnull error) {
|
||||
NSLog(@"Error onDBEventOnce: %@", [error debugDescription]);
|
||||
callback(@[@{@"eventName": DATABASE_ERROR_EVENT, @"path": _path, @"refId": _refId, @"code": @([error code]), @"details": [error debugDescription], @"message": [error localizedDescription], @"description": [error description]}]);
|
||||
}];
|
||||
}
|
||||
|
||||
- (void)removeEventHandler:(NSNumber *)listenerId eventName:(NSString *)eventName {
|
||||
FIRDatabaseHandle handle = (FIRDatabaseHandle) [_listeners[listenerId] integerValue];
|
||||
if (handle) {
|
||||
[_listeners removeObjectForKey:listenerId];
|
||||
[_query removeObserverWithHandle:handle];
|
||||
}
|
||||
}
|
||||
|
||||
+ (NSDictionary *)snapshotToDict:(FIRDataSnapshot *)snapshot {
|
||||
NSMutableDictionary *dict = [[NSMutableDictionary alloc] init];
|
||||
[dict setValue:snapshot.key forKey:@"key"];
|
||||
NSDictionary *val = snapshot.value;
|
||||
dict[@"value"] = val;
|
||||
// Snapshot ordering
|
||||
NSMutableArray *childKeys = [NSMutableArray array];
|
||||
if (snapshot.childrenCount > 0) {
|
||||
// Since JS does not respect object ordering of keys
|
||||
// we keep a list of the keys and their ordering
|
||||
// in the snapshot event
|
||||
NSEnumerator *children = [snapshot children];
|
||||
FIRDataSnapshot *child;
|
||||
while (child = [children nextObject]) {
|
||||
[childKeys addObject:child.key];
|
||||
}
|
||||
}
|
||||
dict[@"childKeys"] = childKeys;
|
||||
[dict setValue:@(snapshot.hasChildren) forKey:@"hasChildren"];
|
||||
[dict setValue:@(snapshot.exists) forKey:@"exists"];
|
||||
[dict setValue:@(snapshot.childrenCount) forKey:@"childrenCount"];
|
||||
[dict setValue:snapshot.priority forKey:@"priority"];
|
||||
return dict;
|
||||
}
|
||||
|
||||
- (NSDictionary *)getAndSendDatabaseError:(NSError *)error listenerId:(NSNumber *)listenerId {
|
||||
NSDictionary *event = @{@"eventName": DATABASE_ERROR_EVENT, @"path": _path, @"refId": _refId, @"listenerId": listenerId, @"code": @([error code]), @"details": [error debugDescription], @"message": [error localizedDescription], @"description": [error description]};
|
||||
|
||||
@try {
|
||||
[_emitter sendEventWithName:DATABASE_ERROR_EVENT body:event];
|
||||
} @catch (NSException *err) {
|
||||
NSLog(@"An error occurred in getAndSendDatabaseError: %@", [err debugDescription]);
|
||||
NSLog(@"Tried to send: %@ with %@", DATABASE_ERROR_EVENT, event);
|
||||
}
|
||||
|
||||
return event;
|
||||
}
|
||||
|
||||
- (void)sendJSEvent:(NSString *)type title:(NSString *)title props:(NSDictionary *)props {
|
||||
@try {
|
||||
[_emitter sendEventWithName:type body:@{@"eventName": title, @"body": props}];
|
||||
} @catch (NSException *err) {
|
||||
NSLog(@"An error occurred in sendJSEvent: %@", [err debugDescription]);
|
||||
NSLog(@"Tried to send: %@ with %@", title, props);
|
||||
}
|
||||
}
|
||||
|
||||
- (FIRDatabaseQuery *)buildQueryAtPathWithModifiers:(FIRDatabase *)database path:(NSString *)path modifiers:(NSArray *)modifiers {
|
||||
FIRDatabaseQuery *query = [[database reference] child:path];
|
||||
|
||||
for (NSDictionary *modifier in modifiers) {
|
||||
NSString *type = [modifier valueForKey:@"type"];
|
||||
NSString *name = [modifier valueForKey:@"name"];
|
||||
if ([type isEqualToString:@"orderBy"]) {
|
||||
if ([name isEqualToString:@"orderByKey"]) {
|
||||
query = [query queryOrderedByKey];
|
||||
} else if ([name isEqualToString:@"orderByPriority"]) {
|
||||
query = [query queryOrderedByPriority];
|
||||
} else if ([name isEqualToString:@"orderByValue"]) {
|
||||
query = [query queryOrderedByValue];
|
||||
} else if ([name isEqualToString:@"orderByChild"]) {
|
||||
NSString *key = [modifier valueForKey:@"key"];
|
||||
query = [query queryOrderedByChild:key];
|
||||
}
|
||||
} else if ([type isEqualToString:@"limit"]) {
|
||||
int limit = [[modifier valueForKey:@"limit"] integerValue];
|
||||
if ([name isEqualToString:@"limitToLast"]) {
|
||||
query = [query queryLimitedToLast:limit];
|
||||
} else if ([name isEqualToString:@"limitToFirst"]) {
|
||||
query = [query queryLimitedToFirst:limit];
|
||||
}
|
||||
} else if ([type isEqualToString:@"filter"]) {
|
||||
NSString *valueType = [modifier valueForKey:@"valueType"];
|
||||
NSString *key = [modifier valueForKey:@"key"];
|
||||
id value = [self getIdValue:[modifier valueForKey:@"value"] type:valueType];
|
||||
if ([name isEqualToString:@"equalTo"]) {
|
||||
if (key != nil) {
|
||||
query = [query queryEqualToValue:value childKey:key];
|
||||
} else {
|
||||
query = [query queryEqualToValue:value];
|
||||
}
|
||||
} else if ([name isEqualToString:@"endAt"]) {
|
||||
if (key != nil) {
|
||||
query = [query queryEndingAtValue:value childKey:key];
|
||||
} else {
|
||||
query = [query queryEndingAtValue:value];
|
||||
}
|
||||
} else if ([name isEqualToString:@"startAt"]) {
|
||||
if (key != nil) {
|
||||
query = [query queryStartingAtValue:value childKey:key];
|
||||
} else {
|
||||
query = [query queryStartingAtValue:value];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return query;
|
||||
}
|
||||
|
||||
- (id)getIdValue:(NSString *)value type:(NSString *)type {
|
||||
if ([type isEqualToString:@"number"]) {
|
||||
return @(value.doubleValue);
|
||||
} else if ([type isEqualToString:@"boolean"]) {
|
||||
return @(value.boolValue);
|
||||
} else {
|
||||
return value;
|
||||
}
|
||||
}
|
||||
|
||||
- (BOOL)hasListeners {
|
||||
return [[_listeners allKeys] count] > 0;
|
||||
}
|
||||
|
||||
- (int)eventTypeFromName:(NSString *)name {
|
||||
int eventType = FIRDataEventTypeValue;
|
||||
|
||||
if ([name isEqualToString:DATABASE_VALUE_EVENT]) {
|
||||
eventType = FIRDataEventTypeValue;
|
||||
} else if ([name isEqualToString:DATABASE_CHILD_ADDED_EVENT]) {
|
||||
eventType = FIRDataEventTypeChildAdded;
|
||||
} else if ([name isEqualToString:DATABASE_CHILD_MODIFIED_EVENT]) {
|
||||
eventType = FIRDataEventTypeChildChanged;
|
||||
} else if ([name isEqualToString:DATABASE_CHILD_REMOVED_EVENT]) {
|
||||
eventType = FIRDataEventTypeChildRemoved;
|
||||
} else if ([name isEqualToString:DATABASE_CHILD_MOVED_EVENT]) {
|
||||
eventType = FIRDataEventTypeChildMoved;
|
||||
}
|
||||
return eventType;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
#else
|
||||
@implementation RNFirebaseDatabase
|
||||
@end
|
||||
#endif
|
|
@ -21,6 +21,8 @@ typedef void (^RCTNotificationResponseCallback)();
|
|||
+ (void)didReceiveRemoteNotification:(nonnull NSDictionary *)userInfo;
|
||||
+ (void)didReceiveRemoteNotification:(nonnull NSDictionary *)userInfo fetchCompletionHandler:(nonnull RCTRemoteNotificationCallback)completionHandler;
|
||||
+ (void)didReceiveLocalNotification:(nonnull UILocalNotification *)notification;
|
||||
+ (void)didReceiveNotificationResponse:(nonnull UNNotificationResponse *)response withCompletionHandler:(nonnull RCTNotificationResponseCallback)completionHandler;
|
||||
+ (void)willPresentNotification:(nonnull UNNotification *)notification withCompletionHandler:(nonnull RCTWillPresentNotificationCallback)completionHandler;
|
||||
#endif
|
||||
|
||||
@end
|
||||
|
|
|
@ -145,6 +145,24 @@ RCT_EXPORT_MODULE()
|
|||
[[NSNotificationCenter defaultCenter] postNotificationName:MESSAGING_NOTIFICATION_RECEIVED object:self userInfo:@{@"data": data}];
|
||||
}
|
||||
|
||||
+ (void)willPresentNotification:(UNNotification *)notification withCompletionHandler:(nonnull RCTWillPresentNotificationCallback)completionHandler
|
||||
{
|
||||
NSMutableDictionary* data = [[NSMutableDictionary alloc] initWithDictionary: notification.request.content.userInfo];
|
||||
[data setValue:@"will_present_notification" forKey:@"_notificationType"];
|
||||
[[NSNotificationCenter defaultCenter] postNotificationName:MESSAGING_NOTIFICATION_RECEIVED object:self userInfo:@{@"data": data, @"completionHandler": completionHandler}];
|
||||
}
|
||||
|
||||
+ (void)didReceiveNotificationResponse:(UNNotificationResponse *)response withCompletionHandler:(nonnull RCTNotificationResponseCallback)completionHandler
|
||||
{
|
||||
NSMutableDictionary* data = [[NSMutableDictionary alloc] initWithDictionary: response.notification.request.content.userInfo];
|
||||
[data setValue:@"notification_response" forKey:@"_notificationType"];
|
||||
[data setValue:@YES forKey:@"opened_from_tray"];
|
||||
if (response.actionIdentifier) {
|
||||
[data setValue:response.actionIdentifier forKey:@"_actionIdentifier"];
|
||||
}
|
||||
[[NSNotificationCenter defaultCenter] postNotificationName:MESSAGING_NOTIFICATION_RECEIVED object:self userInfo:@{@"data": data, @"completionHandler": completionHandler}];
|
||||
}
|
||||
|
||||
- (id)init {
|
||||
self = [super init];
|
||||
if (self != nil) {
|
||||
|
|
|
@ -89,6 +89,29 @@ export default class Reference extends ReferenceBase {
|
|||
return promisify('set', this.database._native)(path, _value);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param priority
|
||||
* @returns {*}
|
||||
*/
|
||||
setPriority(priority: string | number | null) {
|
||||
const path = this.path;
|
||||
const _priority = this._serializeAnyType(priority);
|
||||
return promisify('priority', FirebaseDatabase)(path, _priority);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param priority
|
||||
* @returns {*}
|
||||
*/
|
||||
setWithPriority(value: any, priority: string | number | null) {
|
||||
const path = this.path;
|
||||
const _priority = this._serializeAnyType(priority);
|
||||
const _value = this._serializeAnyType(value);
|
||||
return promisify('withPriority', FirebaseDatabase)(path, _value, _priority);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param val
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "react-native-firebase",
|
||||
"version": "2.0.3",
|
||||
"version": "2.0.4",
|
||||
"author": "Invertase <contact@invertase.io> (http://invertase.io)",
|
||||
"description": "A well tested, feature rich Firebase implementation for React Native, supporting iOS & Android. Individual module support for Auth, Database, Messaging, Remote Config, Storage, Admob, Analytics, Crash Reporting, and Performance.",
|
||||
"main": "index",
|
||||
|
|
|
@ -90,16 +90,17 @@ PODS:
|
|||
- GoogleToolboxForMac/NSString+URLArguments (2.1.1)
|
||||
- GTMSessionFetcher/Core (1.1.10)
|
||||
- Protobuf (3.3.0)
|
||||
- React (0.44.3):
|
||||
- React/Core (= 0.44.3)
|
||||
- React/Core (0.44.3):
|
||||
- React (0.44.0):
|
||||
- React/Core (= 0.44.0)
|
||||
- React/Core (0.44.0):
|
||||
- React/cxxreact
|
||||
- Yoga (= 0.44.3.React)
|
||||
- React/cxxreact (0.44.3):
|
||||
- Yoga (= 0.44.0.React)
|
||||
- React/cxxreact (0.44.0):
|
||||
- React/jschelpers
|
||||
- React/jschelpers (0.44.3)
|
||||
- RNFirebase (2.0.0)
|
||||
- Yoga (0.44.3.React)
|
||||
- React/jschelpers (0.44.0)
|
||||
- RNFirebase (2.0.4):
|
||||
- React
|
||||
- Yoga (0.44.0.React)
|
||||
|
||||
DEPENDENCIES:
|
||||
- Firebase/AdMob
|
||||
|
@ -142,9 +143,9 @@ SPEC CHECKSUMS:
|
|||
GoogleToolboxForMac: 8e329f1b599f2512c6b10676d45736bcc2cbbeb0
|
||||
GTMSessionFetcher: 30d874b96d0d76028f61fbd122801e3f030d47db
|
||||
Protobuf: d582fecf68201eac3d79ed61369ef45734394b9c
|
||||
React: 6361345ebeb769a929e10a06baf0c868d6d03ad5
|
||||
RNFirebase: dcc4dcb1c9400a9bc01866e50d1351272a7df311
|
||||
Yoga: c90474ca3ec1edba44c97b6c381f03e222a9e287
|
||||
React: d2077cc20245ccdc8bfe1fdc002f2003318ae8d8
|
||||
RNFirebase: 3e5a3ff431c5c8a997152f5f19d354e1ca66f65d
|
||||
Yoga: a92a5d8e128905bf9f29c82f870192a6e873dd98
|
||||
|
||||
PODFILE CHECKSUM: 45666f734ebfc8b3b0f2be0a83bc2680caeb502f
|
||||
|
||||
|
|
|
@ -17,6 +17,7 @@ import rootTests from './rootTests';
|
|||
import transactionTests from './transactionTests';
|
||||
import queryTests from './queryTests';
|
||||
import issueSpecificTests from './issueSpecificTests';
|
||||
import priorityTests from './priorityTests';
|
||||
|
||||
import DatabaseContents from '../../support/DatabaseContents';
|
||||
|
||||
|
@ -24,6 +25,7 @@ const testGroups = [
|
|||
issueSpecificTests, factoryTests, keyTests, parentTests, childTests, rootTests,
|
||||
pushTests, onTests, onValueTests, onChildAddedTests, offTests, onceTests, updateTests,
|
||||
removeTests, setTests, transactionTests, queryTests, refTests, isEqualTests,
|
||||
priorityTests,
|
||||
];
|
||||
|
||||
function registerTestSuite(testSuite) {
|
||||
|
|
|
@ -0,0 +1,43 @@
|
|||
import DatabaseContents from '../../support/DatabaseContents';
|
||||
|
||||
function setTests({ describe, it, firebase }) {
|
||||
describe('ref().priority', () => {
|
||||
it('setPriority() should correctly set a priority for all non-null values', async () => {
|
||||
await Promise.map(Object.keys(DatabaseContents.DEFAULT), async (dataRef) => {
|
||||
// Setup
|
||||
|
||||
const ref = firebase.native.database().ref(`tests/types/${dataRef}`);
|
||||
|
||||
// Test
|
||||
|
||||
await ref.setPriority(1);
|
||||
|
||||
// Assertion
|
||||
|
||||
await ref.once('value').then((snapshot) => {
|
||||
if (snapshot.val() !== null) {
|
||||
snapshot.getPriority().should.eql(1);
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it('setWithPriority() should correctly set the priority', async () => {
|
||||
// Setup
|
||||
|
||||
const ref = firebase.native.database().ref('tests/types/number');
|
||||
|
||||
// Test
|
||||
|
||||
await ref.setWithPriority(DatabaseContents.DEFAULT.number, '2');
|
||||
|
||||
// Assertion
|
||||
|
||||
await ref.once('value').then((snapshot) => {
|
||||
snapshot.getPriority().should.eql('2');
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
export default setTests;
|
Loading…
Reference in New Issue