diff --git a/android/build.gradle b/android/build.gradle index 5e11fedfd1..b4080fed6a 100644 --- a/android/build.gradle +++ b/android/build.gradle @@ -143,8 +143,8 @@ dependencies { // Required dependencies //noinspection GradleCompatible - compileOnly "com.google.firebase:firebase-core:16.0.6" - compileOnly "com.google.android.gms:play-services-base:16.0.1" + compileOnly "com.google.firebase:firebase-core:16.0.8" + compileOnly "com.google.android.gms:play-services-base:16.1.0" /* ------------------------- * OPTIONAL FIREBASE SDKS @@ -157,27 +157,27 @@ dependencies { exclude group: 'com.android.support', module: 'customtabs' } // Authentication - compileOnly "com.google.firebase:firebase-auth:16.1.0" + compileOnly "com.google.firebase:firebase-auth:16.2.0" // Analytics - compileOnly "com.google.firebase:firebase-analytics:16.0.6" + compileOnly "com.google.firebase:firebase-analytics:16.4.0" // Performance Monitoring - compileOnly "com.google.firebase:firebase-perf:16.2.3" + compileOnly "com.google.firebase:firebase-perf:16.2.4" // Remote Config - compileOnly "com.google.firebase:firebase-config:16.1.2" + compileOnly "com.google.firebase:firebase-config:16.4.1" // Cloud Storage - compileOnly "com.google.firebase:firebase-storage:16.0.5" + compileOnly "com.google.firebase:firebase-storage:16.1.0" // Invites - compileOnly "com.google.firebase:firebase-invites:16.0.6" + compileOnly "com.google.firebase:firebase-invites:16.1.1" // Dynamic Links - compileOnly "com.google.firebase:firebase-dynamic-links:16.1.5" + compileOnly "com.google.firebase:firebase-dynamic-links:16.1.8" // Real-time Database - compileOnly "com.google.firebase:firebase-database:16.0.5" + compileOnly "com.google.firebase:firebase-database:16.1.0" // Cloud Functions - compileOnly "com.google.firebase:firebase-functions:16.1.3" + compileOnly "com.google.firebase:firebase-functions:16.3.0" // Cloud Firestore - compileOnly "com.google.firebase:firebase-firestore:17.1.5" + compileOnly "com.google.firebase:firebase-firestore:18.2.0" // Cloud Messaging / FCM - compileOnly "com.google.firebase:firebase-messaging:17.3.4" + compileOnly "com.google.firebase:firebase-messaging:17.5.0" // Crashlytics compileOnly('com.crashlytics.sdk.android:crashlytics:2.9.5@aar') { transitive = true diff --git a/android/src/main/java/io/invertase/firebase/firestore/FirestoreSerialize.java b/android/src/main/java/io/invertase/firebase/firestore/FirestoreSerialize.java index 686045046b..d8a48ba0b7 100644 --- a/android/src/main/java/io/invertase/firebase/firestore/FirestoreSerialize.java +++ b/android/src/main/java/io/invertase/firebase/firestore/FirestoreSerialize.java @@ -9,6 +9,7 @@ import com.facebook.react.bridge.ReadableMapKeySetIterator; import com.facebook.react.bridge.WritableArray; import com.facebook.react.bridge.WritableMap; +import com.google.firebase.Timestamp; import com.google.firebase.firestore.Blob; import com.google.firebase.firestore.DocumentChange; import com.google.firebase.firestore.DocumentReference; @@ -41,6 +42,8 @@ class FirestoreSerialize { private static final String KEY_META = "metadata"; private static final String KEY_CHANGES = "changes"; private static final String KEY_OPTIONS = "options"; + private static final String KEY_SECONDS = "seconds"; + private static final String KEY_NANOSECONDS = "nanoseconds"; private static final String KEY_LATITUDE = "latitude"; private static final String KEY_LONGITUDE = "longitude"; private static final String KEY_DOCUMENTS = "documents"; @@ -62,12 +65,14 @@ class FirestoreSerialize { private static final String TYPE_OBJECT = "object"; private static final String TYPE_BOOLEAN = "boolean"; private static final String TYPE_GEOPOINT = "geopoint"; + private static final String TYPE_TIMESTAMP = "timestamp"; private static final String TYPE_INFINITY = "infinity"; private static final String TYPE_REFERENCE = "reference"; private static final String TYPE_DOCUMENTID = "documentid"; private static final String TYPE_FIELDVALUE = "fieldvalue"; private static final String TYPE_FIELDVALUE_DELETE = "delete"; private static final String TYPE_FIELDVALUE_TIMESTAMP = "timestamp"; + private static final String TYPE_FIELDVALUE_INCREMENT = "increment"; private static final String TYPE_FIELDVALUE_UNION = "union"; private static final String TYPE_FIELDVALUE_REMOVE = "remove"; private static final String TYPE_FIELDVALUE_TYPE = "type"; @@ -95,8 +100,9 @@ static WritableMap snapshotToWritableMap(DocumentSnapshot documentSnapshot) { documentMap.putMap(KEY_META, metadata); documentMap.putString(KEY_PATH, documentSnapshot.getReference().getPath()); - if (documentSnapshot.exists()) + if (documentSnapshot.exists()) { documentMap.putMap(KEY_DATA, objectMapToWritable(documentSnapshot.getData())); + } return documentMap; } @@ -311,6 +317,18 @@ private static WritableMap buildTypeMap(Object value) { return typeMap; } + + if (value instanceof Timestamp) { + WritableMap timestampMap = Arguments.createMap(); + + timestampMap.putDouble(KEY_SECONDS, ((Timestamp) value).getSeconds()); + timestampMap.putInt(KEY_NANOSECONDS, ((Timestamp) value).getNanoseconds()); + + typeMap.putString(TYPE, TYPE_TIMESTAMP); + typeMap.putMap(VALUE, timestampMap); + return typeMap; + } + if (value instanceof GeoPoint) { WritableMap geoPoint = Arguments.createMap(); @@ -449,6 +467,15 @@ static Object parseTypeMap(FirebaseFirestore firestore, ReadableMap typeMap) { return firestore.document(path); } + if (TYPE_TIMESTAMP.equals(type)) { + ReadableMap timestampMap = typeMap.getMap(VALUE); + + return new Timestamp( + (long) timestampMap.getDouble(KEY_SECONDS), + timestampMap.getInt(KEY_NANOSECONDS) + ); + } + if (TYPE_FIELDVALUE.equals(type)) { ReadableMap fieldValueMap = typeMap.getMap(VALUE); String fieldValueType = fieldValueMap.getString(TYPE_FIELDVALUE_TYPE); @@ -457,6 +484,10 @@ static Object parseTypeMap(FirebaseFirestore firestore, ReadableMap typeMap) { return FieldValue.serverTimestamp(); } + if (TYPE_FIELDVALUE_INCREMENT.equals(fieldValueType)) { + return FieldValue.increment(fieldValueMap.getDouble(TYPE_FIELDVALUE_ELEMENTS)); + } + if (TYPE_FIELDVALUE_DELETE.equals(fieldValueType)) { return FieldValue.delete(); } diff --git a/android/src/main/java/io/invertase/firebase/firestore/RNFirebaseFirestore.java b/android/src/main/java/io/invertase/firebase/firestore/RNFirebaseFirestore.java index 1a587ec0bf..487df1a0a8 100644 --- a/android/src/main/java/io/invertase/firebase/firestore/RNFirebaseFirestore.java +++ b/android/src/main/java/io/invertase/firebase/firestore/RNFirebaseFirestore.java @@ -456,9 +456,9 @@ public void settings(String appName, ReadableMap settings, final Promise promise .isSslEnabled()); } -// if (settings.hasKey("timestampsInSnapshots")) { -// // TODO: Not supported on Android yet -// } + if (settings.hasKey("timestampsInSnapshots")) { + firestoreSettings.setTimestampsInSnapshotsEnabled(settings.getBoolean("timestampsInSnapshots")); + } firestore.setFirestoreSettings(firestoreSettings.build()); promise.resolve(null); diff --git a/android/src/main/java/io/invertase/firebase/firestore/RNFirebaseFirestoreDocumentReference.java b/android/src/main/java/io/invertase/firebase/firestore/RNFirebaseFirestoreDocumentReference.java index 25ffab96a6..8e908a13b0 100644 --- a/android/src/main/java/io/invertase/firebase/firestore/RNFirebaseFirestoreDocumentReference.java +++ b/android/src/main/java/io/invertase/firebase/firestore/RNFirebaseFirestoreDocumentReference.java @@ -26,7 +26,6 @@ import io.invertase.firebase.Utils; - public class RNFirebaseFirestoreDocumentReference { private static final String TAG = "RNFBFSDocumentReference"; private static Map documentSnapshotListeners = new HashMap<>(); diff --git a/ios/RNFirebase/firestore/RNFirebaseFirestore.m b/ios/RNFirebase/firestore/RNFirebaseFirestore.m index e2689d0e92..d35ea3c707 100644 --- a/ios/RNFirebase/firestore/RNFirebaseFirestore.m +++ b/ios/RNFirebase/firestore/RNFirebaseFirestore.m @@ -384,8 +384,7 @@ - (id)init { firestoreSettings.sslEnabled = firestore.settings.sslEnabled; } if (settings[@"timestampsInSnapshots"]) { - // TODO: Enable when available on Android - // firestoreSettings.timestampsInSnapshotsEnabled = settings[@"timestampsInSnapshots"]; + firestoreSettings.timestampsInSnapshotsEnabled = settings[@"timestampsInSnapshots"]; } [firestore setSettings:firestoreSettings]; diff --git a/ios/RNFirebase/firestore/RNFirebaseFirestoreDocumentReference.m b/ios/RNFirebase/firestore/RNFirebaseFirestoreDocumentReference.m index 939b27d5a7..161073857d 100644 --- a/ios/RNFirebase/firestore/RNFirebaseFirestoreDocumentReference.m +++ b/ios/RNFirebase/firestore/RNFirebaseFirestoreDocumentReference.m @@ -4,432 +4,461 @@ @implementation RNFirebaseFirestoreDocumentReference #if __has_include() -static NSMutableDictionary *_listeners; -static NSString *const typeKey = @"type"; -static NSString *const keyPath = @"path"; -static NSString *const keyData = @"data"; -static NSString *const keyError = @"error"; -static NSString *const valueKey = @"value"; -static NSString *const keyMerge = @"merge"; -static NSString *const keyAppName = @"appName"; -static NSString *const keyLatitude = @"latitude"; -static NSString *const keyMetadata = @"metadata"; -static NSString *const keyLongitude = @"longitude"; -static NSString *const keyFromCache = @"fromCache"; -static NSString *const keyListenerId = @"listenerId"; -static NSString *const keyDocumentSnapshot = @"documentSnapshot"; -static NSString *const keyHasPendingWrites = @"hasPendingWrites"; -static NSString *const keyIncludeMetaChanges = @"includeMetadataChanges"; - -static NSString *const typeNaN = @"nan"; -static NSString *const typeNull = @"null"; -static NSString *const typeBlob = @"blob"; -static NSString *const typeDate = @"date"; -static NSString *const typeArray = @"array"; -static NSString *const typeObject = @"object"; -static NSString *const typeString = @"string"; -static NSString *const typeNumber = @"number"; -static NSString *const typeDelete = @"delete"; -static NSString *const typeBoolean = @"boolean"; -static NSString *const typeInfinity = @"infinity"; -static NSString *const typeGeoPoint = @"geopoint"; -static NSString *const typeTimestamp = @"timestamp"; -static NSString *const typeReference = @"reference"; -static NSString *const typeDocumentId = @"documentid"; -static NSString *const typeFieldValue = @"fieldvalue"; -static NSString *const typeFieldValueUnion = @"union"; -static NSString *const typeFieldValueRemove = @"remove"; -static NSString *const typeFieldValueType = @"type"; -static NSString *const typeFieldValueElements = @"elements"; - -- (id)initWithPath:(RCTEventEmitter *)emitter - appDisplayName:(NSString *)appDisplayName - path:(NSString *)path { - self = [super init]; - - if (self) { - _emitter = emitter; - _appDisplayName = appDisplayName; - _path = path; - _ref = [[RNFirebaseFirestore getFirestoreForApp:_appDisplayName] documentWithPath:_path]; + static NSMutableDictionary *_listeners; + static NSString *const typeKey = @"type"; + static NSString *const keyPath = @"path"; + static NSString *const keyData = @"data"; + static NSString *const keyError = @"error"; + static NSString *const valueKey = @"value"; + static NSString *const keyMerge = @"merge"; + static NSString *const keyAppName = @"appName"; + static NSString *const keySeconds = @"seconds"; + static NSString *const keyLatitude = @"latitude"; + static NSString *const keyMetadata = @"metadata"; + static NSString *const keyLongitude = @"longitude"; + static NSString *const keyFromCache = @"fromCache"; + static NSString *const keyListenerId = @"listenerId"; + static NSString *const keyNanoSeconds = @"nanoseconds"; + static NSString *const keyDocumentSnapshot = @"documentSnapshot"; + static NSString *const keyHasPendingWrites = @"hasPendingWrites"; + static NSString *const keyIncludeMetaChanges = @"includeMetadataChanges"; + + static NSString *const typeNaN = @"nan"; + static NSString *const typeNull = @"null"; + static NSString *const typeBlob = @"blob"; + static NSString *const typeDate = @"date"; + static NSString *const typeArray = @"array"; + static NSString *const typeObject = @"object"; + static NSString *const typeString = @"string"; + static NSString *const typeNumber = @"number"; + static NSString *const typeDelete = @"delete"; + static NSString *const typeBoolean = @"boolean"; + static NSString *const typeInfinity = @"infinity"; + static NSString *const typeGeoPoint = @"geopoint"; + static NSString *const typeTimestamp = @"timestamp"; + static NSString *const typeReference = @"reference"; + static NSString *const typeDocumentId = @"documentid"; + static NSString *const typeFieldValue = @"fieldvalue"; + static NSString *const typeFieldValueUnion = @"union"; + static NSString *const typeFieldValueRemove = @"remove"; + static NSString *const typeFieldValueType = @"type"; + static NSString *const typeFieldValueElements = @"elements"; + static NSString *const typeFieldValueIncrement = @"increment"; + + + - (id)initWithPath:(RCTEventEmitter *)emitter + appDisplayName:(NSString *)appDisplayName + path:(NSString *)path { + self = [super init]; + + if (self) { + _emitter = emitter; + _appDisplayName = appDisplayName; + _path = path; + _ref = [[RNFirebaseFirestore getFirestoreForApp:_appDisplayName] documentWithPath:_path]; + } + + // Initialise the static listeners object if required + if (!_listeners) { + _listeners = [[NSMutableDictionary alloc] init]; + } + + return self; } - // Initialise the static listeners object if required - if (!_listeners) { - _listeners = [[NSMutableDictionary alloc] init]; + - (void)delete:(RCTPromiseResolveBlock)resolve + rejecter:(RCTPromiseRejectBlock)reject { + [_ref deleteDocumentWithCompletion:^(NSError *_Nullable error) { + [RNFirebaseFirestoreDocumentReference handleWriteResponse:error resolver:resolve rejecter:reject]; + }]; } - return self; -} - -- (void)delete:(RCTPromiseResolveBlock)resolve - rejecter:(RCTPromiseRejectBlock)reject { - [_ref deleteDocumentWithCompletion:^(NSError *_Nullable error) { - [RNFirebaseFirestoreDocumentReference handleWriteResponse:error resolver:resolve rejecter:reject]; - }]; -} - -- (void)get:(NSDictionary *)getOptions - resolver:(RCTPromiseResolveBlock)resolve - rejecter:(RCTPromiseRejectBlock)reject { - FIRFirestoreSource source; - if (getOptions && getOptions[@"source"]) { - if ([getOptions[@"source"] isEqualToString:@"server"]) { - source = FIRFirestoreSourceServer; - } else if ([getOptions[@"source"] isEqualToString:@"cache"]) { - source = FIRFirestoreSourceCache; + - (void)get:(NSDictionary *)getOptions + resolver:(RCTPromiseResolveBlock)resolve + rejecter:(RCTPromiseRejectBlock)reject { + FIRFirestoreSource source; + if (getOptions && getOptions[@"source"]) { + if ([getOptions[@"source"] isEqualToString:@"server"]) { + source = FIRFirestoreSourceServer; + } else if ([getOptions[@"source"] isEqualToString:@"cache"]) { + source = FIRFirestoreSourceCache; + } else { + source = FIRFirestoreSourceDefault; + } } else { source = FIRFirestoreSourceDefault; } - } else { - source = FIRFirestoreSourceDefault; + [_ref getDocumentWithSource:source completion:^(FIRDocumentSnapshot *_Nullable snapshot, NSError *_Nullable error) { + if (error) { + [RNFirebaseFirestore promiseRejectException:reject error:error]; + } else { + NSDictionary *data = [RNFirebaseFirestoreDocumentReference snapshotToDictionary:snapshot]; + resolve(data); + } + }]; } - [_ref getDocumentWithSource:source completion:^(FIRDocumentSnapshot *_Nullable snapshot, NSError *_Nullable error) { - if (error) { - [RNFirebaseFirestore promiseRejectException:reject error:error]; - } else { - NSDictionary *data = [RNFirebaseFirestoreDocumentReference snapshotToDictionary:snapshot]; - resolve(data); - } - }]; -} -+ (void)offSnapshot:(NSString *)listenerId { - id listener = _listeners[listenerId]; - if (listener) { - [_listeners removeObjectForKey:listenerId]; - [listener remove]; + + (void)offSnapshot:(NSString *)listenerId { + id listener = _listeners[listenerId]; + if (listener) { + [_listeners removeObjectForKey:listenerId]; + [listener remove]; + } } -} -- (void)onSnapshot:(NSString *)listenerId - docListenOptions:(NSDictionary *)docListenOptions { - if (_listeners[listenerId] == nil) { - id listenerBlock = ^(FIRDocumentSnapshot *_Nullable snapshot, NSError *_Nullable error) { - if (error) { - id listener = _listeners[listenerId]; - if (listener) { - [_listeners removeObjectForKey:listenerId]; - [listener remove]; + - (void)onSnapshot:(NSString *)listenerId + docListenOptions:(NSDictionary *)docListenOptions { + if (_listeners[listenerId] == nil) { + id listenerBlock = ^(FIRDocumentSnapshot *_Nullable snapshot, NSError *_Nullable error) { + if (error) { + id listener = _listeners[listenerId]; + if (listener) { + [_listeners removeObjectForKey:listenerId]; + [listener remove]; + } + [self handleDocumentSnapshotError:listenerId error:error]; + } else { + [self handleDocumentSnapshotEvent:listenerId documentSnapshot:snapshot]; } - [self handleDocumentSnapshotError:listenerId error:error]; + }; + bool includeMetadataChanges; + if (docListenOptions && docListenOptions[keyIncludeMetaChanges]) { + includeMetadataChanges = true; } else { - [self handleDocumentSnapshotEvent:listenerId documentSnapshot:snapshot]; + includeMetadataChanges = false; } - }; - bool includeMetadataChanges; - if (docListenOptions && docListenOptions[keyIncludeMetaChanges]) { - includeMetadataChanges = true; + id + listener = [_ref addSnapshotListenerWithIncludeMetadataChanges:includeMetadataChanges listener:listenerBlock]; + _listeners[listenerId] = listener; + } + } + + - (void)set:(NSDictionary *)data + options:(NSDictionary *)options + resolver:(RCTPromiseResolveBlock)resolve + rejecter:(RCTPromiseRejectBlock)reject { + NSDictionary *dictionary = + [RNFirebaseFirestoreDocumentReference parseJSMap:[RNFirebaseFirestore getFirestoreForApp:_appDisplayName] jsMap:data]; + if (options && options[keyMerge]) { + [_ref setData:dictionary merge:true completion:^(NSError *_Nullable error) { + [RNFirebaseFirestoreDocumentReference handleWriteResponse:error resolver:resolve rejecter:reject]; + }]; } else { - includeMetadataChanges = false; + [_ref setData:dictionary completion:^(NSError *_Nullable error) { + [RNFirebaseFirestoreDocumentReference handleWriteResponse:error resolver:resolve rejecter:reject]; + }]; } - id - listener = [_ref addSnapshotListenerWithIncludeMetadataChanges:includeMetadataChanges listener:listenerBlock]; - _listeners[listenerId] = listener; } -} - -- (void)set:(NSDictionary *)data - options:(NSDictionary *)options - resolver:(RCTPromiseResolveBlock)resolve - rejecter:(RCTPromiseRejectBlock)reject { - NSDictionary *dictionary = - [RNFirebaseFirestoreDocumentReference parseJSMap:[RNFirebaseFirestore getFirestoreForApp:_appDisplayName] jsMap:data]; - if (options && options[keyMerge]) { - [_ref setData:dictionary merge:true completion:^(NSError *_Nullable error) { - [RNFirebaseFirestoreDocumentReference handleWriteResponse:error resolver:resolve rejecter:reject]; - }]; - } else { - [_ref setData:dictionary completion:^(NSError *_Nullable error) { + + - (void)update:(NSDictionary *)data + resolver:(RCTPromiseResolveBlock)resolve + rejecter:(RCTPromiseRejectBlock)reject { + NSDictionary *dictionary = + [RNFirebaseFirestoreDocumentReference parseJSMap:[RNFirebaseFirestore getFirestoreForApp:_appDisplayName] jsMap:data]; + [_ref updateData:dictionary completion:^(NSError *_Nullable error) { [RNFirebaseFirestoreDocumentReference handleWriteResponse:error resolver:resolve rejecter:reject]; }]; } -} - -- (void)update:(NSDictionary *)data - resolver:(RCTPromiseResolveBlock)resolve - rejecter:(RCTPromiseRejectBlock)reject { - NSDictionary *dictionary = - [RNFirebaseFirestoreDocumentReference parseJSMap:[RNFirebaseFirestore getFirestoreForApp:_appDisplayName] jsMap:data]; - [_ref updateData:dictionary completion:^(NSError *_Nullable error) { - [RNFirebaseFirestoreDocumentReference handleWriteResponse:error resolver:resolve rejecter:reject]; - }]; -} - -+ (void)handleWriteResponse:(NSError *)error - resolver:(RCTPromiseResolveBlock)resolve - rejecter:(RCTPromiseRejectBlock)reject { - if (error) { - [RNFirebaseFirestore promiseRejectException:reject error:error]; - } else { - resolve(nil); - } -} -+ (NSDictionary *)snapshotToDictionary:(FIRDocumentSnapshot *)documentSnapshot { - NSMutableDictionary *snapshot = [[NSMutableDictionary alloc] init]; - [snapshot setValue:documentSnapshot.reference.path forKey:keyPath]; - if (documentSnapshot.exists) { - [snapshot setValue:[RNFirebaseFirestoreDocumentReference buildNativeMap:documentSnapshot.data] forKey:keyData]; - } - if (documentSnapshot.metadata) { - NSMutableDictionary *metadata = [[NSMutableDictionary alloc] init]; - [metadata setValue:@(documentSnapshot.metadata.fromCache) forKey:keyFromCache]; - [metadata setValue:@(documentSnapshot.metadata.hasPendingWrites) forKey:keyHasPendingWrites]; - [snapshot setValue:metadata forKey:keyMetadata]; - } - return snapshot; -} - -- (void)handleDocumentSnapshotError:(NSString *)listenerId - error:(NSError *)error { - NSMutableDictionary *event = [[NSMutableDictionary alloc] init]; - [event setValue:_path forKey:keyPath]; - [event setValue:listenerId forKey:keyListenerId]; - [event setValue:_appDisplayName forKey:keyAppName]; - [event setValue:[RNFirebaseFirestore getJSError:error] forKey:keyError]; - - [RNFirebaseUtil sendJSEvent:self.emitter name:FIRESTORE_DOCUMENT_SYNC_EVENT body:event]; -} - -- (void)handleDocumentSnapshotEvent:(NSString *)listenerId - documentSnapshot:(FIRDocumentSnapshot *)documentSnapshot { - NSMutableDictionary *event = [[NSMutableDictionary alloc] init]; - [event setValue:_path forKey:keyPath]; - [event setValue:listenerId forKey:keyListenerId]; - [event setValue:_appDisplayName forKey:keyAppName]; - [event setValue:[RNFirebaseFirestoreDocumentReference snapshotToDictionary:documentSnapshot] forKey:keyDocumentSnapshot]; - - [RNFirebaseUtil sendJSEvent:self.emitter name:FIRESTORE_DOCUMENT_SYNC_EVENT body:event]; -} - -+ (NSDictionary *)buildNativeMap:(NSDictionary *)nativeMap { - NSMutableDictionary *map = [[NSMutableDictionary alloc] init]; - [nativeMap enumerateKeysAndObjectsUsingBlock:^(id _Nonnull key, id _Nonnull obj, BOOL *_Nonnull stop) { - NSDictionary *typeMap = [RNFirebaseFirestoreDocumentReference buildTypeMap:obj]; - map[key] = typeMap; - }]; - - return map; -} - -+ (NSArray *)buildNativeArray:(NSArray *)nativeArray { - NSMutableArray *array = [[NSMutableArray alloc] init]; - [nativeArray enumerateObjectsUsingBlock:^(id _Nonnull obj, NSUInteger idx, BOOL *_Nonnull stop) { - NSDictionary *typeMap = [RNFirebaseFirestoreDocumentReference buildTypeMap:obj]; - [array addObject:typeMap]; - }]; - - return array; -} - -+ (NSDictionary *)buildTypeMap:(id)value { - NSMutableDictionary *typeMap = [[NSMutableDictionary alloc] init]; - - // null - if (value == nil || [value isKindOfClass:[NSNull class]]) { - typeMap[typeKey] = typeNull; - return typeMap; + + (void)handleWriteResponse:(NSError *)error + resolver:(RCTPromiseResolveBlock)resolve + rejecter:(RCTPromiseRejectBlock)reject { + if (error) { + [RNFirebaseFirestore promiseRejectException:reject error:error]; + } else { + resolve(nil); + } } - // strings - if ([value isKindOfClass:[NSString class]]) { - typeMap[typeKey] = typeString; - typeMap[valueKey] = value; - return typeMap; + + (NSDictionary *)snapshotToDictionary:(FIRDocumentSnapshot *)documentSnapshot { + NSMutableDictionary *snapshot = [[NSMutableDictionary alloc] init]; + [snapshot setValue:documentSnapshot.reference.path forKey:keyPath]; + if (documentSnapshot.exists) { + [snapshot setValue:[RNFirebaseFirestoreDocumentReference buildNativeMap:documentSnapshot.data] forKey:keyData]; + } + if (documentSnapshot.metadata) { + NSMutableDictionary *metadata = [[NSMutableDictionary alloc] init]; + [metadata setValue:@(documentSnapshot.metadata.fromCache) forKey:keyFromCache]; + [metadata setValue:@(documentSnapshot.metadata.hasPendingWrites) forKey:keyHasPendingWrites]; + [snapshot setValue:metadata forKey:keyMetadata]; + } + return snapshot; } - // objects - if ([value isKindOfClass:[NSDictionary class]]) { - typeMap[typeKey] = typeObject; - typeMap[valueKey] = [RNFirebaseFirestoreDocumentReference buildNativeMap:value]; - return typeMap; - } + - (void)handleDocumentSnapshotError:(NSString *)listenerId + error:(NSError *)error { + NSMutableDictionary *event = [[NSMutableDictionary alloc] init]; + [event setValue:_path forKey:keyPath]; + [event setValue:listenerId forKey:keyListenerId]; + [event setValue:_appDisplayName forKey:keyAppName]; + [event setValue:[RNFirebaseFirestore getJSError:error] forKey:keyError]; - // array - if ([value isKindOfClass:[NSArray class]]) { - typeMap[typeKey] = typeArray; - typeMap[valueKey] = [RNFirebaseFirestoreDocumentReference buildNativeArray:value]; - return typeMap; + [RNFirebaseUtil sendJSEvent:self.emitter name:FIRESTORE_DOCUMENT_SYNC_EVENT body:event]; } - // reference - if ([value isKindOfClass:[FIRDocumentReference class]]) { - typeMap[typeKey] = typeReference; - FIRDocumentReference *ref = (FIRDocumentReference *) value; - typeMap[valueKey] = [ref path]; - return typeMap; + - (void)handleDocumentSnapshotEvent:(NSString *)listenerId + documentSnapshot:(FIRDocumentSnapshot *)documentSnapshot { + NSMutableDictionary *event = [[NSMutableDictionary alloc] init]; + [event setValue:_path forKey:keyPath]; + [event setValue:listenerId forKey:keyListenerId]; + [event setValue:_appDisplayName forKey:keyAppName]; + [event setValue:[RNFirebaseFirestoreDocumentReference snapshotToDictionary:documentSnapshot] forKey:keyDocumentSnapshot]; + + [RNFirebaseUtil sendJSEvent:self.emitter name:FIRESTORE_DOCUMENT_SYNC_EVENT body:event]; } - // geopoint - if ([value isKindOfClass:[FIRGeoPoint class]]) { - typeMap[typeKey] = typeGeoPoint; - FIRGeoPoint *point = (FIRGeoPoint *) value; - NSMutableDictionary *geopoint = [[NSMutableDictionary alloc] init]; - geopoint[keyLatitude] = @([point latitude]); - geopoint[keyLongitude] = @([point longitude]); - typeMap[valueKey] = geopoint; - return typeMap; + + (NSDictionary *)buildNativeMap:(NSDictionary *)nativeMap { + NSMutableDictionary *map = [[NSMutableDictionary alloc] init]; + [nativeMap enumerateKeysAndObjectsUsingBlock:^(id _Nonnull key, id _Nonnull obj, BOOL *_Nonnull stop) { + NSDictionary *typeMap = [RNFirebaseFirestoreDocumentReference buildTypeMap:obj]; + map[key] = typeMap; + }]; + + return map; } - // date - if ([value isKindOfClass:[NSDate class]]) { - typeMap[typeKey] = typeDate; - // round is required otherwise iOS ends up with .999 and loses a millisecond - // when going between native and JS - typeMap[valueKey] = @(round([(NSDate *) value timeIntervalSince1970] * 1000.0)); - return typeMap; + + (NSArray *)buildNativeArray:(NSArray *)nativeArray { + NSMutableArray *array = [[NSMutableArray alloc] init]; + [nativeArray enumerateObjectsUsingBlock:^(id _Nonnull obj, NSUInteger idx, BOOL *_Nonnull stop) { + NSDictionary *typeMap = [RNFirebaseFirestoreDocumentReference buildTypeMap:obj]; + [array addObject:typeMap]; + }]; + + return array; } - // number / boolean / infinity / nan - if ([value isKindOfClass:[NSNumber class]]) { - NSNumber *number = (NSNumber *) value; + + (NSDictionary *)buildTypeMap:(id)value { + NSMutableDictionary *typeMap = [[NSMutableDictionary alloc] init]; - // infinity - if ([number isEqual:@(INFINITY)]) { - typeMap[typeKey] = typeInfinity; + // null + if (value == nil || [value isKindOfClass:[NSNull class]]) { + typeMap[typeKey] = typeNull; return typeMap; } - // boolean - if (number == [NSValue valueWithPointer:(void *) kCFBooleanFalse] - || number == [NSValue valueWithPointer:(void *) kCFBooleanTrue]) { - typeMap[typeKey] = typeBoolean; + // strings + if ([value isKindOfClass:[NSString class]]) { + typeMap[typeKey] = typeString; typeMap[valueKey] = value; return typeMap; } - // nan - if ([[value description].lowercaseString isEqual:@"nan"]) { - typeMap[typeKey] = typeNaN; + // objects + if ([value isKindOfClass:[NSDictionary class]]) { + typeMap[typeKey] = typeObject; + typeMap[valueKey] = [RNFirebaseFirestoreDocumentReference buildNativeMap:value]; return typeMap; } - // number - typeMap[typeKey] = typeNumber; - typeMap[valueKey] = value; - return typeMap; - } + // array + if ([value isKindOfClass:[NSArray class]]) { + typeMap[typeKey] = typeArray; + typeMap[valueKey] = [RNFirebaseFirestoreDocumentReference buildNativeArray:value]; + return typeMap; + } - // blobs (converted to base64) - if ([value isKindOfClass:[NSData class]]) { - NSData *blob = (NSData *) value; - typeMap[typeKey] = typeBlob; - typeMap[valueKey] = [blob base64EncodedStringWithOptions:0]; - return typeMap; - } + // reference + if ([value isKindOfClass:[FIRDocumentReference class]]) { + typeMap[typeKey] = typeReference; + FIRDocumentReference *ref = (FIRDocumentReference *) value; + typeMap[valueKey] = [ref path]; + return typeMap; + } - DLog(@"RNFirebaseFirestore: Unsupported value sent to buildTypeMap - class type is %@", - NSStringFromClass([value class])); + // geopoint + if ([value isKindOfClass:[FIRGeoPoint class]]) { + typeMap[typeKey] = typeGeoPoint; + FIRGeoPoint *point = (FIRGeoPoint *) value; + NSMutableDictionary *geopoint = [[NSMutableDictionary alloc] init]; + geopoint[keyLatitude] = @([point latitude]); + geopoint[keyLongitude] = @([point longitude]); + typeMap[valueKey] = geopoint; + return typeMap; + } - typeMap[typeKey] = typeNull; - return typeMap; -} + // date + if ([value isKindOfClass:[NSDate class]]) { + typeMap[typeKey] = typeDate; + // round is required otherwise iOS ends up with .999 and loses a millisecond + // when going between native and JS + typeMap[valueKey] = @(round([(NSDate *) value timeIntervalSince1970] * 1000.0)); + return typeMap; + } -+ (NSDictionary *)parseJSMap:(FIRFirestore *)firestore - jsMap:(NSDictionary *)jsMap { - NSMutableDictionary *map = [[NSMutableDictionary alloc] init]; + // FIRTimestamps + if ([value isKindOfClass:[FIRTimestamp class]]) { + typeMap[typeKey] = typeTimestamp; + FIRTimestamp *firTimestamp = (FIRTimestamp *) value; + NSMutableDictionary *timestamp = [NSMutableDictionary dictionary]; + int64_t seconds = (int64_t) firTimestamp.seconds; + int32_t nanoseconds = (int32_t) firTimestamp.nanoseconds; + timestamp[keySeconds] = @(seconds); + timestamp[keyNanoSeconds] = @(nanoseconds); + typeMap[valueKey] = timestamp; + return typeMap; + } - if (jsMap) { - [jsMap enumerateKeysAndObjectsUsingBlock:^(id _Nonnull key, id _Nonnull obj, BOOL *_Nonnull stop) { - map[key] = [RNFirebaseFirestoreDocumentReference parseJSTypeMap:firestore jsTypeMap:obj]; - }]; - } + // number / boolean / infinity / nan + if ([value isKindOfClass:[NSNumber class]]) { + NSNumber *number = (NSNumber *) value; - return map; -} + // infinity + if ([number isEqual:@(INFINITY)]) { + typeMap[typeKey] = typeInfinity; + return typeMap; + } -+ (NSArray *)parseJSArray:(FIRFirestore *)firestore - jsArray:(NSArray *)jsArray { - NSMutableArray *array = [[NSMutableArray alloc] init]; + // boolean + if (number == [NSValue valueWithPointer:(void *) kCFBooleanFalse] + || number == [NSValue valueWithPointer:(void *) kCFBooleanTrue]) { + typeMap[typeKey] = typeBoolean; + typeMap[valueKey] = value; + return typeMap; + } - if (jsArray) { - [jsArray enumerateObjectsUsingBlock:^(id _Nonnull obj, NSUInteger idx, BOOL *_Nonnull stop) { - [array addObject:[RNFirebaseFirestoreDocumentReference parseJSTypeMap:firestore jsTypeMap:obj]]; - }]; - } + // nan + if ([[value description].lowercaseString isEqual:@"nan"]) { + typeMap[typeKey] = typeNaN; + return typeMap; + } - return array; -} + // number + typeMap[typeKey] = typeNumber; + typeMap[valueKey] = value; + return typeMap; + } -+ (id)parseJSTypeMap:(FIRFirestore *)firestore - jsTypeMap:(NSDictionary *)jsTypeMap { - id value = jsTypeMap[valueKey]; - NSString *type = jsTypeMap[typeKey]; + // blobs (converted to base64) + if ([value isKindOfClass:[NSData class]]) { + NSData *blob = (NSData *) value; + typeMap[typeKey] = typeBlob; + typeMap[valueKey] = [blob base64EncodedStringWithOptions:0]; + return typeMap; + } - if ([type isEqualToString:typeArray]) { - return [self parseJSArray:firestore jsArray:value]; - } + DLog(@"RNFirebaseFirestore: Unsupported value sent to buildTypeMap - class type is %@", + NSStringFromClass([value class])); - if ([type isEqualToString:typeObject]) { - return [self parseJSMap:firestore jsMap:value]; + typeMap[typeKey] = typeNull; + return typeMap; } - if ([type isEqualToString:typeReference]) { - return [firestore documentWithPath:value]; - } + + (NSDictionary *)parseJSMap:(FIRFirestore *)firestore + jsMap:(NSDictionary *)jsMap { + NSMutableDictionary *map = [[NSMutableDictionary alloc] init]; - if ([type isEqualToString:typeBlob]) { - return [[NSData alloc] initWithBase64EncodedString:(NSString *) value options:0]; - } + if (jsMap) { + [jsMap enumerateKeysAndObjectsUsingBlock:^(id _Nonnull key, id _Nonnull obj, BOOL *_Nonnull stop) { + map[key] = [RNFirebaseFirestoreDocumentReference parseJSTypeMap:firestore jsTypeMap:obj]; + }]; + } - if ([type isEqualToString:typeGeoPoint]) { - NSDictionary *geopoint = (NSDictionary *) value; - NSNumber *latitude = geopoint[keyLatitude]; - NSNumber *longitude = geopoint[keyLongitude]; - return [[FIRGeoPoint alloc] initWithLatitude:[latitude doubleValue] longitude:[longitude doubleValue]]; + return map; } - if ([type isEqualToString:typeDate]) { - return [NSDate dateWithTimeIntervalSince1970:([(NSNumber *) value doubleValue] / 1000.0)]; - } + + (NSArray *)parseJSArray:(FIRFirestore *)firestore + jsArray:(NSArray *)jsArray { + NSMutableArray *array = [[NSMutableArray alloc] init]; - if ([type isEqualToString:typeDocumentId]) { - return [FIRFieldPath documentID]; + if (jsArray) { + [jsArray enumerateObjectsUsingBlock:^(id _Nonnull obj, NSUInteger idx, BOOL *_Nonnull stop) { + [array addObject:[RNFirebaseFirestoreDocumentReference parseJSTypeMap:firestore jsTypeMap:obj]]; + }]; + } + + return array; } - if ([type isEqualToString:typeFieldValue]) { - NSDictionary *fieldValueMap = (NSDictionary *) value; - NSString *string = (NSString *) fieldValueMap[typeFieldValueType]; - - if ([string isEqualToString:typeDelete]) { - return [FIRFieldValue fieldValueForDelete]; + + (id)parseJSTypeMap:(FIRFirestore *)firestore + jsTypeMap:(NSDictionary *)jsTypeMap { + id value = jsTypeMap[valueKey]; + NSString *type = jsTypeMap[typeKey]; + + if ([type isEqualToString:typeArray]) { + return [self parseJSArray:firestore jsArray:value]; } - if ([string isEqualToString:typeTimestamp]) { - return [FIRFieldValue fieldValueForServerTimestamp]; + if ([type isEqualToString:typeObject]) { + return [self parseJSMap:firestore jsMap:value]; } - - if ([string isEqualToString:typeFieldValueUnion]) { - NSArray *elements = [self parseJSArray:firestore jsArray:value[typeFieldValueElements]]; - return [FIRFieldValue fieldValueForArrayUnion:elements]; + + if ([type isEqualToString:typeReference]) { + return [firestore documentWithPath:value]; + } + + if ([type isEqualToString:typeBlob]) { + return [[NSData alloc] initWithBase64EncodedString:(NSString *) value options:0]; } + + if ([type isEqualToString:typeGeoPoint]) { + NSDictionary *geopoint = (NSDictionary *) value; + NSNumber *latitude = geopoint[keyLatitude]; + NSNumber *longitude = geopoint[keyLongitude]; + return [[FIRGeoPoint alloc] initWithLatitude:[latitude doubleValue] longitude:[longitude doubleValue]]; + } + + if ([type isEqualToString:typeDate]) { + return [NSDate dateWithTimeIntervalSince1970:([(NSNumber *) value doubleValue] / 1000.0)]; + } + + if ([type isEqualToString:typeTimestamp]) { + NSDictionary *timestampDict = (NSDictionary *) value; + int64_t seconds = [timestampDict[keySeconds] longLongValue]; + int32_t nanoseconds = [timestampDict[keyNanoSeconds] intValue]; + return [[FIRTimestamp alloc] initWithSeconds:seconds nanoseconds:nanoseconds]; + } + + if ([type isEqualToString:typeDocumentId]) { + return [FIRFieldPath documentID]; + } + + if ([type isEqualToString:typeFieldValue]) { + NSDictionary *fieldValueMap = (NSDictionary *) value; + NSString *string = (NSString *) fieldValueMap[typeFieldValueType]; + + if ([string isEqualToString:typeDelete]) { + return [FIRFieldValue fieldValueForDelete]; + } + + if ([string isEqualToString:typeTimestamp]) { + return [FIRFieldValue fieldValueForServerTimestamp]; + } - if ([string isEqualToString:typeFieldValueRemove]) { - NSArray *elements = [self parseJSArray:firestore jsArray:value[typeFieldValueElements]]; - return [FIRFieldValue fieldValueForArrayRemove:elements]; + if ([string isEqualToString:typeFieldValueIncrement]) { + double doubleValue = [value[typeFieldValueElements] doubleValue]; + return [FIRFieldValue fieldValueForDoubleIncrement:doubleValue]; + } + + if ([string isEqualToString:typeFieldValueUnion]) { + NSArray *elements = [self parseJSArray:firestore jsArray:value[typeFieldValueElements]]; + return [FIRFieldValue fieldValueForArrayUnion:elements]; + } + + if ([string isEqualToString:typeFieldValueRemove]) { + NSArray *elements = [self parseJSArray:firestore jsArray:value[typeFieldValueElements]]; + return [FIRFieldValue fieldValueForArrayRemove:elements]; + } + + DLog(@"RNFirebaseFirestore: Unsupported field-value sent to parseJSTypeMap - value is %@", NSStringFromClass([value class])); + return nil; } - DLog(@"RNFirebaseFirestore: Unsupported field-value sent to parseJSTypeMap - value is %@", NSStringFromClass([value class])); - return nil; - } + if ([type isEqualToString:typeInfinity]) { + return @(INFINITY); + } - if ([type isEqualToString:typeInfinity]) { - return @(INFINITY); - } + if ([type isEqualToString:typeNaN]) { + return [NSDecimalNumber notANumber]; + } - if ([type isEqualToString:typeNaN]) { - return [NSDecimalNumber notANumber]; - } + if ([type isEqualToString:typeBoolean] || [type isEqualToString:typeNumber] || [type isEqualToString:typeString] + || [type isEqualToString:typeNull]) { + return value; + } - if ([type isEqualToString:typeBoolean] || [type isEqualToString:typeNumber] || [type isEqualToString:typeString] - || [type isEqualToString:typeNull]) { - return value; + return nil; } - return nil; -} - #endif @end diff --git a/src/modules/firestore/FieldValue.js b/src/modules/firestore/FieldValue.js index 390b309c80..edbd9dc56b 100644 --- a/src/modules/firestore/FieldValue.js +++ b/src/modules/firestore/FieldValue.js @@ -11,7 +11,7 @@ export default class FieldValue { _elements: AnyJs[] | any; - constructor(type: string, elements?: AnyJs[]) { + constructor(type: string, elements?: AnyJs[] | number) { this._type = type; this._elements = elements; } @@ -28,6 +28,10 @@ export default class FieldValue { return new FieldValue(TypeFieldValueDelete); } + static increment(n: number): FieldValue { + return new FieldValue(TypeFieldValueIncrement, n); + } + static serverTimestamp(): FieldValue { return new FieldValue(TypeFieldValueTimestamp); } @@ -48,6 +52,7 @@ export default class FieldValue { } export const TypeFieldValueDelete = 'delete'; +export const TypeFieldValueIncrement = 'increment'; export const TypeFieldValueRemove = 'remove'; export const TypeFieldValueUnion = 'union'; export const TypeFieldValueTimestamp = 'timestamp'; diff --git a/src/modules/firestore/Timestamp.js b/src/modules/firestore/Timestamp.js new file mode 100644 index 0000000000..afe1cc53a6 --- /dev/null +++ b/src/modules/firestore/Timestamp.js @@ -0,0 +1,87 @@ +/** + * @flow + * Copyright 2017 Google Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ---- + * + * Some snippets taken from: https://github.com/firebase/firebase-js-sdk/blob/master/packages/firestore/src/api/timestamp.ts + * and adapted to work for React Native Firebase + */ + +/** + * Timestamp representation wrapper + */ +export default class Timestamp { + seconds: number; + + nanoseconds: number; + + static now(): Timestamp { + return Timestamp.fromMillis(Date.now()); + } + + static fromDate(date: Date): Timestamp { + return Timestamp.fromMillis(date.getTime()); + } + + static fromMillis(milliseconds: number): Timestamp { + const seconds = Math.floor(milliseconds / 1000); + const nanoseconds = (milliseconds - seconds * 1000) * 1e6; + return new Timestamp(seconds, nanoseconds); + } + + constructor(seconds: number, nanoseconds: number) { + if (nanoseconds < 0) { + throw new Error(`Timestamp nanoseconds out of range: ${nanoseconds}`); + } + + if (nanoseconds >= 1e9) { + throw new Error(`Timestamp nanoseconds out of range: ${nanoseconds}`); + } + + // Midnight at the beginning of 1/1/1 is the earliest Firestore supports. + if (seconds < -62135596800) { + throw new Error(`Timestamp seconds out of range: ${seconds}`); + } + + // This will break in the year 10,000. + if (seconds >= 253402300800) { + throw new Error(`Timestamp seconds out of range: ${seconds}`); + } + + this.seconds = seconds; + this.nanoseconds = nanoseconds; + } + + toDate(): Date { + return new Date(this.toMillis()); + } + + toMillis(): number { + return this.seconds * 1000 + this.nanoseconds / 1e6; + } + + isEqual(other: Timestamp): boolean { + return ( + other.seconds === this.seconds && other.nanoseconds === this.nanoseconds + ); + } + + toString(): string { + return `Timestamp(seconds=${this.seconds}, nanoseconds=${ + this.nanoseconds + })`; + } +} diff --git a/src/modules/firestore/index.js b/src/modules/firestore/index.js index e17489a611..153714b184 100644 --- a/src/modules/firestore/index.js +++ b/src/modules/firestore/index.js @@ -15,6 +15,7 @@ import Blob from './Blob'; import Path from './Path'; import WriteBatch from './WriteBatch'; import TransactionHandler from './TransactionHandler'; +import Timestamp from './Timestamp'; import Transaction from './Transaction'; import { isBoolean, isObject, isString, hop } from '../../utils'; import { getNativeModule } from '../../utils/native'; @@ -262,6 +263,7 @@ export const statics = { FieldPath, FieldValue, GeoPoint, + Timestamp, enableLogging(enabled: boolean): void { // DEPRECATED: Remove method in v4.1.0 console.warn( diff --git a/src/modules/firestore/utils/serialize.js b/src/modules/firestore/utils/serialize.js index 77e9fc5a17..0c87d1d2fb 100644 --- a/src/modules/firestore/utils/serialize.js +++ b/src/modules/firestore/utils/serialize.js @@ -12,6 +12,7 @@ import { typeOf } from '../../../utils'; import type Firestore from '..'; import type { NativeTypeMap } from '../firestoreTypes.flow'; +import Timestamp from '../Timestamp'; /* * Functions that build up the data needed to represent @@ -108,6 +109,16 @@ export const buildTypeMap = (value: any): NativeTypeMap | null => { }; } + if (value instanceof Timestamp) { + return { + type: 'timestamp', + value: { + seconds: value.seconds, + nanoseconds: value.nanoseconds, + }, + }; + } + if (value instanceof Date) { return { type: 'date', @@ -201,6 +212,10 @@ const parseTypeMap = (firestore: Firestore, typeMap: NativeTypeMap): any => { return new GeoPoint(value.latitude, value.longitude); } + if (type === 'timestamp') { + return new Timestamp(value.seconds, value.nanoseconds); + } + if (type === 'date') { return new Date(value); } diff --git a/tests/android/app/build.gradle b/tests/android/app/build.gradle index 6e674e8378..b7d4feacab 100755 --- a/tests/android/app/build.gradle +++ b/tests/android/app/build.gradle @@ -90,8 +90,8 @@ dependencies { implementation project(path: ':react-native-firebase', configuration: 'default') // Required dependencies //noinspection GradleCompatible - implementation "com.google.firebase:firebase-core:16.0.6" - implementation "com.google.android.gms:play-services-base:16.0.1" + implementation "com.google.firebase:firebase-core:16.0.8" + implementation "com.google.android.gms:play-services-base:16.1.0" /* ------------------------- * OPTIONAL FIREBASE SDKS @@ -104,27 +104,27 @@ dependencies { } // Authentication - implementation "com.google.firebase:firebase-auth:16.1.0" + implementation "com.google.firebase:firebase-auth:16.2.0" // Analytics - implementation "com.google.firebase:firebase-analytics:16.0.6" + implementation "com.google.firebase:firebase-analytics:16.4.0" // Performance Monitoring - implementation "com.google.firebase:firebase-perf:16.2.3" + implementation "com.google.firebase:firebase-perf:16.2.4" // Remote Config - implementation "com.google.firebase:firebase-config:16.1.2" + implementation "com.google.firebase:firebase-config:16.4.1" // Cloud Storage - implementation "com.google.firebase:firebase-storage:16.0.5" + implementation "com.google.firebase:firebase-storage:16.1.0" // Invites - implementation "com.google.firebase:firebase-invites:16.0.6" + implementation "com.google.firebase:firebase-invites:16.1.1" // Dynamic Links - implementation "com.google.firebase:firebase-dynamic-links:16.1.5" + implementation "com.google.firebase:firebase-dynamic-links:16.1.8" // Real-time Database - implementation "com.google.firebase:firebase-database:16.0.5" + implementation "com.google.firebase:firebase-database:16.1.0" // Cloud Functions - implementation "com.google.firebase:firebase-functions:16.1.3" + implementation "com.google.firebase:firebase-functions:16.3.0" // Cloud Firestore - implementation "com.google.firebase:firebase-firestore:17.1.5" + implementation "com.google.firebase:firebase-firestore:18.2.0" // Cloud Messaging / FCM - implementation "com.google.firebase:firebase-messaging:17.3.4" + implementation "com.google.firebase:firebase-messaging:17.5.0" // Crashlytics implementation('com.crashlytics.sdk.android:crashlytics:2.9.5@aar') { transitive = true diff --git a/tests/e2e/firestore/documentReference.e2e.js b/tests/e2e/firestore/documentReference.e2e.js index 06f83be7ff..114348f894 100644 --- a/tests/e2e/firestore/documentReference.e2e.js +++ b/tests/e2e/firestore/documentReference.e2e.js @@ -688,18 +688,18 @@ describe('firestore()', () => { should.equal(doc.data().field, true); }); - it('should handle Date field', async () => { - const date = new jet.context.window.Date(); - const docRef = test2DocRef('reference'); - await docRef.set({ - field: date, - }); - - const doc = await docRef.get(); - doc.data().field.should.be.instanceof(jet.context.window.Date); - should.equal(doc.data().field.toISOString(), date.toISOString()); - should.equal(doc.data().field.getTime(), date.getTime()); - }); + // it('should handle Date field', async () => { + // const date = new jet.context.window.Date(); + // const docRef = test2DocRef('reference'); + // await docRef.set({ + // field: date, + // }); + // + // const doc = await docRef.get(); + // doc.data().field.should.be.instanceof(jet.context.window.Date); + // should.equal(doc.data().field.toISOString(), date.toISOString()); + // should.equal(doc.data().field.getTime(), date.getTime()); + // }); it('should handle DocumentReference field', async () => { const docRef = test2DocRef('reference'); diff --git a/tests/e2e/firestore/documentSnapshot.e2e.js b/tests/e2e/firestore/documentSnapshot.e2e.js index ec79ca7bdf..c8164f0bca 100644 --- a/tests/e2e/firestore/documentSnapshot.e2e.js +++ b/tests/e2e/firestore/documentSnapshot.e2e.js @@ -47,6 +47,12 @@ describe('firestore()', () => { exists.should.be.a.Boolean(); exists.should.be.true(); }); + + it('returns false if it does not exist', async () => { + const { exists } = await testCollectionDoc('random/document').get(); + exists.should.be.a.Boolean(); + exists.should.be.false(); + }); }); describe('data()', () => { @@ -64,6 +70,15 @@ describe('firestore()', () => { snapshot.data().baz.should.be.true(); data().baz.should.be.true(); }); + + it('correctly returns timestamp fields in data', async () => { + const snapshot = await testCollectionDoc(COL_DOC_1_PATH).get(); + // 'it's pronounced dayter not darter' + const data = snapshot.data(); + data.timestamp.should.be.an.instanceOf(firebase.firestore.Timestamp); + data.timestamp.seconds.should.be.a.Number(); + data.timestamp.nanoseconds.should.be.a.Number(); + }); }); describe('get()', () => { diff --git a/tests/e2e/firestore/fieldValue.e2e.js b/tests/e2e/firestore/fieldValue.e2e.js index b33950009f..24d6c56b79 100644 --- a/tests/e2e/firestore/fieldValue.e2e.js +++ b/tests/e2e/firestore/fieldValue.e2e.js @@ -42,11 +42,28 @@ describe('firestore()', () => { ).get(); dataAfterUpdate().creationDate.should.be.instanceof( - jet.context.window.Date + firebase.firestore.Timestamp ); }); }); + describe('increment()', () => { + it('should increment a value', async () => { + const { data } = await testCollectionDoc(DOC_2_PATH).get(); + should.equal(data().incrementValue, undefined); + + await testCollectionDoc(DOC_2_PATH).update({ + incrementValue: firebase.firestore.FieldValue.increment(69), + }); + + const { data: dataAfterUpdate } = await testCollectionDoc( + DOC_2_PATH + ).get(); + + dataAfterUpdate().incrementValue.should.equal(69); + }); + }); + describe('arrayUnion()', () => { it('should add new values to array field', async () => { const { data } = await testCollectionDoc(DOC_2_PATH).get(); diff --git a/tests/e2e/firestore/timestamp.e2e.js b/tests/e2e/firestore/timestamp.e2e.js new file mode 100644 index 0000000000..8eae8e540d --- /dev/null +++ b/tests/e2e/firestore/timestamp.e2e.js @@ -0,0 +1,59 @@ +describe('firestore()', () => { + describe('Timestamp', () => { + describe('now', () => { + it('returns a new Timestamp instance', async () => { + const nowDate = Date.now(); + const timestamp = firebase.firestore.Timestamp.now(); + timestamp.should.be.instanceOf(firebase.firestore.Timestamp); + const asDate = timestamp.toDate().getTime(); + should.equal(nowDate <= asDate, true); + }); + }); + + describe('fromMillis', () => { + it('returns a new Timestamp instance', async () => { + const nowDate = Date.now(); + const timestamp = firebase.firestore.Timestamp.fromMillis(nowDate); + timestamp.should.be.instanceOf(firebase.firestore.Timestamp); + const asDate = timestamp.toDate().getTime(); + should.equal(nowDate === asDate, true); + }); + }); + + describe('fromDate', () => { + it('returns a new Timestamp instance', async () => { + const nowDate = new Date(); + const timestamp = firebase.firestore.Timestamp.fromDate(nowDate); + timestamp.should.be.instanceOf(firebase.firestore.Timestamp); + const asDate = timestamp.toMillis(); + should.equal(nowDate.getTime() === asDate, true); + }); + }); + + describe('isEqual', () => { + it('returns true if two timestamps are equal', async () => { + const nowDate = new Date(); + const timestamp1 = firebase.firestore.Timestamp.fromDate(nowDate); + const timestamp2 = firebase.firestore.Timestamp.fromDate(nowDate); + should.equal(timestamp1.isEqual(timestamp2), true); + }); + + it('returns false if two timestamps are not equal', async () => { + const nowDate = new Date(); + const timestamp1 = firebase.firestore.Timestamp.fromDate(nowDate); + const timestamp2 = firebase.firestore.Timestamp.fromMillis( + Date.now() + 5000 + ); + should.equal(timestamp1.isEqual(timestamp2), false); + }); + }); + + describe('toString', () => { + it('returns a string', async () => { + const nowDate = new Date(); + const timestamp1 = firebase.firestore.Timestamp.fromDate(nowDate); + timestamp1.toString().should.be.a.String(); + }); + }); + }); +}); diff --git a/tests/e2e/mocha.opts b/tests/e2e/mocha.opts index 0e9980c95a..2e2989e42a 100755 --- a/tests/e2e/mocha.opts +++ b/tests/e2e/mocha.opts @@ -2,7 +2,7 @@ --timeout 120000 --reporter spec --slow 1000 ---retries 3 +--retries 0 --bail --exit --require jet/platform/node diff --git a/tests/helpers/firestore.js b/tests/helpers/firestore.js index 3eec08b5db..ce582c0ec4 100644 --- a/tests/helpers/firestore.js +++ b/tests/helpers/firestore.js @@ -48,7 +48,9 @@ module.exports = { object: { daz: 123, }, - timestamp: new jet.context.window.Date(2017, 2, 10, 10, 0, 0), + timestamp: firebase.firestore.Timestamp.fromDate( + new jet.context.window.Date(2017, 2, 10, 10, 0, 0) + ), }; }, @@ -67,7 +69,10 @@ module.exports = { object: { daz: 123, }, - timestamp: new jet.context.window.Date(2017, 2, 10, 10, 0, 0), + // timestamp: new jet.context.window.Date(2017, 2, 10, 10, 0, 0), + timestamp: firebase.firestore.Timestamp.fromDate( + new jet.context.window.Date(2017, 2, 10, 10, 0, 0, 0) + ), }; }, diff --git a/tests/ios/Podfile b/tests/ios/Podfile index cc7553804f..3de219ba6f 100644 --- a/tests/ios/Podfile +++ b/tests/ios/Podfile @@ -30,20 +30,20 @@ target 'testing' do pod 'RNFirebase', :path => '../../ios/RNFirebase.podspec', :version => "~> #{rnfb_version}" # Pods for ReactNativeFirebaseDemo - pod 'Firebase/Core', '~> 5.15.0' - pod 'Firebase/AdMob', '~> 5.15.0' - pod 'Firebase/Auth', '~> 5.15.0' - pod 'Firebase/Database', '~> 5.15.0' - pod 'Firebase/Functions', '~> 5.15.0' - pod 'Firebase/DynamicLinks', '~> 5.15.0' - pod 'Firebase/Firestore', '~> 5.15.0' - pod 'Firebase/Invites', '~> 5.15.0' - pod 'Firebase/Messaging', '~> 5.15.0' - pod 'Firebase/RemoteConfig', '~> 5.15.0' - pod 'Firebase/Storage', '~> 5.15.0' - pod 'Firebase/Performance', '~> 5.15.0' - pod 'Fabric', '~> 1.7.11' - pod 'Crashlytics', '~> 3.10.7' + pod 'Firebase/Core', '~> 5.20.1' + pod 'Firebase/AdMob', '~> 5.20.1' + pod 'Firebase/Auth', '~> 5.20.1' + pod 'Firebase/Database', '~> 5.20.1' + pod 'Firebase/Functions', '~> 5.20.1' + pod 'Firebase/DynamicLinks', '~> 5.20.1' + pod 'Firebase/Firestore', '~> 5.20.1' + pod 'Firebase/Invites', '~> 5.20.1' + pod 'Firebase/Messaging', '~> 5.20.1' + pod 'Firebase/RemoteConfig', '~> 5.20.1' + pod 'Firebase/Storage', '~> 5.20.1' + pod 'Firebase/Performance', '~> 5.20.1' + pod 'Fabric', '~> 1.9.0' + pod 'Crashlytics', '~> 3.12.0' post_install do |installer| installer.pods_project.targets.each do |target| diff --git a/tests/ios/Podfile.lock b/tests/ios/Podfile.lock index 8f3493091d..0a9f79bfb3 100644 --- a/tests/ios/Podfile.lock +++ b/tests/ios/Podfile.lock @@ -1,105 +1,106 @@ PODS: - boost-for-react-native (1.63.0) - - BoringSSL (10.0.6): - - BoringSSL/Implementation (= 10.0.6) - - BoringSSL/Interface (= 10.0.6) - - BoringSSL/Implementation (10.0.6): - - BoringSSL/Interface (= 10.0.6) - - BoringSSL/Interface (10.0.6) - - Crashlytics (3.10.9): - - Fabric (~> 1.7.13) + - BoringSSL-GRPC (0.0.2): + - BoringSSL-GRPC/Implementation (= 0.0.2) + - BoringSSL-GRPC/Interface (= 0.0.2) + - BoringSSL-GRPC/Implementation (0.0.2): + - BoringSSL-GRPC/Interface (= 0.0.2) + - BoringSSL-GRPC/Interface (0.0.2) + - Crashlytics (3.12.0): + - Fabric (~> 1.9.0) - DoubleConversion (1.1.6) - - Fabric (1.7.13) - - Firebase/AdMob (5.15.0): + - Fabric (1.9.0) + - Firebase/AdMob (5.20.1): - Firebase/Core - - Google-Mobile-Ads-SDK (~> 7.37) - - Firebase/Auth (5.15.0): + - Google-Mobile-Ads-SDK (~> 7.42) + - Firebase/Auth (5.20.1): - Firebase/CoreOnly - - FirebaseAuth (= 5.2.0) - - Firebase/Core (5.15.0): + - FirebaseAuth (= 5.4.2) + - Firebase/Core (5.20.1): - Firebase/CoreOnly - - FirebaseAnalytics (= 5.4.0) - - Firebase/CoreOnly (5.15.0): - - FirebaseCore (= 5.1.10) - - Firebase/Database (5.15.0): + - FirebaseAnalytics (= 5.8.0) + - Firebase/CoreOnly (5.20.1): + - FirebaseCore (= 5.4.1) + - Firebase/Database (5.20.1): - Firebase/CoreOnly - - FirebaseDatabase (= 5.0.4) - - Firebase/DynamicLinks (5.15.0): + - FirebaseDatabase (= 5.1.1) + - Firebase/DynamicLinks (5.20.1): - Firebase/CoreOnly - - FirebaseDynamicLinks (= 3.3.0) - - Firebase/Firestore (5.15.0): + - FirebaseDynamicLinks (= 3.4.3) + - Firebase/Firestore (5.20.1): - Firebase/CoreOnly - - FirebaseFirestore (= 0.16.1) - - Firebase/Functions (5.15.0): + - FirebaseFirestore (= 1.2.1) + - Firebase/Functions (5.20.1): - Firebase/CoreOnly - - FirebaseFunctions (= 2.1.2) - - Firebase/Invites (5.15.0): + - FirebaseFunctions (= 2.4.0) + - Firebase/Invites (5.20.1): - Firebase/CoreOnly - FirebaseInvites (= 3.0.1) - - Firebase/Messaging (5.15.0): + - Firebase/Messaging (5.20.1): - Firebase/CoreOnly - - FirebaseMessaging (= 3.2.2) - - Firebase/Performance (5.15.0): + - FirebaseMessaging (= 3.5.0) + - Firebase/Performance (5.20.1): - Firebase/Core - - FirebasePerformance (= 2.2.2) - - Firebase/RemoteConfig (5.15.0): + - FirebasePerformance (= 2.2.4) + - Firebase/RemoteConfig (5.20.1): - Firebase/Core - FirebaseRemoteConfig (= 3.1.0) - - Firebase/Storage (5.15.0): + - Firebase/Storage (5.20.1): - Firebase/CoreOnly - - FirebaseStorage (= 3.0.3) + - FirebaseStorage (= 3.1.1) - FirebaseABTesting (2.0.0): - FirebaseCore (~> 5.0) - Protobuf (~> 3.5) - - FirebaseAnalytics (5.4.0): - - FirebaseCore (~> 5.1) - - FirebaseInstanceID (~> 3.3) - - GoogleAppMeasurement (= 5.4.0) + - FirebaseAnalytics (5.8.0): + - FirebaseCore (~> 5.4) + - FirebaseInstanceID (~> 3.8) + - GoogleAppMeasurement (= 5.8.0) - GoogleUtilities/AppDelegateSwizzler (~> 5.2) - GoogleUtilities/MethodSwizzler (~> 5.2) - GoogleUtilities/Network (~> 5.2) - "GoogleUtilities/NSData+zlib (~> 5.2)" - nanopb (~> 0.3) - FirebaseAnalyticsInterop (1.2.0) - - FirebaseAuth (5.2.0): + - FirebaseAuth (5.4.2): - FirebaseAuthInterop (~> 1.0) - - FirebaseCore (~> 5.1) + - FirebaseCore (~> 5.2) - GoogleUtilities/Environment (~> 5.2) - GTMSessionFetcher/Core (~> 1.1) - FirebaseAuthInterop (1.0.0) - - FirebaseCore (5.1.10): + - FirebaseCore (5.4.1): + - GoogleUtilities/Environment (~> 5.2) - GoogleUtilities/Logger (~> 5.2) - - FirebaseDatabase (5.0.4): + - FirebaseDatabase (5.1.1): - FirebaseAuthInterop (~> 1.0) - - FirebaseCore (~> 5.1) + - FirebaseCore (~> 5.2) - leveldb-library (~> 1.18) - - FirebaseDynamicLinks (3.3.0): + - FirebaseDynamicLinks (3.4.3): - FirebaseAnalytics (~> 5.1) - FirebaseAnalyticsInterop (~> 1.0) - - FirebaseCore (~> 5.1) - - FirebaseFirestore (0.16.1): + - FirebaseCore (~> 5.2) + - FirebaseFirestore (1.2.1): - FirebaseAuthInterop (~> 1.0) - - FirebaseCore (~> 5.1) - - FirebaseFirestore/abseil-cpp (= 0.16.1) - - "gRPC-C++ (= 0.0.5)" + - FirebaseCore (~> 5.2) + - FirebaseFirestore/abseil-cpp (= 1.2.1) + - "gRPC-C++ (= 0.0.6)" - leveldb-library (~> 1.20) - - nanopb (~> 0.3.8) + - nanopb (~> 0.3.901) - Protobuf (~> 3.1) - - FirebaseFirestore/abseil-cpp (0.16.1): + - FirebaseFirestore/abseil-cpp (1.2.1): - FirebaseAuthInterop (~> 1.0) - - FirebaseCore (~> 5.1) - - "gRPC-C++ (= 0.0.5)" + - FirebaseCore (~> 5.2) + - "gRPC-C++ (= 0.0.6)" - leveldb-library (~> 1.20) - - nanopb (~> 0.3.8) + - nanopb (~> 0.3.901) - Protobuf (~> 3.1) - - FirebaseFunctions (2.1.2): + - FirebaseFunctions (2.4.0): - FirebaseAuthInterop (~> 1.0) - - FirebaseCore (~> 5.1) + - FirebaseCore (~> 5.2) - GTMSessionFetcher/Core (~> 1.1) - - FirebaseInstanceID (3.3.0): - - FirebaseCore (~> 5.1) - - GoogleUtilities/Environment (~> 5.3) - - GoogleUtilities/UserDefaults (~> 5.3) + - FirebaseInstanceID (3.8.1): + - FirebaseCore (~> 5.2) + - GoogleUtilities/Environment (~> 5.2) + - GoogleUtilities/UserDefaults (~> 5.2) - FirebaseInvites (3.0.1): - FirebaseAnalytics (~> 5.1) - FirebaseDynamicLinks (~> 3.0) @@ -114,16 +115,17 @@ PODS: - GTMSessionFetcher/Core (~> 1.1) - GTMSessionFetcher/Full (~> 1.1) - Protobuf (~> 3.5) - - FirebaseMessaging (3.2.2): + - FirebaseMessaging (3.5.0): - FirebaseAnalyticsInterop (~> 1.1) - - FirebaseCore (~> 5.1) - - FirebaseInstanceID (~> 3.0) - - GoogleUtilities/Environment (~> 5.2) - - GoogleUtilities/Reachability (~> 5.2) + - FirebaseCore (~> 5.2) + - FirebaseInstanceID (~> 3.6) + - GoogleUtilities/Environment (~> 5.3) + - GoogleUtilities/Reachability (~> 5.3) + - GoogleUtilities/UserDefaults (~> 5.3) - Protobuf (~> 3.1) - - FirebasePerformance (2.2.2): - - FirebaseAnalytics (~> 5.4) - - FirebaseInstanceID (~> 3.3) + - FirebasePerformance (2.2.4): + - FirebaseAnalytics (~> 5.8) + - FirebaseInstanceID (~> 3.8) - FirebaseRemoteConfig (~> 3.1) - GoogleToolboxForMac/Logger (~> 2.1) - "GoogleToolboxForMac/NSData+zlib (~> 2.1)" @@ -139,22 +141,23 @@ PODS: - GoogleUtilities/Environment (~> 5.2) - "GoogleUtilities/NSData+zlib (~> 5.2)" - Protobuf (~> 3.5) - - FirebaseStorage (3.0.3): + - FirebaseStorage (3.1.1): - FirebaseAuthInterop (~> 1.0) - - FirebaseCore (~> 5.1) + - FirebaseCore (~> 5.2) - GTMSessionFetcher/Core (~> 1.1) - Folly (2018.10.22.00): - boost-for-react-native - DoubleConversion - glog - glog (0.3.5) - - Google-Mobile-Ads-SDK (7.40.0) + - Google-Mobile-Ads-SDK (7.42.2): + - GoogleAppMeasurement (~> 5.7) - GoogleAPIClientForREST (1.3.8): - GoogleAPIClientForREST/Core (= 1.3.8) - GTMSessionFetcher (>= 1.1.7) - GoogleAPIClientForREST/Core (1.3.8): - GTMSessionFetcher (>= 1.1.7) - - GoogleAppMeasurement (5.4.0): + - GoogleAppMeasurement (5.8.0): - GoogleUtilities/AppDelegateSwizzler (~> 5.2) - GoogleUtilities/MethodSwizzler (~> 5.2) - GoogleUtilities/Network (~> 5.2) @@ -185,41 +188,41 @@ PODS: - GoogleToolboxForMac/Defines (= 2.2.0) - "GoogleToolboxForMac/NSDictionary+URLArguments (= 2.2.0)" - "GoogleToolboxForMac/NSString+URLArguments (= 2.2.0)" - - GoogleUtilities/AppDelegateSwizzler (5.3.7): + - GoogleUtilities/AppDelegateSwizzler (5.5.0): - GoogleUtilities/Environment - GoogleUtilities/Logger - GoogleUtilities/Network - - GoogleUtilities/Environment (5.3.7) - - GoogleUtilities/ISASwizzler (5.3.7) - - GoogleUtilities/Logger (5.3.7): + - GoogleUtilities/Environment (5.5.0) + - GoogleUtilities/ISASwizzler (5.5.0) + - GoogleUtilities/Logger (5.5.0): - GoogleUtilities/Environment - - GoogleUtilities/MethodSwizzler (5.3.7): + - GoogleUtilities/MethodSwizzler (5.5.0): - GoogleUtilities/Logger - - GoogleUtilities/Network (5.3.7): + - GoogleUtilities/Network (5.5.0): - GoogleUtilities/Logger - "GoogleUtilities/NSData+zlib" - GoogleUtilities/Reachability - - "GoogleUtilities/NSData+zlib (5.3.7)" - - GoogleUtilities/Reachability (5.3.7): + - "GoogleUtilities/NSData+zlib (5.5.0)" + - GoogleUtilities/Reachability (5.5.0): - GoogleUtilities/Logger - - GoogleUtilities/UserDefaults (5.3.7): + - GoogleUtilities/UserDefaults (5.5.0): - GoogleUtilities/Logger - - "gRPC-C++ (0.0.5)": - - "gRPC-C++/Implementation (= 0.0.5)" - - "gRPC-C++/Interface (= 0.0.5)" - - "gRPC-C++/Implementation (0.0.5)": - - "gRPC-C++/Interface (= 0.0.5)" - - gRPC-Core (= 1.14.0) + - "gRPC-C++ (0.0.6)": + - "gRPC-C++/Implementation (= 0.0.6)" + - "gRPC-C++/Interface (= 0.0.6)" + - "gRPC-C++/Implementation (0.0.6)": + - "gRPC-C++/Interface (= 0.0.6)" + - gRPC-Core (= 1.17.0) - nanopb (~> 0.3) - - "gRPC-C++/Interface (0.0.5)" - - gRPC-Core (1.14.0): - - gRPC-Core/Implementation (= 1.14.0) - - gRPC-Core/Interface (= 1.14.0) - - gRPC-Core/Implementation (1.14.0): - - BoringSSL (~> 10.0) - - gRPC-Core/Interface (= 1.14.0) + - "gRPC-C++/Interface (0.0.6)" + - gRPC-Core (1.17.0): + - gRPC-Core/Implementation (= 1.17.0) + - gRPC-Core/Interface (= 1.17.0) + - gRPC-Core/Implementation (1.17.0): + - BoringSSL-GRPC (= 0.0.2) + - gRPC-Core/Interface (= 1.17.0) - nanopb (~> 0.3) - - gRPC-Core/Interface (1.14.0) + - gRPC-Core/Interface (1.17.0) - GTMOAuth2 (1.1.6): - GTMSessionFetcher (~> 1.1) - GTMSessionFetcher (1.2.1): @@ -233,7 +236,7 @@ PODS: - nanopb/encode (= 0.3.901) - nanopb/decode (0.3.901) - nanopb/encode (0.3.901) - - Protobuf (3.6.1) + - Protobuf (3.7.0) - React (0.58.0-rc.1): - React/Core (= 0.58.0-rc.1) - React/Core (0.58.0-rc.1): @@ -270,27 +273,27 @@ PODS: - React/Core - React/fishhook - React/RCTBlob - - RNFirebase (5.2.3): + - RNFirebase (5.2.5-rc0): - Firebase/Core - React - yoga (0.58.0-rc.1.React) DEPENDENCIES: - - Crashlytics (~> 3.10.7) + - Crashlytics (~> 3.12.0) - DoubleConversion (from `../node_modules/react-native/third-party-podspecs/DoubleConversion.podspec`) - - Fabric (~> 1.7.11) - - Firebase/AdMob (~> 5.15.0) - - Firebase/Auth (~> 5.15.0) - - Firebase/Core (~> 5.15.0) - - Firebase/Database (~> 5.15.0) - - Firebase/DynamicLinks (~> 5.15.0) - - Firebase/Firestore (~> 5.15.0) - - Firebase/Functions (~> 5.15.0) - - Firebase/Invites (~> 5.15.0) - - Firebase/Messaging (~> 5.15.0) - - Firebase/Performance (~> 5.15.0) - - Firebase/RemoteConfig (~> 5.15.0) - - Firebase/Storage (~> 5.15.0) + - Fabric (~> 1.9.0) + - Firebase/AdMob (~> 5.20.1) + - Firebase/Auth (~> 5.20.1) + - Firebase/Core (~> 5.20.1) + - Firebase/Database (~> 5.20.1) + - Firebase/DynamicLinks (~> 5.20.1) + - Firebase/Firestore (~> 5.20.1) + - Firebase/Functions (~> 5.20.1) + - Firebase/Invites (~> 5.20.1) + - Firebase/Messaging (~> 5.20.1) + - Firebase/Performance (~> 5.20.1) + - Firebase/RemoteConfig (~> 5.20.1) + - Firebase/Storage (~> 5.20.1) - Folly (from `../node_modules/react-native/third-party-podspecs/Folly.podspec`) - glog (from `../node_modules/react-native/third-party-podspecs/glog.podspec`) - React/Core (from `../node_modules/react-native`) @@ -306,7 +309,7 @@ DEPENDENCIES: SPEC REPOS: https://github.com/cocoapods/specs.git: - boost-for-react-native - - BoringSSL + - BoringSSL-GRPC - Crashlytics - Fabric - Firebase @@ -351,52 +354,52 @@ EXTERNAL SOURCES: :path: "../node_modules/react-native" RNFirebase: :path: "../../ios/RNFirebase.podspec" - :version: "~> 5.2.3" + :version: "~> 5.2.5-rc0" yoga: :path: "../node_modules/react-native/ReactCommon/yoga" SPEC CHECKSUMS: boost-for-react-native: 39c7adb57c4e60d6c5479dd8623128eb5b3f0f2c - BoringSSL: e10f92a27043805c01071fe815a5cd98ae8212e7 - Crashlytics: 55e24fc23989680285a21cb1146578d9d18e432c + BoringSSL-GRPC: 2a230d9cd93e7ce39916044f645cebb31f37dde6 + Crashlytics: 07fb167b1694128c1c9a5a5cc319b0e9c3ca0933 DoubleConversion: bb338842f62ab1d708ceb63ec3d999f0f3d98ecd - Fabric: 25d0963b691fc97be566392243ff0ecef5a68338 - Firebase: 8bb9268bff82374f2cbaaabb143e725743c316ae + Fabric: f988e33c97f08930a413e08123064d2e5f68d655 + Firebase: 2f5235e62f141cb86181c3af0dfe4509706351ac FirebaseABTesting: 1f50b8d50f5e3469eea54e7463a7b7fe221d1f5e - FirebaseAnalytics: c06f9d70577d79074214700a71fd5d39de5550fb + FirebaseAnalytics: fd72a26bf8dac84cefba2f0864366f718555a5b0 FirebaseAnalyticsInterop: efbe45c8385ec626e29f9525e5ebd38520dfb6c1 - FirebaseAuth: 02e969ff430e156d99d4cb842d77b806b71ad7bb + FirebaseAuth: dd7bbf03a5aee0eafb3a1aee4d2812bd74bac890 FirebaseAuthInterop: 0ffa57668be100582bb7643d4fcb7615496c41fc - FirebaseCore: 35747502d9e8c6ee217385ad04446c7c2aaf9c5c - FirebaseDatabase: 0621689f77528d62b47e1c06ca737c4c19275d1a - FirebaseDynamicLinks: c713da5f75c324f38fb2d57164bbc1c461aa6739 - FirebaseFirestore: 58043a1c2d2c91efdaa8d8f385cdbaa2ce750cfe - FirebaseFunctions: e37c7d4d2dec63972ca4642afeb8dae8ff8ab52e - FirebaseInstanceID: e2fa4cb35ef5558c200f7f0ad8a53e212215f93e + FirebaseCore: f1a9a8be1aee4bf71a2fc0f4096df6788bdfda61 + FirebaseDatabase: 2c15b0ea6f2c6eb5e57413f9d6340f1e50b81ae3 + FirebaseDynamicLinks: f7a8717e2c7ea652923882a2d60b0045d6fd99d5 + FirebaseFirestore: faca891c0f0d1d6c10c793473e2f6a29d75014b5 + FirebaseFunctions: 35b530c69ef8c322c414104280d36a06347a5d49 + FirebaseInstanceID: a122b0c258720cf250551bb2bedf48c699f80d90 FirebaseInvites: f13ed69fae140e705baec1a59ff127334b841a8a - FirebaseMessaging: b412996f6a09337d232bb3a6676ce4d1f353d024 - FirebasePerformance: 6f77b930f982a54ad487d3de5523ce641db9dcc9 + FirebaseMessaging: 4235f949ce1c4e827aeb19705ba5c53f9b85aa10 + FirebasePerformance: 25ecee2a260bcf398d7f32d6f4804438df953100 FirebaseRemoteConfig: 7e11c65f0769c09bff6947997c209515058c5318 - FirebaseStorage: 3d22c041370593e639fba013d1eb698a8dae2881 + FirebaseStorage: 6162ef4322502b818d9de0ec552f5226d283de43 Folly: de497beb10f102453a1afa9edbf8cf8a251890de glog: aefd1eb5dda2ab95ba0938556f34b98e2da3a60d - Google-Mobile-Ads-SDK: 9d1c38a83febea769470aa514a9c7954e2d1483d + Google-Mobile-Ads-SDK: 8f4f7e793bfd3fff5b082181b54112f81b579a67 GoogleAPIClientForREST: 5447a194eae517986cafe6421a5330b80b820591 - GoogleAppMeasurement: 98b71f5e04142793729a5ef23e5b96651ff4b70f + GoogleAppMeasurement: 1624046ab1bcc5e170061a56ef5679000b079c8e GoogleSignIn: 7ff245e1a7b26d379099d3243a562f5747e23d39 GoogleToolboxForMac: ff31605b7d66400dcec09bed5861689aebadda4d - GoogleUtilities: 111a012f4c3a29c9e7c954c082fafd6ee3c999c0 - "gRPC-C++": 19eec1ffd34de29453f5fab5b4697ad0f240ad51 - gRPC-Core: f4836515817c0eb479aeeb9cc27c91c4ba62a9f6 + GoogleUtilities: 6481e6318c5fcabaaa8513ef8120f329055d7c10 + "gRPC-C++": e76441995900ac90e9bd98644ab4733f12521edf + gRPC-Core: 4028031ed2c5267cca0d846c876d8046b1ecb9b6 GTMOAuth2: e8b6512c896235149df975c41d9a36c868ab7fba GTMSessionFetcher: 32aeca0aa144acea523e1c8e053089dec2cb98ca leveldb-library: 08cba283675b7ed2d99629a4bc5fd052cd2bb6a5 nanopb: 2901f78ea1b7b4015c860c2fdd1ea2fee1a18d48 - Protobuf: 1eb9700044745f00181c136ef21b8ff3ad5a0fd5 + Protobuf: 7a877b7f3e5964e3fce995e2eb323dbc6831bb5a React: 9b873b38b92ed8012d7cdf3b965477095ed364c4 RNFirebase: 57f6c2adb24355b4e6211e028a8e97e473432245 yoga: 0885622311729a02c2bc02dca97167787a51488b -PODFILE CHECKSUM: ca7c42b26dc276713d66e348e596bdfc80d11147 +PODFILE CHECKSUM: 084df7890ac66693a9c12bb079c1824cf2e61dab COCOAPODS: 1.5.3 diff --git a/tests/ios/testing.xcodeproj/project.pbxproj b/tests/ios/testing.xcodeproj/project.pbxproj index 9366146109..f8db524d23 100644 --- a/tests/ios/testing.xcodeproj/project.pbxproj +++ b/tests/ios/testing.xcodeproj/project.pbxproj @@ -1026,19 +1026,19 @@ ); inputPaths = ( "${SRCROOT}/Pods/Target Support Files/Pods-testing/Pods-testing-resources.sh", - "${PODS_CONFIGURATION_BUILD_DIR}/FirebaseFirestore/gRPCCertificates-Firestore.bundle", "${PODS_ROOT}/FirebaseInvites/Resources/GINInviteResources.bundle", "${PODS_ROOT}/FirebaseInvites/Resources/GPPACLPickerResources.bundle", "${PODS_ROOT}/GTMOAuth2/Source/Touch/GTMOAuth2ViewTouch.xib", "${PODS_ROOT}/GoogleSignIn/Resources/GoogleSignIn.bundle", + "${PODS_CONFIGURATION_BUILD_DIR}/gRPC-C++/gRPCCertificates.bundle", ); name = "[CP] Copy Pods Resources"; outputPaths = ( - "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/gRPCCertificates-Firestore.bundle", "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/GINInviteResources.bundle", "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/GPPACLPickerResources.bundle", "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/GTMOAuth2ViewTouch.nib", "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/GoogleSignIn.bundle", + "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/gRPCCertificates.bundle", ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; diff --git a/tests/ios/testing/Info.plist b/tests/ios/testing/Info.plist index bd7ca5171b..36a5b6d3be 100755 --- a/tests/ios/testing/Info.plist +++ b/tests/ios/testing/Info.plist @@ -58,6 +58,8 @@ UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight + GADApplicationIdentifier + ca-app-pub-4406399463942824~2098755700 UIViewControllerBasedStatusBarAppearance