From 04cbb63891b7fb5176dd9b4209e0ce641e26007f Mon Sep 17 00:00:00 2001 From: Chris Bianca Date: Fri, 16 Jun 2017 16:58:28 +0100 Subject: [PATCH 1/8] [android][database] Fix hanging db when querying database object with large numeric keys --- .../main/java/io/invertase/firebase/Utils.java | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/android/src/main/java/io/invertase/firebase/Utils.java b/android/src/main/java/io/invertase/firebase/Utils.java index 985f5c57..4fc6583e 100644 --- a/android/src/main/java/io/invertase/firebase/Utils.java +++ b/android/src/main/java/io/invertase/firebase/Utils.java @@ -211,16 +211,22 @@ public class Utils { } /** + * Data should be treated as an array if: + * 1) All the keys are integers + * 2) More than half the keys between 0 and the maximum key in the object have non-empty values + * + * Definition from: https://firebase.googleblog.com/2014/04/best-practices-arrays-in-firebase.html * * @param snapshot * @return */ private static boolean isArray(DataSnapshot snapshot) { long expectedKey = -1; + long maxAllowedKey = (snapshot.getChildrenCount() * 2) - 1; for (DataSnapshot child : snapshot.getChildren()) { try { long key = Long.parseLong(child.getKey()); - if (key > expectedKey) { + if (key > expectedKey && key <= maxAllowedKey) { expectedKey = key; } else { return false; @@ -233,16 +239,22 @@ public class Utils { } /** + * Data should be treated as an array if: + * 1) All the keys are integers + * 2) More than half the keys between 0 and the maximum key in the object have non-empty values + * + * Definition from: https://firebase.googleblog.com/2014/04/best-practices-arrays-in-firebase.html * * @param mutableData * @return */ private static boolean isArray(MutableData mutableData) { long expectedKey = -1; + long maxAllowedKey = (mutableData.getChildrenCount() * 2) - 1; for (MutableData child : mutableData.getChildren()) { try { long key = Long.parseLong(child.getKey()); - if (key > expectedKey) { + if (key > expectedKey && key <= maxAllowedKey) { expectedKey++; } else { return false; From d6558a85bf32c8a70678ed269d9358622f077c0e Mon Sep 17 00:00:00 2001 From: Chris Bianca Date: Fri, 16 Jun 2017 17:06:10 +0100 Subject: [PATCH 2/8] 1.2.0 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index e3faa9f1..8ed98036 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "react-native-firebase", - "version": "1.1.0", + "version": "1.2.0", "author": "Invertase (http://invertase.io)", "description": "A react native firebase library supporting both android and ios native firebase SDK's", "main": "index", From cb9ede86079c751c9ce44a92064555074aba6690 Mon Sep 17 00:00:00 2001 From: Chris Bianca Date: Fri, 16 Jun 2017 17:08:47 +0100 Subject: [PATCH 3/8] Revert "1.2.0" This reverts commit d6558a85bf32c8a70678ed269d9358622f077c0e. --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 8ed98036..e3faa9f1 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "react-native-firebase", - "version": "1.2.0", + "version": "1.1.0", "author": "Invertase (http://invertase.io)", "description": "A react native firebase library supporting both android and ios native firebase SDK's", "main": "index", From 566ddb8e09214ca03093e3688d88b56502f2f4be Mon Sep 17 00:00:00 2001 From: Chris Bianca Date: Fri, 16 Jun 2017 17:21:45 +0100 Subject: [PATCH 4/8] 1.1.1 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index e3faa9f1..247f2914 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "react-native-firebase", - "version": "1.1.0", + "version": "1.1.1", "author": "Invertase (http://invertase.io)", "description": "A react native firebase library supporting both android and ios native firebase SDK's", "main": "index", From 389c8c8040030695cf443fa3ceba6aa3d671fd6f Mon Sep 17 00:00:00 2001 From: Chris Bianca Date: Fri, 16 Jun 2017 17:51:46 +0100 Subject: [PATCH 5/8] [docs] Alphabetise features, add supported versions --- README.md | 29 ++++++++++++++++++++--------- docs/README.md | 28 +++++++++++++++++++--------- 2 files changed, 39 insertions(+), 18 deletions(-) diff --git a/README.md b/README.md index 3956cbc8..50ce9fe4 100644 --- a/README.md +++ b/README.md @@ -42,19 +42,30 @@ The native SDKs also allow us to hook into device sdk's which are not possible w | Firebase Features | v1 | [v2](https://github.com/invertase/react-native-firebase/pull/130) | Web SDK | | ---------------------- | :---: | :---: | :---: | +| AdMob | ❌ | ✅ | ❌ | | Analytics             | ✅ | ✅ | ❌ | -| Cloud Messaging | ✅ | ✅ | ❌ | -| Authentication | ✅ | ✅ | ✅ | -| Realtime Database | ✅ | ✅ | ✅ | -| - Offline Persistance | ✅ | ✅ | ❌ | -| Storage | ✅ | ✅ | ❌ | -| Performance Monitoring | ✅ | ✅ | ❌ | -| Crash Reporting | ✅ | ✅ | ❌ | -| Remote Config | ✅ | ✅ | ❌ | | App Indexing           | ❌ | ❌ | ❌ | +| Authentication | ✅ | ✅ | ✅ | +| Cloud Messaging | ✅ | ✅ | ❌ | +| Crash Reporting | ✅ | ✅ | ❌ | | Dynamic Links | ❌ | ❌ | ❌ | | Invites | ❌ | ❌ | ❌ | -| AdMob | ❌ | ✅ | ❌ | +| Performance Monitoring | ✅ | ✅ | ❌ | +| Realtime Database | ✅ | ✅ | ✅ | +| - Offline Persistance | ✅ | ✅ | ❌ | +| Remote Config | ✅ | ✅ | ❌ | +| Storage | ✅ | ✅ | ❌ | + +--- +### Supported versions - Firebase / React Native + +> The table below shows the minimum supported versions of the Firebase SDKs and React Native + +| | v1 | [v2](https://github.com/invertase/react-native-firebase/pull/130) +| ---------------------- | :---: | :---: | +| React Native | 0.36.0+ | 0.40.0 + | +| Firebase Android SDK | 10.2.0+ | 11.0.0 + | +| Firebase iOS SDK | 3.15.0+ | 4.0.0 + | --- diff --git a/docs/README.md b/docs/README.md index cc7249ae..3da98dcf 100644 --- a/docs/README.md +++ b/docs/README.md @@ -32,17 +32,27 @@ The native SDKs also allow us to hook into device sdk's which are not possible w | Firebase Features | v1 | [v2](https://github.com/invertase/react-native-firebase/pull/130) | Web SDK | | ---------------------- | :---: | :---: | :---: | +| AdMob | ❌ | ✅ | ❌ | | Analytics             | ✅ | ✅ | ❌ | -| Cloud Messaging | ✅ | ✅ | ❌ | -| Authentication | ✅ | ✅ | ✅ | -| Realtime Database | ✅ | ✅ | ✅ | -| - Offline Persistance | ✅ | ✅ | ❌ | -| Storage | ✅ | ✅ | ❌ | -| Performance Monitoring | ✅ | ✅ | ❌ | -| Crash Reporting | ✅ | ✅ | ❌ | -| Remote Config | ✅ | ✅ | ❌ | | App Indexing           | ❌ | ❌ | ❌ | +| Authentication | ✅ | ✅ | ✅ | +| Cloud Messaging | ✅ | ✅ | ❌ | +| Crash Reporting | ✅ | ✅ | ❌ | | Dynamic Links | ❌ | ❌ | ❌ | | Invites | ❌ | ❌ | ❌ | -| AdMob | ❌ | ✅ | ❌ | +| Performance Monitoring | ✅ | ✅ | ❌ | +| Realtime Database | ✅ | ✅ | ✅ | +| - Offline Persistance | ✅ | ✅ | ❌ | +| Remote Config | ✅ | ✅ | ❌ | +| Storage | ✅ | ✅ | ❌ | +--- +### Supported versions - Firebase / React Native + +> The table below shows the minimum supported versions of the Firebase SDKs and React Native + +| | v1 | [v2](https://github.com/invertase/react-native-firebase/pull/130) +| ---------------------- | :---: | :---: | +| React Native | 0.36.0+ | 0.40.0 + | +| Firebase Android SDK | 10.2.0+ | 11.0.0 + | +| Firebase iOS SDK | 3.15.0+ | 4.0.0 + | From 782958d026f2e2b9acf624c13cbf3e7fd892d5f2 Mon Sep 17 00:00:00 2001 From: Chris Bianca Date: Mon, 19 Jun 2017 12:25:58 +0100 Subject: [PATCH 6/8] [messaging] Update typescript definition to match interface changes --- docs/installation-android.md | 22 +++---- index.d.ts | 106 ++++++++++++++++----------------- lib/modules/messaging/index.js | 4 +- 3 files changed, 66 insertions(+), 66 deletions(-) diff --git a/docs/installation-android.md b/docs/installation-android.md index 603bb504..afab665b 100644 --- a/docs/installation-android.md +++ b/docs/installation-android.md @@ -77,18 +77,18 @@ dependencies { compile(project(':react-native-firebase')) { transitive = false } - compile "com.google.firebase:firebase-core:10.2.6" + compile "com.google.firebase:firebase-core:11.0.0" # RNFirebase optional dependencies - compile "com.google.firebase:firebase-ads:10.2.6" - compile "com.google.firebase:firebase-analytics:10.2.6" - compile "com.google.firebase:firebase-auth:10.2.6" - compile "com.google.firebase:firebase-config:10.2.6" - compile "com.google.firebase:firebase-crash:10.2.6" - compile "com.google.firebase:firebase-database:10.2.6" - compile "com.google.firebase:firebase-messaging:10.2.6" - compile "com.google.firebase:firebase-perf:10.2.6" - compile "com.google.firebase:firebase-storage:10.2.6" + compile "com.google.firebase:firebase-ads:11.0.0" + compile "com.google.firebase:firebase-analytics:11.0.0" + compile "com.google.firebase:firebase-auth:11.0.0" + compile "com.google.firebase:firebase-config:11.0.0" + compile "com.google.firebase:firebase-crash:11.0.0" + compile "com.google.firebase:firebase-database:11.0.0" + compile "com.google.firebase:firebase-messaging:11.0.0" + compile "com.google.firebase:firebase-perf:11.0.0" + compile "com.google.firebase:firebase-storage:11.0.0" } ``` @@ -175,6 +175,6 @@ In the same file, add the `firebase-perf` module to your dependencies: ``` dependencies { ... - compile "com.google.firebase:firebase-perf:10.2.6" + compile "com.google.firebase:firebase-perf:11.0.0" } ``` diff --git a/index.d.ts b/index.d.ts index 91674053..dfd653e2 100644 --- a/index.d.ts +++ b/index.d.ts @@ -13,14 +13,14 @@ declare module "react-native-firebase" { on(type: string, handler: (msg: any) => void): any; /** mimics firebase Web SDK */ database(): RNFirebase.database.Database; - /**RNFirebase mimics the Web Firebase SDK Storage, - * whilst providing some iOS and Android specific functionality. + /**RNFirebase mimics the Web Firebase SDK Storage, + * whilst providing some iOS and Android specific functionality. */ storage(): RNFirebase.storage.Storage; /** * Firebase Cloud Messaging (FCM) allows you to send push messages at no cost to both Android & iOS platforms. * Assuming the installation instructions have been followed, FCM is ready to go. - * As the Firebase Web SDK has limited messaging functionality, + * As the Firebase Web SDK has limited messaging functionality, * the following methods within react-native-firebase have been created to handle FCM in the React Native environment. */ messaging(): RNFirebase.messaging.Messaging; @@ -51,20 +51,20 @@ declare module "react-native-firebase" { }; /** - * pass custom options by passing an object with configuration options. - * The configuration object will be generated first by the native configuration object, if set and then will be overridden if passed in JS. + * pass custom options by passing an object with configuration options. + * The configuration object will be generated first by the native configuration object, if set and then will be overridden if passed in JS. * That is, all of the following key/value pairs are optional if the native configuration is set. */ interface configurationOptions { /** - * default false + * default false * When set to true, RNFirebase will log messages to the console and fire debug events we can listen to in js - * @usage + * @usage * firebase.on('debug', msg => console.log('Received debug message', msg)) */ debug?: boolean; /** - * default false + * default false * When set to true, database persistence will be enabled. */ persistence?: boolean; @@ -73,47 +73,47 @@ declare module "react-native-firebase" { */ bundleID?: string; /** - * defualt "" + * defualt "" * The Google App ID that is used to uniquely identify an instance of an app. */ googleAppID?: string; /** - * deufalt "" + * deufalt "" * The database root (i.e. https://my-app.firebaseio.com) */ databaseURL?: string; /** - * defualt "" + * defualt "" * URL scheme to set up durable deep link service */ deepLinkURLScheme?: string; /** - * defualt "" + * defualt "" * The Google Cloud storage bucket name */ storageBucket?: string; /** - * default "" + * default "" * The Android client ID used in Google AppInvite when an iOS app has it's android version */ androidClientID?: string; /** - * default "" + * default "" * The Project number from the Google Developer's console used to configure Google Cloud Messaging */ GCMSenderID?: string; /** - * default "" + * default "" * The tracking ID for Google Analytics */ trackingID?: string; /** - * default "" + * default "" * The OAuth2 client ID for iOS application used to authenticate Google Users for signing in with Google */ clientID?: string; /** - * defualt "" + * defualt "" * The secret iOS API key used for authenticating requests from our app */ APIKey?: string @@ -270,11 +270,11 @@ declare module "react-native-firebase" { * */ ref(path?: string): RnReference /** - * register listener + * register listener */ on(path: string, modifiersString: string, modifiers: Array, eventName: string, cb: () => void, errorCb: () => void): any /** - * unregister listener + * unregister listener */ off(path: string, modifiersString: string, eventName?: string, origCB?: () => void): any /** @@ -376,13 +376,13 @@ declare module "react-native-firebase" { setAnalyticsCollectionEnabled(enabled: boolean): void /** * Sets the current screen name, which specifies the current visual context in your app. - * Whilst screenClassOverride is optional, - * it is recommended it is always sent as your current class name, + * Whilst screenClassOverride is optional, + * it is recommended it is always sent as your current class name, * for example on Android it will always show as 'MainActivity' if not specified. */ setCurrentScreen(screenName: string, screenClassOverride?: string): void /** - * Sets the minimum engagement time required before starting a session. + * Sets the minimum engagement time required before starting a session. * The default value is 10000 (10 seconds) */ setMinimumSessionDuration(miliseconds: number): void @@ -393,9 +393,9 @@ declare module "react-native-firebase" { setSessionTimeoutDuration(miliseconds: number): void /** * Gives a user a uniqiue identificaition. - * @example + * @example * const id = firebase.auth().currentUser.uid; - * + * * firebase.analytics().setUserId(id); */ setUserId(id: string): void @@ -420,7 +420,7 @@ declare module "react-native-firebase" { */ emailVerified: boolean /** - * + * */ isAnonymous: boolean /** @@ -457,19 +457,19 @@ declare module "react-native-firebase" { */ reload(): Promise /** - * Sends a verification email to a user. + * Sends a verification email to a user. * This will Promise reject is the user is anonymous. */ sendEmailVerification(): Promise /** * Updates the user's email address. - * See Firebase docs for more information on security & email validation. + * See Firebase docs for more information on security & email validation. * This will Promise reject is the user is anonymous. */ updateEmail(email: string): Promise /** - * Important: this is a security sensitive operation that requires the user to have recently signed in. - * If this requirement isn't met, ask the user to authenticate again and then call firebase.User#reauthenticate. + * Important: this is a security sensitive operation that requires the user to have recently signed in. + * If this requirement isn't met, ask the user to authenticate again and then call firebase.User#reauthenticate. * This will Promise reject is the user is anonymous. */ updatePassword(password: string): Promise @@ -498,48 +498,48 @@ declare module "react-native-firebase" { */ currentUser: User | null /** - * Listen for changes in the users auth state (logging in and out). - * This method returns a unsubscribe function to stop listening to events. + * Listen for changes in the users auth state (logging in and out). + * This method returns a unsubscribe function to stop listening to events. * Always ensure you unsubscribe from the listener when no longer needed to prevent updates to components no longer in use. */ onAuthStateChanged( nextOrObserver: Object, error?: (a: RnError) => any, completed?: () => any): () => any; /** - * We can create a user by calling the createUserWithEmailAndPassword() function. + * We can create a user by calling the createUserWithEmailAndPassword() function. * The method accepts two parameters, an email and a password. */ createUserWithEmailAndPassword(email: string, password: string): Promise /** - * To sign a user in with their email and password, use the signInWithEmailAndPassword() function. + * To sign a user in with their email and password, use the signInWithEmailAndPassword() function. * It accepts two parameters, the user's email and password: */ signInWithEmailAndPassword(email: string, password: string): Promise /** - * Sign an anonymous user. + * Sign an anonymous user. * If the user has already signed in, that user will be returned */ signInAnonymously(): Promise /** - * Sign in the user with a 3rd party credential provider. + * Sign in the user with a 3rd party credential provider. * credential requires the following properties: */ signInWithCredential(credential: Credential): Promise /** - * Sign a user in with a self-signed JWT token. - * To sign a user using a self-signed custom token, - * use the signInWithCustomToken() function. + * Sign a user in with a self-signed JWT token. + * To sign a user using a self-signed custom token, + * use the signInWithCustomToken() function. * It accepts one parameter, the custom token: */ signInWithCustomToken(token: string): Promise /** - * Sends a password reset email to the given email address. - * Unlike the web SDK, + * Sends a password reset email to the given email address. + * Unlike the web SDK, * the email will contain a password reset link rather than a code. */ sendPasswordResetEmail(email: string): Promise /** - * Completes the password reset process, + * Completes the password reset process, * given a confirmation code and new password. */ signOut(): Promise @@ -559,13 +559,13 @@ declare module "react-native-firebase" { */ unsubscribeFromTopic(topic: string): void /** - * When the application has been opened from a notification - * getInitialNotification is called and the notification payload is returned. + * When the application has been opened from a notification + * getInitialNotification is called and the notification payload is returned. * Use onMessage for notifications when the app is running. */ getInitialNotification(): Promise /** - * Returns the devices FCM token. + * Returns the devices FCM token. * This token can be used in the Firebase console to send messages to directly. */ getToken(forceRefresh?: Boolean): Promise @@ -573,14 +573,14 @@ declare module "react-native-firebase" { * On the event a devices FCM token is refreshed by Google, * the new token is returned in a callback listener. */ - onTokenRefresh(listener: (token: string) => any): void + onTokenRefresh(listener: (token: string) => any): () => any /** - * On a new message, - * the payload object is passed to the listener callback. + * On a new message, + * the payload object is passed to the listener callback. * This method is only triggered when the app is running. * Use getInitialNotification for notifications which cause the app to open. */ - onMessage(listener: (message: any) => any): void + onMessage(listener: (message: any) => any): () => any /** * Create a local notification from the device itself. */ @@ -600,17 +600,17 @@ declare module "react-native-firebase" { */ getScheduledLocalNotifications(): Promise /** - * Cancels a location notification by ID, + * Cancels a location notification by ID, * or all notifications by *. */ cancelLocalNotification(id: string): void /** - * Removes all delivered notifications from device by ID, + * Removes all delivered notifications from device by ID, * or all notifications by *. */ removeDeliveredNotification(id: string): void /** - * IOS + * IOS * Requests app notification permissions in an Alert dialog. */ requestPermissions(): void @@ -654,7 +654,7 @@ declare module "react-native-firebase" { */ logcat(level: number, tag: string, message: string): void /** - * Files a crash report, along with any previous logs to Firebase. + * Files a crash report, along with any previous logs to Firebase. * An Error object must be passed into the report method. */ report(error: RnError, maxStackSize: Number): void @@ -662,4 +662,4 @@ declare module "react-native-firebase" { } } } -} \ No newline at end of file +} diff --git a/lib/modules/messaging/index.js b/lib/modules/messaging/index.js index ba613ad1..43a6cfba 100644 --- a/lib/modules/messaging/index.js +++ b/lib/modules/messaging/index.js @@ -203,7 +203,7 @@ export default class Messaging extends Base { * @param listener * @returns {*} */ - onMessage(listener: Function) { + onMessage(listener: Function): () => any { return FirebaseMessagingEvt.addListener( EVENT_TYPE.Notification, async(event) => { @@ -225,7 +225,7 @@ export default class Messaging extends Base { * @param listener * @returns {*} */ - onTokenRefresh(listener: Function) { + onTokenRefresh(listener: Function): () => any { return FirebaseMessagingEvt.addListener(EVENT_TYPE.RefreshToken, listener).remove; } From cd347383a4ec4afdb469b4d5ba8879e0d99a887a Mon Sep 17 00:00:00 2001 From: Chris Bianca Date: Mon, 19 Jun 2017 13:14:36 +0100 Subject: [PATCH 7/8] [messaging] Correctly bind messaging listeners --- lib/modules/messaging/index.js | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/lib/modules/messaging/index.js b/lib/modules/messaging/index.js index 43a6cfba..8e3b174b 100644 --- a/lib/modules/messaging/index.js +++ b/lib/modules/messaging/index.js @@ -204,7 +204,7 @@ export default class Messaging extends Base { * @returns {*} */ onMessage(listener: Function): () => any { - return FirebaseMessagingEvt.addListener( + const rnListener = FirebaseMessagingEvt.addListener( EVENT_TYPE.Notification, async(event) => { const data = { @@ -217,7 +217,8 @@ export default class Messaging extends Base { data.finish(); } } - ).remove; + ); + return () => rnListener.remove(); } /** @@ -226,7 +227,8 @@ export default class Messaging extends Base { * @returns {*} */ onTokenRefresh(listener: Function): () => any { - return FirebaseMessagingEvt.addListener(EVENT_TYPE.RefreshToken, listener).remove; + const rnListener = FirebaseMessagingEvt.addListener(EVENT_TYPE.RefreshToken, listener); + return () => rnListener.remove(); } /** From c8dcba3344db1a55b5fb1bb5b00e92aa13f1c04a Mon Sep 17 00:00:00 2001 From: Chris Bianca Date: Tue, 20 Jun 2017 10:17:56 +0100 Subject: [PATCH 8/8] [docs] Update iOS install documentation --- docs/installation-ios.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/installation-ios.md b/docs/installation-ios.md index 3df9e5ea..5aaaa45f 100644 --- a/docs/installation-ios.md +++ b/docs/installation-ios.md @@ -12,9 +12,9 @@ and this to the `didFinishLaunchingWithOptions:(NSDictionary *)launchOptions` me `[FIRApp configure];` -## 2) Link RNFirebase +## 2) Setup RNFirebase -Unfortunately, due to the fact that Firebase is much easier to setup using Cocoapods, `react-native link` is not recommended as it is not customisable enough for our needs and we have had numerous problems reported. +Unfortunately, due to the fact that Firebase is much easier to setup using Cocoapods, *we do not recommend* `react-native link` as it is not customisable enough for our needs and we have had numerous problems reported. ### 2.0) If you don't already have Cocoapods set up Follow the instructions to install Cocoapods and create your Podfile [here](https://firebase.google.com/docs/ios/setup#add_the_sdk).