mirror of
https://github.com/zhigang1992/react-native-firebase.git
synced 2026-04-18 08:20:47 +08:00
merge master
This commit is contained in:
56
.github/ISSUE_TEMPLATE/Bug_report.md
vendored
56
.github/ISSUE_TEMPLATE/Bug_report.md
vendored
@@ -1,20 +1,19 @@
|
||||
---
|
||||
name: ⚠️ Bug/Issue report
|
||||
about: Please provide as much detail as possible to help us with a bug or issue. Issues
|
||||
name: ⚠️ Bug/Issue report
|
||||
about: Please provide as much detail as possible to help us with a bug or issue. Issues
|
||||
will be closed if they do not follow the template.
|
||||
|
||||
---
|
||||
|
||||
<!---
|
||||
BEFORE YOU MAKE AN ISSUE
|
||||
|
||||
The issue list of this repo is exclusively for bug reports.
|
||||
|
||||
1) For feature requests, please use our Canny board: https://react-native-firebase.canny.io/feature-requests
|
||||
|
||||
2) For questions and support please use our Discord chat: https://discord.gg/C9aK28N or Stack Overflow: https://stackoverflow.com/questions/tagged/react-native-firebase
|
||||
|
||||
3) If this is a setup issue then please make sure you've correctly followed the setup guides, most setup issues such as 'duplicate dex files', 'default app has not been initialized' etc are all down to an incorrect setup as the guides haven't been correctly followed.
|
||||
<!---
|
||||
BEFORE YOU MAKE AN ISSUE
|
||||
|
||||
The issue list of this repo is exclusively for bug reports.
|
||||
|
||||
1) For feature requests, please use our Canny board: https://react-native-firebase.canny.io/feature-requests
|
||||
|
||||
2) For questions and support please use our Discord chat: https://discord.gg/C9aK28N or Stack Overflow: https://stackoverflow.com/questions/tagged/react-native-firebase
|
||||
|
||||
3) If this is a setup issue then please make sure you've correctly followed the setup guides, most setup issues such as 'duplicate dex files', 'default app has not been initialized' etc are all down to an incorrect setup as the guides haven't been correctly followed.
|
||||
-->
|
||||
|
||||
### Issue
|
||||
@@ -23,29 +22,38 @@ The issue list of this repo is exclusively for bug reports.
|
||||
|
||||
### Environment
|
||||
|
||||
<!--- (e.g. iOS, Android, Both) --->
|
||||
|
||||
1. Application Target Platform:
|
||||
|
||||
<!--- (e.g. macOS Sierra, Windows 10) --->
|
||||
<!--- (e.g. iOS, Android, Both) --->
|
||||
|
||||
2. Development Operating System:
|
||||
|
||||
<!--- (Xcode or Android Studio version, iOS or Android SDK version - if relevant) --->
|
||||
<!--- (e.g. macOS Sierra, Windows 10) --->
|
||||
|
||||
3. Build Tools:
|
||||
|
||||
<!--- (e.g. 0.45.1) --->
|
||||
<!--- (Xcode or Android Studio version, iOS or Android SDK version - if relevant) --->
|
||||
|
||||
4. React Native version:
|
||||
4. `React Native` version:
|
||||
|
||||
<!--- (e.g. 2.1.3) --->
|
||||
<!--- (e.g. 0.52.0) --->
|
||||
|
||||
5. RNFirebase Version:
|
||||
5. `React Native Firebase` Version:
|
||||
|
||||
<!--- (e.g. 4.3.0) --->
|
||||
|
||||
6. `Firebase` Module:
|
||||
|
||||
<!--- (e.g. database, auth, messaging, analytics etc - or N/A if not applicable) --->
|
||||
|
||||
6. Firebase Module:
|
||||
7. Are you using `typescript`?
|
||||
|
||||
<!-- Love react-native-firebase? Please consider supporting our collective:
|
||||
👉 https://opencollective.com/react-native-firebase/donate -->
|
||||
<!--- yes/no --->
|
||||
|
||||
---
|
||||
|
||||
Loving `react-native-firebase`? Please consider supporting them with any of the below:
|
||||
|
||||
* 👉 Back financially via [Open Collective](https://opencollective.com/react-native-firebase/donate)
|
||||
* 👉 Follow [`React Native Firebase`](https://twitter.com/rnfirebase) and [`Invertase`](https://twitter.com/invertaseio) on Twitter
|
||||
* 👉 Star this repo on GitHub ⭐️
|
||||
|
||||
@@ -75,9 +75,15 @@ coverage
|
||||
yarn.lock
|
||||
tests
|
||||
bridge/
|
||||
lib/.watchmanconfig
|
||||
buddybuild_postclone.sh
|
||||
bin/test.js
|
||||
.github
|
||||
example
|
||||
codorials
|
||||
.vscode
|
||||
.nyc_output
|
||||
React-Native-Firebase.svg
|
||||
CONTRIBUTING.md
|
||||
CODE_OF_CONDUCT.md
|
||||
android/.settings
|
||||
README.md
|
||||
|
||||
56
README.md
56
README.md
@@ -35,40 +35,40 @@ All in all, RNFirebase provides much faster performance (~2x) over the web SDK a
|
||||
|
||||
> '**?**' indicates partial support
|
||||
|
||||
| Firebase Features | v2.2.x | v3.3.x | v4.0.x | Web SDK |
|
||||
| -------------------------- | :----: | :----: | :----: | :-----: |
|
||||
| **AdMob** | ✅ | ✅ | ✅ | ❌ |
|
||||
| **Analytics** | ✅ | ✅ | ✅ | ❌ |
|
||||
| **App Indexing** | ❌ | ❌ | ❌ | ❌ |
|
||||
| **Authentication** | ✅ | ✅ | ✅ | ✅ |
|
||||
| _-- Phone Auth_ | ❌ | ✅ | ✅ | ❌ |
|
||||
| **Core** | **?** | ✅ | ✅ | ✅ |
|
||||
| _-- Multiple Apps_ | ❌ | ✅ | ✅ | ✅ |
|
||||
| **Cloud Firestore** | ❌ | ✅ | ✅ | **?** |
|
||||
| **Cloud Messaging (FCM)** | **?** | **?** | ✅ | ❌ |
|
||||
| **Crashlytics** | ❌ | ✅ | ✅ | ❌ |
|
||||
| **Crash Reporting** | ✅ | ✅ | ✅ | ❌ |
|
||||
| **Dynamic Links** | ❌ | ✅ | ✅ | ❌ |
|
||||
| **[Functions Callable](https://firebase.googleblog.com/2018/04/launching-cloud-functions-for-firebase-1-0.html?m=1)** | ❌ | ❌ | [v4.1+](https://github.com/invertase/react-native-firebase/milestone/6) | ✅ |
|
||||
| **Invites** | ❌ | ❌ | ✅ | ❌ |
|
||||
| **Instance ID** | ❌ | ❌ | **?** | ❌ |
|
||||
| **Performance Monitoring** | ✅ | ✅ | ✅ | ❌ |
|
||||
| **Realtime Database** | ✅ | ✅ | ✅ | ✅ |
|
||||
| _-- Offline Persistence_ | ✅ | ✅ | ✅ | **?** |
|
||||
| **Remote Config** | ✅ | ✅ | ✅ | ❌ |
|
||||
| **Storage** | ✅ | ✅ | ✅ | **?** |
|
||||
| Firebase Features | v2.2.x | v3.3.x | v4.2.x | Web SDK |
|
||||
| --------------------------------------------------------------------------------------------------------------------------------- | :----: | :----: | :----: | :-----: |
|
||||
| **AdMob** | ✅ | ✅ | ✅ | ❌ |
|
||||
| **Analytics** | ✅ | ✅ | ✅ | ❌ |
|
||||
| **App Indexing** | ❌ | ❌ | ❌ | ❌ |
|
||||
| **Authentication** | ✅ | ✅ | ✅ | ✅ |
|
||||
| _-- Phone Auth_ | ❌ | ✅ | ✅ | ❌ |
|
||||
| **Core** | **?** | ✅ | ✅ | ✅ |
|
||||
| _-- Multiple Apps_ | ❌ | ✅ | ✅ | ✅ |
|
||||
| **Cloud Firestore** | ❌ | ✅ | ✅ | **?** |
|
||||
| **Cloud Messaging (FCM)** | **?** | **?** | ✅ | ❌ |
|
||||
| **Crashlytics** | ❌ | ✅ | ✅ | ❌ |
|
||||
| **Crash Reporting** | ✅ | ✅ | ✅ | ❌ |
|
||||
| **Dynamic Links** | ❌ | ✅ | ✅ | ❌ |
|
||||
| **[Functions Callable](https://firebase.googleblog.com/2018/04/launching-cloud-functions-for-firebase-1-0.html?m=1)** | ❌ | ❌ | ✅ | ✅ |
|
||||
| **Invites** | ❌ | ❌ | ✅ | ❌ |
|
||||
| **Instance ID** | ❌ | ❌ | **?** | ❌ |
|
||||
| **Performance Monitoring** | ✅ | ✅ | ✅ | ❌ |
|
||||
| **Realtime Database** | ✅ | ✅ | ✅ | ✅ |
|
||||
| _-- Offline Persistence_ | ✅ | ✅ | ✅ | **?** |
|
||||
| **Remote Config** | ✅ | ✅ | ✅ | ❌ |
|
||||
| **Storage** | ✅ | ✅ | ✅ | **?** |
|
||||
|
||||
---
|
||||
|
||||
### Supported versions - React Native / Firebase
|
||||
|
||||
> The table below shows the supported versions of React Native and the Firebase SDKs for different versions of `react-native-firebase`
|
||||
> The table below shows the supported versions of React Native and the Firebase SDKs for different versions of `react-native-firebase`.
|
||||
|
||||
| | 2.2.x | 3.3.x | 4.0.x |
|
||||
|------------------------|----------|----------|----------|
|
||||
| React Native | 0.47 + | 0.50 + | 0.52 + |
|
||||
| Firebase Android SDK | 11.0.0 + | 11.8.0 + | 12.0.0 + |
|
||||
| Firebase iOS SDK | 4.0.0 + | 4.7.0 + | 4.11.0 + |
|
||||
| | 2.2.x | 3.3.x | 4.0.x | 4.1.x | 4.2.x |
|
||||
| -------------------- | -------- | -------- | -------- | -------- | --------- |
|
||||
| React Native | 0.47 + | 0.50 + | 0.52 + | 0.52 + | 0.52-55.x |
|
||||
| Firebase Android SDK | 11.0.0 + | 11.8.0 + | 12.0.0 + | 15.0.0 + | 15.0.0 + |
|
||||
| Firebase iOS SDK | 4.0.0 + | 4.7.0 + | 4.11.0 + | 4.13.0 + | 5.0.0 + |
|
||||
|
||||
---
|
||||
|
||||
|
||||
@@ -1,14 +1,14 @@
|
||||
buildscript {
|
||||
repositories {
|
||||
jcenter()
|
||||
google()
|
||||
jcenter()
|
||||
maven {
|
||||
url 'https://maven.fabric.io/public'
|
||||
}
|
||||
}
|
||||
dependencies {
|
||||
classpath 'com.android.tools.build:gradle:3.1.0'
|
||||
classpath 'io.fabric.tools:gradle:1.25.1'
|
||||
classpath 'com.android.tools.build:gradle:3.1.2'
|
||||
classpath 'io.fabric.tools:gradle:1.25.4'
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,7 +17,6 @@ apply plugin: 'com.android.library'
|
||||
def DEFAULT_COMPILE_SDK_VERSION = 27
|
||||
def DEFAULT_BUILD_TOOLS_VERSION = "27.0.3"
|
||||
def DEFAULT_TARGET_SDK_VERSION = 26
|
||||
def DEFAULT_FIREBASE_VERSION = "12.0.0"
|
||||
def DEFAULT_SUPPORT_LIB_VERSION = "27.0.2"
|
||||
|
||||
android {
|
||||
@@ -39,15 +38,6 @@ android {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
allprojects {
|
||||
repositories {
|
||||
jcenter()
|
||||
mavenLocal()
|
||||
google()
|
||||
}
|
||||
}
|
||||
|
||||
rootProject.gradle.buildFinished { buildResult ->
|
||||
if (buildResult.getFailure() != null) {
|
||||
try {
|
||||
@@ -82,28 +72,29 @@ rootProject.gradle.buildFinished { buildResult ->
|
||||
}
|
||||
}
|
||||
|
||||
def firebaseVersion = rootProject.hasProperty('googlePlayServicesVersion') ? rootProject.googlePlayServicesVersion : DEFAULT_FIREBASE_VERSION
|
||||
def supportVersion = rootProject.hasProperty('supportLibVersion') ? rootProject.supportLibVersion : DEFAULT_SUPPORT_LIB_VERSION
|
||||
|
||||
dependencies {
|
||||
// compile fileTree(include: ['*.jar'], dir: 'libs')
|
||||
api "com.facebook.react:react-native:+" // From node_modules
|
||||
api "com.android.support:support-v4:$supportVersion"
|
||||
compileOnly 'me.leolin:ShortcutBadger:1.1.21@aar'
|
||||
compileOnly "com.google.android.gms:play-services-base:$firebaseVersion"
|
||||
compileOnly "com.google.firebase:firebase-core:$firebaseVersion"
|
||||
compileOnly "com.google.firebase:firebase-config:$firebaseVersion"
|
||||
compileOnly "com.google.firebase:firebase-auth:$firebaseVersion"
|
||||
compileOnly "com.google.firebase:firebase-database:$firebaseVersion"
|
||||
compileOnly "com.google.firebase:firebase-storage:$firebaseVersion"
|
||||
compileOnly "com.google.firebase:firebase-messaging:$firebaseVersion"
|
||||
compileOnly "com.google.firebase:firebase-crash:$firebaseVersion"
|
||||
compileOnly "com.google.firebase:firebase-perf:$firebaseVersion"
|
||||
compileOnly "com.google.firebase:firebase-ads:$firebaseVersion"
|
||||
compileOnly "com.google.firebase:firebase-firestore:$firebaseVersion"
|
||||
compileOnly "com.google.firebase:firebase-invites:$firebaseVersion"
|
||||
compileOnly "com.google.firebase:firebase-functions:$firebaseVersion"
|
||||
compileOnly('com.crashlytics.sdk.android:crashlytics:2.9.1@aar') {
|
||||
|
||||
// Firebase SDKs
|
||||
compileOnly('com.crashlytics.sdk.android:crashlytics:2.9.3@aar') {
|
||||
transitive = true
|
||||
}
|
||||
compileOnly "com.google.android.gms:play-services-base:15.0.1"
|
||||
compileOnly "com.google.firebase:firebase-ads:15.0.1"
|
||||
compileOnly "com.google.firebase:firebase-auth:16.0.2"
|
||||
compileOnly "com.google.firebase:firebase-config:16.0.0"
|
||||
compileOnly "com.google.firebase:firebase-core:16.0.1"
|
||||
compileOnly "com.google.firebase:firebase-crash:16.0.1"
|
||||
compileOnly "com.google.firebase:firebase-database:16.0.1"
|
||||
compileOnly "com.google.firebase:firebase-firestore:17.0.2"
|
||||
compileOnly "com.google.firebase:firebase-functions:16.0.1"
|
||||
compileOnly "com.google.firebase:firebase-invites:16.0.1"
|
||||
compileOnly "com.google.firebase:firebase-storage:16.0.1"
|
||||
compileOnly "com.google.firebase:firebase-messaging:17.1.0"
|
||||
compileOnly "com.google.firebase:firebase-perf:16.0.0"
|
||||
compileOnly 'me.leolin:ShortcutBadger:1.1.21@aar'
|
||||
}
|
||||
|
||||
@@ -69,11 +69,21 @@ public class Utils {
|
||||
case "java.lang.String":
|
||||
map.putString(key, (String) value);
|
||||
break;
|
||||
case "org.json.JSONObject$1":
|
||||
map.putString(key, value.toString());
|
||||
break;
|
||||
default:
|
||||
if (List.class.isAssignableFrom(value.getClass())) {
|
||||
map.putArray(key, Arguments.makeNativeArray((List<Object>) value));
|
||||
} else if (Map.class.isAssignableFrom(value.getClass())) {
|
||||
map.putMap(key, Arguments.makeNativeMap((Map<String, Object>) value));
|
||||
WritableMap childMap = Arguments.createMap();
|
||||
Map<String, Object> valueMap = (Map<String, Object>) value;
|
||||
|
||||
for (Map.Entry<String, Object> entry : valueMap.entrySet()) {
|
||||
mapPutValue(entry.getKey(), entry.getValue(), childMap);
|
||||
}
|
||||
|
||||
map.putMap(key, childMap);
|
||||
} else {
|
||||
Log.d(TAG, "utils:mapPutValue:unknownType:" + type);
|
||||
map.putNull(key);
|
||||
|
||||
@@ -41,7 +41,7 @@ import com.google.firebase.auth.GithubAuthProvider;
|
||||
import com.google.firebase.auth.OAuthProvider;
|
||||
import com.google.firebase.auth.PhoneAuthCredential;
|
||||
import com.google.firebase.auth.PhoneAuthProvider;
|
||||
import com.google.firebase.auth.ProviderQueryResult;
|
||||
import com.google.firebase.auth.SignInMethodQueryResult;
|
||||
import com.google.firebase.auth.TwitterAuthProvider;
|
||||
import com.google.firebase.auth.UserInfo;
|
||||
import com.google.firebase.auth.UserProfileChangeRequest;
|
||||
@@ -55,10 +55,12 @@ import com.google.firebase.auth.EmailAuthProvider;
|
||||
|
||||
import io.invertase.firebase.Utils;
|
||||
|
||||
@SuppressWarnings("ThrowableResultOfMethodCallIgnored")
|
||||
@SuppressWarnings({"ThrowableResultOfMethodCallIgnored", "JavaDoc"})
|
||||
class RNFirebaseAuth extends ReactContextBaseJavaModule {
|
||||
private static final String TAG = "RNFirebaseAuth";
|
||||
private String mVerificationId;
|
||||
private String mLastPhoneNumber;
|
||||
private PhoneAuthProvider.ForceResendingToken mForceResendingToken;
|
||||
private PhoneAuthCredential mCredential;
|
||||
private ReactContext mReactContext;
|
||||
private HashMap<String, FirebaseAuth.AuthStateListener> mAuthListeners = new HashMap<>();
|
||||
@@ -203,7 +205,7 @@ class RNFirebaseAuth extends ReactContextBaseJavaModule {
|
||||
signInAnonymously(appName, promise, true);
|
||||
}
|
||||
|
||||
public void signInAnonymously(String appName, final Promise promise, final boolean withData) {
|
||||
private void signInAnonymously(String appName, final Promise promise, final boolean withData) {
|
||||
FirebaseApp firebaseApp = FirebaseApp.getInstance(appName);
|
||||
FirebaseAuth firebaseAuth = FirebaseAuth.getInstance(firebaseApp);
|
||||
|
||||
@@ -246,7 +248,7 @@ class RNFirebaseAuth extends ReactContextBaseJavaModule {
|
||||
createUserWithEmailAndPassword(appName, email, password, promise, true);
|
||||
}
|
||||
|
||||
public void createUserWithEmailAndPassword(String appName, final String email, final String password, final Promise promise, final boolean withData) {
|
||||
private void createUserWithEmailAndPassword(String appName, final String email, final String password, final Promise promise, final boolean withData) {
|
||||
Log.d(TAG, "createUserWithEmailAndPassword");
|
||||
FirebaseApp firebaseApp = FirebaseApp.getInstance(appName);
|
||||
FirebaseAuth firebaseAuth = FirebaseAuth.getInstance(firebaseApp);
|
||||
@@ -289,7 +291,7 @@ class RNFirebaseAuth extends ReactContextBaseJavaModule {
|
||||
signInWithEmailAndPassword(appName, email, password, promise, true);
|
||||
}
|
||||
|
||||
public void signInWithEmailAndPassword(String appName, final String email, final String password, final Promise promise, final boolean withData) {
|
||||
private void signInWithEmailAndPassword(String appName, final String email, final String password, final Promise promise, final boolean withData) {
|
||||
Log.d(TAG, "signInWithEmailAndPassword");
|
||||
FirebaseApp firebaseApp = FirebaseApp.getInstance(appName);
|
||||
FirebaseAuth firebaseAuth = FirebaseAuth.getInstance(firebaseApp);
|
||||
@@ -315,6 +317,37 @@ class RNFirebaseAuth extends ReactContextBaseJavaModule {
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Signs in using an email and sign-in email link.
|
||||
*
|
||||
* @param appName
|
||||
* @param email
|
||||
* @param emailLink
|
||||
* @param promise
|
||||
*/
|
||||
@ReactMethod
|
||||
private void signInWithEmailLink(String appName, final String email, final String emailLink, final Promise promise) {
|
||||
Log.d(TAG, "signInWithEmailLink");
|
||||
FirebaseApp firebaseApp = FirebaseApp.getInstance(appName);
|
||||
FirebaseAuth firebaseAuth = FirebaseAuth.getInstance(firebaseApp);
|
||||
|
||||
firebaseAuth.signInWithEmailLink(email, emailLink)
|
||||
.addOnSuccessListener(new OnSuccessListener<AuthResult>() {
|
||||
@Override
|
||||
public void onSuccess(AuthResult authResult) {
|
||||
Log.d(TAG, "signInWithEmailLink:onComplete:success");
|
||||
promiseWithAuthResult(authResult, promise);
|
||||
}
|
||||
})
|
||||
.addOnFailureListener(new OnFailureListener() {
|
||||
@Override
|
||||
public void onFailure(@NonNull Exception exception) {
|
||||
Log.e(TAG, "signInWithEmailLink:onComplete:failure", exception);
|
||||
promiseRejectAuthException(promise, exception);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@ReactMethod
|
||||
public void signInWithCustomToken(String appName, final String token, final Promise promise) {
|
||||
@@ -327,7 +360,7 @@ class RNFirebaseAuth extends ReactContextBaseJavaModule {
|
||||
signInWithCustomToken(appName, token, promise, true);
|
||||
}
|
||||
|
||||
public void signInWithCustomToken(String appName, final String token, final Promise promise, final boolean withData) {
|
||||
private void signInWithCustomToken(String appName, final String token, final Promise promise, final boolean withData) {
|
||||
Log.d(TAG, "signInWithCustomToken");
|
||||
FirebaseApp firebaseApp = FirebaseApp.getInstance(appName);
|
||||
FirebaseAuth firebaseAuth = FirebaseAuth.getInstance(firebaseApp);
|
||||
@@ -360,8 +393,7 @@ class RNFirebaseAuth extends ReactContextBaseJavaModule {
|
||||
* @param promise
|
||||
*/
|
||||
@ReactMethod
|
||||
public void sendPasswordResetEmail(String appName, final String email,
|
||||
ReadableMap actionCodeSettings, final Promise promise) {
|
||||
public void sendPasswordResetEmail(String appName, final String email, ReadableMap actionCodeSettings, final Promise promise) {
|
||||
Log.d(TAG, "sendPasswordResetEmail");
|
||||
FirebaseApp firebaseApp = FirebaseApp.getInstance(appName);
|
||||
FirebaseAuth firebaseAuth = FirebaseAuth.getInstance(firebaseApp);
|
||||
@@ -388,6 +420,39 @@ class RNFirebaseAuth extends ReactContextBaseJavaModule {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* sendSignInLinkToEmail
|
||||
*
|
||||
* @param email
|
||||
* @param promise
|
||||
*/
|
||||
@ReactMethod
|
||||
public void sendSignInLinkToEmail(String appName, String email, ReadableMap actionCodeSettings, final Promise promise) {
|
||||
Log.d(TAG, "sendSignInLinkToEmail");
|
||||
FirebaseApp firebaseApp = FirebaseApp.getInstance(appName);
|
||||
FirebaseAuth firebaseAuth = FirebaseAuth.getInstance(firebaseApp);
|
||||
|
||||
OnCompleteListener<Void> listener = new OnCompleteListener<Void>() {
|
||||
@Override
|
||||
public void onComplete(@NonNull Task<Void> task) {
|
||||
if (task.isSuccessful()) {
|
||||
Log.d(TAG, "sendSignInLinkToEmail:onComplete:success");
|
||||
promiseNoUser(promise, false);
|
||||
} else {
|
||||
Exception exception = task.getException();
|
||||
Log.e(TAG, "sendSignInLinkToEmail:onComplete:failure", exception);
|
||||
promiseRejectAuthException(promise, exception);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
ActionCodeSettings settings = buildActionCodeSettings(actionCodeSettings);
|
||||
firebaseAuth.sendSignInLinkToEmail(email, settings).addOnCompleteListener(listener);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* ----------------------
|
||||
* .currentUser methods
|
||||
* ---------------------- */
|
||||
@@ -395,7 +460,7 @@ class RNFirebaseAuth extends ReactContextBaseJavaModule {
|
||||
/**
|
||||
* delete
|
||||
*
|
||||
* @param promise
|
||||
* @param promise Promise
|
||||
*/
|
||||
@ReactMethod
|
||||
public void delete(String appName, final Promise promise) {
|
||||
@@ -628,7 +693,7 @@ class RNFirebaseAuth extends ReactContextBaseJavaModule {
|
||||
signInWithCredential(appName, provider, authToken, authSecret, promise, true);
|
||||
}
|
||||
|
||||
public void signInWithCredential(String appName, String provider, String authToken, String authSecret, final Promise promise, final boolean withData) {
|
||||
private void signInWithCredential(String appName, String provider, String authToken, String authSecret, final Promise promise, final boolean withData) {
|
||||
FirebaseApp firebaseApp = FirebaseApp.getInstance(appName);
|
||||
FirebaseAuth firebaseAuth = FirebaseAuth.getInstance(firebaseApp);
|
||||
|
||||
@@ -666,76 +731,105 @@ class RNFirebaseAuth extends ReactContextBaseJavaModule {
|
||||
* @param phoneNumber
|
||||
*/
|
||||
@ReactMethod
|
||||
public void signInWithPhoneNumber(String appName, final String phoneNumber, final Promise promise) {
|
||||
public void signInWithPhoneNumber(String appName, final String phoneNumber, final boolean forceResend, final Promise promise) {
|
||||
Log.d(TAG, "signInWithPhoneNumber");
|
||||
FirebaseApp firebaseApp = FirebaseApp.getInstance(appName);
|
||||
final FirebaseAuth firebaseAuth = FirebaseAuth.getInstance(firebaseApp);
|
||||
Activity activity = mReactContext.getCurrentActivity();
|
||||
|
||||
// reset force resending token if phone number changes
|
||||
if (!phoneNumber.equals(mLastPhoneNumber)) {
|
||||
mForceResendingToken = null;
|
||||
mLastPhoneNumber = phoneNumber;
|
||||
}
|
||||
|
||||
// Reset the verification Id
|
||||
mVerificationId = null;
|
||||
|
||||
PhoneAuthProvider.getInstance(firebaseAuth).verifyPhoneNumber(phoneNumber, 60, TimeUnit.SECONDS,
|
||||
mReactContext.getCurrentActivity(), new PhoneAuthProvider.OnVerificationStateChangedCallbacks() {
|
||||
private boolean promiseResolved = false;
|
||||
PhoneAuthProvider.OnVerificationStateChangedCallbacks callbacks = new PhoneAuthProvider.OnVerificationStateChangedCallbacks() {
|
||||
private boolean promiseResolved = false;
|
||||
|
||||
@Override
|
||||
public void onVerificationCompleted(final PhoneAuthCredential phoneAuthCredential) {
|
||||
// User has been automatically verified, log them in
|
||||
firebaseAuth.signInWithCredential(phoneAuthCredential)
|
||||
.addOnCompleteListener(new OnCompleteListener<AuthResult>() {
|
||||
@Override
|
||||
public void onComplete(@NonNull Task<AuthResult> task) {
|
||||
if (task.isSuccessful()) {
|
||||
// onAuthStateChanged will pick up the user change
|
||||
Log.d(TAG, "signInWithPhoneNumber:autoVerified:signInWithCredential:onComplete:success");
|
||||
// To ensure that there is no hanging promise, we resolve it with a null verificationId
|
||||
// as calling ConfirmationResult.confirm(code) is invalid in this case anyway
|
||||
if (!promiseResolved) {
|
||||
WritableMap verificationMap = Arguments.createMap();
|
||||
verificationMap.putNull("verificationId");
|
||||
promise.resolve(verificationMap);
|
||||
}
|
||||
} else {
|
||||
// With phone auth, the credential will only every be rejected if the user
|
||||
// account linked to the phone number has been disabled
|
||||
Exception exception = task.getException();
|
||||
Log.e(TAG, "signInWithPhoneNumber:autoVerified:signInWithCredential:onComplete:failure", exception);
|
||||
if (promiseResolved) {
|
||||
// In the scenario where an SMS code has been sent, we have no way to report
|
||||
// back to the front-end that as the promise has already been used
|
||||
} else {
|
||||
promiseRejectAuthException(promise, exception);
|
||||
}
|
||||
@Override
|
||||
public void onVerificationCompleted(final PhoneAuthCredential phoneAuthCredential) {
|
||||
// User has been automatically verified, log them in
|
||||
firebaseAuth.signInWithCredential(phoneAuthCredential)
|
||||
.addOnCompleteListener(new OnCompleteListener<AuthResult>() {
|
||||
@Override
|
||||
public void onComplete(@NonNull Task<AuthResult> task) {
|
||||
if (task.isSuccessful()) {
|
||||
// onAuthStateChanged will pick up the user change
|
||||
Log.d(TAG, "signInWithPhoneNumber:autoVerified:signInWithCredential:onComplete:success");
|
||||
// To ensure that there is no hanging promise, we resolve it with a null verificationId
|
||||
// as calling ConfirmationResult.confirm(code) is invalid in this case anyway
|
||||
if (!promiseResolved) {
|
||||
WritableMap verificationMap = Arguments.createMap();
|
||||
verificationMap.putNull("verificationId");
|
||||
promise.resolve(verificationMap);
|
||||
}
|
||||
} else {
|
||||
// With phone auth, the credential will only every be rejected if the user
|
||||
// account linked to the phone number has been disabled
|
||||
Exception exception = task.getException();
|
||||
Log.e(TAG, "signInWithPhoneNumber:autoVerified:signInWithCredential:onComplete:failure", exception);
|
||||
// In the scenario where an SMS code has been sent, we have no way to report
|
||||
// back to the front-end that as the promise has already been used
|
||||
if (!promiseResolved) {
|
||||
promiseRejectAuthException(promise, exception);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onVerificationFailed(FirebaseException e) {
|
||||
// This callback is invoked in an invalid request for verification is made,
|
||||
// e.g. phone number format is incorrect, or the SMS quota for the project
|
||||
// has been exceeded
|
||||
Log.d(TAG, "signInWithPhoneNumber:verification:failed");
|
||||
promiseRejectAuthException(promise, e);
|
||||
}
|
||||
@Override
|
||||
public void onVerificationFailed(FirebaseException e) {
|
||||
// This callback is invoked in an invalid request for verification is made,
|
||||
// e.g. phone number format is incorrect, or the SMS quota for the project
|
||||
// has been exceeded
|
||||
Log.d(TAG, "signInWithPhoneNumber:verification:failed");
|
||||
promiseRejectAuthException(promise, e);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCodeSent(String verificationId, PhoneAuthProvider.ForceResendingToken forceResendingToken) {
|
||||
// TODO: This isn't being saved anywhere if the activity gets restarted when going to the SMS app
|
||||
mVerificationId = verificationId;
|
||||
WritableMap verificationMap = Arguments.createMap();
|
||||
verificationMap.putString("verificationId", verificationId);
|
||||
promise.resolve(verificationMap);
|
||||
promiseResolved = true;
|
||||
}
|
||||
@Override
|
||||
public void onCodeSent(String verificationId, PhoneAuthProvider.ForceResendingToken forceResendingToken) {
|
||||
// TODO: This isn't being saved anywhere if the activity gets restarted when going to the SMS app
|
||||
mVerificationId = verificationId;
|
||||
mForceResendingToken = forceResendingToken;
|
||||
WritableMap verificationMap = Arguments.createMap();
|
||||
verificationMap.putString("verificationId", verificationId);
|
||||
promise.resolve(verificationMap);
|
||||
promiseResolved = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCodeAutoRetrievalTimeOut(String verificationId) {
|
||||
super.onCodeAutoRetrievalTimeOut(verificationId);
|
||||
// Purposefully not doing anything with this at the moment
|
||||
}
|
||||
});
|
||||
@Override
|
||||
public void onCodeAutoRetrievalTimeOut(String verificationId) {
|
||||
super.onCodeAutoRetrievalTimeOut(verificationId);
|
||||
// Purposefully not doing anything with this at the moment
|
||||
}
|
||||
};
|
||||
|
||||
if (activity != null) {
|
||||
if (forceResend && mForceResendingToken != null) {
|
||||
PhoneAuthProvider.getInstance(firebaseAuth)
|
||||
.verifyPhoneNumber(
|
||||
phoneNumber,
|
||||
60,
|
||||
TimeUnit.SECONDS,
|
||||
activity,
|
||||
callbacks,
|
||||
mForceResendingToken
|
||||
);
|
||||
} else {
|
||||
PhoneAuthProvider.getInstance(firebaseAuth)
|
||||
.verifyPhoneNumber(
|
||||
phoneNumber,
|
||||
60,
|
||||
TimeUnit.SECONDS,
|
||||
activity,
|
||||
callbacks
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ReactMethod
|
||||
@@ -769,13 +863,19 @@ class RNFirebaseAuth extends ReactContextBaseJavaModule {
|
||||
* @param timeout
|
||||
*/
|
||||
@ReactMethod
|
||||
public void verifyPhoneNumber(final String appName, final String phoneNumber, final String requestKey, final int timeout) {
|
||||
public void verifyPhoneNumber(final String appName, final String phoneNumber, final String requestKey, final int timeout, final boolean forceResend) {
|
||||
FirebaseApp firebaseApp = FirebaseApp.getInstance(appName);
|
||||
final FirebaseAuth firebaseAuth = FirebaseAuth.getInstance(firebaseApp);
|
||||
final Activity activity = mReactContext.getCurrentActivity();
|
||||
|
||||
Log.d(TAG, "verifyPhoneNumber:" + phoneNumber);
|
||||
|
||||
// reset force resending token if phone number changes
|
||||
if (!phoneNumber.equals(mLastPhoneNumber)) {
|
||||
mForceResendingToken = null;
|
||||
mLastPhoneNumber = phoneNumber;
|
||||
}
|
||||
|
||||
// Reset the credential
|
||||
mCredential = null;
|
||||
|
||||
@@ -820,9 +920,11 @@ class RNFirebaseAuth extends ReactContextBaseJavaModule {
|
||||
@Override
|
||||
public void onCodeSent(String verificationId, PhoneAuthProvider.ForceResendingToken forceResendingToken) {
|
||||
Log.d(TAG, "verifyPhoneNumber:verification:onCodeSent");
|
||||
mForceResendingToken = forceResendingToken;
|
||||
WritableMap state = Arguments.createMap();
|
||||
state.putString("verificationId", verificationId);
|
||||
|
||||
|
||||
// todo forceResendingToken - it's actually just an empty class ... no actual token >.>
|
||||
// Parcel parcel = Parcel.obtain();
|
||||
// forceResendingToken.writeToParcel(parcel, 0);
|
||||
@@ -850,15 +952,26 @@ class RNFirebaseAuth extends ReactContextBaseJavaModule {
|
||||
};
|
||||
|
||||
if (activity != null) {
|
||||
PhoneAuthProvider.getInstance(firebaseAuth)
|
||||
.verifyPhoneNumber(
|
||||
phoneNumber,
|
||||
timeout,
|
||||
TimeUnit.SECONDS,
|
||||
activity,
|
||||
callbacks
|
||||
//, PhoneAuthProvider.ForceResendingToken.zzboe() // TODO FORCE RESENDING
|
||||
);
|
||||
if (forceResend && mForceResendingToken != null) {
|
||||
PhoneAuthProvider.getInstance(firebaseAuth)
|
||||
.verifyPhoneNumber(
|
||||
phoneNumber,
|
||||
timeout,
|
||||
TimeUnit.SECONDS,
|
||||
activity,
|
||||
callbacks,
|
||||
mForceResendingToken
|
||||
);
|
||||
} else {
|
||||
PhoneAuthProvider.getInstance(firebaseAuth)
|
||||
.verifyPhoneNumber(
|
||||
phoneNumber,
|
||||
timeout,
|
||||
TimeUnit.SECONDS,
|
||||
activity,
|
||||
callbacks
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -961,6 +1074,9 @@ class RNFirebaseAuth extends ReactContextBaseJavaModule {
|
||||
case ActionCodeResult.PASSWORD_RESET:
|
||||
actionType = "PASSWORD_RESET";
|
||||
break;
|
||||
case ActionCodeResult.SIGN_IN_WITH_EMAIL_LINK:
|
||||
actionType = "EMAIL_SIGNIN";
|
||||
break;
|
||||
}
|
||||
|
||||
writableMap.putString("actionType", actionType);
|
||||
@@ -1067,7 +1183,7 @@ class RNFirebaseAuth extends ReactContextBaseJavaModule {
|
||||
reauthenticate(appName, provider, authToken, authSecret, promise, true);
|
||||
}
|
||||
|
||||
public void reauthenticate(String appName, String provider, String authToken, String authSecret, final Promise promise, final boolean withData) {
|
||||
private void reauthenticate(String appName, String provider, String authToken, String authSecret, final Promise promise, final boolean withData) {
|
||||
FirebaseApp firebaseApp = FirebaseApp.getInstance(appName);
|
||||
final FirebaseAuth firebaseAuth = FirebaseAuth.getInstance(firebaseApp);
|
||||
|
||||
@@ -1131,7 +1247,13 @@ class RNFirebaseAuth extends ReactContextBaseJavaModule {
|
||||
}
|
||||
return PhoneAuthProvider.getCredential(authToken, authSecret);
|
||||
case "password":
|
||||
// authToken = email
|
||||
// authSecret = password
|
||||
return EmailAuthProvider.getCredential(authToken, authSecret);
|
||||
case "emailLink":
|
||||
// authToken = email
|
||||
// authSecret = link
|
||||
return EmailAuthProvider.getCredentialWithLink(authToken, authSecret);
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
@@ -1166,19 +1288,19 @@ class RNFirebaseAuth extends ReactContextBaseJavaModule {
|
||||
}
|
||||
|
||||
@ReactMethod
|
||||
public void fetchProvidersForEmail(String appName, String email, final Promise promise) {
|
||||
public void fetchSignInMethodsForEmail(String appName, String email, final Promise promise) {
|
||||
FirebaseApp firebaseApp = FirebaseApp.getInstance(appName);
|
||||
FirebaseAuth firebaseAuth = FirebaseAuth.getInstance(firebaseApp);
|
||||
|
||||
Log.d(TAG, "fetchProvidersForEmail");
|
||||
|
||||
firebaseAuth.fetchProvidersForEmail(email)
|
||||
.addOnCompleteListener(new OnCompleteListener<ProviderQueryResult>() {
|
||||
firebaseAuth.fetchSignInMethodsForEmail(email)
|
||||
.addOnCompleteListener(new OnCompleteListener<SignInMethodQueryResult>() {
|
||||
@Override
|
||||
public void onComplete(@NonNull Task<ProviderQueryResult> task) {
|
||||
public void onComplete(@NonNull Task<SignInMethodQueryResult> task) {
|
||||
if (task.isSuccessful()) {
|
||||
Log.d(TAG, "fetchProvidersForEmail:onComplete:success");
|
||||
List<String> providers = task.getResult().getProviders();
|
||||
List<String> providers = task.getResult().getSignInMethods();
|
||||
WritableArray array = Arguments.createArray();
|
||||
|
||||
if (providers != null) {
|
||||
@@ -1282,8 +1404,7 @@ class RNFirebaseAuth extends ReactContextBaseJavaModule {
|
||||
WritableMap additionalUserInfoMap = Arguments.createMap();
|
||||
additionalUserInfoMap.putBoolean("isNewUser", authResult.getAdditionalUserInfo().isNewUser());
|
||||
if (authResult.getAdditionalUserInfo().getProfile() != null) {
|
||||
WritableMap profileMap = mapToWritableMap(authResult.getAdditionalUserInfo().getProfile());
|
||||
additionalUserInfoMap.putMap("profile", profileMap);
|
||||
Utils.mapPutValue("profile", authResult.getAdditionalUserInfo().getProfile(), additionalUserInfoMap);
|
||||
}
|
||||
if (authResult.getAdditionalUserInfo().getProviderId() != null) {
|
||||
additionalUserInfoMap.putString("providerId", authResult.getAdditionalUserInfo().getProviderId());
|
||||
@@ -1300,65 +1421,6 @@ class RNFirebaseAuth extends ReactContextBaseJavaModule {
|
||||
}
|
||||
}
|
||||
|
||||
private WritableMap mapToWritableMap(Map<String, Object> map) {
|
||||
WritableMap writableMap = Arguments.createMap();
|
||||
for (String key : map.keySet()) {
|
||||
Object value = map.get(key);
|
||||
if (value == null) {
|
||||
writableMap.putNull(key);
|
||||
} else if (value instanceof Boolean) {
|
||||
writableMap.putBoolean(key, (Boolean) value);
|
||||
} else if (value instanceof Integer) {
|
||||
writableMap.putDouble(key, ((Integer) value).doubleValue());
|
||||
} else if (value instanceof Long) {
|
||||
writableMap.putDouble(key, ((Long) value).doubleValue());
|
||||
} else if (value instanceof Double) {
|
||||
writableMap.putDouble(key, (Double) value);
|
||||
} else if (value instanceof Float) {
|
||||
writableMap.putDouble(key, ((Float) value).doubleValue());
|
||||
} else if (value instanceof String) {
|
||||
writableMap.putString(key, (String) value);
|
||||
} else if (Map.class.isAssignableFrom(value.getClass())) {
|
||||
writableMap.putMap(key, mapToWritableMap((Map<String, Object>) value));
|
||||
} else if (List.class.isAssignableFrom(value.getClass())) {
|
||||
writableMap.putArray(key, listToWritableArray((List<Object>) value));
|
||||
} else {
|
||||
Log.e(TAG, "mapToWritableMap: Cannot convert object of type " + value.getClass());
|
||||
}
|
||||
}
|
||||
|
||||
return writableMap;
|
||||
}
|
||||
|
||||
private WritableArray listToWritableArray(List<Object> list) {
|
||||
WritableArray writableArray = Arguments.createArray();
|
||||
for (Object item : list) {
|
||||
if (item == null) {
|
||||
writableArray.pushNull();
|
||||
} else if (item instanceof Boolean) {
|
||||
writableArray.pushBoolean((Boolean) item);
|
||||
} else if (item instanceof Integer) {
|
||||
writableArray.pushDouble(((Integer) item).doubleValue());
|
||||
} else if (item instanceof Long) {
|
||||
writableArray.pushDouble(((Long) item).doubleValue());
|
||||
} else if (item instanceof Double) {
|
||||
writableArray.pushDouble((Double) item);
|
||||
} else if (item instanceof Float) {
|
||||
writableArray.pushDouble(((Float) item).doubleValue());
|
||||
} else if (item instanceof String) {
|
||||
writableArray.pushString((String) item);
|
||||
} else if (Map.class.isAssignableFrom(item.getClass())) {
|
||||
writableArray.pushMap(mapToWritableMap((Map<String, Object>) item));
|
||||
} else if (List.class.isAssignableFrom(item.getClass())) {
|
||||
writableArray.pushArray(listToWritableArray((List<Object>) item));
|
||||
} else {
|
||||
Log.e(TAG, "listToWritableArray: Cannot convert object of type " + item.getClass());
|
||||
}
|
||||
}
|
||||
return writableArray;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* promiseRejectAuthException
|
||||
*
|
||||
@@ -1387,7 +1449,7 @@ class RNFirebaseAuth extends ReactContextBaseJavaModule {
|
||||
error.putString("nativeErrorCode", code);
|
||||
message = authException.getMessage();
|
||||
} catch (Exception e) {
|
||||
Matcher matcher = Pattern.compile("\\[(.*):.*\\]").matcher(message);
|
||||
Matcher matcher = Pattern.compile("([A-Z]*_[A-Z]*)").matcher(message);
|
||||
if (matcher.find()) {
|
||||
code = matcher.group(1).trim();
|
||||
switch (code) {
|
||||
@@ -1439,6 +1501,10 @@ class RNFirebaseAuth extends ReactContextBaseJavaModule {
|
||||
case "OPERATION_NOT_ALLOWED":
|
||||
message = "This operation is not allowed. You must enable this service in the console.";
|
||||
break;
|
||||
case "INVALID_IDENTIFIER":
|
||||
code = "INVALID_EMAIL";
|
||||
message = invalidEmail;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1576,7 +1642,7 @@ class RNFirebaseAuth extends ReactContextBaseJavaModule {
|
||||
ReadableMap ios = actionCodeSettings.getMap("iOS");
|
||||
String url = actionCodeSettings.getString("url");
|
||||
if (android != null) {
|
||||
boolean installApp = android.hasKey("installApp") ? android.getBoolean("installApp") : false;
|
||||
boolean installApp = android.hasKey("installApp") && android.getBoolean("installApp");
|
||||
String minimumVersion = android.hasKey("minimumVersion") ? android.getString("minimumVersion") : null;
|
||||
String packageName = android.getString("packageName");
|
||||
builder = builder.setAndroidPackageName(packageName, installApp, minimumVersion);
|
||||
|
||||
@@ -500,7 +500,12 @@ public class RNFirebaseDatabase extends ReactContextBaseJavaModule {
|
||||
public static FirebaseDatabase getDatabaseForApp(String appName, String dbURL) {
|
||||
FirebaseDatabase firebaseDatabase;
|
||||
if(dbURL != null && dbURL.length() > 0) {
|
||||
firebaseDatabase = FirebaseDatabase.getInstance(dbURL);
|
||||
if (appName != null && appName.length() > 0) {
|
||||
FirebaseApp firebaseApp = FirebaseApp.getInstance(appName);
|
||||
firebaseDatabase = FirebaseDatabase.getInstance(firebaseApp, dbURL);
|
||||
} else {
|
||||
firebaseDatabase = FirebaseDatabase.getInstance(dbURL);
|
||||
}
|
||||
} else {
|
||||
FirebaseApp firebaseApp = FirebaseApp.getInstance(appName);
|
||||
firebaseDatabase = FirebaseDatabase.getInstance(firebaseApp);
|
||||
|
||||
@@ -91,9 +91,10 @@ public class RNFirebaseFirestore extends ReactContextBaseJavaModule {
|
||||
|
||||
@ReactMethod
|
||||
public void collectionGet(String appName, String path, ReadableArray filters,
|
||||
ReadableArray orders, ReadableMap options, final Promise promise) {
|
||||
ReadableArray orders, ReadableMap options, ReadableMap getOptions,
|
||||
final Promise promise) {
|
||||
RNFirebaseFirestoreCollectionReference ref = getCollectionForAppPath(appName, path, filters, orders, options);
|
||||
ref.get(promise);
|
||||
ref.get(getOptions, promise);
|
||||
}
|
||||
|
||||
@ReactMethod
|
||||
@@ -165,14 +166,9 @@ public class RNFirebaseFirestore extends ReactContextBaseJavaModule {
|
||||
}
|
||||
|
||||
@ReactMethod
|
||||
public void documentGet(String appName, String path, final Promise promise) {
|
||||
public void documentGet(String appName, String path, ReadableMap getOptions, final Promise promise) {
|
||||
RNFirebaseFirestoreDocumentReference ref = getDocumentForAppPath(appName, path);
|
||||
ref.get(promise);
|
||||
}
|
||||
|
||||
@ReactMethod
|
||||
public void documentGetAll(String appName, ReadableArray documents, final Promise promise) {
|
||||
// Not supported on Android out of the box
|
||||
ref.get(getOptions, promise);
|
||||
}
|
||||
|
||||
@ReactMethod
|
||||
@@ -205,12 +201,18 @@ public class RNFirebaseFirestore extends ReactContextBaseJavaModule {
|
||||
FirebaseFirestoreSettings.Builder firestoreSettings = new FirebaseFirestoreSettings.Builder();
|
||||
if (settings.hasKey("host")) {
|
||||
firestoreSettings.setHost(settings.getString("host"));
|
||||
} else {
|
||||
firestoreSettings.setHost(firestore.getFirestoreSettings().getHost());
|
||||
}
|
||||
if (settings.hasKey("persistence")) {
|
||||
firestoreSettings.setPersistenceEnabled(settings.getBoolean("persistence"));
|
||||
} else {
|
||||
firestoreSettings.setPersistenceEnabled(firestore.getFirestoreSettings().isPersistenceEnabled());
|
||||
}
|
||||
if (settings.hasKey("ssl")) {
|
||||
firestoreSettings.setSslEnabled(settings.getBoolean("ssl"));
|
||||
} else {
|
||||
firestoreSettings.setSslEnabled(firestore.getFirestoreSettings().isSslEnabled());
|
||||
}
|
||||
if (settings.hasKey("timestampsInSnapshots")) {
|
||||
// TODO: Not supported on Android yet
|
||||
|
||||
@@ -12,15 +12,15 @@ import com.facebook.react.bridge.ReadableMap;
|
||||
import com.facebook.react.bridge.WritableMap;
|
||||
import com.google.android.gms.tasks.OnCompleteListener;
|
||||
import com.google.android.gms.tasks.Task;
|
||||
import com.google.firebase.firestore.DocumentListenOptions;
|
||||
import com.google.firebase.firestore.EventListener;
|
||||
import com.google.firebase.firestore.FieldPath;
|
||||
import com.google.firebase.firestore.FirebaseFirestore;
|
||||
import com.google.firebase.firestore.FirebaseFirestoreException;
|
||||
import com.google.firebase.firestore.ListenerRegistration;
|
||||
import com.google.firebase.firestore.MetadataChanges;
|
||||
import com.google.firebase.firestore.Query;
|
||||
import com.google.firebase.firestore.QueryListenOptions;
|
||||
import com.google.firebase.firestore.QuerySnapshot;
|
||||
import com.google.firebase.firestore.Source;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
@@ -53,8 +53,21 @@ public class RNFirebaseFirestoreCollectionReference {
|
||||
this.reactContext = reactContext;
|
||||
}
|
||||
|
||||
void get(final Promise promise) {
|
||||
query.get().addOnCompleteListener(new OnCompleteListener<QuerySnapshot>() {
|
||||
void get(ReadableMap getOptions, final Promise promise) {
|
||||
Source source;
|
||||
if (getOptions != null && getOptions.hasKey("source")) {
|
||||
String optionsSource = getOptions.getString("source");
|
||||
if ("server".equals(optionsSource)) {
|
||||
source = Source.SERVER;
|
||||
} else if ("cache".equals(optionsSource)) {
|
||||
source = Source.CACHE;
|
||||
} else {
|
||||
source = Source.DEFAULT;
|
||||
}
|
||||
} else {
|
||||
source = Source.DEFAULT;
|
||||
}
|
||||
query.get(source).addOnCompleteListener(new OnCompleteListener<QuerySnapshot>() {
|
||||
@Override
|
||||
public void onComplete(@NonNull Task<QuerySnapshot> task) {
|
||||
if (task.isSuccessful()) {
|
||||
@@ -92,19 +105,17 @@ public class RNFirebaseFirestoreCollectionReference {
|
||||
}
|
||||
}
|
||||
};
|
||||
QueryListenOptions options = new QueryListenOptions();
|
||||
if (queryListenOptions != null) {
|
||||
if (queryListenOptions.hasKey("includeDocumentMetadataChanges")
|
||||
&& queryListenOptions.getBoolean("includeDocumentMetadataChanges")) {
|
||||
options.includeDocumentMetadataChanges();
|
||||
}
|
||||
if (queryListenOptions.hasKey("includeQueryMetadataChanges")
|
||||
&& queryListenOptions.getBoolean("includeQueryMetadataChanges")) {
|
||||
options.includeQueryMetadataChanges();
|
||||
}
|
||||
MetadataChanges metadataChanges;
|
||||
|
||||
if (queryListenOptions != null
|
||||
&& queryListenOptions.hasKey("includeMetadataChanges")
|
||||
&& queryListenOptions.getBoolean("includeMetadataChanges")) {
|
||||
metadataChanges = MetadataChanges.INCLUDE;
|
||||
} else {
|
||||
metadataChanges = MetadataChanges.EXCLUDE;
|
||||
}
|
||||
|
||||
ListenerRegistration listenerRegistration = this.query.addSnapshotListener(options, listener);
|
||||
ListenerRegistration listenerRegistration = this.query.addSnapshotListener(metadataChanges, listener);
|
||||
collectionSnapshotListeners.put(listenerId, listenerRegistration);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,13 +10,14 @@ import com.facebook.react.bridge.ReadableMap;
|
||||
import com.facebook.react.bridge.WritableMap;
|
||||
import com.google.android.gms.tasks.OnCompleteListener;
|
||||
import com.google.android.gms.tasks.Task;
|
||||
import com.google.firebase.firestore.DocumentListenOptions;
|
||||
import com.google.firebase.firestore.DocumentReference;
|
||||
import com.google.firebase.firestore.DocumentSnapshot;
|
||||
import com.google.firebase.firestore.EventListener;
|
||||
import com.google.firebase.firestore.FirebaseFirestoreException;
|
||||
import com.google.firebase.firestore.ListenerRegistration;
|
||||
import com.google.firebase.firestore.MetadataChanges;
|
||||
import com.google.firebase.firestore.SetOptions;
|
||||
import com.google.firebase.firestore.Source;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
@@ -55,8 +56,21 @@ public class RNFirebaseFirestoreDocumentReference {
|
||||
});
|
||||
}
|
||||
|
||||
void get(final Promise promise) {
|
||||
this.ref.get().addOnCompleteListener(new OnCompleteListener<DocumentSnapshot>() {
|
||||
void get(final ReadableMap getOptions, final Promise promise) {
|
||||
Source source;
|
||||
if (getOptions != null && getOptions.hasKey("source")) {
|
||||
String optionsSource = getOptions.getString("source");
|
||||
if ("server".equals(optionsSource)) {
|
||||
source = Source.SERVER;
|
||||
} else if ("cache".equals(optionsSource)) {
|
||||
source = Source.CACHE;
|
||||
} else {
|
||||
source = Source.DEFAULT;
|
||||
}
|
||||
} else {
|
||||
source = Source.DEFAULT;
|
||||
}
|
||||
this.ref.get(source).addOnCompleteListener(new OnCompleteListener<DocumentSnapshot>() {
|
||||
@Override
|
||||
public void onComplete(@NonNull Task<DocumentSnapshot> task) {
|
||||
if (task.isSuccessful()) {
|
||||
@@ -94,11 +108,15 @@ public class RNFirebaseFirestoreDocumentReference {
|
||||
}
|
||||
}
|
||||
};
|
||||
DocumentListenOptions options = new DocumentListenOptions();
|
||||
if (docListenOptions != null && docListenOptions.hasKey("includeMetadataChanges") && docListenOptions.getBoolean("includeMetadataChanges")) {
|
||||
options.includeMetadataChanges();
|
||||
MetadataChanges metadataChanges;
|
||||
if (docListenOptions != null
|
||||
&& docListenOptions.hasKey("includeMetadataChanges")
|
||||
&& docListenOptions.getBoolean("includeMetadataChanges")) {
|
||||
metadataChanges = MetadataChanges.INCLUDE;
|
||||
} else {
|
||||
metadataChanges = MetadataChanges.EXCLUDE;
|
||||
}
|
||||
ListenerRegistration listenerRegistration = this.ref.addSnapshotListener(options, listener);
|
||||
ListenerRegistration listenerRegistration = this.ref.addSnapshotListener(metadataChanges, listener);
|
||||
documentSnapshotListeners.put(listenerId, listenerRegistration);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
package io.invertase.firebase.instanceid;
|
||||
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import android.util.Log;
|
||||
|
||||
import com.facebook.react.bridge.Promise;
|
||||
@@ -42,4 +44,26 @@ public class RNFirebaseInstanceId extends ReactContextBaseJavaModule {
|
||||
String id = FirebaseInstanceId.getInstance().getId();
|
||||
promise.resolve(id);
|
||||
}
|
||||
|
||||
@ReactMethod
|
||||
public void getToken(String authorizedEntity, String scope, Promise promise) {
|
||||
try {
|
||||
String token = FirebaseInstanceId.getInstance().getToken(authorizedEntity, scope);
|
||||
Log.d(TAG, "Firebase token for " + authorizedEntity + ": " + token);
|
||||
promise.resolve(token);
|
||||
} catch (IOException e) {
|
||||
promise.reject("iid/request-failed", "getToken request failed", e);
|
||||
}
|
||||
}
|
||||
|
||||
@ReactMethod
|
||||
public void deleteToken(String authorizedEntity, String scope, Promise promise) {
|
||||
try {
|
||||
FirebaseInstanceId.getInstance().deleteToken(authorizedEntity, scope);
|
||||
Log.d(TAG, "Firebase token deleted for " + authorizedEntity);
|
||||
promise.resolve(null);
|
||||
} catch (IOException e) {
|
||||
promise.reject("iid/request-failed", "deleteToken request failed", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -140,13 +140,13 @@ public class RNFirebaseInvites extends ReactContextBaseJavaModule implements Act
|
||||
ib = ib.setAdditionalReferralParameters(arpMap);
|
||||
}
|
||||
if (androidMap.hasKey("emailHtmlContent")) {
|
||||
ib = ib.setEmailHtmlContent(invitationMap.getString("emailHtmlContent"));
|
||||
ib = ib.setEmailHtmlContent(androidMap.getString("emailHtmlContent"));
|
||||
}
|
||||
if (androidMap.hasKey("emailSubject")) {
|
||||
ib = ib.setEmailSubject(invitationMap.getString("emailSubject"));
|
||||
ib = ib.setEmailSubject(androidMap.getString("emailSubject"));
|
||||
}
|
||||
if (androidMap.hasKey("googleAnalyticsTrackingId")) {
|
||||
ib = ib.setGoogleAnalyticsTrackingId(invitationMap.getString("googleAnalyticsTrackingId"));
|
||||
ib = ib.setGoogleAnalyticsTrackingId(androidMap.getString("googleAnalyticsTrackingId"));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -174,7 +174,11 @@ public class RNFirebaseLinks extends ReactContextBaseJavaModule implements Activ
|
||||
|
||||
// Looks at the internals of the link data to detect whether it's an invitation or not
|
||||
private boolean isInvitation(PendingDynamicLinkData pendingDynamicLinkData) {
|
||||
return FirebaseAppInvite.getInvitation(pendingDynamicLinkData) != null;
|
||||
FirebaseAppInvite invite = FirebaseAppInvite.getInvitation(pendingDynamicLinkData);
|
||||
if (invite != null && invite.getInvitationId() != null && !invite.getInvitationId().isEmpty()) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private DynamicLink.Builder getDynamicLinkBuilder(final ReadableMap linkData) {
|
||||
|
||||
@@ -4,7 +4,9 @@ import android.content.BroadcastReceiver;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.IntentFilter;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.support.v4.content.LocalBroadcastManager;
|
||||
import android.support.v4.app.NotificationManagerCompat;
|
||||
import android.util.Log;
|
||||
|
||||
import com.facebook.react.bridge.Promise;
|
||||
@@ -14,6 +16,8 @@ import com.facebook.react.bridge.ReactMethod;
|
||||
import com.facebook.react.bridge.ReadableMap;
|
||||
import com.facebook.react.bridge.ReadableMapKeySetIterator;
|
||||
import com.facebook.react.bridge.WritableMap;
|
||||
import com.google.android.gms.tasks.OnCompleteListener;
|
||||
import com.google.android.gms.tasks.Task;
|
||||
import com.google.firebase.iid.FirebaseInstanceId;
|
||||
import com.google.firebase.messaging.FirebaseMessaging;
|
||||
import com.google.firebase.messaging.RemoteMessage;
|
||||
@@ -56,7 +60,8 @@ public class RNFirebaseMessaging extends ReactContextBaseJavaModule {
|
||||
// Non Web SDK methods
|
||||
@ReactMethod
|
||||
public void hasPermission(Promise promise) {
|
||||
promise.resolve(true);
|
||||
Boolean enabled = NotificationManagerCompat.from(getReactApplicationContext()).areNotificationsEnabled();
|
||||
promise.resolve(enabled);
|
||||
}
|
||||
|
||||
@ReactMethod
|
||||
@@ -96,15 +101,37 @@ public class RNFirebaseMessaging extends ReactContextBaseJavaModule {
|
||||
}
|
||||
|
||||
@ReactMethod
|
||||
public void subscribeToTopic(String topic, Promise promise) {
|
||||
FirebaseMessaging.getInstance().subscribeToTopic(topic);
|
||||
promise.resolve(null);
|
||||
public void subscribeToTopic(String topic, final Promise promise) {
|
||||
FirebaseMessaging.getInstance().subscribeToTopic(topic).addOnCompleteListener(new OnCompleteListener<Void>() {
|
||||
@Override
|
||||
public void onComplete(@NonNull Task<Void> task) {
|
||||
if (task.isSuccessful()) {
|
||||
Log.d(TAG, "subscribeToTopic:onComplete:success");
|
||||
promise.resolve(null);
|
||||
} else {
|
||||
Exception exception = task.getException();
|
||||
Log.e(TAG, "subscribeToTopic:onComplete:failure", exception);
|
||||
promise.reject(exception);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@ReactMethod
|
||||
public void unsubscribeFromTopic(String topic, Promise promise) {
|
||||
FirebaseMessaging.getInstance().unsubscribeFromTopic(topic);
|
||||
promise.resolve(null);
|
||||
public void unsubscribeFromTopic(String topic, final Promise promise) {
|
||||
FirebaseMessaging.getInstance().unsubscribeFromTopic(topic).addOnCompleteListener(new OnCompleteListener<Void>() {
|
||||
@Override
|
||||
public void onComplete(@NonNull Task<Void> task) {
|
||||
if (task.isSuccessful()) {
|
||||
Log.d(TAG, "unsubscribeFromTopic:onComplete:success");
|
||||
promise.resolve(null);
|
||||
} else {
|
||||
Exception exception = task.getException();
|
||||
Log.e(TAG, "unsubscribeFromTopic:onComplete:failure", exception);
|
||||
promise.reject(exception);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private class MessageReceiver extends BroadcastReceiver {
|
||||
|
||||
@@ -142,12 +142,19 @@ public class DisplayNotificationTask extends AsyncTask<Void, Void, Void> {
|
||||
if (android.containsKey("contentInfo")) {
|
||||
nb = nb.setContentInfo(android.getString("contentInfo"));
|
||||
}
|
||||
if (notification.containsKey("defaults")) {
|
||||
double[] defaultsArray = android.getDoubleArray("defaults");
|
||||
int defaults = 0;
|
||||
for (Double d : defaultsArray) {
|
||||
defaults |= d.intValue();
|
||||
if (android.containsKey("defaults")) {
|
||||
Double defaultValues = android.getDouble("defaults");
|
||||
int defaults = defaultValues.intValue();
|
||||
|
||||
if (defaults == 0) {
|
||||
ArrayList<Integer> defaultsArray = android.getIntegerArrayList("defaults");
|
||||
if(defaultsArray != null) {
|
||||
for (Integer defaultValue : defaultsArray) {
|
||||
defaults |= defaultValue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
nb = nb.setDefaults(defaults);
|
||||
}
|
||||
if (android.containsKey("group")) {
|
||||
@@ -200,7 +207,7 @@ public class DisplayNotificationTask extends AsyncTask<Void, Void, Void> {
|
||||
nb = nb.setPriority(priority.intValue());
|
||||
}
|
||||
if (android.containsKey("progress")) {
|
||||
Bundle progress = android.getBundle("lights");
|
||||
Bundle progress = android.getBundle("progress");
|
||||
Double max = progress.getDouble("max");
|
||||
Double progressI = progress.getDouble("progress");
|
||||
nb = nb.setProgress(max.intValue(), progressI.intValue(), progress.getBoolean("indeterminate"));
|
||||
@@ -288,6 +295,11 @@ public class DisplayNotificationTask extends AsyncTask<Void, Void, Void> {
|
||||
if (reactContext != null) {
|
||||
Utils.sendEvent(reactContext, "notifications_notification_displayed", Arguments.fromBundle(notification));
|
||||
}
|
||||
|
||||
if (promise != null) {
|
||||
promise.resolve(null);
|
||||
}
|
||||
|
||||
} catch (Exception e) {
|
||||
Log.e(TAG, "Failed to send notification", e);
|
||||
if (promise != null) {
|
||||
@@ -299,9 +311,11 @@ public class DisplayNotificationTask extends AsyncTask<Void, Void, Void> {
|
||||
}
|
||||
|
||||
private NotificationCompat.Action createAction(Bundle action, Class intentClass, Bundle notification) {
|
||||
boolean showUserInterface = action.containsKey("showUserInterface") && action.getBoolean("showUserInterface");
|
||||
String actionKey = action.getString("action");
|
||||
PendingIntent actionIntent = createIntent(intentClass, notification, actionKey);
|
||||
|
||||
PendingIntent actionIntent = showUserInterface ?
|
||||
createIntent(intentClass, notification, actionKey) :
|
||||
createBroadcastIntent(notification, actionKey);
|
||||
int icon = getIcon(action.getString("icon"));
|
||||
String title = action.getString("title");
|
||||
|
||||
@@ -339,10 +353,21 @@ public class DisplayNotificationTask extends AsyncTask<Void, Void, Void> {
|
||||
}
|
||||
|
||||
String notificationId = notification.getString("notificationId");
|
||||
|
||||
return PendingIntent.getActivity(context, notificationId.hashCode(), intent, PendingIntent.FLAG_UPDATE_CURRENT);
|
||||
}
|
||||
|
||||
private PendingIntent createBroadcastIntent(Bundle notification, String action) {
|
||||
Intent intent = new Intent(context, RNFirebaseBackgroundNotificationActionReceiver.class);
|
||||
intent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);
|
||||
|
||||
String notificationId = notification.getString("notificationId") + action;
|
||||
|
||||
intent.setAction("io.invertase.firebase.notifications.BackgroundAction");
|
||||
intent.putExtra("action", action);
|
||||
intent.putExtra("notification", notification);
|
||||
return PendingIntent.getBroadcast(context, notificationId.hashCode(), intent, PendingIntent.FLAG_UPDATE_CURRENT);
|
||||
}
|
||||
|
||||
private RemoteInput createRemoteInput(Bundle remoteInput) {
|
||||
String resultKey = remoteInput.getString("resultKey");
|
||||
|
||||
@@ -374,7 +399,7 @@ public class DisplayNotificationTask extends AsyncTask<Void, Void, Void> {
|
||||
} else if (image.startsWith("file://")) {
|
||||
return BitmapFactory.decodeFile(image.replace("file://", ""));
|
||||
} else {
|
||||
int largeIconResId = RNFirebaseNotificationManager.getResourceId(context,"mipmap", image);
|
||||
int largeIconResId = getIcon(image);
|
||||
return BitmapFactory.decodeResource(context.getResources(), largeIconResId);
|
||||
}
|
||||
}
|
||||
@@ -392,11 +417,11 @@ public class DisplayNotificationTask extends AsyncTask<Void, Void, Void> {
|
||||
}
|
||||
|
||||
private int getIcon(String icon) {
|
||||
int smallIconResourceId = RNFirebaseNotificationManager.getResourceId(context,"mipmap", icon);
|
||||
if (smallIconResourceId == 0) {
|
||||
smallIconResourceId = RNFirebaseNotificationManager.getResourceId(context,"drawable", icon);
|
||||
int resourceId = RNFirebaseNotificationManager.getResourceId(context,"mipmap", icon);
|
||||
if (resourceId == 0) {
|
||||
resourceId = RNFirebaseNotificationManager.getResourceId(context,"drawable", icon);
|
||||
}
|
||||
return smallIconResourceId;
|
||||
return resourceId;
|
||||
}
|
||||
|
||||
private Class getMainActivityClass() {
|
||||
|
||||
@@ -0,0 +1,50 @@
|
||||
package io.invertase.firebase.notifications;
|
||||
|
||||
import android.content.BroadcastReceiver;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.os.Bundle;
|
||||
|
||||
import com.facebook.react.HeadlessJsTaskService;
|
||||
import com.facebook.react.ReactApplication;
|
||||
import com.facebook.react.bridge.Arguments;
|
||||
import com.facebook.react.bridge.ReactContext;
|
||||
import com.facebook.react.bridge.WritableMap;
|
||||
|
||||
import io.invertase.firebase.Utils;
|
||||
|
||||
public class RNFirebaseBackgroundNotificationActionReceiver extends BroadcastReceiver {
|
||||
static boolean isBackgroundNotficationIntent(Intent intent) {
|
||||
return intent.getExtras() != null && intent.hasExtra("action") && intent.hasExtra("notification");
|
||||
}
|
||||
|
||||
static WritableMap toNotificationOpenMap(Intent intent) {
|
||||
Bundle extras = intent.getExtras();
|
||||
WritableMap notificationMap = Arguments.makeNativeMap(extras.getBundle("notification"));
|
||||
WritableMap notificationOpenMap = Arguments.createMap();
|
||||
notificationOpenMap.putString("action", extras.getString("action"));
|
||||
notificationOpenMap.putMap("notification", notificationMap);
|
||||
return notificationOpenMap;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onReceive(Context context, Intent intent) {
|
||||
if (!isBackgroundNotficationIntent(intent)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (Utils.isAppInForeground(context)) {
|
||||
WritableMap notificationOpenMap = toNotificationOpenMap(intent);
|
||||
|
||||
ReactApplication reactApplication = (ReactApplication)context.getApplicationContext();
|
||||
ReactContext reactContext = reactApplication.getReactNativeHost().getReactInstanceManager().getCurrentReactContext();
|
||||
|
||||
Utils.sendEvent(reactContext, "notifications_notification_opened", notificationOpenMap);
|
||||
} else {
|
||||
Intent serviceIntent = new Intent(context, RNFirebaseBackgroundNotificationActionsService.class);
|
||||
serviceIntent.putExtras(intent.getExtras());
|
||||
context.startService(serviceIntent);
|
||||
HeadlessJsTaskService.acquireWakeLockNow(context);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
package io.invertase.firebase.notifications;
|
||||
|
||||
import android.content.Intent;
|
||||
|
||||
import com.facebook.react.HeadlessJsTaskService;
|
||||
import com.facebook.react.bridge.WritableMap;
|
||||
import com.facebook.react.jstasks.HeadlessJsTaskConfig;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
import static io.invertase.firebase.notifications.RNFirebaseBackgroundNotificationActionReceiver.isBackgroundNotficationIntent;
|
||||
import static io.invertase.firebase.notifications.RNFirebaseBackgroundNotificationActionReceiver.toNotificationOpenMap;
|
||||
|
||||
public class RNFirebaseBackgroundNotificationActionsService extends HeadlessJsTaskService {
|
||||
@Override
|
||||
protected @Nullable HeadlessJsTaskConfig getTaskConfig(Intent intent) {
|
||||
if (isBackgroundNotficationIntent(intent)) {
|
||||
WritableMap notificationOpenMap = toNotificationOpenMap(intent);
|
||||
|
||||
return new HeadlessJsTaskConfig(
|
||||
"RNFirebaseBackgroundNotificationAction",
|
||||
notificationOpenMap,
|
||||
60000,
|
||||
true
|
||||
);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -37,6 +37,7 @@ import java.io.IOException;
|
||||
import java.net.HttpURLConnection;
|
||||
import java.net.URL;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Calendar;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
@@ -86,6 +87,7 @@ public class RNFirebaseNotificationManager {
|
||||
try {
|
||||
cancelAlarm(notificationId);
|
||||
preferences.edit().remove(notificationId).apply();
|
||||
promise.resolve(null);
|
||||
} catch (SecurityException e) {
|
||||
// TODO: Identify what these situations are
|
||||
// In some devices/situations cancelAllLocalNotifications can throw a SecurityException.
|
||||
@@ -130,6 +132,18 @@ public class RNFirebaseNotificationManager {
|
||||
}
|
||||
}
|
||||
|
||||
public void deleteChannelGroup(String groupId) {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
||||
notificationManager.deleteNotificationChannelGroup(groupId);
|
||||
}
|
||||
}
|
||||
|
||||
public void deleteChannel(String channelId) {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
||||
notificationManager.deleteNotificationChannel(channelId);
|
||||
}
|
||||
}
|
||||
|
||||
public void displayNotification(ReadableMap notification, Promise promise) {
|
||||
Bundle notificationBundle = Arguments.toBundle(notification);
|
||||
displayNotification(notificationBundle, promise);
|
||||
@@ -319,17 +333,19 @@ public class RNFirebaseNotificationManager {
|
||||
// fireDate is stored in the Bundle as Long after notifications are rescheduled.
|
||||
// This would lead to a fireDate of 0.0 when trying to extract a Double from the bundle.
|
||||
// Instead always try extract a Long
|
||||
Long fireDate = schedule.getLong("fireDate", -1);
|
||||
if (fireDate == -1) {
|
||||
Long fireDate = -1L;
|
||||
try {
|
||||
fireDate = (long) schedule.getDouble("fireDate", -1);
|
||||
if (fireDate == -1) {
|
||||
if (promise == null) {
|
||||
Log.e(TAG, "Missing schedule information");
|
||||
} else {
|
||||
promise.reject("notification/schedule_notification_error", "Missing fireDate information");
|
||||
}
|
||||
return;
|
||||
} catch (ClassCastException e) {
|
||||
fireDate = schedule.getLong("fireDate", -1);
|
||||
}
|
||||
if (fireDate == -1) {
|
||||
if (promise == null) {
|
||||
Log.e(TAG, "Missing schedule information");
|
||||
} else {
|
||||
promise.reject("notification/schedule_notification_error", "Missing fireDate information");
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// Scheduled alarms are cleared on restart
|
||||
@@ -352,6 +368,21 @@ public class RNFirebaseNotificationManager {
|
||||
notificationIntent, PendingIntent.FLAG_UPDATE_CURRENT);
|
||||
|
||||
if (schedule.containsKey("repeatInterval")) {
|
||||
// If fireDate you specify is in the past, the alarm triggers immediately.
|
||||
// So we need to adjust the time for correct operation.
|
||||
if (fireDate < System.currentTimeMillis()) {
|
||||
Calendar newFireDate = Calendar.getInstance();
|
||||
Calendar currentFireDate = Calendar.getInstance();
|
||||
currentFireDate.setTimeInMillis(fireDate);
|
||||
|
||||
newFireDate.add(Calendar.DATE, 1);
|
||||
newFireDate.set(Calendar.HOUR_OF_DAY, currentFireDate.get(Calendar.HOUR_OF_DAY));
|
||||
newFireDate.set(Calendar.MINUTE, currentFireDate.get(Calendar.MINUTE));
|
||||
newFireDate.set(Calendar.SECOND, currentFireDate.get(Calendar.SECOND));
|
||||
|
||||
fireDate = newFireDate.getTimeInMillis();
|
||||
}
|
||||
|
||||
Long interval = null;
|
||||
switch (schedule.getString("repeatInterval")) {
|
||||
case "minute":
|
||||
|
||||
@@ -162,6 +162,18 @@ public class RNFirebaseNotifications extends ReactContextBaseJavaModule implemen
|
||||
notificationManager.createChannels(channelsArray);
|
||||
promise.resolve(null);
|
||||
}
|
||||
|
||||
@ReactMethod
|
||||
public void deleteChannelGroup(String channelId, Promise promise) {
|
||||
notificationManager.deleteChannelGroup(channelId);
|
||||
promise.resolve(null);
|
||||
}
|
||||
|
||||
@ReactMethod
|
||||
public void deleteChannel(String channelId, Promise promise) {
|
||||
notificationManager.deleteChannel(channelId);
|
||||
promise.resolve(null);
|
||||
}
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
// End Android specific methods
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
package io.invertase.firebase.storage;
|
||||
|
||||
import android.content.ContentResolver;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.util.Log;
|
||||
import android.os.Environment;
|
||||
|
||||
@@ -7,16 +9,15 @@ import java.io.File;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.HashMap;
|
||||
|
||||
import android.net.Uri;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.webkit.MimeTypeMap;
|
||||
|
||||
import com.facebook.react.bridge.Arguments;
|
||||
import com.facebook.react.bridge.Promise;
|
||||
import com.facebook.react.bridge.WritableArray;
|
||||
import com.facebook.react.bridge.WritableMap;
|
||||
import com.facebook.react.bridge.ReactMethod;
|
||||
import com.facebook.react.bridge.ReadableMap;
|
||||
@@ -49,7 +50,7 @@ public class RNFirebaseStorage extends ReactContextBaseJavaModule {
|
||||
private static final String ExternalDirectoryPath = "EXTERNAL_DIRECTORY_PATH";
|
||||
private static final String ExternalStorageDirectoryPath = "EXTERNAL_STORAGE_DIRECTORY_PATH";
|
||||
private static final String PicturesDirectoryPath = "PICTURES_DIRECTORY_PATH";
|
||||
private static final String TemporaryDirectoryPath = "TEMPORARY_DIRECTORY_PATH";
|
||||
private static final String TemporaryDirectoryPath = "TEMP_DIRECTORY_PATH";
|
||||
private static final String CachesDirectoryPath = "CACHES_DIRECTORY_PATH";
|
||||
|
||||
private static final String FileTypeRegular = "FILETYPE_REGULAR";
|
||||
@@ -185,7 +186,7 @@ public class RNFirebaseStorage extends ReactContextBaseJavaModule {
|
||||
@ReactMethod
|
||||
public void updateMetadata(String appName, final String path, final ReadableMap metadata, final Promise promise) {
|
||||
StorageReference reference = this.getReference(path, appName);
|
||||
StorageMetadata md = buildMetadataFromMap(metadata);
|
||||
StorageMetadata md = buildMetadataFromMap(metadata, null);
|
||||
|
||||
reference.updateMetadata(md).addOnSuccessListener(new OnSuccessListener<StorageMetadata>() {
|
||||
@Override
|
||||
@@ -338,7 +339,7 @@ public class RNFirebaseStorage extends ReactContextBaseJavaModule {
|
||||
|
||||
try {
|
||||
Uri file = getURI(localPath);
|
||||
StorageMetadata md = buildMetadataFromMap(metadata);
|
||||
StorageMetadata md = buildMetadataFromMap(metadata, file);
|
||||
UploadTask uploadTask = reference.putFile(file, md);
|
||||
|
||||
// register observers to listen for when the download is done or if it fails
|
||||
@@ -356,30 +357,51 @@ public class RNFirebaseStorage extends ReactContextBaseJavaModule {
|
||||
@Override
|
||||
public void onSuccess(UploadTask.TaskSnapshot taskSnapshot) {
|
||||
Log.d(TAG, "putFile success " + taskSnapshot);
|
||||
WritableMap resp = getUploadTaskAsMap(taskSnapshot);
|
||||
sendJSEvent(appName, STORAGE_STATE_CHANGED, path, resp);
|
||||
// to avoid readable map already consumed errors we run this three times
|
||||
getUploadTaskAsMap(taskSnapshot, new OnSuccessListener<WritableMap>() {
|
||||
@Override
|
||||
public void onSuccess(WritableMap event) {
|
||||
sendJSEvent(appName, STORAGE_STATE_CHANGED, path, event);
|
||||
}
|
||||
});
|
||||
|
||||
// to avoid readable map already consumed errors
|
||||
resp = getUploadTaskAsMap(taskSnapshot);
|
||||
sendJSEvent(appName, STORAGE_UPLOAD_SUCCESS, path, resp);
|
||||
getUploadTaskAsMap(taskSnapshot, new OnSuccessListener<WritableMap>() {
|
||||
@Override
|
||||
public void onSuccess(WritableMap event) {
|
||||
sendJSEvent(appName, STORAGE_UPLOAD_SUCCESS, path, event);
|
||||
}
|
||||
});
|
||||
|
||||
resp = getUploadTaskAsMap(taskSnapshot);
|
||||
promise.resolve(resp);
|
||||
getUploadTaskAsMap(taskSnapshot, new OnSuccessListener<WritableMap>() {
|
||||
@Override
|
||||
public void onSuccess(WritableMap event) {
|
||||
promise.resolve(event);
|
||||
}
|
||||
});
|
||||
}
|
||||
})
|
||||
.addOnProgressListener(new OnProgressListener<UploadTask.TaskSnapshot>() {
|
||||
@Override
|
||||
public void onProgress(UploadTask.TaskSnapshot taskSnapshot) {
|
||||
Log.d(TAG, "putFile progress " + taskSnapshot);
|
||||
sendJSEvent(appName, STORAGE_STATE_CHANGED, path, getUploadTaskAsMap(taskSnapshot));
|
||||
getUploadTaskAsMap(taskSnapshot, new OnSuccessListener<WritableMap>() {
|
||||
@Override
|
||||
public void onSuccess(WritableMap event) {
|
||||
sendJSEvent(appName, STORAGE_STATE_CHANGED, path, event);
|
||||
}
|
||||
});
|
||||
}
|
||||
})
|
||||
.addOnPausedListener(new OnPausedListener<UploadTask.TaskSnapshot>() {
|
||||
@Override
|
||||
public void onPaused(UploadTask.TaskSnapshot taskSnapshot) {
|
||||
Log.d(TAG, "putFile paused " + taskSnapshot);
|
||||
WritableMap event = getUploadTaskAsMap(taskSnapshot);
|
||||
sendJSEvent(appName, STORAGE_STATE_CHANGED, path, event);
|
||||
getUploadTaskAsMap(taskSnapshot, new OnSuccessListener<WritableMap>() {
|
||||
@Override
|
||||
public void onSuccess(WritableMap event) {
|
||||
sendJSEvent(appName, STORAGE_STATE_CHANGED, path, event);
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
} catch (Exception exception) {
|
||||
@@ -426,13 +448,11 @@ public class RNFirebaseStorage extends ReactContextBaseJavaModule {
|
||||
* @param metadata
|
||||
* @return
|
||||
*/
|
||||
private StorageMetadata buildMetadataFromMap(ReadableMap metadata) {
|
||||
private StorageMetadata buildMetadataFromMap(ReadableMap metadata, @Nullable Uri file) {
|
||||
StorageMetadata.Builder metadataBuilder = new StorageMetadata.Builder();
|
||||
|
||||
try {
|
||||
|
||||
Map<String, Object> m = Utils.recursivelyDeconstructReadableMap(metadata);
|
||||
|
||||
Map<String, Object> customMetadata = (Map<String, Object>) m.get("customMetadata");
|
||||
if (customMetadata != null) {
|
||||
for (Map.Entry<String, Object> entry : customMetadata.entrySet()) {
|
||||
@@ -444,8 +464,24 @@ public class RNFirebaseStorage extends ReactContextBaseJavaModule {
|
||||
metadataBuilder.setContentDisposition((String) m.get("contentDisposition"));
|
||||
metadataBuilder.setContentEncoding((String) m.get("contentEncoding"));
|
||||
metadataBuilder.setContentLanguage((String) m.get("contentLanguage"));
|
||||
metadataBuilder.setContentType((String) m.get("contentType"));
|
||||
|
||||
if (metadata.hasKey("contentType")) {
|
||||
metadataBuilder.setContentType((String) m.get("contentType"));
|
||||
} else if (file != null) {
|
||||
String mimeType = null;
|
||||
|
||||
if (file.getScheme().equals(ContentResolver.SCHEME_CONTENT)) {
|
||||
ContentResolver cr = getReactApplicationContext().getContentResolver();
|
||||
mimeType = cr.getType(file);
|
||||
} else {
|
||||
String fileExtension = MimeTypeMap.getFileExtensionFromUrl(file
|
||||
.toString());
|
||||
mimeType = MimeTypeMap.getSingleton().getMimeTypeFromExtension(
|
||||
fileExtension.toLowerCase());
|
||||
}
|
||||
|
||||
if (mimeType != null) metadataBuilder.setContentType(mimeType);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
Log.e(TAG, "error while building meta data " + e.getMessage());
|
||||
}
|
||||
@@ -476,24 +512,32 @@ public class RNFirebaseStorage extends ReactContextBaseJavaModule {
|
||||
* @param taskSnapshot
|
||||
* @return
|
||||
*/
|
||||
private WritableMap getUploadTaskAsMap(UploadTask.TaskSnapshot taskSnapshot) {
|
||||
WritableMap resp = Arguments.createMap();
|
||||
|
||||
private void getUploadTaskAsMap(final UploadTask.TaskSnapshot taskSnapshot, final OnSuccessListener<WritableMap> listener) {
|
||||
if (taskSnapshot != null) {
|
||||
resp.putDouble("bytesTransferred", taskSnapshot.getBytesTransferred());
|
||||
resp.putString("downloadURL", taskSnapshot.getDownloadUrl() != null ? taskSnapshot.getDownloadUrl().toString() : null);
|
||||
taskSnapshot.getStorage().getDownloadUrl().addOnSuccessListener(new OnSuccessListener<Uri>() {
|
||||
@Override
|
||||
public void onSuccess(Uri downloadUrl) {
|
||||
WritableMap resp = Arguments.createMap();
|
||||
|
||||
StorageMetadata d = taskSnapshot.getMetadata();
|
||||
if (d != null) {
|
||||
WritableMap metadata = getMetadataAsMap(d);
|
||||
resp.putMap("metadata", metadata);
|
||||
}
|
||||
resp.putDouble("bytesTransferred", taskSnapshot.getBytesTransferred());
|
||||
resp.putString("downloadURL", downloadUrl.toString());
|
||||
|
||||
resp.putString("ref", taskSnapshot.getStorage().getPath());
|
||||
resp.putString("state", this.getTaskStatus(taskSnapshot.getTask()));
|
||||
resp.putDouble("totalBytes", taskSnapshot.getTotalByteCount());
|
||||
StorageMetadata d = taskSnapshot.getMetadata();
|
||||
if (d != null) {
|
||||
WritableMap metadata = getMetadataAsMap(d);
|
||||
resp.putMap("metadata", metadata);
|
||||
}
|
||||
|
||||
resp.putString("ref", taskSnapshot.getStorage().getPath());
|
||||
resp.putString("state", RNFirebaseStorage.this.getTaskStatus(taskSnapshot.getTask()));
|
||||
resp.putDouble("totalBytes", taskSnapshot.getTotalByteCount());
|
||||
|
||||
listener.onSuccess(resp);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
listener.onSuccess(Arguments.createMap());
|
||||
}
|
||||
return resp;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -519,17 +563,6 @@ public class RNFirebaseStorage extends ReactContextBaseJavaModule {
|
||||
metadata.putString("contentLanguage", storageMetadata.getContentLanguage());
|
||||
metadata.putString("contentType", storageMetadata.getContentType());
|
||||
|
||||
WritableArray downloadURLs = Arguments.createArray();
|
||||
List<Uri> _downloadURLS = storageMetadata.getDownloadUrls();
|
||||
|
||||
if (_downloadURLS != null) {
|
||||
for (Uri uri : _downloadURLS) {
|
||||
downloadURLs.pushString(uri.getPath());
|
||||
}
|
||||
}
|
||||
|
||||
metadata.putArray("downloadURLs", downloadURLs);
|
||||
|
||||
WritableMap customMetadata = Arguments.createMap();
|
||||
for (String key : storageMetadata.getCustomMetadataKeys()) {
|
||||
customMetadata.putString(key, storageMetadata.getCustomMetadata(key));
|
||||
@@ -568,12 +601,10 @@ public class RNFirebaseStorage extends ReactContextBaseJavaModule {
|
||||
*/
|
||||
private void sendJSEvent(String appName, final String name, final String path, WritableMap body) {
|
||||
WritableMap event = Arguments.createMap();
|
||||
|
||||
event.putString("appName", appName);
|
||||
event.putString("eventName", name);
|
||||
event.putString("path", path);
|
||||
event.putMap("body", body);
|
||||
|
||||
event.putString("path", path);
|
||||
event.putString("eventName", name);
|
||||
event.putString("appName", appName);
|
||||
Utils.sendEvent(this.getReactApplicationContext(), STORAGE_EVENT, event);
|
||||
}
|
||||
|
||||
@@ -653,7 +684,7 @@ public class RNFirebaseStorage extends ReactContextBaseJavaModule {
|
||||
final Map<String, Object> constants = new HashMap<>();
|
||||
|
||||
constants.put(DocumentDirectoryPath, this.getReactApplicationContext().getFilesDir().getAbsolutePath());
|
||||
constants.put(TemporaryDirectoryPath, null);
|
||||
constants.put(TemporaryDirectoryPath, this.getReactApplicationContext().getCacheDir().getAbsolutePath());
|
||||
constants.put(PicturesDirectoryPath, Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES).getAbsolutePath());
|
||||
constants.put(CachesDirectoryPath, this.getReactApplicationContext().getCacheDir().getAbsolutePath());
|
||||
constants.put(FileTypeRegular, 0);
|
||||
|
||||
@@ -15,7 +15,7 @@ def enableProguardInReleaseBuilds = false
|
||||
|
||||
android {
|
||||
compileSdkVersion 27
|
||||
buildToolsVersion '27.0.2'
|
||||
// buildToolsVersion '27.0.2'
|
||||
|
||||
defaultConfig {
|
||||
applicationId "com.testing"
|
||||
@@ -78,40 +78,46 @@ android {
|
||||
}
|
||||
}
|
||||
|
||||
project.ext.firebaseVersion = '12.0.0'
|
||||
|
||||
dependencies {
|
||||
//noinspection GradleDynamicVersion
|
||||
implementation "com.facebook.react:react-native:+"
|
||||
implementation(project(':react-native-firebase')) {
|
||||
implementation project(':react-native-firebase')
|
||||
|
||||
implementation(project(':bridge')) {
|
||||
transitive = false
|
||||
}
|
||||
|
||||
implementation project(':bridge')
|
||||
|
||||
implementation fileTree(dir: "libs", include: ["*.jar"])
|
||||
implementation "com.google.android.gms:play-services-base:$firebaseVersion"
|
||||
implementation "com.google.firebase:firebase-ads:$firebaseVersion"
|
||||
implementation "com.google.firebase:firebase-auth:$firebaseVersion"
|
||||
implementation "com.google.firebase:firebase-config:$firebaseVersion"
|
||||
implementation "com.google.firebase:firebase-core:$firebaseVersion"
|
||||
implementation "com.google.firebase:firebase-crash:$firebaseVersion"
|
||||
implementation "com.google.firebase:firebase-database:$firebaseVersion"
|
||||
implementation "com.google.firebase:firebase-messaging:$firebaseVersion"
|
||||
implementation "com.google.firebase:firebase-perf:$firebaseVersion"
|
||||
implementation "com.google.firebase:firebase-storage:$firebaseVersion"
|
||||
implementation "com.google.firebase:firebase-firestore:$firebaseVersion"
|
||||
implementation "com.google.firebase:firebase-invites:$firebaseVersion"
|
||||
implementation "com.google.firebase:firebase-functions:$firebaseVersion"
|
||||
implementation('com.crashlytics.sdk.android:crashlytics:2.9.1@aar') {
|
||||
implementation('com.crashlytics.sdk.android:crashlytics:2.9.3@aar') {
|
||||
transitive = true
|
||||
}
|
||||
|
||||
// RNFirebase required dependencies
|
||||
implementation "com.google.firebase:firebase-core:16.0.1"
|
||||
implementation "com.google.android.gms:play-services-base:15.0.1"
|
||||
|
||||
// RNFirebase optional dependencies
|
||||
implementation "com.google.firebase:firebase-ads:15.0.1"
|
||||
implementation "com.google.firebase:firebase-auth:16.0.2"
|
||||
implementation "com.google.firebase:firebase-config:16.0.0"
|
||||
implementation "com.google.firebase:firebase-crash:16.0.1"
|
||||
implementation "com.google.firebase:firebase-database:16.0.1"
|
||||
implementation "com.google.firebase:firebase-firestore:17.0.2"
|
||||
implementation "com.google.firebase:firebase-functions:16.0.1"
|
||||
implementation "com.google.firebase:firebase-invites:16.0.1"
|
||||
implementation "com.google.firebase:firebase-storage:16.0.1"
|
||||
implementation "com.google.firebase:firebase-messaging:17.1.0"
|
||||
implementation "com.google.firebase:firebase-perf:16.0.0"
|
||||
|
||||
implementation "com.facebook.react:react-native:+"
|
||||
implementation "com.android.support:appcompat-v7:27.1.0"
|
||||
implementation 'com.android.support:support-annotations:27.1.1'
|
||||
implementation fileTree(dir: "libs", include: ["*.jar"])
|
||||
|
||||
// Tests
|
||||
androidTestImplementation(project(path: ":detox"))
|
||||
androidTestImplementation 'junit:junit:4.12'
|
||||
androidTestImplementation 'com.android.support.test:runner:1.0.1'
|
||||
androidTestImplementation 'com.android.support.test:rules:1.0.1'
|
||||
androidTestImplementation 'com.android.support.test:runner:1.0.2'
|
||||
androidTestImplementation 'com.android.support.test:rules:1.0.2'
|
||||
}
|
||||
|
||||
// Run this once to be able to run the application with BUCK
|
||||
|
||||
@@ -1,71 +1,111 @@
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
package="com.testing">
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
package="com.testing">
|
||||
|
||||
<uses-permission android:name="android.permission.INTERNET" />
|
||||
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />
|
||||
<uses-permission android:name="android.permission.SYSTEM_OVERLAY_WINDOW" />
|
||||
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
|
||||
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
|
||||
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
|
||||
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
|
||||
<uses-permission android:name="android.permission.VIBRATE" />
|
||||
<uses-permission android:name="android.permission.INTERNET" />
|
||||
<uses-permission android:name="android.permission.VIBRATE" />
|
||||
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />
|
||||
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
|
||||
<uses-permission android:name="android.permission.SYSTEM_OVERLAY_WINDOW" />
|
||||
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
|
||||
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
|
||||
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
|
||||
|
||||
|
||||
<application
|
||||
android:name="com.testing.MainApplication"
|
||||
android:allowBackup="true"
|
||||
android:icon="@drawable/ic_launcher"
|
||||
android:label="@string/app_name"
|
||||
android:launchMode="singleTask"
|
||||
android:theme="@style/AppTheme">
|
||||
<service
|
||||
android:name="io.invertase.firebase.messaging.RNFirebaseMessagingService"
|
||||
android:enabled="true"
|
||||
android:exported="true">
|
||||
<intent-filter>
|
||||
<action android:name="com.google.firebase.MESSAGING_EVENT" />
|
||||
</intent-filter>
|
||||
</service>
|
||||
<application
|
||||
android:name="com.testing.MainApplication"
|
||||
android:allowBackup="false"
|
||||
android:icon="@drawable/ic_launcher"
|
||||
android:label="@string/app_name"
|
||||
android:launchMode="singleTask"
|
||||
android:theme="@style/AppTheme">
|
||||
<service
|
||||
android:name="io.invertase.firebase.messaging.RNFirebaseMessagingService"
|
||||
android:enabled="true"
|
||||
android:exported="true"
|
||||
tools:ignore="ExportedService">
|
||||
<intent-filter>
|
||||
<action android:name="com.google.firebase.MESSAGING_EVENT" />
|
||||
</intent-filter>
|
||||
</service>
|
||||
|
||||
<service android:name="io.invertase.firebase.messaging.RNFirebaseInstanceIdService" android:exported="false">
|
||||
<intent-filter>
|
||||
<action android:name="com.google.firebase.INSTANCE_ID_EVENT"/>
|
||||
</intent-filter>
|
||||
</service>
|
||||
<service
|
||||
android:name="io.invertase.firebase.messaging.RNFirebaseInstanceIdService"
|
||||
android:exported="false">
|
||||
<intent-filter>
|
||||
<action android:name="com.google.firebase.INSTANCE_ID_EVENT" />
|
||||
</intent-filter>
|
||||
</service>
|
||||
|
||||
<service android:name="io.invertase.firebase.messaging.RNFirebaseBackgroundMessagingService" />
|
||||
<service android:name="io.invertase.firebase.messaging.RNFirebaseBackgroundMessagingService" />
|
||||
|
||||
<receiver android:name="io.invertase.firebase.notifications.RNFirebaseNotificationReceiver"/>
|
||||
<receiver android:enabled="true" android:exported="true" android:name="io.invertase.firebase.notifications.RNFirebaseNotificationsRebootReceiver">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.BOOT_COMPLETED"/>
|
||||
<action android:name="android.intent.action.QUICKBOOT_POWERON"/>
|
||||
<action android:name="com.htc.intent.action.QUICKBOOT_POWERON"/>
|
||||
<category android:name="android.intent.category.DEFAULT" />
|
||||
</intent-filter>
|
||||
</receiver>
|
||||
<receiver android:name="io.invertase.firebase.notifications.RNFirebaseNotificationReceiver" />
|
||||
<receiver
|
||||
android:name="io.invertase.firebase.notifications.RNFirebaseNotificationsRebootReceiver"
|
||||
android:enabled="true"
|
||||
android:exported="true">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.BOOT_COMPLETED" />
|
||||
<action android:name="android.intent.action.QUICKBOOT_POWERON" />
|
||||
<action android:name="com.htc.intent.action.QUICKBOOT_POWERON" />
|
||||
|
||||
<!-- App Links -->
|
||||
<intent-filter android:autoVerify="true">
|
||||
<action android:name="android.intent.action.VIEW" />
|
||||
<category android:name="android.intent.category.DEFAULT" />
|
||||
<category android:name="android.intent.category.BROWSABLE" />
|
||||
<data android:host="je786.app.goo.gl" android:scheme="http"/>
|
||||
<data android:host="je786.app.goo.gl" android:scheme="https"/>
|
||||
</intent-filter>
|
||||
<category android:name="android.intent.category.DEFAULT" />
|
||||
</intent-filter>
|
||||
</receiver>
|
||||
|
||||
<activity
|
||||
android:name="com.testing.MainActivity"
|
||||
android:configChanges="keyboard|keyboardHidden|orientation|screenSize"
|
||||
android:label="@string/app_name"
|
||||
android:launchMode="singleTop"
|
||||
android:windowSoftInputMode="adjustResize">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN" />
|
||||
<category android:name="android.intent.category.LAUNCHER" />
|
||||
</intent-filter>
|
||||
</activity>
|
||||
<activity android:name="com.facebook.react.devsupport.DevSettingsActivity" />
|
||||
</application>
|
||||
|
||||
<activity
|
||||
android:name="com.testing.MainActivity"
|
||||
android:configChanges="keyboard|keyboardHidden|orientation|screenSize"
|
||||
android:label="@string/app_name"
|
||||
android:launchMode="singleTop"
|
||||
android:windowSoftInputMode="adjustResize">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN" />
|
||||
<category android:name="android.intent.category.LAUNCHER" />
|
||||
</intent-filter>
|
||||
<!-- App Links -->
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.VIEW" />
|
||||
|
||||
<category android:name="android.intent.category.DEFAULT" />
|
||||
<category android:name="android.intent.category.BROWSABLE" />
|
||||
|
||||
<data
|
||||
android:scheme="http"
|
||||
android:host="je786.app.goo.gl" />
|
||||
</intent-filter>
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.VIEW" />
|
||||
|
||||
<category android:name="android.intent.category.DEFAULT" />
|
||||
<category android:name="android.intent.category.BROWSABLE" />
|
||||
|
||||
<data
|
||||
android:scheme="http"
|
||||
android:host="je786.app.goo.gl" />
|
||||
</intent-filter>
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.VIEW" />
|
||||
|
||||
<category android:name="android.intent.category.DEFAULT" />
|
||||
<category android:name="android.intent.category.BROWSABLE" />
|
||||
|
||||
<data
|
||||
android:scheme="https"
|
||||
android:host="je786.app.goo.gl" />
|
||||
</intent-filter>
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.VIEW" />
|
||||
|
||||
<category android:name="android.intent.category.DEFAULT" />
|
||||
<category android:name="android.intent.category.BROWSABLE" />
|
||||
|
||||
<data
|
||||
android:scheme="https"
|
||||
android:host="je786.app.goo.gl" />
|
||||
</intent-filter>
|
||||
</activity>
|
||||
<activity android:name="com.facebook.react.devsupport.DevSettingsActivity" />
|
||||
</application>
|
||||
</manifest>
|
||||
|
||||
@@ -32,6 +32,10 @@ public class MainActivity extends ReactActivity {
|
||||
public void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
checkWindowPerms();
|
||||
// ATTENTION: This was auto-generated to handle app links.
|
||||
Intent appLinkIntent = getIntent();
|
||||
String appLinkAction = appLinkIntent.getAction();
|
||||
Uri appLinkData = appLinkIntent.getData();
|
||||
}
|
||||
|
||||
public void checkWindowPerms() {
|
||||
|
||||
@@ -21,7 +21,7 @@ import io.invertase.firebase.firestore.RNFirebaseFirestorePackage;
|
||||
import io.invertase.firebase.functions.RNFirebaseFunctionsPackage;
|
||||
import io.invertase.firebase.instanceid.RNFirebaseInstanceIdPackage;
|
||||
import io.invertase.firebase.invites.RNFirebaseInvitesPackage;
|
||||
import io.invertase.firebase.links.RNFirebaseLinksPackage;
|
||||
//import io.invertase.firebase.links.RNFirebaseLinksPackage;
|
||||
import io.invertase.firebase.messaging.RNFirebaseMessagingPackage;
|
||||
import io.invertase.firebase.notifications.RNFirebaseNotificationsPackage;
|
||||
import io.invertase.firebase.perf.RNFirebasePerformancePackage;
|
||||
@@ -55,7 +55,7 @@ public class MainApplication extends Application implements ReactApplication {
|
||||
new RNFirebaseFunctionsPackage(),
|
||||
new RNFirebaseInstanceIdPackage(),
|
||||
new RNFirebaseInvitesPackage(),
|
||||
new RNFirebaseLinksPackage(),
|
||||
// new RNFirebaseLinksPackage(),
|
||||
new RNFirebaseMessagingPackage(),
|
||||
new RNFirebaseNotificationsPackage(),
|
||||
new RNFirebasePerformancePackage(),
|
||||
|
||||
@@ -1,24 +1,24 @@
|
||||
buildscript {
|
||||
repositories {
|
||||
jcenter()
|
||||
google()
|
||||
jcenter()
|
||||
maven {
|
||||
url 'https://maven.fabric.io/public'
|
||||
}
|
||||
}
|
||||
dependencies {
|
||||
classpath 'com.android.tools.build:gradle:3.0.1'
|
||||
classpath 'com.google.gms:google-services:3.1.2'
|
||||
classpath 'com.android.tools.build:gradle:3.1.3'
|
||||
classpath 'com.google.gms:google-services:4.0.1'
|
||||
classpath 'com.google.firebase:firebase-plugins:1.1.1'
|
||||
classpath 'io.fabric.tools:gradle:1.25.1'
|
||||
classpath 'io.fabric.tools:gradle:1.25.4'
|
||||
}
|
||||
}
|
||||
|
||||
allprojects {
|
||||
repositories {
|
||||
mavenLocal()
|
||||
jcenter()
|
||||
google()
|
||||
jcenter()
|
||||
maven {
|
||||
url "$rootDir/../node_modules/react-native/android"
|
||||
}
|
||||
@@ -28,7 +28,7 @@ allprojects {
|
||||
subprojects {
|
||||
ext {
|
||||
compileSdk = 27
|
||||
buildTools = "27.0.2"
|
||||
buildTools = "27.0.3"
|
||||
minSdk = 18
|
||||
targetSdk = 26
|
||||
}
|
||||
@@ -47,4 +47,3 @@ subprojects {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,12 +1,9 @@
|
||||
# Project-wide Gradle settings.
|
||||
|
||||
# IDE (e.g. Android Studio) users:
|
||||
# Gradle settings configured through the IDE *will override*
|
||||
# any settings specified in this file.
|
||||
|
||||
# For more details on how to configure your build environment visit
|
||||
# http://www.gradle.org/docs/current/userguide/build_environment.html
|
||||
|
||||
# Specifies the JVM arguments used for the daemon process.
|
||||
# The setting is particularly useful for tweaking memory settings.
|
||||
# Default value: -Xmx10248m -XX:MaxPermSize=256m
|
||||
@@ -14,11 +11,8 @@ org.gradle.daemon=true
|
||||
org.gradle.parallel=true
|
||||
org.gradle.configureondemand=true
|
||||
org.gradle.jvmargs=-Xmx3g -XX:MaxPermSize=2048m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8
|
||||
|
||||
# When configured, Gradle will run in incubating parallel mode.
|
||||
# This option should only be used with decoupled projects. More details, visit
|
||||
# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
|
||||
# org.gradle.parallel=true
|
||||
|
||||
android.useDeprecatedNdk=true
|
||||
android.enableAapt2=false
|
||||
|
||||
@@ -3,4 +3,4 @@ distributionBase=GRADLE_USER_HOME
|
||||
distributionPath=wrapper/dists
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
zipStorePath=wrapper/dists
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-4.3-all.zip
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-4.4-all.zip
|
||||
|
||||
@@ -21,7 +21,8 @@ describe('auth()', () => {
|
||||
});
|
||||
|
||||
describe('checkActionCode()', () => {
|
||||
it('errors on invalid code', async () => {
|
||||
// todo Android has changed the format of the error response
|
||||
xit('errors on invalid code', async () => {
|
||||
try {
|
||||
await firebase.auth().checkActionCode('fooby shooby dooby');
|
||||
} catch (e) {
|
||||
@@ -35,7 +36,8 @@ describe('auth()', () => {
|
||||
});
|
||||
|
||||
describe('verifyPasswordResetCode()', () => {
|
||||
it('errors on invalid code', async () => {
|
||||
// todo Android has changed the format of the error response
|
||||
xit('errors on invalid code', async () => {
|
||||
try {
|
||||
await firebase.auth().verifyPasswordResetCode('fooby shooby dooby');
|
||||
} catch (e) {
|
||||
@@ -49,7 +51,8 @@ describe('auth()', () => {
|
||||
});
|
||||
|
||||
describe('confirmPasswordReset()', () => {
|
||||
it('errors on invalid code', async () => {
|
||||
// todo Android has changed the format of the error response
|
||||
xit('errors on invalid code', async () => {
|
||||
try {
|
||||
await firebase
|
||||
.auth()
|
||||
@@ -924,7 +927,7 @@ describe('auth()', () => {
|
||||
});
|
||||
});
|
||||
|
||||
describe('fetchProvidersForEmail()', () => {
|
||||
describe('fetchProvidersForEmail/fetchSignInMethodsForEmail()', () => {
|
||||
it('it should return password provider for an email address', () =>
|
||||
new Promise((resolve, reject) => {
|
||||
const successCb = providers => {
|
||||
@@ -958,7 +961,7 @@ describe('auth()', () => {
|
||||
|
||||
return firebase
|
||||
.auth()
|
||||
.fetchProvidersForEmail('test@i-do-not-exist.com')
|
||||
.fetchSignInMethodsForEmail('test@i-do-not-exist.com')
|
||||
.then(successCb)
|
||||
.catch(failureCb);
|
||||
}));
|
||||
@@ -977,7 +980,7 @@ describe('auth()', () => {
|
||||
|
||||
return firebase
|
||||
.auth()
|
||||
.fetchProvidersForEmail('foobar')
|
||||
.fetchSignInMethodsForEmail('foobar')
|
||||
.then(successCb)
|
||||
.catch(failureCb);
|
||||
}));
|
||||
@@ -1099,9 +1102,7 @@ describe('auth()', () => {
|
||||
} catch (error) {
|
||||
// Reject
|
||||
await firebase.auth().currentUser.delete();
|
||||
Promise.reject(
|
||||
new Error('sendPasswordResetEmail() caused an error', error)
|
||||
);
|
||||
throw new Error('sendPasswordResetEmail() caused an error', error);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
55
bridge/e2e/auth/emailLink.e2e.js
Normal file
55
bridge/e2e/auth/emailLink.e2e.js
Normal file
@@ -0,0 +1,55 @@
|
||||
describe('auth() -> emailLink Provider', () => {
|
||||
describe('sendSignInLinkToEmail', () => {
|
||||
it('should send email', async () => {
|
||||
const random = randomString(12, '#aA');
|
||||
const email = `${random}@${random}.com`;
|
||||
// const email = 'MANUAL TEST EMAIL HERE';
|
||||
const actionCodeSettings = {
|
||||
url: 'http://localhost:1337/authLinkFoo?bar=1234',
|
||||
handleCodeInApp: true,
|
||||
iOS: {
|
||||
bundleId: 'com.testing',
|
||||
},
|
||||
android: {
|
||||
packageName: 'com.testing',
|
||||
installApp: true,
|
||||
minimumVersion: '12',
|
||||
},
|
||||
};
|
||||
await firebase.auth().sendSignInLinkToEmail(email, actionCodeSettings);
|
||||
});
|
||||
});
|
||||
|
||||
describe('isSignInWithEmailLink', () => {
|
||||
it('should return true/false', async () => {
|
||||
const emailLink1 =
|
||||
'https://www.example.com/action?mode=signIn&oobCode=oobCode';
|
||||
const emailLink2 =
|
||||
'https://www.example.com/action?mode=verifyEmail&oobCode=oobCode';
|
||||
const emailLink3 = 'https://www.example.com/action?mode=signIn';
|
||||
const emailLink4 =
|
||||
'https://x59dg.app.goo.gl/?link=https://rnfirebase-b9ad4.firebaseapp.com/__/auth/action?apiKey%3Dfoo%26mode%3DsignIn%26oobCode%3Dbar';
|
||||
|
||||
should.equal(true, firebase.auth().isSignInWithEmailLink(emailLink1));
|
||||
should.equal(false, firebase.auth().isSignInWithEmailLink(emailLink2));
|
||||
should.equal(false, firebase.auth().isSignInWithEmailLink(emailLink3));
|
||||
should.equal(true, firebase.auth().isSignInWithEmailLink(emailLink4));
|
||||
});
|
||||
});
|
||||
|
||||
// FOR MANUAL TESTING ONLY
|
||||
xdescribe('signInWithEmailLink', () => {
|
||||
it('should signIn', async () => {
|
||||
const email = 'MANUAL TEST EMAIL HERE';
|
||||
const emailLink = 'MANUAL TEST CODE HERE';
|
||||
|
||||
const userCredential = await firebase
|
||||
.auth()
|
||||
.signInWithEmailLink(email, emailLink);
|
||||
|
||||
userCredential.user.email.should.equal(email);
|
||||
|
||||
await await firebase.auth().signOut();
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -22,6 +22,36 @@ describe('auth() -> Providers', () => {
|
||||
});
|
||||
});
|
||||
|
||||
describe('credentialWithLink', () => {
|
||||
it('should return a credential object', () => {
|
||||
const email = 'email@email.com';
|
||||
const link = 'link';
|
||||
const credential = firebase.auth.EmailAuthProvider.credentialWithLink(
|
||||
email,
|
||||
link
|
||||
);
|
||||
credential.providerId.should.equal('emailLink');
|
||||
credential.token.should.equal(email);
|
||||
credential.secret.should.equal(link);
|
||||
});
|
||||
});
|
||||
|
||||
describe('EMAIL_PASSWORD_SIGN_IN_METHOD', () => {
|
||||
it('should return password', () => {
|
||||
firebase.auth.EmailAuthProvider.EMAIL_PASSWORD_SIGN_IN_METHOD.should.equal(
|
||||
'password'
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe('EMAIL_LINK_SIGN_IN_METHOD', () => {
|
||||
it('should return emailLink', () => {
|
||||
firebase.auth.EmailAuthProvider.EMAIL_LINK_SIGN_IN_METHOD.should.equal(
|
||||
'emailLink'
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe('PROVIDER_ID', () => {
|
||||
it('should return password', () => {
|
||||
firebase.auth.EmailAuthProvider.PROVIDER_ID.should.equal('password');
|
||||
|
||||
@@ -70,7 +70,8 @@ describe('config()', () => {
|
||||
should.equal(keys.length, 2);
|
||||
});
|
||||
|
||||
it('get all keys as an array if no prefix provided', async () => {
|
||||
xit('get all keys as an array if no prefix provided', async () => {
|
||||
// TODO flakey on Android
|
||||
const keys = await firebase.config().getKeysByPrefix();
|
||||
keys.should.be.Array();
|
||||
should.equal(keys.length, 4);
|
||||
|
||||
@@ -122,6 +122,52 @@ describe('firestore()', () => {
|
||||
documentSnapshot.should.be.instanceOf(DocumentSnapshot);
|
||||
});
|
||||
});
|
||||
|
||||
it('should support GetOptions source=`default`', async () => {
|
||||
const collection = testCollection(TEST_COLLECTION_NAME);
|
||||
const querySnapshot = await collection.get({ source: 'default' });
|
||||
should.equal(querySnapshot.size >= 1, true);
|
||||
querySnapshot.metadata.should.be.an.Object();
|
||||
should.equal(querySnapshot.metadata.fromCache, false);
|
||||
});
|
||||
|
||||
it('should support GetOptions source=`server`', async () => {
|
||||
const collection = testCollection(TEST_COLLECTION_NAME);
|
||||
const querySnapshot = await collection.get({ source: 'server' });
|
||||
should.equal(querySnapshot.size >= 1, true);
|
||||
querySnapshot.metadata.should.be.an.Object();
|
||||
should.equal(querySnapshot.metadata.fromCache, false);
|
||||
});
|
||||
|
||||
// TODO: Investigate why this isn't returning `fromCache=true`
|
||||
xit('should support GetOptions source=`cache`', async () => {
|
||||
const collection = testCollection(TEST_COLLECTION_NAME);
|
||||
const querySnapshot = await collection.get({ source: 'cache' });
|
||||
should.equal(querySnapshot.size >= 1, true);
|
||||
querySnapshot.metadata.should.be.an.Object();
|
||||
should.equal(querySnapshot.metadata.fromCache, true);
|
||||
});
|
||||
|
||||
it('should error with invalid GetOptions source option', async () => {
|
||||
const collectionRef = testCollection(TEST_COLLECTION_NAME);
|
||||
try {
|
||||
await collectionRef.get(() => {});
|
||||
return Promise.reject(
|
||||
new Error('get() did not reject with invalid argument.')
|
||||
);
|
||||
} catch (e) {
|
||||
// do nothing
|
||||
}
|
||||
try {
|
||||
await collectionRef.get({ source: 'invalid' });
|
||||
return Promise.reject(
|
||||
new Error('get() did not reject with invalid source property.')
|
||||
);
|
||||
} catch (e) {
|
||||
// do nothing
|
||||
}
|
||||
return Promise.resolve();
|
||||
});
|
||||
});
|
||||
|
||||
describe('onSnapshot()', () => {
|
||||
@@ -415,8 +461,7 @@ describe('firestore()', () => {
|
||||
// await new Promise(resolve2 => {
|
||||
// unsubscribe = collectionRef.onSnapshot(
|
||||
// {
|
||||
// includeQueryMetadataChanges: true,
|
||||
// includeDocumentMetadataChanges: true,
|
||||
// includeMetadataChanges: true,
|
||||
// },
|
||||
// snapshot => {
|
||||
// snapshot.forEach(doc => callback(doc.data()));
|
||||
@@ -504,8 +549,7 @@ describe('firestore()', () => {
|
||||
// };
|
||||
// unsubscribe = collectionRef.onSnapshot(
|
||||
// {
|
||||
// includeQueryMetadataChanges: true,
|
||||
// includeDocumentMetadataChanges: true,
|
||||
// includeMetadataChanges: true,
|
||||
// },
|
||||
// observer
|
||||
// );
|
||||
@@ -555,7 +599,7 @@ describe('firestore()', () => {
|
||||
// (() => {
|
||||
// colRef.onSnapshot(
|
||||
// {
|
||||
// includeQueryMetadataChanges: true,
|
||||
// includeMetadataChanges: true,
|
||||
// },
|
||||
// () => {},
|
||||
// 'error'
|
||||
@@ -566,7 +610,7 @@ describe('firestore()', () => {
|
||||
// (() => {
|
||||
// colRef.onSnapshot(
|
||||
// {
|
||||
// includeQueryMetadataChanges: true,
|
||||
// includeMetadataChanges: true,
|
||||
// },
|
||||
// {
|
||||
// next: () => {},
|
||||
@@ -579,7 +623,7 @@ describe('firestore()', () => {
|
||||
// (() => {
|
||||
// colRef.onSnapshot(
|
||||
// {
|
||||
// includeQueryMetadataChanges: true,
|
||||
// includeMetadataChanges: true,
|
||||
// },
|
||||
// {
|
||||
// next: 'error',
|
||||
@@ -591,7 +635,7 @@ describe('firestore()', () => {
|
||||
// (() => {
|
||||
// colRef.onSnapshot(
|
||||
// {
|
||||
// includeQueryMetadataChanges: true,
|
||||
// includeMetadataChanges: true,
|
||||
// },
|
||||
// 'error'
|
||||
// );
|
||||
|
||||
@@ -67,6 +67,62 @@ describe('firestore()', () => {
|
||||
snapshot.id.should.equal(COL2_DOC_1_ID);
|
||||
snapshot.metadata.should.be.an.Object();
|
||||
});
|
||||
|
||||
it('should support GetOptions source=`default`', async () => {
|
||||
await resetTestCollectionDoc(COL2_DOC_1_PATH, COL2_DOC_1());
|
||||
const snapshot = await test2DocRef(COL2_DOC_1_ID).get({
|
||||
source: 'default',
|
||||
});
|
||||
snapshot.id.should.equal(COL2_DOC_1_ID);
|
||||
snapshot.metadata.should.be.an.Object();
|
||||
should.equal(snapshot.metadata.fromCache, false);
|
||||
});
|
||||
|
||||
it('should support GetOptions source=`server`', async () => {
|
||||
await resetTestCollectionDoc(COL2_DOC_1_PATH, COL2_DOC_1());
|
||||
const snapshot = await test2DocRef(COL2_DOC_1_ID).get({
|
||||
source: 'server',
|
||||
});
|
||||
snapshot.id.should.equal(COL2_DOC_1_ID);
|
||||
snapshot.metadata.should.be.an.Object();
|
||||
should.equal(snapshot.metadata.fromCache, false);
|
||||
});
|
||||
|
||||
// TODO: For some reason when using `cache` it's not seeing the data as available, even if
|
||||
// first requesting it from the server, although interestingly it works fine in the old
|
||||
// tests app
|
||||
xit('should support GetOptions source=`cache`', async () => {
|
||||
await resetTestCollectionDoc(COL2_DOC_1_PATH, COL2_DOC_1());
|
||||
const ref = test2DocRef(COL2_DOC_1_ID);
|
||||
// Make sure the reference data is populated in the cache
|
||||
await ref.get({ source: 'server' });
|
||||
// Retrieve the cached version
|
||||
const snapshot = await ref.get({ source: 'cache' });
|
||||
snapshot.id.should.equal(COL2_DOC_1_ID);
|
||||
snapshot.metadata.should.be.an.Object();
|
||||
should.equal(snapshot.metadata.fromCache, true);
|
||||
});
|
||||
|
||||
it('should error with invalid GetOptions source option', async () => {
|
||||
const docRef = test2DocRef(COL2_DOC_1_ID);
|
||||
try {
|
||||
await docRef.get(() => {});
|
||||
return Promise.reject(
|
||||
new Error('get() did not reject with invalid argument.')
|
||||
);
|
||||
} catch (e) {
|
||||
// do nothing
|
||||
}
|
||||
try {
|
||||
await docRef.get({ source: 'invalid' });
|
||||
return Promise.reject(
|
||||
new Error('get() did not reject with invalid source property.')
|
||||
);
|
||||
} catch (e) {
|
||||
// do nothing
|
||||
}
|
||||
return Promise.resolve();
|
||||
});
|
||||
});
|
||||
|
||||
describe('onSnapshot()', () => {
|
||||
|
||||
147
bridge/e2e/storage/storage.e2e.js
Normal file
147
bridge/e2e/storage/storage.e2e.js
Normal file
@@ -0,0 +1,147 @@
|
||||
describe('storage()', () => {
|
||||
describe('ref()', () => {
|
||||
describe('toString()', () => {
|
||||
it('returns the correct bucket path to the file', () => {
|
||||
const app = firebase.app();
|
||||
firebase
|
||||
.storage()
|
||||
.ref('/uploadNope.jpeg')
|
||||
.toString()
|
||||
.should.equal(`gs://${app.options.storageBucket}/uploadNope.jpeg`);
|
||||
});
|
||||
});
|
||||
|
||||
describe('downloadFile()', () => {
|
||||
it('errors if permission denied', async () => {
|
||||
try {
|
||||
await firebase
|
||||
.storage()
|
||||
.ref('/not.jpg')
|
||||
.downloadFile(
|
||||
`${firebase.storage.Native.DOCUMENT_DIRECTORY_PATH}/not.jpg`
|
||||
);
|
||||
return Promise.reject(new Error('No permission denied error'));
|
||||
} catch (error) {
|
||||
error.code.should.equal('storage/unauthorized');
|
||||
error.message.includes('not authorized').should.be.true();
|
||||
return Promise.resolve();
|
||||
}
|
||||
});
|
||||
|
||||
it('downloads a file', async () => {
|
||||
const meta = await firebase
|
||||
.storage()
|
||||
.ref('/ok.jpeg')
|
||||
.downloadFile(
|
||||
`${firebase.storage.Native.DOCUMENT_DIRECTORY_PATH}/ok.jpeg`
|
||||
);
|
||||
|
||||
meta.state.should.eql(firebase.storage.TaskState.SUCCESS);
|
||||
meta.bytesTransferred.should.eql(meta.totalBytes);
|
||||
});
|
||||
});
|
||||
|
||||
describe('putFile()', () => {
|
||||
before(async () => {
|
||||
await firebase
|
||||
.storage()
|
||||
.ref('/ok.jpeg')
|
||||
.downloadFile(
|
||||
`${firebase.storage.Native.DOCUMENT_DIRECTORY_PATH}/ok.jpeg`
|
||||
);
|
||||
await firebase
|
||||
.storage()
|
||||
.ref('/cat.gif')
|
||||
.downloadFile(
|
||||
`${firebase.storage.Native.DOCUMENT_DIRECTORY_PATH}/cat.gif`
|
||||
);
|
||||
await firebase
|
||||
.storage()
|
||||
.ref('/hei.heic')
|
||||
.downloadFile(
|
||||
`${firebase.storage.Native.DOCUMENT_DIRECTORY_PATH}/hei.heic`
|
||||
);
|
||||
});
|
||||
|
||||
it('errors if permission denied', async () => {
|
||||
try {
|
||||
await firebase
|
||||
.storage()
|
||||
.ref('/uploadNope.jpeg')
|
||||
.putFile(
|
||||
`${firebase.storage.Native.DOCUMENT_DIRECTORY_PATH}/ok.jpeg`
|
||||
);
|
||||
return Promise.reject(new Error('No permission denied error'));
|
||||
} catch (error) {
|
||||
error.code.should.equal('storage/unauthorized');
|
||||
error.message.includes('not authorized').should.be.true();
|
||||
return Promise.resolve();
|
||||
}
|
||||
});
|
||||
|
||||
it('uploads a file', async () => {
|
||||
const uploadTaskSnapshot = await firebase
|
||||
.storage()
|
||||
.ref('/uploadOk.jpeg')
|
||||
.putFile(
|
||||
`${firebase.storage.Native.DOCUMENT_DIRECTORY_PATH}/ok.jpeg`
|
||||
);
|
||||
|
||||
await firebase
|
||||
.storage()
|
||||
.ref('/uploadCat.gif')
|
||||
.putFile(
|
||||
`${firebase.storage.Native.DOCUMENT_DIRECTORY_PATH}/cat.gif`
|
||||
);
|
||||
|
||||
await firebase
|
||||
.storage()
|
||||
.ref('/uploadHei.heic')
|
||||
.putFile(
|
||||
`${firebase.storage.Native.DOCUMENT_DIRECTORY_PATH}/hei.heic`
|
||||
);
|
||||
|
||||
uploadTaskSnapshot.state.should.eql(firebase.storage.TaskState.SUCCESS);
|
||||
uploadTaskSnapshot.bytesTransferred.should.eql(
|
||||
uploadTaskSnapshot.totalBytes
|
||||
);
|
||||
uploadTaskSnapshot.metadata.should.be.an.Object();
|
||||
uploadTaskSnapshot.downloadURL.should.be.a.String();
|
||||
});
|
||||
});
|
||||
|
||||
describe('on()', () => {
|
||||
before(async () => {
|
||||
await firebase
|
||||
.storage()
|
||||
.ref('/ok.jpeg')
|
||||
.downloadFile(
|
||||
`${firebase.storage.Native.DOCUMENT_DIRECTORY_PATH}/ok.jpeg`
|
||||
);
|
||||
});
|
||||
|
||||
it('listens to upload state', () => {
|
||||
const { resolve, reject, promise } = Promise.defer();
|
||||
const path = `${
|
||||
firebase.storage.Native.DOCUMENT_DIRECTORY_PATH
|
||||
}/ok.jpeg`;
|
||||
const ref = firebase.storage().ref('/uploadOk.jpeg');
|
||||
|
||||
const unsubscribe = ref.putFile(path).on(
|
||||
firebase.storage.TaskEvent.STATE_CHANGED,
|
||||
snapshot => {
|
||||
if (snapshot.state === firebase.storage.TaskState.SUCCESS) {
|
||||
resolve();
|
||||
}
|
||||
},
|
||||
error => {
|
||||
unsubscribe();
|
||||
reject(error);
|
||||
}
|
||||
);
|
||||
|
||||
return promise;
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -93,6 +93,25 @@ console.log = (...args) => {
|
||||
return originalLog(...args);
|
||||
};
|
||||
|
||||
/**
|
||||
* Old style deferred promise shim - for niceness
|
||||
*
|
||||
* @returns {{resolve: null, reject: null}}
|
||||
*/
|
||||
Promise.defer = function defer() {
|
||||
const deferred = {
|
||||
resolve: null,
|
||||
reject: null,
|
||||
};
|
||||
|
||||
deferred.promise = new Promise((resolve, reject) => {
|
||||
deferred.resolve = resolve;
|
||||
deferred.reject = reject;
|
||||
});
|
||||
|
||||
return deferred;
|
||||
};
|
||||
|
||||
global.TestHelpers = {
|
||||
functions: {
|
||||
data: require('./../functions/test-data'),
|
||||
|
||||
@@ -18,21 +18,21 @@ target 'testing' do
|
||||
'RCTWebSocket',
|
||||
]
|
||||
|
||||
pod 'Firebase/AdMob'
|
||||
pod 'Firebase/Auth'
|
||||
pod 'Firebase/Core'
|
||||
pod 'Firebase/Crash'
|
||||
pod 'Firebase/Database'
|
||||
pod 'Firebase/Functions'
|
||||
pod 'Firebase/DynamicLinks'
|
||||
pod 'Firebase/Firestore'
|
||||
pod 'Firebase/Invites'
|
||||
pod 'Firebase/Messaging'
|
||||
pod 'Firebase/RemoteConfig'
|
||||
pod 'Firebase/Storage'
|
||||
pod 'Firebase/Performance'
|
||||
pod 'Firebase/AdMob', '~> 5.3.0'
|
||||
pod 'Firebase/Auth', '~> 5.3.0'
|
||||
pod 'Firebase/Core', '~> 5.3.0'
|
||||
pod 'Firebase/Crash', '~> 5.3.0'
|
||||
pod 'Firebase/Database', '~> 5.3.0'
|
||||
pod 'Firebase/Functions', '~> 5.3.0'
|
||||
pod 'Firebase/DynamicLinks', '~> 5.3.0'
|
||||
pod 'Firebase/Firestore', '~> 5.3.0'
|
||||
pod 'Firebase/Invites', '~> 5.3.0'
|
||||
pod 'Firebase/Messaging', '~> 5.3.0'
|
||||
pod 'Firebase/RemoteConfig', '~> 5.3.0'
|
||||
pod 'Firebase/Storage', '~> 5.3.0'
|
||||
pod 'Firebase/Performance', '~> 5.3.0'
|
||||
pod 'Fabric', '~> 1.7.5'
|
||||
pod 'Crashlytics', '~> 3.10.1'
|
||||
pod 'Crashlytics', '~> 3.10.4'
|
||||
|
||||
pod 'RNFirebase', :path => '../../ios/RNFirebase.podspec'
|
||||
|
||||
|
||||
@@ -1,184 +1,188 @@
|
||||
PODS:
|
||||
- BoringSSL (10.0.2):
|
||||
- BoringSSL/Implementation (= 10.0.2)
|
||||
- BoringSSL/Interface (= 10.0.2)
|
||||
- BoringSSL/Implementation (10.0.2):
|
||||
- BoringSSL/Interface (= 10.0.2)
|
||||
- BoringSSL/Interface (10.0.2)
|
||||
- Crashlytics (3.10.1):
|
||||
- Fabric (~> 1.7.5)
|
||||
- Fabric (1.7.6)
|
||||
- Firebase/AdMob (4.13.0):
|
||||
- BoringSSL (10.0.5):
|
||||
- BoringSSL/Implementation (= 10.0.5)
|
||||
- BoringSSL/Interface (= 10.0.5)
|
||||
- BoringSSL/Implementation (10.0.5):
|
||||
- BoringSSL/Interface (= 10.0.5)
|
||||
- BoringSSL/Interface (10.0.5)
|
||||
- Crashlytics (3.10.4):
|
||||
- Fabric (~> 1.7.9)
|
||||
- Fabric (1.7.9)
|
||||
- Firebase/AdMob (5.3.0):
|
||||
- Firebase/Core
|
||||
- Google-Mobile-Ads-SDK (= 7.30.0)
|
||||
- Firebase/Auth (4.13.0):
|
||||
- Google-Mobile-Ads-SDK (= 7.31.0)
|
||||
- Firebase/Auth (5.3.0):
|
||||
- Firebase/CoreOnly
|
||||
- FirebaseAuth (= 5.0.1)
|
||||
- Firebase/Core (5.3.0):
|
||||
- Firebase/CoreOnly
|
||||
- FirebaseAnalytics (= 5.0.1)
|
||||
- Firebase/CoreOnly (5.3.0):
|
||||
- FirebaseCore (= 5.0.4)
|
||||
- Firebase/Crash (5.3.0):
|
||||
- Firebase/Core
|
||||
- FirebaseAuth (= 4.6.1)
|
||||
- Firebase/Core (4.13.0):
|
||||
- FirebaseAnalytics (= 4.2.0)
|
||||
- FirebaseCore (= 4.0.20)
|
||||
- Firebase/Crash (4.13.0):
|
||||
- FirebaseCrash (= 3.0.0)
|
||||
- Firebase/Database (5.3.0):
|
||||
- Firebase/CoreOnly
|
||||
- FirebaseDatabase (= 5.0.1)
|
||||
- Firebase/DynamicLinks (5.3.0):
|
||||
- Firebase/Core
|
||||
- FirebaseCrash (= 2.0.2)
|
||||
- Firebase/Database (4.13.0):
|
||||
- FirebaseDynamicLinks (= 3.0.1)
|
||||
- Firebase/Firestore (5.3.0):
|
||||
- Firebase/CoreOnly
|
||||
- FirebaseFirestore (= 0.12.4)
|
||||
- Firebase/Functions (5.3.0):
|
||||
- Firebase/CoreOnly
|
||||
- FirebaseFunctions (= 2.0.0)
|
||||
- Firebase/Invites (5.3.0):
|
||||
- Firebase/Core
|
||||
- FirebaseDatabase (= 4.1.5)
|
||||
- Firebase/DynamicLinks (4.13.0):
|
||||
- FirebaseInvites (= 3.0.0)
|
||||
- Firebase/Messaging (5.3.0):
|
||||
- Firebase/CoreOnly
|
||||
- FirebaseMessaging (= 3.0.2)
|
||||
- Firebase/Performance (5.3.0):
|
||||
- Firebase/Core
|
||||
- FirebaseDynamicLinks (= 2.3.2)
|
||||
- Firebase/Firestore (4.13.0):
|
||||
- FirebasePerformance (= 2.0.1)
|
||||
- Firebase/RemoteConfig (5.3.0):
|
||||
- Firebase/Core
|
||||
- FirebaseFirestore (= 0.11.0)
|
||||
- Firebase/Functions (4.13.0):
|
||||
- Firebase/Core
|
||||
- FirebaseFunctions (= 1.0.0)
|
||||
- Firebase/Invites (4.13.0):
|
||||
- Firebase/Core
|
||||
- FirebaseInvites (= 2.0.2)
|
||||
- Firebase/Messaging (4.13.0):
|
||||
- Firebase/Core
|
||||
- FirebaseMessaging (= 2.2.0)
|
||||
- Firebase/Performance (4.13.0):
|
||||
- Firebase/Core
|
||||
- FirebasePerformance (= 1.1.3)
|
||||
- Firebase/RemoteConfig (4.13.0):
|
||||
- Firebase/Core
|
||||
- FirebaseRemoteConfig (= 2.1.3)
|
||||
- Firebase/Storage (4.13.0):
|
||||
- Firebase/Core
|
||||
- FirebaseStorage (= 2.2.0)
|
||||
- FirebaseABTesting (1.0.0):
|
||||
- FirebaseCore (~> 4.0)
|
||||
- Protobuf (~> 3.1)
|
||||
- FirebaseAnalytics (4.2.0):
|
||||
- FirebaseCore (~> 4.0)
|
||||
- FirebaseInstanceID (~> 2.0)
|
||||
- GoogleToolboxForMac/NSData+zlib (~> 2.1)
|
||||
- FirebaseRemoteConfig (= 3.0.0)
|
||||
- Firebase/Storage (5.3.0):
|
||||
- Firebase/CoreOnly
|
||||
- FirebaseStorage (= 3.0.0)
|
||||
- FirebaseABTesting (2.0.0):
|
||||
- FirebaseCore (~> 5.0)
|
||||
- Protobuf (~> 3.5)
|
||||
- FirebaseAnalytics (5.0.1):
|
||||
- FirebaseCore (~> 5.0)
|
||||
- FirebaseInstanceID (~> 3.0)
|
||||
- "GoogleToolboxForMac/NSData+zlib (~> 2.1)"
|
||||
- nanopb (~> 0.3)
|
||||
- FirebaseAuth (4.6.1):
|
||||
- FirebaseAnalytics (~> 4.2)
|
||||
- GoogleToolboxForMac/NSDictionary+URLArguments (~> 2.1)
|
||||
- FirebaseAuth (5.0.1):
|
||||
- FirebaseCore (~> 5.0)
|
||||
- GTMSessionFetcher/Core (~> 1.1)
|
||||
- FirebaseCore (4.0.20):
|
||||
- GoogleToolboxForMac/NSData+zlib (~> 2.1)
|
||||
- FirebaseCrash (2.0.2):
|
||||
- FirebaseAnalytics (~> 4.0)
|
||||
- FirebaseInstanceID (~> 2.0)
|
||||
- FirebaseCore (5.0.4):
|
||||
- "GoogleToolboxForMac/NSData+zlib (~> 2.1)"
|
||||
- FirebaseCrash (3.0.0):
|
||||
- FirebaseAnalytics (~> 5.0)
|
||||
- FirebaseInstanceID (~> 3.0)
|
||||
- GoogleToolboxForMac/Logger (~> 2.1)
|
||||
- GoogleToolboxForMac/NSData+zlib (~> 2.1)
|
||||
- Protobuf (~> 3.1)
|
||||
- FirebaseDatabase (4.1.5):
|
||||
- FirebaseAnalytics (~> 4.1)
|
||||
- FirebaseCore (~> 4.0)
|
||||
- "GoogleToolboxForMac/NSData+zlib (~> 2.1)"
|
||||
- Protobuf (~> 3.5)
|
||||
- FirebaseDatabase (5.0.1):
|
||||
- FirebaseCore (~> 5.0)
|
||||
- leveldb-library (~> 1.18)
|
||||
- FirebaseDynamicLinks (2.3.2):
|
||||
- FirebaseAnalytics (~> 4.0)
|
||||
- FirebaseFirestore (0.11.0):
|
||||
- FirebaseAnalytics (~> 4.1)
|
||||
- FirebaseCore (~> 4.0)
|
||||
- FirebaseDynamicLinks (3.0.1):
|
||||
- FirebaseAnalytics (~> 5.0)
|
||||
- FirebaseFirestore (0.12.4):
|
||||
- FirebaseCore (~> 5.0)
|
||||
- FirebaseFirestore/abseil-cpp (= 0.12.4)
|
||||
- gRPC-ProtoRPC (~> 1.0)
|
||||
- leveldb-library (~> 1.18)
|
||||
- Protobuf (~> 3.5)
|
||||
- FirebaseFunctions (1.0.0):
|
||||
- FirebaseAnalytics (~> 4.1)
|
||||
- FirebaseCore (~> 4.0)
|
||||
- Protobuf (~> 3.1)
|
||||
- FirebaseFirestore/abseil-cpp (0.12.4):
|
||||
- FirebaseCore (~> 5.0)
|
||||
- gRPC-ProtoRPC (~> 1.0)
|
||||
- leveldb-library (~> 1.18)
|
||||
- Protobuf (~> 3.1)
|
||||
- FirebaseFunctions (2.0.0):
|
||||
- FirebaseCore (~> 5.0)
|
||||
- GTMSessionFetcher/Core (~> 1.1)
|
||||
- FirebaseInstanceID (2.0.10):
|
||||
- FirebaseCore (~> 4.0)
|
||||
- FirebaseInvites (2.0.2):
|
||||
- FirebaseAnalytics (~> 4.0)
|
||||
- FirebaseDynamicLinks (~> 2.2)
|
||||
- FirebaseInstanceID (3.1.1):
|
||||
- FirebaseCore (~> 5.0)
|
||||
- FirebaseInvites (3.0.0):
|
||||
- FirebaseAnalytics (~> 5.0)
|
||||
- FirebaseDynamicLinks (~> 3.0)
|
||||
- GoogleAPIClientForREST (~> 1.0)
|
||||
- GoogleSignIn (~> 4.1)
|
||||
- GoogleToolboxForMac/Logger (~> 2.1)
|
||||
- GoogleToolboxForMac/NSDictionary+URLArguments (~> 2.1)
|
||||
- GoogleToolboxForMac/NSString+URLArguments (~> 2.1)
|
||||
- "GoogleToolboxForMac/NSDictionary+URLArguments (~> 2.1)"
|
||||
- "GoogleToolboxForMac/NSString+URLArguments (~> 2.1)"
|
||||
- GoogleToolboxForMac/StringEncoding (~> 2.1)
|
||||
- GoogleToolboxForMac/URLBuilder (~> 2.1)
|
||||
- GTMOAuth2 (~> 1.0)
|
||||
- GTMSessionFetcher/Core (~> 1.1)
|
||||
- GTMSessionFetcher/Full (~> 1.1)
|
||||
- Protobuf (~> 3.5)
|
||||
- FirebaseMessaging (3.0.2):
|
||||
- FirebaseCore (~> 5.0)
|
||||
- FirebaseInstanceID (~> 3.0)
|
||||
- GoogleToolboxForMac/Logger (~> 2.1)
|
||||
- Protobuf (~> 3.1)
|
||||
- FirebaseMessaging (2.2.0):
|
||||
- FirebaseAnalytics (~> 4.1)
|
||||
- FirebaseCore (~> 4.0)
|
||||
- FirebaseInstanceID (~> 2.0)
|
||||
- FirebasePerformance (2.0.1):
|
||||
- FirebaseAnalytics (~> 5.0)
|
||||
- FirebaseInstanceID (~> 3.1)
|
||||
- FirebaseSwizzlingUtilities/ISASwizzling (~> 2.0)
|
||||
- FirebaseSwizzlingUtilities/MethodSwizzling (~> 2.0)
|
||||
- GoogleToolboxForMac/Logger (~> 2.1)
|
||||
- Protobuf (~> 3.5)
|
||||
- FirebasePerformance (1.1.3):
|
||||
- FirebaseAnalytics (~> 4.1)
|
||||
- FirebaseInstanceID (~> 2.0)
|
||||
- FirebaseSwizzlingUtilities/ISASwizzling (~> 1.0)
|
||||
- FirebaseSwizzlingUtilities/MethodSwizzling (~> 1.0)
|
||||
- GoogleToolboxForMac/Logger (~> 2.1)
|
||||
- GoogleToolboxForMac/NSData+zlib (~> 2.1)
|
||||
- "GoogleToolboxForMac/NSData+zlib (~> 2.1)"
|
||||
- GTMSessionFetcher/Core (~> 1.1)
|
||||
- Protobuf (~> 3.5)
|
||||
- FirebaseRemoteConfig (2.1.3):
|
||||
- FirebaseABTesting (~> 1.0)
|
||||
- FirebaseAnalytics (~> 4.1)
|
||||
- FirebaseCore (~> 4.0)
|
||||
- FirebaseInstanceID (~> 2.0)
|
||||
- GoogleToolboxForMac/NSData+zlib (~> 2.1)
|
||||
- FirebaseRemoteConfig (3.0.0):
|
||||
- FirebaseABTesting (~> 2.0)
|
||||
- FirebaseAnalytics (~> 5.0)
|
||||
- FirebaseCore (~> 5.0)
|
||||
- FirebaseInstanceID (~> 3.0)
|
||||
- "GoogleToolboxForMac/NSData+zlib (~> 2.1)"
|
||||
- Protobuf (~> 3.5)
|
||||
- FirebaseStorage (2.2.0):
|
||||
- FirebaseAnalytics (~> 4.1)
|
||||
- FirebaseCore (~> 4.0)
|
||||
- FirebaseStorage (3.0.0):
|
||||
- FirebaseCore (~> 5.0)
|
||||
- GTMSessionFetcher/Core (~> 1.1)
|
||||
- FirebaseSwizzlingUtilities/ISASwizzling (1.0.1)
|
||||
- FirebaseSwizzlingUtilities/MethodSwizzling (1.0.1):
|
||||
- FirebaseCore (~> 4.0)
|
||||
- Google-Mobile-Ads-SDK (7.30.0)
|
||||
- FirebaseSwizzlingUtilities/ISASwizzling (2.0.0)
|
||||
- FirebaseSwizzlingUtilities/MethodSwizzling (2.0.0):
|
||||
- FirebaseCore (~> 5.0)
|
||||
- Google-Mobile-Ads-SDK (7.31.0)
|
||||
- GoogleAPIClientForREST (1.3.4):
|
||||
- GoogleAPIClientForREST/Core (= 1.3.4)
|
||||
- GTMSessionFetcher (>= 1.1.7)
|
||||
- GoogleAPIClientForREST/Core (1.3.4):
|
||||
- GTMSessionFetcher (>= 1.1.7)
|
||||
- GoogleSignIn (4.1.2):
|
||||
- GoogleToolboxForMac/NSDictionary+URLArguments (~> 2.1)
|
||||
- GoogleToolboxForMac/NSString+URLArguments (~> 2.1)
|
||||
- "GoogleToolboxForMac/NSDictionary+URLArguments (~> 2.1)"
|
||||
- "GoogleToolboxForMac/NSString+URLArguments (~> 2.1)"
|
||||
- GTMOAuth2 (~> 1.0)
|
||||
- GTMSessionFetcher/Core (~> 1.1)
|
||||
- GoogleToolboxForMac/Core (2.1.3):
|
||||
- GoogleToolboxForMac/Defines (= 2.1.3)
|
||||
- GoogleToolboxForMac/DebugUtils (2.1.3):
|
||||
- GoogleToolboxForMac/Defines (= 2.1.3)
|
||||
- GoogleToolboxForMac/Defines (2.1.3)
|
||||
- GoogleToolboxForMac/Logger (2.1.3):
|
||||
- GoogleToolboxForMac/Defines (= 2.1.3)
|
||||
- GoogleToolboxForMac/NSData+zlib (2.1.3):
|
||||
- GoogleToolboxForMac/Defines (= 2.1.3)
|
||||
- GoogleToolboxForMac/NSDictionary+URLArguments (2.1.3):
|
||||
- GoogleToolboxForMac/DebugUtils (= 2.1.3)
|
||||
- GoogleToolboxForMac/Defines (= 2.1.3)
|
||||
- GoogleToolboxForMac/NSString+URLArguments (= 2.1.3)
|
||||
- GoogleToolboxForMac/NSString+URLArguments (2.1.3)
|
||||
- GoogleToolboxForMac/StringEncoding (2.1.3):
|
||||
- GoogleToolboxForMac/Defines (= 2.1.3)
|
||||
- GoogleToolboxForMac/URLBuilder (2.1.3):
|
||||
- GoogleToolboxForMac/Core (= 2.1.3)
|
||||
- GoogleToolboxForMac/Defines (= 2.1.3)
|
||||
- GoogleToolboxForMac/NSDictionary+URLArguments (= 2.1.3)
|
||||
- GoogleToolboxForMac/NSString+URLArguments (= 2.1.3)
|
||||
- gRPC (1.11.0):
|
||||
- gRPC-RxLibrary (= 1.11.0)
|
||||
- gRPC/Main (= 1.11.0)
|
||||
- gRPC-Core (1.11.0):
|
||||
- gRPC-Core/Implementation (= 1.11.0)
|
||||
- gRPC-Core/Interface (= 1.11.0)
|
||||
- gRPC-Core/Implementation (1.11.0):
|
||||
- GoogleToolboxForMac/Core (2.1.4):
|
||||
- GoogleToolboxForMac/Defines (= 2.1.4)
|
||||
- GoogleToolboxForMac/DebugUtils (2.1.4):
|
||||
- GoogleToolboxForMac/Defines (= 2.1.4)
|
||||
- GoogleToolboxForMac/Defines (2.1.4)
|
||||
- GoogleToolboxForMac/Logger (2.1.4):
|
||||
- GoogleToolboxForMac/Defines (= 2.1.4)
|
||||
- "GoogleToolboxForMac/NSData+zlib (2.1.4)":
|
||||
- GoogleToolboxForMac/Defines (= 2.1.4)
|
||||
- "GoogleToolboxForMac/NSDictionary+URLArguments (2.1.4)":
|
||||
- GoogleToolboxForMac/DebugUtils (= 2.1.4)
|
||||
- GoogleToolboxForMac/Defines (= 2.1.4)
|
||||
- "GoogleToolboxForMac/NSString+URLArguments (= 2.1.4)"
|
||||
- "GoogleToolboxForMac/NSString+URLArguments (2.1.4)"
|
||||
- GoogleToolboxForMac/StringEncoding (2.1.4):
|
||||
- GoogleToolboxForMac/Defines (= 2.1.4)
|
||||
- GoogleToolboxForMac/URLBuilder (2.1.4):
|
||||
- GoogleToolboxForMac/Core (= 2.1.4)
|
||||
- GoogleToolboxForMac/Defines (= 2.1.4)
|
||||
- "GoogleToolboxForMac/NSDictionary+URLArguments (= 2.1.4)"
|
||||
- "GoogleToolboxForMac/NSString+URLArguments (= 2.1.4)"
|
||||
- gRPC (1.13.0):
|
||||
- gRPC-RxLibrary (= 1.13.0)
|
||||
- gRPC/Main (= 1.13.0)
|
||||
- gRPC-Core (1.13.0):
|
||||
- gRPC-Core/Implementation (= 1.13.0)
|
||||
- gRPC-Core/Interface (= 1.13.0)
|
||||
- gRPC-Core/Implementation (1.13.0):
|
||||
- BoringSSL (~> 10.0)
|
||||
- gRPC-Core/Interface (= 1.11.0)
|
||||
- gRPC-Core/Interface (= 1.13.0)
|
||||
- nanopb (~> 0.3)
|
||||
- gRPC-Core/Interface (1.11.0)
|
||||
- gRPC-ProtoRPC (1.11.0):
|
||||
- gRPC (= 1.11.0)
|
||||
- gRPC-RxLibrary (= 1.11.0)
|
||||
- gRPC-Core/Interface (1.13.0)
|
||||
- gRPC-ProtoRPC (1.13.0):
|
||||
- gRPC-ProtoRPC/Main (= 1.13.0)
|
||||
- gRPC-ProtoRPC/Main (1.13.0):
|
||||
- gRPC (= 1.13.0)
|
||||
- gRPC-RxLibrary (= 1.13.0)
|
||||
- Protobuf (~> 3.0)
|
||||
- gRPC-RxLibrary (1.11.0)
|
||||
- gRPC/Main (1.11.0):
|
||||
- gRPC-Core (= 1.11.0)
|
||||
- gRPC-RxLibrary (= 1.11.0)
|
||||
- gRPC-RxLibrary (1.13.0)
|
||||
- gRPC/Main (1.13.0):
|
||||
- gRPC-Core (= 1.13.0)
|
||||
- gRPC-RxLibrary (= 1.13.0)
|
||||
- GTMOAuth2 (1.1.6):
|
||||
- GTMSessionFetcher (~> 1.1)
|
||||
- GTMSessionFetcher (1.1.15):
|
||||
@@ -192,7 +196,7 @@ PODS:
|
||||
- nanopb/encode (= 0.3.8)
|
||||
- nanopb/decode (0.3.8)
|
||||
- nanopb/encode (0.3.8)
|
||||
- Protobuf (3.5.0)
|
||||
- Protobuf (3.6.0)
|
||||
- React (0.55.3):
|
||||
- React/Core (= 0.55.3)
|
||||
- React/Core (0.55.3):
|
||||
@@ -208,27 +212,27 @@ PODS:
|
||||
- React/Core
|
||||
- React/fishhook
|
||||
- React/RCTBlob
|
||||
- RNFirebase (4.0.7):
|
||||
- RNFirebase (4.2.0):
|
||||
- Firebase/Core
|
||||
- React
|
||||
- yoga (0.55.3.React)
|
||||
|
||||
DEPENDENCIES:
|
||||
- Crashlytics (~> 3.10.1)
|
||||
- Crashlytics (~> 3.10.4)
|
||||
- Fabric (~> 1.7.5)
|
||||
- Firebase/AdMob
|
||||
- Firebase/Auth
|
||||
- Firebase/Core
|
||||
- Firebase/Crash
|
||||
- Firebase/Database
|
||||
- Firebase/DynamicLinks
|
||||
- Firebase/Firestore
|
||||
- Firebase/Functions
|
||||
- Firebase/Invites
|
||||
- Firebase/Messaging
|
||||
- Firebase/Performance
|
||||
- Firebase/RemoteConfig
|
||||
- Firebase/Storage
|
||||
- Firebase/AdMob (~> 5.3.0)
|
||||
- Firebase/Auth (~> 5.3.0)
|
||||
- Firebase/Core (~> 5.3.0)
|
||||
- Firebase/Crash (~> 5.3.0)
|
||||
- Firebase/Database (~> 5.3.0)
|
||||
- Firebase/DynamicLinks (~> 5.3.0)
|
||||
- Firebase/Firestore (~> 5.3.0)
|
||||
- Firebase/Functions (~> 5.3.0)
|
||||
- Firebase/Invites (~> 5.3.0)
|
||||
- Firebase/Messaging (~> 5.3.0)
|
||||
- Firebase/Performance (~> 5.3.0)
|
||||
- Firebase/RemoteConfig (~> 5.3.0)
|
||||
- Firebase/Storage (~> 5.3.0)
|
||||
- React/Core (from `../node_modules/react-native`)
|
||||
- React/RCTNetwork (from `../node_modules/react-native`)
|
||||
- React/RCTText (from `../node_modules/react-native`)
|
||||
@@ -236,52 +240,88 @@ DEPENDENCIES:
|
||||
- RNFirebase (from `../../ios/RNFirebase.podspec`)
|
||||
- yoga (from `../node_modules/react-native/ReactCommon/yoga`)
|
||||
|
||||
SPEC REPOS:
|
||||
https://github.com/cocoapods/specs.git:
|
||||
- BoringSSL
|
||||
- Crashlytics
|
||||
- Fabric
|
||||
- Firebase
|
||||
- FirebaseABTesting
|
||||
- FirebaseAnalytics
|
||||
- FirebaseAuth
|
||||
- FirebaseCore
|
||||
- FirebaseCrash
|
||||
- FirebaseDatabase
|
||||
- FirebaseDynamicLinks
|
||||
- FirebaseFirestore
|
||||
- FirebaseFunctions
|
||||
- FirebaseInstanceID
|
||||
- FirebaseInvites
|
||||
- FirebaseMessaging
|
||||
- FirebasePerformance
|
||||
- FirebaseRemoteConfig
|
||||
- FirebaseStorage
|
||||
- FirebaseSwizzlingUtilities
|
||||
- Google-Mobile-Ads-SDK
|
||||
- GoogleAPIClientForREST
|
||||
- GoogleSignIn
|
||||
- GoogleToolboxForMac
|
||||
- gRPC
|
||||
- gRPC-Core
|
||||
- gRPC-ProtoRPC
|
||||
- gRPC-RxLibrary
|
||||
- GTMOAuth2
|
||||
- GTMSessionFetcher
|
||||
- leveldb-library
|
||||
- nanopb
|
||||
- Protobuf
|
||||
|
||||
EXTERNAL SOURCES:
|
||||
React:
|
||||
:path: ../node_modules/react-native
|
||||
:path: "../node_modules/react-native"
|
||||
RNFirebase:
|
||||
:path: ../../ios/RNFirebase.podspec
|
||||
:path: "../../ios/RNFirebase.podspec"
|
||||
yoga:
|
||||
:path: ../node_modules/react-native/ReactCommon/yoga
|
||||
:path: "../node_modules/react-native/ReactCommon/yoga"
|
||||
|
||||
SPEC CHECKSUMS:
|
||||
BoringSSL: 60dd24df4af296bf41d78e5841dbb95d75f88c0d
|
||||
Crashlytics: aee1a064cbbf99b32efa3f056a5f458d846bc8ff
|
||||
Fabric: f8d42c893bb187326a7968b62abe55c36a987a46
|
||||
Firebase: 5ec5e863d269d82d66b4bf56856726f8fb8f0fb3
|
||||
FirebaseABTesting: d07d0ee833b842d5153549e4c7e2e2cb1c23a3f9
|
||||
FirebaseAnalytics: 7ef69e76a5142f643aeb47c780e1cdce4e23632e
|
||||
FirebaseAuth: bf22cacf22c60ab454bf2636f556d8892b10b53f
|
||||
FirebaseCore: 90cb1c53d69b556f112a1bf72b5fcfaad7650790
|
||||
FirebaseCrash: a7d980468dc8aa2db9792493c3e02722d601f6ab
|
||||
FirebaseDatabase: 5f0bc6134c5c237cf55f9e1249d406770a75eafd
|
||||
FirebaseDynamicLinks: 38b68641d24e78d0277a9205d988ce22875d5a25
|
||||
FirebaseFirestore: e92a096ce80c7b4b905d4e9d41dbd944adc9d2a5
|
||||
FirebaseFunctions: 3745fada03bd706a9b5c0b9ae7b2d490fa594d21
|
||||
FirebaseInstanceID: 8d20d890d65c917f9f7d9950b6e10a760ad34321
|
||||
FirebaseInvites: ae15e0636f9eb42bdf5c1ef4c8f7bd4a88f9878b
|
||||
FirebaseMessaging: 75cdb862e86c30e0913a2ff307e48d49357c5b73
|
||||
FirebasePerformance: 85bdc3f3d630deb629e85695fcab23364d68f5db
|
||||
FirebaseRemoteConfig: 3e95fb7c072308492e85fa41d59d38b3d6fd2372
|
||||
FirebaseStorage: 0c223481c8f89ed300cf1239ddd2d9833622c65f
|
||||
FirebaseSwizzlingUtilities: 6006111d30248d2321ffac0231e246663e704ea3
|
||||
Google-Mobile-Ads-SDK: 7404f68120ae8682afeb5af001fbf4aad731c78e
|
||||
BoringSSL: cf3f1793eb6e3c445c4d150456341f149c268a35
|
||||
Crashlytics: 915a7787b84f635fb2a81f92a90e265c2c413f76
|
||||
Fabric: a2917d3895e4c1569b9c3170de7320ea1b1e6661
|
||||
Firebase: 68afeeb05461db02d7c9e3215cda28068670f4aa
|
||||
FirebaseABTesting: 1f50b8d50f5e3469eea54e7463a7b7fe221d1f5e
|
||||
FirebaseAnalytics: b3628aea54c50464c32c393fb2ea032566e7ecc2
|
||||
FirebaseAuth: 463b8ce33bd5d05f706dcd4615499e3212b4132b
|
||||
FirebaseCore: 62f1b792a49bb9e8b4073f24606d2c93ffc352f0
|
||||
FirebaseCrash: 8900571fd763fd5bdda04522ec53da979456e3ce
|
||||
FirebaseDatabase: 482bad9c2abd422bb2321194fb8c937e67426a89
|
||||
FirebaseDynamicLinks: d624a7adc81a8fd70d52be5a6a47a2bc0644b923
|
||||
FirebaseFirestore: 53f6fe858494c39dbfd5237655e0641152a88c89
|
||||
FirebaseFunctions: 141da172b7491276d9da8715b8ca88f9e439ffb6
|
||||
FirebaseInstanceID: f3f0657372592ecdfdfe2cac604a5a75758376a6
|
||||
FirebaseInvites: d7534f94d0610b892bac8ee0cf4218a14be46c28
|
||||
FirebaseMessaging: 6894b8fe0a0cf26c3b13dad729f1131654ae0bdb
|
||||
FirebasePerformance: 1ebd87ffee5ca814582db1dc9e25651792ba02db
|
||||
FirebaseRemoteConfig: 3c57e4644bd6976b671ae0b725cd709f198bd1f5
|
||||
FirebaseStorage: 7ca4bb7b58a25fa647b04f524033fc7cb7eb272b
|
||||
FirebaseSwizzlingUtilities: 6c22677c50d0b6f5f0dc637c1233f13694a3003f
|
||||
Google-Mobile-Ads-SDK: 6e529e748b45507a2ca904e0b5a52669ba3920c4
|
||||
GoogleAPIClientForREST: f7951c455df271bc6259b3ddb4073d0026475ccf
|
||||
GoogleSignIn: d9ef55b10f0aa401a5de2747f59b725e4b9732ac
|
||||
GoogleToolboxForMac: 2501e2ad72a52eb3dfe7bd9aee7dad11b858bd20
|
||||
gRPC: 70703dc9ba31c72341fc7f37745cc1c379edee96
|
||||
gRPC-Core: 164639cd8ae18ca8b65477fafb2efbaecf4f181a
|
||||
gRPC-ProtoRPC: bb5fddf3424aa4fad74d76736578a79fe40e244e
|
||||
gRPC-RxLibrary: 26d53d1b1f306befd4ad4e15bd6de27839a82481
|
||||
GoogleToolboxForMac: 91c824d21e85b31c2aae9bb011c5027c9b4e738f
|
||||
gRPC: 81b990caa01d7c32605d300c2ffd1b5ba0ef9e49
|
||||
gRPC-Core: a56b086a8ef5ced6f6ba5be5bc0a63fca185015a
|
||||
gRPC-ProtoRPC: 842797fbe05dfcf891afb4a5048e5ccf5f06ef86
|
||||
gRPC-RxLibrary: fa6852f98d6ec0b73c0ec2f6406c26943099d501
|
||||
GTMOAuth2: c77fe325e4acd453837e72d91e3b5f13116857b2
|
||||
GTMSessionFetcher: 5fa5b80fd20e439ef5f545fb2cb3ca6c6714caa2
|
||||
leveldb-library: 08cba283675b7ed2d99629a4bc5fd052cd2bb6a5
|
||||
nanopb: 5601e6bca2dbf1ed831b519092ec110f66982ca3
|
||||
Protobuf: 8a9838fba8dae3389230e1b7f8c104aa32389c03
|
||||
React: 573d89cf10312b17920df6328eaf9ab8059283bf
|
||||
RNFirebase: 05ef1e1c1681af418f3500fda194a2d17d45be07
|
||||
yoga: 9403c2451c1b47d8cee3e4f1b6fd0ececc63839c
|
||||
Protobuf: 0fc0ad8bec688b2a3017a139953e01374fedbd5f
|
||||
React: aa2040dbb6f317b95314968021bd2888816e03d5
|
||||
RNFirebase: 2b25fd2e60269f26bb0a76c71dcc942b35a77df0
|
||||
yoga: a23273df0088bf7f2bb7e5d7b00044ea57a2a54a
|
||||
|
||||
PODFILE CHECKSUM: 582ceaad051470812ad9203e13b5ea8ad20c78ac
|
||||
PODFILE CHECKSUM: af3286375d5c28aa5d912b64dee23c8f7c4f9282
|
||||
|
||||
COCOAPODS: 1.3.1
|
||||
COCOAPODS: 1.5.3
|
||||
|
||||
24
bridge/ios/testing.xcodeproj/project.pbxproj
Executable file → Normal file
24
bridge/ios/testing.xcodeproj/project.pbxproj
Executable file → Normal file
@@ -595,7 +595,6 @@
|
||||
00DD1BFF1BD5951E006B06BC /* Bundle React Native code and images */,
|
||||
CC0F353E1D461097008BB94F /* Embed Frameworks */,
|
||||
7D57265F10EEF7CD92D7973F /* Copy Detox Framework */,
|
||||
4EEB648E968FA6F093B42978 /* [CP] Embed Pods Frameworks */,
|
||||
CC8D61273332DE7812CFF010 /* [CP] Copy Pods Resources */,
|
||||
);
|
||||
buildRules = (
|
||||
@@ -971,21 +970,6 @@
|
||||
shellPath = /bin/sh;
|
||||
shellScript = "export NODE_BINARY=node\n../node_modules/react-native/scripts/react-native-xcode.sh";
|
||||
};
|
||||
4EEB648E968FA6F093B42978 /* [CP] Embed Pods Frameworks */ = {
|
||||
isa = PBXShellScriptBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
inputPaths = (
|
||||
);
|
||||
name = "[CP] Embed Pods Frameworks";
|
||||
outputPaths = (
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
shellPath = /bin/sh;
|
||||
shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-testing/Pods-testing-frameworks.sh\"\n";
|
||||
showEnvVarsInLog = 0;
|
||||
};
|
||||
7D57265F10EEF7CD92D7973F /* Copy Detox Framework */ = {
|
||||
isa = PBXShellScriptBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
@@ -1029,11 +1013,15 @@
|
||||
"${PODS_ROOT}/FirebaseInvites/Resources/GPPACLPickerResources.bundle",
|
||||
"${PODS_ROOT}/GTMOAuth2/Source/Touch/GTMOAuth2ViewTouch.xib",
|
||||
"${PODS_ROOT}/GoogleSignIn/Resources/GoogleSignIn.bundle",
|
||||
"$PODS_CONFIGURATION_BUILD_DIR/gRPC/gRPCCertificates.bundle",
|
||||
"${PODS_CONFIGURATION_BUILD_DIR}/gRPC/gRPCCertificates.bundle",
|
||||
);
|
||||
name = "[CP] Copy Pods Resources";
|
||||
outputPaths = (
|
||||
"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}",
|
||||
"${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;
|
||||
|
||||
5200
bridge/package-lock.json
generated
5200
bridge/package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@@ -13,7 +13,7 @@
|
||||
"test-android-reuse": "detox test --configuration android.emu.debug --reuse",
|
||||
"test-android-cover": "nyc detox test --configuration android.emu.debug",
|
||||
"test-android-cover-reuse": "nyc detox test --configuration android.emu.debug --reuse",
|
||||
"test-ios": "detox test --configuration ios.sim.debug",
|
||||
"test-ios": "detox test --configuration ios.sim.debug --loglevel warn",
|
||||
"test-ios-reuse": "detox test --configuration ios.sim.debug --reuse --loglevel warn",
|
||||
"test-ios-cover": "nyc detox test --configuration ios.sim.debug",
|
||||
"test-ios-cover-reuse": "nyc detox test --configuration ios.sim.debug --reuse --loglevel warn",
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
#import "RNFirebase.h"
|
||||
#import "RNFirebaseUtil.h"
|
||||
#import <FirebaseCore/FirebaseCore.h>
|
||||
#import <React/RCTUtils.h>
|
||||
|
||||
@implementation RNFirebase
|
||||
RCT_EXPORT_MODULE(RNFirebase);
|
||||
@@ -28,7 +29,7 @@ RCT_EXPORT_METHOD(initializeApp:
|
||||
callback:
|
||||
(RCTResponseSenderBlock) callback) {
|
||||
|
||||
dispatch_sync(dispatch_get_main_queue(), ^{
|
||||
RCTUnsafeExecuteOnMainQueueSync(^{
|
||||
FIRApp *existingApp = [RNFirebaseUtil getApp:appDisplayName];
|
||||
|
||||
if (!existingApp) {
|
||||
|
||||
@@ -31,6 +31,10 @@
|
||||
}
|
||||
|
||||
- (void)requestAd {
|
||||
#ifndef __LP64__
|
||||
return; // prevent crash on 32bit
|
||||
#endif
|
||||
|
||||
if (_unitId == nil || _size == nil || _request == nil) {
|
||||
[self setRequested:NO];
|
||||
return;
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
#import "RNFirebaseAnalytics.h"
|
||||
#import <React/RCTUtils.h>
|
||||
|
||||
#if __has_include(<FirebaseAnalytics/FIRAnalytics.h>)
|
||||
#import <FirebaseAnalytics/FIRAnalytics.h>
|
||||
#import <FirebaseAnalytics/FIRAnalyticsConfiguration.h>
|
||||
#import <FirebaseCore/FIRAnalyticsConfiguration.h>
|
||||
|
||||
@implementation RNFirebaseAnalytics
|
||||
RCT_EXPORT_MODULE();
|
||||
@@ -16,7 +17,7 @@ RCT_EXPORT_METHOD(setAnalyticsCollectionEnabled:(BOOL) enabled) {
|
||||
}
|
||||
|
||||
RCT_EXPORT_METHOD(setCurrentScreen:(NSString *) screenName screenClass:(NSString *) screenClassOverriew) {
|
||||
dispatch_sync(dispatch_get_main_queue(), ^{
|
||||
RCTUnsafeExecuteOnMainQueueSync(^{
|
||||
[FIRAnalytics setScreenName:screenName screenClass:screenClassOverriew];
|
||||
});
|
||||
}
|
||||
|
||||
@@ -128,15 +128,7 @@ RCT_EXPORT_METHOD(signOut:
|
||||
RCT_EXPORT_METHOD(signInAnonymously:(NSString *) appDisplayName
|
||||
resolver:(RCTPromiseResolveBlock) resolve
|
||||
rejecter:(RCTPromiseRejectBlock) reject) {
|
||||
FIRApp *firApp = [RNFirebaseUtil getApp:appDisplayName];
|
||||
|
||||
[[FIRAuth authWithApp:firApp] signInAnonymouslyWithCompletion:^(FIRUser *user, NSError *error) {
|
||||
if (error) {
|
||||
[self promiseRejectAuthException:reject error:error];
|
||||
} else {
|
||||
[self promiseWithUser:resolve rejecter:reject user:user];
|
||||
}
|
||||
}];
|
||||
[self signInAnonymously:appDisplayName withData:false resolver:resolve rejecter:reject];
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -149,13 +141,22 @@ RCT_EXPORT_METHOD(signInAnonymously:(NSString *) appDisplayName
|
||||
RCT_EXPORT_METHOD(signInAnonymouslyAndRetrieveData:(NSString *) appDisplayName
|
||||
resolver:(RCTPromiseResolveBlock) resolve
|
||||
rejecter:(RCTPromiseRejectBlock) reject) {
|
||||
[self signInAnonymously:appDisplayName withData:true resolver:resolve rejecter:reject];
|
||||
}
|
||||
|
||||
-(void)signInAnonymously:(NSString *)appDisplayName
|
||||
withData:(BOOL)withData
|
||||
resolver:(RCTPromiseResolveBlock) resolve
|
||||
rejecter:(RCTPromiseRejectBlock) reject {
|
||||
FIRApp *firApp = [RNFirebaseUtil getApp:appDisplayName];
|
||||
|
||||
[[FIRAuth authWithApp:firApp] signInAnonymouslyAndRetrieveDataWithCompletion:^(FIRAuthDataResult *authResult, NSError *error) {
|
||||
[[FIRAuth authWithApp:firApp] signInAnonymouslyWithCompletion:^(FIRAuthDataResult *authResult, NSError *error) {
|
||||
if (error) {
|
||||
[self promiseRejectAuthException:reject error:error];
|
||||
} else {
|
||||
} else if (withData) {
|
||||
[self promiseWithAuthResult:resolve rejecter:reject authResult:authResult];
|
||||
} else {
|
||||
[self promiseWithUser:resolve rejecter:reject user:authResult.user];
|
||||
}
|
||||
}];
|
||||
}
|
||||
@@ -174,15 +175,7 @@ RCT_EXPORT_METHOD(signInWithEmailAndPassword:(NSString *) appDisplayName
|
||||
pass:(NSString *) password
|
||||
resolver:(RCTPromiseResolveBlock) resolve
|
||||
rejecter:(RCTPromiseRejectBlock) reject) {
|
||||
FIRApp *firApp = [RNFirebaseUtil getApp:appDisplayName];
|
||||
|
||||
[[FIRAuth authWithApp:firApp] signInWithEmail:email password:password completion:^(FIRUser *user, NSError *error) {
|
||||
if (error) {
|
||||
[self promiseRejectAuthException:reject error:error];
|
||||
} else {
|
||||
[self promiseWithUser:resolve rejecter:reject user:user];
|
||||
}
|
||||
}];
|
||||
[self signInWithEmail:appDisplayName email:email password:password withData:false resolver:resolve rejecter:reject];
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -196,12 +189,48 @@ RCT_EXPORT_METHOD(signInWithEmailAndPassword:(NSString *) appDisplayName
|
||||
*/
|
||||
RCT_EXPORT_METHOD(signInAndRetrieveDataWithEmailAndPassword:(NSString *) appDisplayName
|
||||
email:(NSString *) email
|
||||
pass:(NSString *) password
|
||||
password:(NSString *) password
|
||||
resolver:(RCTPromiseResolveBlock) resolve
|
||||
rejecter:(RCTPromiseRejectBlock) reject) {
|
||||
[self signInWithEmail:appDisplayName email:email password:password withData:true resolver:resolve rejecter:reject];
|
||||
}
|
||||
|
||||
-(void)signInWithEmail:(NSString *)appDisplayName
|
||||
email:(NSString *)email
|
||||
password:(NSString *)password
|
||||
withData:(BOOL)withData
|
||||
resolver:(RCTPromiseResolveBlock) resolve
|
||||
rejecter:(RCTPromiseRejectBlock) reject {
|
||||
FIRApp *firApp = [RNFirebaseUtil getApp:appDisplayName];
|
||||
|
||||
[[FIRAuth authWithApp:firApp] signInWithEmail:email password:password completion:^(FIRAuthDataResult *authResult, NSError *error) {
|
||||
if (error) {
|
||||
[self promiseRejectAuthException:reject error:error];
|
||||
} else if (withData) {
|
||||
[self promiseWithAuthResult:resolve rejecter:reject authResult:authResult];
|
||||
} else {
|
||||
[self promiseWithUser:resolve rejecter:reject user:authResult.user];
|
||||
}
|
||||
}];
|
||||
}
|
||||
|
||||
/**
|
||||
signInWithEmailLink
|
||||
|
||||
@param NSString NSString email
|
||||
@param NSString NSString emailLink
|
||||
@param RCTPromiseResolveBlock resolve
|
||||
@param RCTPromiseRejectBlock reject
|
||||
@return return
|
||||
*/
|
||||
RCT_EXPORT_METHOD(signInWithEmailLink:(NSString *) appDisplayName
|
||||
email:(NSString *) email
|
||||
emailLink:(NSString *) emailLink
|
||||
resolver:(RCTPromiseResolveBlock) resolve
|
||||
rejecter:(RCTPromiseRejectBlock) reject) {
|
||||
FIRApp *firApp = [RNFirebaseUtil getApp:appDisplayName];
|
||||
|
||||
[[FIRAuth authWithApp:firApp] signInAndRetrieveDataWithEmail:email password:password completion:^(FIRAuthDataResult *authResult, NSError *error) {
|
||||
[[FIRAuth authWithApp:firApp] signInWithEmail:email link:emailLink completion:^(FIRAuthDataResult *authResult, NSError *error) {
|
||||
if (error) {
|
||||
[self promiseRejectAuthException:reject error:error];
|
||||
} else {
|
||||
@@ -224,15 +253,7 @@ RCT_EXPORT_METHOD(createUserWithEmailAndPassword:(NSString *) appDisplayName
|
||||
pass:(NSString *) password
|
||||
resolver:(RCTPromiseResolveBlock) resolve
|
||||
rejecter:(RCTPromiseRejectBlock) reject) {
|
||||
FIRApp *firApp = [RNFirebaseUtil getApp:appDisplayName];
|
||||
|
||||
[[FIRAuth authWithApp:firApp] createUserWithEmail:email password:password completion:^(FIRUser *user, NSError *error) {
|
||||
if (error) {
|
||||
[self promiseRejectAuthException:reject error:error];
|
||||
} else {
|
||||
[self promiseWithUser:resolve rejecter:reject user:user];
|
||||
}
|
||||
}];
|
||||
[self createUserWithEmail:appDisplayName email:email password:password withData:false resolver:resolve rejecter:reject];
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -246,18 +267,28 @@ RCT_EXPORT_METHOD(createUserWithEmailAndPassword:(NSString *) appDisplayName
|
||||
*/
|
||||
RCT_EXPORT_METHOD(createUserAndRetrieveDataWithEmailAndPassword:(NSString *) appDisplayName
|
||||
email:(NSString *) email
|
||||
pass:(NSString *) password
|
||||
password:(NSString *) password
|
||||
resolver:(RCTPromiseResolveBlock) resolve
|
||||
rejecter:(RCTPromiseRejectBlock) reject) {
|
||||
[self createUserWithEmail:appDisplayName email:email password:password withData:true resolver:resolve rejecter:reject];
|
||||
}
|
||||
|
||||
-(void)createUserWithEmail:(NSString *)appDisplayName
|
||||
email:(NSString *)email
|
||||
password:(NSString *)password
|
||||
withData:(BOOL)withData
|
||||
resolver:(RCTPromiseResolveBlock) resolve
|
||||
rejecter:(RCTPromiseRejectBlock) reject {
|
||||
FIRApp *firApp = [RNFirebaseUtil getApp:appDisplayName];
|
||||
|
||||
[[FIRAuth authWithApp:firApp] createUserAndRetrieveDataWithEmail:email password:password
|
||||
completion:^(FIRAuthDataResult * _Nullable authResult, NSError * _Nullable error) {
|
||||
if (error) {
|
||||
[self promiseRejectAuthException:reject error:error];
|
||||
} else {
|
||||
[self promiseWithAuthResult:resolve rejecter:reject authResult:authResult];
|
||||
}
|
||||
[[FIRAuth authWithApp:firApp] createUserWithEmail:email password:password completion:^(FIRAuthDataResult *authResult, NSError *error) {
|
||||
if (error) {
|
||||
[self promiseRejectAuthException:reject error:error];
|
||||
} else if (withData) {
|
||||
[self promiseWithAuthResult:resolve rejecter:reject authResult:authResult];
|
||||
} else {
|
||||
[self promiseWithUser:resolve rejecter:reject user:authResult.user];
|
||||
}
|
||||
}];
|
||||
}
|
||||
|
||||
@@ -511,21 +542,7 @@ RCT_EXPORT_METHOD(signInWithCredential:(NSString *) appDisplayName
|
||||
secret:(NSString *) authSecret
|
||||
resolver:(RCTPromiseResolveBlock) resolve
|
||||
rejecter:(RCTPromiseRejectBlock) reject) {
|
||||
FIRApp *firApp = [RNFirebaseUtil getApp:appDisplayName];
|
||||
|
||||
FIRAuthCredential *credential = [self getCredentialForProvider:provider token:authToken secret:authSecret];
|
||||
|
||||
if (credential == nil) {
|
||||
return reject(@"auth/invalid-credential", @"The supplied auth credential is malformed, has expired or is not currently supported.", nil);
|
||||
}
|
||||
|
||||
[[FIRAuth authWithApp:firApp] signInWithCredential:credential completion:^(FIRUser *user, NSError *error) {
|
||||
if (error) {
|
||||
[self promiseRejectAuthException:reject error:error];
|
||||
} else {
|
||||
[self promiseWithUser:resolve rejecter:reject user:user];
|
||||
}
|
||||
}];
|
||||
[self signInWithCredential:appDisplayName provider:provider token:authToken secret:authSecret withData:false resolver:resolve rejecter:reject];
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -544,6 +561,16 @@ RCT_EXPORT_METHOD(signInAndRetrieveDataWithCredential:(NSString *) appDisplayNam
|
||||
secret:(NSString *) authSecret
|
||||
resolver:(RCTPromiseResolveBlock) resolve
|
||||
rejecter:(RCTPromiseRejectBlock) reject) {
|
||||
[self signInWithCredential:appDisplayName provider:provider token:authToken secret:authSecret withData:true resolver:resolve rejecter:reject];
|
||||
}
|
||||
|
||||
-(void)signInWithCredential:(NSString *)appDisplayName
|
||||
provider:(NSString *) provider
|
||||
token:(NSString *) authToken
|
||||
secret:(NSString *) authSecret
|
||||
withData:(BOOL)withData
|
||||
resolver:(RCTPromiseResolveBlock) resolve
|
||||
rejecter:(RCTPromiseRejectBlock) reject {
|
||||
FIRApp *firApp = [RNFirebaseUtil getApp:appDisplayName];
|
||||
|
||||
FIRAuthCredential *credential = [self getCredentialForProvider:provider token:authToken secret:authSecret];
|
||||
@@ -555,8 +582,10 @@ RCT_EXPORT_METHOD(signInAndRetrieveDataWithCredential:(NSString *) appDisplayNam
|
||||
[[FIRAuth authWithApp:firApp] signInAndRetrieveDataWithCredential:credential completion:^(FIRAuthDataResult *authResult, NSError *error) {
|
||||
if (error) {
|
||||
[self promiseRejectAuthException:reject error:error];
|
||||
} else {
|
||||
} else if (withData) {
|
||||
[self promiseWithAuthResult:resolve rejecter:reject authResult:authResult];
|
||||
} else {
|
||||
[self promiseWithUser:resolve rejecter:reject user:authResult.user];
|
||||
}
|
||||
}];
|
||||
}
|
||||
@@ -655,6 +684,9 @@ RCT_EXPORT_METHOD(checkActionCode:
|
||||
case FIRActionCodeOperationRecoverEmail:
|
||||
actionType = @"RECOVER_EMAIL";
|
||||
break;
|
||||
case FIRActionCodeOperationEmailLink:
|
||||
actionType = @"EMAIL_SIGNIN";
|
||||
break;
|
||||
}
|
||||
|
||||
NSDictionary *result = @{@"data": @{@"email": [info dataForKey:FIRActionCodeEmailKey], @"fromEmail": [info dataForKey:FIRActionCodeFromEmailKey],}, @"actionType": actionType,};
|
||||
@@ -695,6 +727,35 @@ RCT_EXPORT_METHOD(sendPasswordResetEmail:(NSString *) appDisplayName
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
sendSignInLinkToEmail
|
||||
|
||||
@param NSString email
|
||||
@param NSDictionary actionCodeSettings
|
||||
@param RCTPromiseResolveBlock resolve
|
||||
@param RCTPromiseRejectBlock reject
|
||||
@return
|
||||
*/
|
||||
RCT_EXPORT_METHOD(sendSignInLinkToEmail:(NSString *) appDisplayName
|
||||
email:(NSString *) email
|
||||
actionCodeSettings:(NSDictionary *) actionCodeSettings
|
||||
resolver:(RCTPromiseResolveBlock) resolve
|
||||
rejecter:(RCTPromiseRejectBlock) reject) {
|
||||
FIRApp *firApp = [RNFirebaseUtil getApp:appDisplayName];
|
||||
|
||||
id handler = ^(NSError *_Nullable error) {
|
||||
if (error) {
|
||||
[self promiseRejectAuthException:reject error:error];
|
||||
} else {
|
||||
[self promiseNoUser:resolve rejecter:reject isError:NO];
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
FIRActionCodeSettings *settings = [self buildActionCodeSettings:actionCodeSettings];
|
||||
[[FIRAuth authWithApp:firApp] sendSignInLinkToEmail:email actionCodeSettings:settings completion:handler];
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
signInAndRetrieveDataWithCustomToken
|
||||
@@ -707,15 +768,7 @@ RCT_EXPORT_METHOD(signInAndRetrieveDataWithCustomToken:(NSString *) appDisplayNa
|
||||
customToken:(NSString *) customToken
|
||||
resolver:(RCTPromiseResolveBlock) resolve
|
||||
rejecter:(RCTPromiseRejectBlock) reject) {
|
||||
FIRApp *firApp = [RNFirebaseUtil getApp:appDisplayName];
|
||||
|
||||
[[FIRAuth authWithApp:firApp] signInAndRetrieveDataWithCustomToken:customToken completion:^(FIRAuthDataResult *authResult, NSError *error) {
|
||||
if (error) {
|
||||
[self promiseRejectAuthException:reject error:error];
|
||||
} else {
|
||||
[self promiseWithAuthResult:resolve rejecter:reject authResult:authResult];
|
||||
}
|
||||
}];
|
||||
[self signInWithCustomToken:appDisplayName customToken:customToken withData:true resolver:resolve rejecter:reject];
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -729,13 +782,23 @@ RCT_EXPORT_METHOD(signInWithCustomToken:(NSString *) appDisplayName
|
||||
customToken:(NSString *) customToken
|
||||
resolver:(RCTPromiseResolveBlock) resolve
|
||||
rejecter:(RCTPromiseRejectBlock) reject) {
|
||||
[self signInWithCustomToken:appDisplayName customToken:customToken withData:false resolver:resolve rejecter:reject];
|
||||
}
|
||||
|
||||
-(void)signInWithCustomToken:(NSString *)appDisplayName
|
||||
customToken:(NSString *) customToken
|
||||
withData:(BOOL)withData
|
||||
resolver:(RCTPromiseResolveBlock) resolve
|
||||
rejecter:(RCTPromiseRejectBlock) reject {
|
||||
FIRApp *firApp = [RNFirebaseUtil getApp:appDisplayName];
|
||||
|
||||
[[FIRAuth authWithApp:firApp] signInWithCustomToken:customToken completion:^(FIRUser *user, NSError *error) {
|
||||
[[FIRAuth authWithApp:firApp] signInWithCustomToken:customToken completion:^(FIRAuthDataResult *authResult, NSError *error) {
|
||||
if (error) {
|
||||
[self promiseRejectAuthException:reject error:error];
|
||||
} else if (withData) {
|
||||
[self promiseWithAuthResult:resolve rejecter:reject authResult:authResult];
|
||||
} else {
|
||||
[self promiseWithUser:resolve rejecter:reject user:user];
|
||||
[self promiseWithUser:resolve rejecter:reject user:authResult.user];
|
||||
}
|
||||
}];
|
||||
}
|
||||
@@ -811,11 +874,11 @@ RCT_EXPORT_METHOD(_confirmVerificationCode:(NSString *) appDisplayName
|
||||
NSString *verificationId = [defaults stringForKey:@"authVerificationID"];
|
||||
FIRAuthCredential *credential = [[FIRPhoneAuthProvider provider] credentialWithVerificationID:verificationId verificationCode:verificationCode];
|
||||
|
||||
[[FIRAuth authWithApp:firApp] signInWithCredential:credential completion:^(FIRUser *user, NSError *error) {
|
||||
[[FIRAuth authWithApp:firApp] signInAndRetrieveDataWithCredential:credential completion:^(FIRAuthDataResult *authResult, NSError *error) {
|
||||
if (error) {
|
||||
[self promiseRejectAuthException:reject error:error];
|
||||
} else {
|
||||
[self promiseWithUser:resolve rejecter:reject user:user];
|
||||
[self promiseWithUser:resolve rejecter:reject user:authResult.user];
|
||||
}
|
||||
}];
|
||||
}
|
||||
@@ -836,26 +899,7 @@ RCT_EXPORT_METHOD(linkWithCredential:(NSString *) appDisplayName
|
||||
authSecret:(NSString *) authSecret
|
||||
resolver:(RCTPromiseResolveBlock) resolve
|
||||
rejecter:(RCTPromiseRejectBlock) reject) {
|
||||
FIRApp *firApp = [RNFirebaseUtil getApp:appDisplayName];
|
||||
FIRAuthCredential *credential = [self getCredentialForProvider:provider token:authToken secret:authSecret];
|
||||
|
||||
if (credential == nil) {
|
||||
return reject(@"auth/invalid-credential", @"The supplied auth credential is malformed, has expired or is not currently supported.", nil);
|
||||
}
|
||||
|
||||
FIRUser *user = [FIRAuth authWithApp:firApp].currentUser;
|
||||
|
||||
if (user) {
|
||||
[user linkWithCredential:credential completion:^(FIRUser *_Nullable _user, NSError *_Nullable error) {
|
||||
if (error) {
|
||||
[self promiseRejectAuthException:reject error:error];
|
||||
} else {
|
||||
[self promiseWithUser:resolve rejecter:reject user:_user];
|
||||
}
|
||||
}];
|
||||
} else {
|
||||
[self promiseNoUser:resolve rejecter:reject isError:YES];
|
||||
}
|
||||
[self linkWithCredential:appDisplayName provider:provider authToken:authToken authSecret:authSecret withData:false resolver:resolve rejecter:reject];
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -874,23 +918,35 @@ RCT_EXPORT_METHOD(linkAndRetrieveDataWithCredential:(NSString *) appDisplayName
|
||||
authSecret:(NSString *) authSecret
|
||||
resolver:(RCTPromiseResolveBlock) resolve
|
||||
rejecter:(RCTPromiseRejectBlock) reject) {
|
||||
[self linkWithCredential:appDisplayName provider:provider authToken:authToken authSecret:authSecret withData:true resolver:resolve rejecter:reject];
|
||||
}
|
||||
|
||||
-(void)linkWithCredential:(NSString *)appDisplayName
|
||||
provider:(NSString *)provider
|
||||
authToken:(NSString *)authToken
|
||||
authSecret:(NSString *)authSecret
|
||||
withData:(BOOL)withData
|
||||
resolver:(RCTPromiseResolveBlock)resolve
|
||||
rejecter:(RCTPromiseRejectBlock)reject {
|
||||
FIRApp *firApp = [RNFirebaseUtil getApp:appDisplayName];
|
||||
FIRAuthCredential *credential = [self getCredentialForProvider:provider token:authToken secret:authSecret];
|
||||
|
||||
|
||||
if (credential == nil) {
|
||||
return reject(@"auth/invalid-credential", @"The supplied auth credential is malformed, has expired or is not currently supported.", nil);
|
||||
}
|
||||
|
||||
|
||||
FIRUser *user = [FIRAuth authWithApp:firApp].currentUser;
|
||||
if (user) {
|
||||
[user linkAndRetrieveDataWithCredential:credential
|
||||
completion:^(FIRAuthDataResult * _Nullable authResult, NSError * _Nullable error) {
|
||||
if (error) {
|
||||
[self promiseRejectAuthException:reject error:error];
|
||||
} else {
|
||||
[self promiseWithAuthResult:resolve rejecter:reject authResult:authResult];
|
||||
}
|
||||
}];
|
||||
if (error) {
|
||||
[self promiseRejectAuthException:reject error:error];
|
||||
} else if (withData) {
|
||||
[self promiseWithAuthResult:resolve rejecter:reject authResult:authResult];
|
||||
} else {
|
||||
[self promiseWithUser:resolve rejecter:reject user:authResult.user];
|
||||
}
|
||||
}];
|
||||
} else {
|
||||
[self promiseNoUser:resolve rejecter:reject isError:YES];
|
||||
}
|
||||
@@ -946,28 +1002,7 @@ RCT_EXPORT_METHOD(reauthenticateWithCredential:(NSString *) appDisplayName
|
||||
authSecret:(NSString *) authSecret
|
||||
resolver:(RCTPromiseResolveBlock) resolve
|
||||
rejecter:(RCTPromiseRejectBlock) reject) {
|
||||
FIRApp *firApp = [RNFirebaseUtil getApp:appDisplayName];
|
||||
|
||||
FIRAuthCredential *credential = [self getCredentialForProvider:provider token:authToken secret:authSecret];
|
||||
|
||||
if (credential == nil) {
|
||||
return reject(@"auth/invalid-credential", @"The supplied auth credential is malformed, has expired or is not currently supported.", nil);
|
||||
}
|
||||
|
||||
FIRUser *user = [FIRAuth authWithApp:firApp].currentUser;
|
||||
|
||||
if (user) {
|
||||
[user reauthenticateWithCredential:credential completion:^(NSError *_Nullable error) {
|
||||
if (error) {
|
||||
[self promiseRejectAuthException:reject error:error];
|
||||
} else {
|
||||
FIRUser *userAfterAuth = [FIRAuth authWithApp:firApp].currentUser;
|
||||
[self promiseWithUser:resolve rejecter:reject user:userAfterAuth];
|
||||
}
|
||||
}];
|
||||
} else {
|
||||
[self promiseNoUser:resolve rejecter:reject isError:YES];
|
||||
}
|
||||
[self reauthenticateWithCredential:appDisplayName provider:provider authToken:authToken authSecret:authSecret withData:false resolver:resolve rejecter:reject];
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -986,6 +1021,16 @@ RCT_EXPORT_METHOD(reauthenticateAndRetrieveDataWithCredential:(NSString *) appDi
|
||||
authSecret:(NSString *) authSecret
|
||||
resolver:(RCTPromiseResolveBlock) resolve
|
||||
rejecter:(RCTPromiseRejectBlock) reject) {
|
||||
[self reauthenticateWithCredential:appDisplayName provider:provider authToken:authToken authSecret:authSecret withData:true resolver:resolve rejecter:reject];
|
||||
}
|
||||
|
||||
-(void)reauthenticateWithCredential:(NSString *) appDisplayName
|
||||
provider:(NSString *) provider
|
||||
authToken:(NSString *) authToken
|
||||
authSecret:(NSString *) authSecret
|
||||
withData:(BOOL) withData
|
||||
resolver:(RCTPromiseResolveBlock) resolve
|
||||
rejecter:(RCTPromiseRejectBlock) reject {
|
||||
FIRApp *firApp = [RNFirebaseUtil getApp:appDisplayName];
|
||||
|
||||
FIRAuthCredential *credential = [self getCredentialForProvider:provider token:authToken secret:authSecret];
|
||||
@@ -1000,8 +1045,10 @@ RCT_EXPORT_METHOD(reauthenticateAndRetrieveDataWithCredential:(NSString *) appDi
|
||||
[user reauthenticateAndRetrieveDataWithCredential:credential completion:^(FIRAuthDataResult * _Nullable authResult, NSError * _Nullable error) {
|
||||
if (error) {
|
||||
[self promiseRejectAuthException:reject error:error];
|
||||
} else {
|
||||
} else if (withData) {
|
||||
[self promiseWithAuthResult:resolve rejecter:reject authResult:authResult];
|
||||
} else {
|
||||
[self promiseWithUser:resolve rejecter:reject user:authResult.user];
|
||||
}
|
||||
}];
|
||||
} else {
|
||||
@@ -1010,14 +1057,14 @@ RCT_EXPORT_METHOD(reauthenticateAndRetrieveDataWithCredential:(NSString *) appDi
|
||||
}
|
||||
|
||||
/**
|
||||
fetchProvidersForEmail
|
||||
fetchSignInMethodsForEmail
|
||||
|
||||
@param NSString email
|
||||
@param RCTPromiseResolveBlock resolve
|
||||
@param RCTPromiseRejectBlock reject
|
||||
@return
|
||||
*/
|
||||
RCT_EXPORT_METHOD(fetchProvidersForEmail:
|
||||
RCT_EXPORT_METHOD(fetchSignInMethodsForEmail:
|
||||
(NSString *) appDisplayName
|
||||
email:
|
||||
(NSString *) email
|
||||
@@ -1027,7 +1074,7 @@ RCT_EXPORT_METHOD(fetchProvidersForEmail:
|
||||
(RCTPromiseRejectBlock) reject) {
|
||||
FIRApp *firApp = [RNFirebaseUtil getApp:appDisplayName];
|
||||
|
||||
[[FIRAuth authWithApp:firApp] fetchProvidersForEmail:email completion:^(NSArray<NSString *> *_Nullable providers, NSError *_Nullable error) {
|
||||
[[FIRAuth authWithApp:firApp] fetchSignInMethodsForEmail:email completion:^(NSArray<NSString *> *_Nullable providers, NSError *_Nullable error) {
|
||||
if (error) {
|
||||
[self promiseRejectAuthException:reject error:error];
|
||||
} else if (!providers) {
|
||||
@@ -1058,6 +1105,8 @@ RCT_EXPORT_METHOD(fetchProvidersForEmail:
|
||||
credential = [FIRGoogleAuthProvider credentialWithIDToken:authToken accessToken:authTokenSecret];
|
||||
} else if ([provider compare:@"password" options:NSCaseInsensitiveSearch] == NSOrderedSame) {
|
||||
credential = [FIREmailAuthProvider credentialWithEmail:authToken password:authTokenSecret];
|
||||
} else if ([provider compare:@"emailLink" options:NSCaseInsensitiveSearch] == NSOrderedSame) {
|
||||
credential = [FIREmailAuthProvider credentialWithEmail:authToken link:authTokenSecret];
|
||||
} else if ([provider compare:@"github.com" options:NSCaseInsensitiveSearch] == NSOrderedSame) {
|
||||
credential = [FIRGitHubAuthProvider credentialWithToken:authToken];
|
||||
} else if ([provider compare:@"phone" options:NSCaseInsensitiveSearch] == NSOrderedSame) {
|
||||
|
||||
@@ -10,14 +10,17 @@
|
||||
@implementation RNFirebaseDatabase
|
||||
RCT_EXPORT_MODULE();
|
||||
|
||||
// TODO document methods
|
||||
// Run on a different thread
|
||||
- (dispatch_queue_t)methodQueue {
|
||||
return dispatch_queue_create("io.invertase.react-native-firebase.database", DISPATCH_QUEUE_SERIAL);
|
||||
}
|
||||
|
||||
- (id)init {
|
||||
self = [super init];
|
||||
if (self != nil) {
|
||||
_dbReferences = [[NSMutableDictionary alloc] init];
|
||||
_transactions = [[NSMutableDictionary alloc] init];
|
||||
_transactionQueue = dispatch_queue_create("io.invertase.react-native-firebase", DISPATCH_QUEUE_CONCURRENT);
|
||||
_transactionQueue = dispatch_queue_create("io.invertase.react-native-firebase.database.transactions", DISPATCH_QUEUE_CONCURRENT);
|
||||
}
|
||||
return self;
|
||||
}
|
||||
@@ -446,7 +449,3 @@ RCT_EXPORT_METHOD(off:(NSString *)key
|
||||
@implementation RNFirebaseDatabase
|
||||
@end
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
#define RNFirebaseCrashlytics_h
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
#if __has_include(<Crashlytics/Crashlytics.h>)
|
||||
#if __has_include(<Crashlytics/Crashlytics/Crashlytics.h>)
|
||||
#import <React/RCTBridgeModule.h>
|
||||
|
||||
@interface RNFirebaseCrashlytics : NSObject <RCTBridgeModule> {
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#import "RNFirebaseCrashlytics.h"
|
||||
|
||||
#if __has_include(<Crashlytics/Crashlytics.h>)
|
||||
#import <Crashlytics/Crashlytics.h>
|
||||
#if __has_include(<Crashlytics/Crashlytics/Crashlytics.h>)
|
||||
#import <Crashlytics/Crashlytics/Crashlytics.h>
|
||||
|
||||
@implementation RNFirebaseCrashlytics
|
||||
RCT_EXPORT_MODULE();
|
||||
|
||||
@@ -10,11 +10,23 @@
|
||||
@implementation RNFirebaseFirestore
|
||||
RCT_EXPORT_MODULE();
|
||||
|
||||
static dispatch_queue_t firestoreQueue;
|
||||
static NSMutableDictionary* initialisedApps;
|
||||
|
||||
// Run on a different thread
|
||||
- (dispatch_queue_t)methodQueue {
|
||||
if (!firestoreQueue) {
|
||||
firestoreQueue = dispatch_queue_create("io.invertase.react-native-firebase.firestore", DISPATCH_QUEUE_SERIAL);
|
||||
}
|
||||
return firestoreQueue;
|
||||
}
|
||||
|
||||
- (id)init {
|
||||
self = [super init];
|
||||
if (self != nil) {
|
||||
initialisedApps = [[NSMutableDictionary alloc] init];
|
||||
_transactions = [[NSMutableDictionary alloc] init];
|
||||
_transactionQueue = dispatch_queue_create("io.invertase.react-native-firebase.firestore", DISPATCH_QUEUE_CONCURRENT);
|
||||
_transactionQueue = dispatch_queue_create("io.invertase.react-native-firebase.firestore.transactions", DISPATCH_QUEUE_CONCURRENT);
|
||||
}
|
||||
return self;
|
||||
}
|
||||
@@ -152,7 +164,7 @@ RCT_EXPORT_METHOD(transactionBegin:(NSString *)appDisplayName
|
||||
} else if ([type isEqualToString:@"set"]) {
|
||||
NSDictionary *options = command[@"options"];
|
||||
if (options && options[@"merge"]) {
|
||||
[transaction setData:data forDocument:ref options:[FIRSetOptions merge]];
|
||||
[transaction setData:data forDocument:ref merge:true];
|
||||
} else {
|
||||
[transaction setData:data forDocument:ref];
|
||||
}
|
||||
@@ -224,9 +236,10 @@ RCT_EXPORT_METHOD(collectionGet:(NSString *)appDisplayName
|
||||
filters:(NSArray *)filters
|
||||
orders:(NSArray *)orders
|
||||
options:(NSDictionary *)options
|
||||
getOptions:(NSDictionary *)getOptions
|
||||
resolver:(RCTPromiseResolveBlock)resolve
|
||||
rejecter:(RCTPromiseRejectBlock)reject) {
|
||||
[[self getCollectionForAppPath:appDisplayName path:path filters:filters orders:orders options:options] get:resolve rejecter:reject];
|
||||
[[self getCollectionForAppPath:appDisplayName path:path filters:filters orders:orders options:options] get:getOptions resolver:resolve rejecter:reject];
|
||||
}
|
||||
|
||||
RCT_EXPORT_METHOD(collectionOffSnapshot:(NSString *)appDisplayName
|
||||
@@ -268,7 +281,7 @@ RCT_EXPORT_METHOD(documentBatch:(NSString *)appDisplayName
|
||||
} else if ([type isEqualToString:@"SET"]) {
|
||||
NSDictionary *options = write[@"options"];
|
||||
if (options && options[@"merge"]) {
|
||||
batch = [batch setData:data forDocument:ref options:[FIRSetOptions merge]];
|
||||
batch = [batch setData:data forDocument:ref merge:true];
|
||||
} else {
|
||||
batch = [batch setData:data forDocument:ref];
|
||||
}
|
||||
@@ -295,16 +308,10 @@ RCT_EXPORT_METHOD(documentDelete:(NSString *)appDisplayName
|
||||
|
||||
RCT_EXPORT_METHOD(documentGet:(NSString *)appDisplayName
|
||||
path:(NSString *)path
|
||||
getOptions:(NSDictionary *)getOptions
|
||||
resolver:(RCTPromiseResolveBlock)resolve
|
||||
rejecter:(RCTPromiseRejectBlock)reject) {
|
||||
[[self getDocumentForAppPath:appDisplayName path:path] get:resolve rejecter:reject];
|
||||
}
|
||||
|
||||
RCT_EXPORT_METHOD(documentGetAll:(NSString *)appDisplayName
|
||||
documents:(NSString *)documents
|
||||
resolver:(RCTPromiseResolveBlock)resolve
|
||||
rejecter:(RCTPromiseRejectBlock)reject) {
|
||||
// Not supported on iOS out of the box
|
||||
[[self getDocumentForAppPath:appDisplayName path:path] get:getOptions resolver:resolve rejecter:reject];
|
||||
}
|
||||
|
||||
RCT_EXPORT_METHOD(documentOffSnapshot:(NSString *)appDisplayName
|
||||
@@ -344,19 +351,31 @@ RCT_EXPORT_METHOD(settings:(NSString *)appDisplayName
|
||||
rejecter:(RCTPromiseRejectBlock)reject) {
|
||||
FIRFirestore *firestore = [RNFirebaseFirestore getFirestoreForApp:appDisplayName];
|
||||
FIRFirestoreSettings *firestoreSettings = [[FIRFirestoreSettings alloc] init];
|
||||
|
||||
// Make sure the dispatch queue is set correctly
|
||||
firestoreSettings.dispatchQueue = firestoreQueue;
|
||||
|
||||
// Apply the settings passed by the user, or ensure that the current settings are preserved
|
||||
if (settings[@"host"]) {
|
||||
firestoreSettings.host = settings[@"host"];
|
||||
} else {
|
||||
firestoreSettings.host = firestore.settings.host;
|
||||
}
|
||||
if (settings[@"persistence"]) {
|
||||
firestoreSettings.persistenceEnabled = settings[@"persistence"];
|
||||
} else {
|
||||
firestoreSettings.persistenceEnabled = firestore.settings.persistenceEnabled;
|
||||
}
|
||||
if (settings[@"ssl"]) {
|
||||
firestoreSettings.sslEnabled = settings[@"ssl"];
|
||||
} else {
|
||||
firestoreSettings.sslEnabled = firestore.settings.sslEnabled;
|
||||
}
|
||||
if (settings[@"timestampsInSnapshots"]) {
|
||||
// TODO: Enable when available on Android
|
||||
// firestoreSettings.timestampsInSnapshotsEnabled = settings[@"timestampsInSnapshots"];
|
||||
}
|
||||
|
||||
[firestore setSettings:firestoreSettings];
|
||||
resolve(nil);
|
||||
}
|
||||
@@ -371,7 +390,17 @@ RCT_EXPORT_METHOD(settings:(NSString *)appDisplayName
|
||||
|
||||
+ (FIRFirestore *)getFirestoreForApp:(NSString *)appDisplayName {
|
||||
FIRApp *app = [RNFirebaseUtil getApp:appDisplayName];
|
||||
return [FIRFirestore firestoreForApp:app];
|
||||
FIRFirestore *firestore = [FIRFirestore firestoreForApp:app];
|
||||
|
||||
// This is the first time we've tried to do something on this Firestore instance
|
||||
// So we need to make sure the dispatch queue is set correctly
|
||||
if (!initialisedApps[appDisplayName]) {
|
||||
initialisedApps[appDisplayName] = @(true);
|
||||
FIRFirestoreSettings *firestoreSettings = [[FIRFirestoreSettings alloc] init];
|
||||
firestoreSettings.dispatchQueue = firestoreQueue;
|
||||
[firestore setSettings:firestoreSettings];
|
||||
}
|
||||
return firestore;
|
||||
}
|
||||
|
||||
- (RNFirebaseFirestoreCollectionReference *)getCollectionForAppPath:(NSString *)appDisplayName path:(NSString *)path filters:(NSArray *)filters orders:(NSArray *)orders options:(NSDictionary *)options {
|
||||
@@ -495,4 +524,3 @@ RCT_EXPORT_METHOD(settings:(NSString *)appDisplayName
|
||||
@implementation RNFirebaseFirestore
|
||||
@end
|
||||
#endif
|
||||
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
@property FIRQuery *query;
|
||||
|
||||
- (id)initWithPathAndModifiers:(RCTEventEmitter *)emitter appDisplayName:(NSString *)appDisplayName path:(NSString *)path filters:(NSArray *)filters orders:(NSArray *)orders options:(NSDictionary *)options;
|
||||
- (void)get:(RCTPromiseResolveBlock) resolve rejecter:(RCTPromiseRejectBlock) reject;
|
||||
- (void)get:(NSDictionary *)getOptions resolver:(RCTPromiseResolveBlock) resolve rejecter:(RCTPromiseRejectBlock) reject;
|
||||
+ (void)offSnapshot:(NSString *)listenerId;
|
||||
- (void)onSnapshot:(NSString *)listenerId queryListenOptions:(NSDictionary *) queryListenOptions;
|
||||
+ (NSDictionary *)snapshotToDictionary:(FIRQuerySnapshot *)querySnapshot;
|
||||
|
||||
@@ -29,9 +29,22 @@ static NSMutableDictionary *_listeners;
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)get:(RCTPromiseResolveBlock) resolve
|
||||
- (void)get:(NSDictionary *) getOptions
|
||||
resolver:(RCTPromiseResolveBlock) resolve
|
||||
rejecter:(RCTPromiseRejectBlock) reject {
|
||||
[_query getDocumentsWithCompletion:^(FIRQuerySnapshot * _Nullable snapshot, NSError * _Nullable error) {
|
||||
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;
|
||||
}
|
||||
[_query getDocumentsWithSource:source completion:^(FIRQuerySnapshot * _Nullable snapshot, NSError * _Nullable error) {
|
||||
if (error) {
|
||||
[RNFirebaseFirestore promiseRejectException:reject error:error];
|
||||
} else {
|
||||
@@ -65,17 +78,14 @@ queryListenOptions:(NSDictionary *) queryListenOptions {
|
||||
}
|
||||
};
|
||||
|
||||
FIRQueryListenOptions *options = [[FIRQueryListenOptions alloc] init];
|
||||
if (queryListenOptions) {
|
||||
if (queryListenOptions[@"includeDocumentMetadataChanges"]) {
|
||||
[options includeDocumentMetadataChanges:TRUE];
|
||||
}
|
||||
if (queryListenOptions[@"includeQueryMetadataChanges"]) {
|
||||
[options includeQueryMetadataChanges:TRUE];
|
||||
}
|
||||
bool includeMetadataChanges;
|
||||
if (queryListenOptions && queryListenOptions[@"includeMetadataChanges"]) {
|
||||
includeMetadataChanges = true;
|
||||
} else {
|
||||
includeMetadataChanges = false;
|
||||
}
|
||||
|
||||
id<FIRListenerRegistration> listener = [_query addSnapshotListenerWithOptions:options listener:listenerBlock];
|
||||
id<FIRListenerRegistration> listener = [_query addSnapshotListenerWithIncludeMetadataChanges:includeMetadataChanges listener:listenerBlock];
|
||||
_listeners[listenerId] = listener;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
|
||||
- (id)initWithPath:(RCTEventEmitter *)emitter appDisplayName:(NSString *)appDisplayName path:(NSString *)path;
|
||||
- (void)delete:(RCTPromiseResolveBlock) resolve rejecter:(RCTPromiseRejectBlock) reject;
|
||||
- (void)get:(RCTPromiseResolveBlock) resolve rejecter:(RCTPromiseRejectBlock) reject;
|
||||
- (void)get:(NSDictionary *)getOptions resolver:(RCTPromiseResolveBlock) resolve rejecter:(RCTPromiseRejectBlock) reject;
|
||||
+ (void)offSnapshot:(NSString *)listenerId;
|
||||
- (void)onSnapshot:(NSString *)listenerId docListenOptions:(NSDictionary *) docListenOptions;
|
||||
- (void)set:(NSDictionary *)data options:(NSDictionary *)options resolver:(RCTPromiseResolveBlock) resolve rejecter:(RCTPromiseRejectBlock) reject;
|
||||
|
||||
@@ -30,9 +30,22 @@ static NSMutableDictionary *_listeners;
|
||||
}];
|
||||
}
|
||||
|
||||
- (void)get:(RCTPromiseResolveBlock) resolve
|
||||
- (void)get:(NSDictionary *) getOptions
|
||||
resolver:(RCTPromiseResolveBlock) resolve
|
||||
rejecter:(RCTPromiseRejectBlock) reject {
|
||||
[_ref getDocumentWithCompletion:^(FIRDocumentSnapshot * _Nullable snapshot, NSError * _Nullable error) {
|
||||
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;
|
||||
}
|
||||
[_ref getDocumentWithSource:source completion:^(FIRDocumentSnapshot * _Nullable snapshot, NSError * _Nullable error) {
|
||||
if (error) {
|
||||
[RNFirebaseFirestore promiseRejectException:reject error:error];
|
||||
} else {
|
||||
@@ -65,11 +78,13 @@ static NSMutableDictionary *_listeners;
|
||||
[self handleDocumentSnapshotEvent:listenerId documentSnapshot:snapshot];
|
||||
}
|
||||
};
|
||||
FIRDocumentListenOptions *options = [[FIRDocumentListenOptions alloc] init];
|
||||
bool includeMetadataChanges;
|
||||
if (docListenOptions && docListenOptions[@"includeMetadataChanges"]) {
|
||||
[options includeMetadataChanges:TRUE];
|
||||
includeMetadataChanges = true;
|
||||
} else {
|
||||
includeMetadataChanges = false;
|
||||
}
|
||||
id<FIRListenerRegistration> listener = [_ref addSnapshotListenerWithOptions:options listener:listenerBlock];
|
||||
id<FIRListenerRegistration> listener = [_ref addSnapshotListenerWithIncludeMetadataChanges:includeMetadataChanges listener:listenerBlock];
|
||||
_listeners[listenerId] = listener;
|
||||
}
|
||||
}
|
||||
@@ -80,7 +95,7 @@ static NSMutableDictionary *_listeners;
|
||||
rejecter:(RCTPromiseRejectBlock) reject {
|
||||
NSDictionary *dictionary = [RNFirebaseFirestoreDocumentReference parseJSMap:[RNFirebaseFirestore getFirestoreForApp:_appDisplayName] jsMap:data];
|
||||
if (options && options[@"merge"]) {
|
||||
[_ref setData:dictionary options:[FIRSetOptions merge] completion:^(NSError * _Nullable error) {
|
||||
[_ref setData:dictionary merge:true completion:^(NSError * _Nullable error) {
|
||||
[RNFirebaseFirestoreDocumentReference handleWriteResponse:error resolver:resolve rejecter:reject];
|
||||
}];
|
||||
} else {
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
#import "RNFirebaseInstanceId.h"
|
||||
|
||||
#if __has_include(<FirebaseInstanceID/FIRInstanceID.h>)
|
||||
//#import <FirebaseMessaging/FirebaseMessaging.h>
|
||||
#import <FirebaseInstanceID/FIRInstanceID.h>
|
||||
|
||||
@implementation RNFirebaseInstanceId
|
||||
@@ -26,6 +27,36 @@ RCT_EXPORT_METHOD(get:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseReject
|
||||
}];
|
||||
}
|
||||
|
||||
RCT_EXPORT_METHOD(getToken:(NSString *)authorizedEntity
|
||||
scope:(NSString *)scope
|
||||
resolver:(RCTPromiseResolveBlock)resolve
|
||||
rejecter:(RCTPromiseRejectBlock)reject) {
|
||||
NSDictionary * options = nil;
|
||||
// if ([FIRMessaging messaging].APNSToken) {
|
||||
// options = @{@"apns_token": [FIRMessaging messaging].APNSToken};
|
||||
// }
|
||||
[[FIRInstanceID instanceID] tokenWithAuthorizedEntity:authorizedEntity scope:scope options:options handler:^(NSString * _Nullable identity, NSError * _Nullable error) {
|
||||
if (error) {
|
||||
reject(@"instance_id_error", @"Failed to getToken", error);
|
||||
} else {
|
||||
resolve(identity);
|
||||
}
|
||||
}];
|
||||
}
|
||||
|
||||
RCT_EXPORT_METHOD(deleteToken:(NSString *)authorizedEntity
|
||||
scope:(NSString *)scope
|
||||
resolver:(RCTPromiseResolveBlock)resolve
|
||||
rejecter:(RCTPromiseRejectBlock)reject) {
|
||||
[[FIRInstanceID instanceID] deleteTokenWithAuthorizedEntity:authorizedEntity scope:scope handler:^(NSError * _Nullable error) {
|
||||
if (error) {
|
||||
reject(@"instance_id_error", @"Failed to deleteToken", error);
|
||||
} else {
|
||||
resolve(nil);
|
||||
}
|
||||
}];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
#else
|
||||
|
||||
@@ -60,11 +60,11 @@ continueUserActivity:(NSUserActivity *)userActivity
|
||||
return [[FIRDynamicLinks dynamicLinks]
|
||||
handleUniversalLink:userActivity.webpageURL
|
||||
completion:^(FIRDynamicLink * _Nullable dynamicLink, NSError * _Nullable error) {
|
||||
if (error != nil){
|
||||
NSLog(@"Failed to handle universal link: %@", [error localizedDescription]);
|
||||
} else {
|
||||
NSURL* url = dynamicLink ? dynamicLink.url : userActivity.webpageURL;
|
||||
if (dynamicLink && dynamicLink.url && error == nil) {
|
||||
NSURL* url = dynamicLink.url;
|
||||
[self sendJSEvent:self name:LINKS_LINK_RECEIVED body:url.absoluteString];
|
||||
} else {
|
||||
NSLog(@"Failed to handle universal link: %@", userActivity.webpageURL);
|
||||
}
|
||||
}];
|
||||
}
|
||||
|
||||
@@ -20,6 +20,7 @@
|
||||
static RNFirebaseMessaging *theRNFirebaseMessaging = nil;
|
||||
static bool jsReady = FALSE;
|
||||
static NSString* initialToken = nil;
|
||||
static NSMutableArray* pendingMessages = nil;
|
||||
|
||||
+ (nonnull instancetype)instance {
|
||||
return theRNFirebaseMessaging;
|
||||
@@ -197,6 +198,12 @@ RCT_EXPORT_METHOD(jsInitialised:(RCTPromiseResolveBlock)resolve rejecter:(RCTPro
|
||||
if (initialToken) {
|
||||
[self sendJSEvent:self name:MESSAGING_TOKEN_REFRESHED body:initialToken];
|
||||
}
|
||||
if (pendingMessages) {
|
||||
for (id message in pendingMessages) {
|
||||
[RNFirebaseUtil sendJSEvent:self name:MESSAGING_MESSAGE_RECEIVED body:message];
|
||||
}
|
||||
pendingMessages = nil;
|
||||
}
|
||||
}
|
||||
|
||||
// ** Start internals **
|
||||
@@ -209,9 +216,13 @@ RCT_EXPORT_METHOD(jsInitialised:(RCTPromiseResolveBlock)resolve rejecter:(RCTPro
|
||||
} else {
|
||||
if ([name isEqualToString:MESSAGING_TOKEN_REFRESHED]) {
|
||||
initialToken = body;
|
||||
} else if ([name isEqualToString:MESSAGING_MESSAGE_RECEIVED]) {
|
||||
if (!pendingMessages) {
|
||||
pendingMessages = [[NSMutableArray alloc] init];
|
||||
}
|
||||
[pendingMessages addObject:body];
|
||||
} else {
|
||||
// TODO: Is this even possible?
|
||||
NSLog(@"Received Remote Message before the bridge is ready");
|
||||
NSLog(@"Received unexpected message type");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
#import <MobileCoreServices/MobileCoreServices.h>
|
||||
#import <Photos/Photos.h>
|
||||
#import <Firebase.h>
|
||||
#import <React/RCTUtils.h>
|
||||
|
||||
@implementation RNFirebaseStorage
|
||||
|
||||
@@ -14,7 +15,7 @@ RCT_EXPORT_MODULE(RNFirebaseStorage);
|
||||
|
||||
// Run on a different thread
|
||||
- (dispatch_queue_t)methodQueue {
|
||||
return dispatch_queue_create("com.invertase.firebase.storage", DISPATCH_QUEUE_SERIAL);
|
||||
return dispatch_queue_create("io.invertase.react-native-firebase.storage", DISPATCH_QUEUE_SERIAL);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -118,7 +119,11 @@ RCT_EXPORT_METHOD(downloadFile:(NSString *) appDisplayName
|
||||
rejecter:(RCTPromiseRejectBlock) reject) {
|
||||
FIRStorageReference *fileRef = [self getReference:path appDisplayName:appDisplayName];
|
||||
NSURL *localFile = [NSURL fileURLWithPath:localPath];
|
||||
FIRStorageDownloadTask *downloadTask = [fileRef writeToFile:localFile];
|
||||
|
||||
__block FIRStorageDownloadTask *downloadTask;
|
||||
RCTUnsafeExecuteOnMainQueueSync(^{
|
||||
downloadTask = [fileRef writeToFile:localFile];
|
||||
});
|
||||
|
||||
// listen for state changes, errors, and completion of the download.
|
||||
[downloadTask observeStatus:FIRStorageTaskStatusResume handler:^(FIRStorageTaskSnapshot *snapshot) {
|
||||
@@ -205,9 +210,10 @@ RCT_EXPORT_METHOD(putFile:(NSString *) appDisplayName
|
||||
resolver:(RCTPromiseResolveBlock) resolve
|
||||
rejecter:(RCTPromiseRejectBlock) reject) {
|
||||
FIRStorageMetadata *firmetadata = [self buildMetadataFromMap:metadata];
|
||||
|
||||
if ([localPath hasPrefix:@"assets-library://"] || [localPath hasPrefix:@"ph://"]) {
|
||||
PHFetchResult *assets;
|
||||
|
||||
|
||||
if ([localPath hasPrefix:@"assets-library://"]) {
|
||||
NSURL *localFile = [[NSURL alloc] initWithString:localPath];
|
||||
assets = [PHAsset fetchAssetsWithALAssetURLs:@[localFile] options:nil];
|
||||
@@ -215,9 +221,9 @@ RCT_EXPORT_METHOD(putFile:(NSString *) appDisplayName
|
||||
NSString *assetId = [localPath substringFromIndex:@"ph://".length];
|
||||
assets = [PHAsset fetchAssetsWithLocalIdentifiers:@[assetId] options:nil];
|
||||
}
|
||||
|
||||
|
||||
PHAsset *asset = [assets firstObject];
|
||||
|
||||
|
||||
// this is based on http://stackoverflow.com/questions/35241449
|
||||
if (asset.mediaType == PHAssetMediaTypeImage) {
|
||||
// images
|
||||
@@ -253,18 +259,18 @@ RCT_EXPORT_METHOD(putFile:(NSString *) appDisplayName
|
||||
if (info[PHImageErrorKey] == nil) {
|
||||
NSURL *tempUrl = [self temporaryFileUrl];
|
||||
exportSession.outputURL = tempUrl;
|
||||
|
||||
|
||||
NSArray<PHAssetResource *> *resources = [PHAssetResource assetResourcesForAsset:asset];
|
||||
for (PHAssetResource *resource in resources) {
|
||||
exportSession.outputFileType = resource.uniformTypeIdentifier;
|
||||
if (exportSession.outputFileType != nil) break;
|
||||
}
|
||||
|
||||
|
||||
[exportSession exportAsynchronouslyWithCompletionHandler:^{
|
||||
if (exportSession.status == AVAssetExportSessionStatusCompleted) {
|
||||
firmetadata.contentType = [self utiToMimeType:exportSession.outputFileType];
|
||||
[self uploadFile:appDisplayName url:tempUrl firmetadata:firmetadata path:path resolver:resolve rejecter:reject];
|
||||
// we're not cleaning up the temporary file at the moment, just relying on the OS to do that in it's own time - todo?
|
||||
// TODO we're not cleaning up the temporary file at the moment, relying on the OS to do it
|
||||
} else {
|
||||
reject(@"storage/temporary-file-failure", @"Unable to create temporary file for upload.", nil);
|
||||
}
|
||||
@@ -275,11 +281,37 @@ RCT_EXPORT_METHOD(putFile:(NSString *) appDisplayName
|
||||
}];
|
||||
}
|
||||
} else {
|
||||
// TODO: Content type for file?
|
||||
NSData *data = [[NSFileManager defaultManager] contentsAtPath:localPath];
|
||||
if (![[NSFileManager defaultManager] fileExistsAtPath:localPath]) {
|
||||
reject(@"storage/file-not-found", @"File specified at path does not exist.", nil);
|
||||
return;
|
||||
}
|
||||
|
||||
// TODO large files should not go through 'data', should use file directly
|
||||
// TODO heic conversion not working here UIImageJPEGRepresentation -> returns nil
|
||||
|
||||
// BOOL isHeic = [self isHeic:localPath];
|
||||
NSData *data = [NSData dataWithContentsOfFile:localPath];
|
||||
|
||||
if ([firmetadata valueForKey:@"contentType"] == nil) {
|
||||
firmetadata.contentType = [self mimeTypeForPath:localPath];
|
||||
}
|
||||
|
||||
// if (isHeic) {
|
||||
// UIImage *image = [UIImage imageWithData: data];
|
||||
// data = UIImageJPEGRepresentation(image, 1);
|
||||
// firmetadata.contentType = @"image/jpeg";
|
||||
// }
|
||||
|
||||
[self uploadData:appDisplayName data:data firmetadata:firmetadata path:path resolver:resolve rejecter:reject];
|
||||
}
|
||||
}
|
||||
|
||||
-(BOOL) isHeic: (NSString*) path {
|
||||
return [[path pathExtension] caseInsensitiveCompare:@"heic"] == NSOrderedSame;
|
||||
}
|
||||
|
||||
- (NSString *)utiToMimeType:(NSString *) dataUTI {
|
||||
return (__bridge_transfer NSString *)UTTypeCopyPreferredTagWithClass((__bridge CFStringRef)dataUTI, kUTTagClassMIMEType);
|
||||
}
|
||||
|
||||
- (NSURL *)temporaryFileUrl {
|
||||
@@ -287,19 +319,33 @@ RCT_EXPORT_METHOD(putFile:(NSString *) appDisplayName
|
||||
return [[NSURL fileURLWithPath:NSTemporaryDirectory()] URLByAppendingPathComponent:filename];
|
||||
}
|
||||
|
||||
- (NSString *)utiToMimeType:(NSString *) dataUTI {
|
||||
return (__bridge_transfer NSString *)UTTypeCopyPreferredTagWithClass((__bridge CFStringRef)dataUTI, kUTTagClassMIMEType);
|
||||
- (NSString*) mimeTypeForPath: (NSString *) path {
|
||||
CFStringRef UTI = UTTypeCreatePreferredIdentifierForTag(kUTTagClassFilenameExtension, (__bridge CFStringRef)[path pathExtension], NULL);
|
||||
CFStringRef mimeType = UTTypeCopyPreferredTagWithClass (UTI, kUTTagClassMIMEType);
|
||||
CFRelease(UTI);
|
||||
|
||||
if (!mimeType) {
|
||||
return @"application/octet-stream";
|
||||
}
|
||||
|
||||
return (__bridge_transfer NSString *) mimeType;
|
||||
}
|
||||
|
||||
- (void)uploadFile:(NSString *)appDisplayName url:(NSURL *)url firmetadata:(FIRStorageMetadata *)firmetadata path:(NSString *)path resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject {
|
||||
FIRStorageReference *fileRef = [self getReference:path appDisplayName:appDisplayName];
|
||||
FIRStorageUploadTask *uploadTask = [fileRef putFile:url metadata:firmetadata];
|
||||
__block FIRStorageUploadTask *uploadTask;
|
||||
RCTUnsafeExecuteOnMainQueueSync(^{
|
||||
uploadTask = [fileRef putFile:url metadata:firmetadata];
|
||||
});
|
||||
[self addUploadObservers:appDisplayName uploadTask:uploadTask path:path resolver:resolve rejecter:reject];
|
||||
}
|
||||
|
||||
- (void)uploadData:(NSString *)appDisplayName data:(NSData *)data firmetadata:(FIRStorageMetadata *)firmetadata path:(NSString *)path resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject {
|
||||
FIRStorageReference *fileRef = [self getReference:path appDisplayName:appDisplayName];
|
||||
FIRStorageUploadTask *uploadTask = [fileRef putData:data metadata:firmetadata];
|
||||
__block FIRStorageUploadTask *uploadTask;
|
||||
RCTUnsafeExecuteOnMainQueueSync(^{
|
||||
uploadTask = [fileRef putData:data metadata:firmetadata];
|
||||
});
|
||||
[self addUploadObservers:appDisplayName uploadTask:uploadTask path:path resolver:resolve rejecter:reject];
|
||||
}
|
||||
|
||||
@@ -307,27 +353,31 @@ RCT_EXPORT_METHOD(putFile:(NSString *) appDisplayName
|
||||
// listen for state changes, errors, and completion of the upload.
|
||||
[uploadTask observeStatus:FIRStorageTaskStatusResume handler:^(FIRStorageTaskSnapshot *snapshot) {
|
||||
// upload resumed, also fires when the upload starts
|
||||
NSDictionary *event = [self getUploadTaskAsDictionary:snapshot];
|
||||
[self sendJSEvent:appDisplayName type:STORAGE_EVENT path:path title:STORAGE_STATE_CHANGED props:event];
|
||||
[self getUploadTaskAsDictionary:snapshot handler:^(NSDictionary *event) {
|
||||
[self sendJSEvent:appDisplayName type:STORAGE_EVENT path:path title:STORAGE_STATE_CHANGED props:event];
|
||||
}];
|
||||
}];
|
||||
|
||||
[uploadTask observeStatus:FIRStorageTaskStatusPause handler:^(FIRStorageTaskSnapshot *snapshot) {
|
||||
// upload paused
|
||||
NSDictionary *event = [self getUploadTaskAsDictionary:snapshot];
|
||||
[self sendJSEvent:appDisplayName type:STORAGE_EVENT path:path title:STORAGE_STATE_CHANGED props:event];
|
||||
[self getUploadTaskAsDictionary:snapshot handler:^(NSDictionary *event) {
|
||||
[self sendJSEvent:appDisplayName type:STORAGE_EVENT path:path title:STORAGE_STATE_CHANGED props:event];
|
||||
}];
|
||||
}];
|
||||
[uploadTask observeStatus:FIRStorageTaskStatusProgress handler:^(FIRStorageTaskSnapshot *snapshot) {
|
||||
// upload reported progress
|
||||
NSDictionary *event = [self getUploadTaskAsDictionary:snapshot];
|
||||
[self sendJSEvent:appDisplayName type:STORAGE_EVENT path:path title:STORAGE_STATE_CHANGED props:event];
|
||||
[self getUploadTaskAsDictionary:snapshot handler:^(NSDictionary *event) {
|
||||
[self sendJSEvent:appDisplayName type:STORAGE_EVENT path:path title:STORAGE_STATE_CHANGED props:event];
|
||||
}];
|
||||
}];
|
||||
|
||||
[uploadTask observeStatus:FIRStorageTaskStatusSuccess handler:^(FIRStorageTaskSnapshot *snapshot) {
|
||||
// upload completed successfully
|
||||
NSDictionary *resp = [self getUploadTaskAsDictionary:snapshot];
|
||||
[self sendJSEvent:appDisplayName type:STORAGE_EVENT path:path title:STORAGE_STATE_CHANGED props:resp];
|
||||
[self sendJSEvent:appDisplayName type:STORAGE_EVENT path:path title:STORAGE_UPLOAD_SUCCESS props:resp];
|
||||
resolve(resp);
|
||||
[self getUploadTaskAsDictionary:snapshot handler:^(NSDictionary *event) {
|
||||
[self sendJSEvent:appDisplayName type:STORAGE_EVENT path:path title:STORAGE_STATE_CHANGED props:event];
|
||||
[self sendJSEvent:appDisplayName type:STORAGE_EVENT path:path title:STORAGE_UPLOAD_SUCCESS props:event];
|
||||
resolve(event);
|
||||
}];
|
||||
}];
|
||||
|
||||
[uploadTask observeStatus:FIRStorageTaskStatusFailure handler:^(FIRStorageTaskSnapshot *snapshot) {
|
||||
@@ -352,10 +402,14 @@ RCT_EXPORT_METHOD(putFile:(NSString *) appDisplayName
|
||||
return @{@"bytesTransferred": @(task.progress.completedUnitCount), @"ref": task.reference.fullPath, @"state": [self getTaskStatus:task.status], @"totalBytes": @(task.progress.totalUnitCount)};
|
||||
}
|
||||
|
||||
- (NSDictionary *)getUploadTaskAsDictionary:(FIRStorageTaskSnapshot *)task {
|
||||
NSString *downloadUrl = [task.metadata.downloadURL absoluteString];
|
||||
NSDictionary *metadata = [task.metadata dictionaryRepresentation];
|
||||
return @{@"bytesTransferred": @(task.progress.completedUnitCount), @"downloadURL": downloadUrl != nil ? downloadUrl : [NSNull null], @"metadata": metadata != nil ? metadata : [NSNull null], @"ref": task.reference.fullPath, @"state": [self getTaskStatus:task.status], @"totalBytes": @(task.progress.totalUnitCount)};
|
||||
- (void)getUploadTaskAsDictionary:(FIRStorageTaskSnapshot *)task
|
||||
handler:(void(^)(NSDictionary *))handler {
|
||||
[[task reference] downloadURLWithCompletion:^(NSURL * _Nullable URL, NSError * _Nullable error) {
|
||||
NSString *downloadUrl = [URL absoluteString];
|
||||
NSDictionary *metadata = [task.metadata dictionaryRepresentation];
|
||||
NSDictionary *dictionary = @{@"bytesTransferred": @(task.progress.completedUnitCount), @"downloadURL": downloadUrl != nil ? downloadUrl : [NSNull null], @"metadata": metadata != nil ? metadata : [NSNull null], @"ref": task.reference.fullPath, @"state": [self getTaskStatus:task.status], @"totalBytes": @(task.progress.totalUnitCount)};
|
||||
handler(dictionary);
|
||||
}];
|
||||
}
|
||||
|
||||
- (FIRStorageMetadata *)buildMetadataFromMap:(NSDictionary *)metadata {
|
||||
|
||||
288
lib/index.d.ts
vendored
288
lib/index.d.ts
vendored
@@ -1,6 +1,6 @@
|
||||
// Type definitions for React Native Firebase v1.0.0-alpha7
|
||||
// Type definitions for React Native Firebase v4.2.0
|
||||
// Project: https://github.com/invertase/react-native-firebase
|
||||
// Definitions by: Tal <https://github.com/taljacobson>
|
||||
// Definitions by: React Native Firebase Contributors
|
||||
// TypeScript Version: 2.1
|
||||
|
||||
declare module 'react-native-firebase' {
|
||||
@@ -25,7 +25,7 @@ declare module 'react-native-firebase' {
|
||||
RNFirebase.auth.Auth,
|
||||
RNFirebase.auth.AuthStatics
|
||||
>;
|
||||
// config: FirebaseModule<RNFirebase.config.Config>;
|
||||
config: FirebaseModuleAndStatics<RNFirebase.config.Config>;
|
||||
crash: FirebaseModuleAndStatics<RNFirebase.crash.Crash>;
|
||||
crashlytics: FirebaseModuleAndStatics<RNFirebase.crashlytics.Crashlytics>;
|
||||
database: FirebaseModuleAndStatics<
|
||||
@@ -36,6 +36,10 @@ declare module 'react-native-firebase' {
|
||||
RNFirebase.firestore.Firestore,
|
||||
RNFirebase.firestore.FirestoreStatics
|
||||
>;
|
||||
functions: FirebaseModuleAndStatics<
|
||||
RNFirebase.functions.Functions,
|
||||
RNFirebase.functions.FunctionsStatics
|
||||
>;
|
||||
iid: FirebaseModuleAndStatics<RNFirebase.iid.InstanceId>;
|
||||
// invites: FirebaseModuleAndStatics<RNFirebase.invites.Invites>
|
||||
links: FirebaseModuleAndStatics<
|
||||
@@ -77,11 +81,12 @@ declare module 'react-native-firebase' {
|
||||
// admob(): RNFirebase.admob.AdMob;
|
||||
analytics(): RNFirebase.Analytics;
|
||||
auth(): RNFirebase.auth.Auth;
|
||||
// config(): RNFirebase.config.Config;
|
||||
config(): RNFirebase.config.Config;
|
||||
crash(): RNFirebase.crash.Crash;
|
||||
crashlytics(): RNFirebase.crashlytics.Crashlytics;
|
||||
database(): RNFirebase.database.Database;
|
||||
firestore(): RNFirebase.firestore.Firestore;
|
||||
functions(): RNFirebase.functions.Functions;
|
||||
iid(): RNFirebase.iid.InstanceId;
|
||||
// invites(): RNFirebase.invites.Invites;
|
||||
links(): RNFirebase.links.Links;
|
||||
@@ -328,7 +333,6 @@ declare module 'react-native-firebase' {
|
||||
|
||||
interface FullMetadata extends storage.UploadMetadata {
|
||||
bucket: string;
|
||||
downloadURLs: string[];
|
||||
fullPath: string;
|
||||
generation: string;
|
||||
metageneration: string;
|
||||
@@ -801,14 +805,14 @@ declare module 'react-native-firebase' {
|
||||
interface PhoneAuthListener {
|
||||
on(
|
||||
event: string,
|
||||
observer: () => PhoneAuthSnapshot,
|
||||
errorCb?: () => PhoneAuthError,
|
||||
successCb?: () => PhoneAuthSnapshot
|
||||
observer: (snapshot: PhoneAuthSnapshot) => void,
|
||||
errorCb?: (error: PhoneAuthError) => void,
|
||||
successCb?: (snapshot: PhoneAuthSnapshot) => void
|
||||
): PhoneAuthListener;
|
||||
|
||||
then(fn: () => PhoneAuthSnapshot): Promise<any>;
|
||||
then(fn: (snapshot: PhoneAuthSnapshot) => void): Promise<any>;
|
||||
|
||||
catch(fn: () => Error): Promise<any>;
|
||||
catch(fn: (error: Error) => void): Promise<any>;
|
||||
}
|
||||
|
||||
namespace auth {
|
||||
@@ -822,6 +826,17 @@ declare module 'react-native-firebase' {
|
||||
credential: (token: string, secret?: string) => AuthCredential;
|
||||
};
|
||||
|
||||
type EmailAuthProvider = {
|
||||
PROVIDER_ID: string;
|
||||
EMAIL_LINK_SIGN_IN_METHOD: string;
|
||||
EMAIL_PASSWORD_SIGN_IN_METHOD: string;
|
||||
credential: (email: string, password: string) => AuthCredential;
|
||||
credentialWithLink: (
|
||||
email: string,
|
||||
emailLink: string
|
||||
) => AuthCredential;
|
||||
};
|
||||
|
||||
interface Auth {
|
||||
readonly app: App;
|
||||
/**
|
||||
@@ -874,6 +889,13 @@ declare module 'react-native-firebase' {
|
||||
password: string
|
||||
): Promise<UserCredential>;
|
||||
|
||||
signInWithEmailLink(
|
||||
email: string,
|
||||
emailLink: string
|
||||
): Promise<UserCredential>;
|
||||
|
||||
isSignInWithEmailLink(emailLink: string): boolean;
|
||||
|
||||
/**
|
||||
* We can create a user by calling the createUserWithEmailAndPassword() function.
|
||||
* The method accepts two parameters, an email and a password.
|
||||
@@ -922,7 +944,7 @@ declare module 'react-native-firebase' {
|
||||
/**
|
||||
* Asynchronously signs in using a phone number.
|
||||
*/
|
||||
signInWithPhoneNumber(phoneNumber: string): Promise<ConfirmationResult>;
|
||||
signInWithPhoneNumber(phoneNumber: string, forceResend?: boolean): Promise<ConfirmationResult>;
|
||||
|
||||
/**
|
||||
* Returns a PhoneAuthListener to listen to phone verification events,
|
||||
@@ -931,7 +953,8 @@ declare module 'react-native-firebase' {
|
||||
*/
|
||||
verifyPhoneNumber(
|
||||
phoneNumber: string,
|
||||
autoVerifyTimeout?: number
|
||||
autoVerifyTimeoutOrForceResend?: number | boolean,
|
||||
forceResend?: boolean,
|
||||
): PhoneAuthListener;
|
||||
|
||||
/**
|
||||
@@ -944,6 +967,11 @@ declare module 'react-native-firebase' {
|
||||
actionCodeSettings?: ActionCodeSettings
|
||||
): Promise<void>;
|
||||
|
||||
sendSignInLinkToEmail(
|
||||
email: string,
|
||||
actionCodeSettings?: ActionCodeSettings
|
||||
): Promise<void>;
|
||||
|
||||
/**
|
||||
* Completes the password reset process, given a confirmation code and new password.
|
||||
*/
|
||||
@@ -970,7 +998,7 @@ declare module 'react-native-firebase' {
|
||||
}
|
||||
|
||||
interface AuthStatics {
|
||||
EmailAuthProvider: AuthProvider;
|
||||
EmailAuthProvider: EmailAuthProvider;
|
||||
PhoneAuthProvider: AuthProvider;
|
||||
GoogleAuthProvider: AuthProvider;
|
||||
GithubAuthProvider: AuthProvider;
|
||||
@@ -1061,6 +1089,8 @@ declare module 'react-native-firebase' {
|
||||
interface InstanceId {
|
||||
delete(): Promise<void>;
|
||||
get(): Promise<string>;
|
||||
getToken(authorizedEntity: string, scope: string): Promise<string>;
|
||||
deleteToken(authorizedEntity: string, scope: string): Promise<void>;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1072,6 +1102,8 @@ declare module 'react-native-firebase' {
|
||||
channelGroups: Android.ChannelGroup[]
|
||||
): Promise<void>;
|
||||
createChannels(channels: Android.Channel[]): Promise<void>;
|
||||
deleteChannelGroup(groupId: string): Promise<void>;
|
||||
deleteChannel(channelId: string): Promise<void>;
|
||||
}
|
||||
|
||||
interface Notifications {
|
||||
@@ -1454,6 +1486,68 @@ declare module 'react-native-firebase' {
|
||||
}
|
||||
}
|
||||
|
||||
namespace config {
|
||||
interface ConfigSnapshot {
|
||||
source: string;
|
||||
val(): any;
|
||||
}
|
||||
|
||||
interface Object<ConfigSnapshot> {
|
||||
[key: string]: ConfigSnapshot;
|
||||
}
|
||||
|
||||
interface Config {
|
||||
/** Enable Remote Config developer mode to allow for frequent refreshes of the cache. */
|
||||
enableDeveloperMode(): void;
|
||||
|
||||
/**
|
||||
* Sets default values for the app to use when accessing values.
|
||||
* Any data fetched and activated will override any default values.
|
||||
* Any values in the defaults but not on Firebase will be untouched.
|
||||
*/
|
||||
setDefaults(defaults: object): void;
|
||||
|
||||
/**
|
||||
* Fetches the remote config data from Firebase, defined in the dashboard.
|
||||
* If duration is defined (seconds), data will be locally cached for this duration.
|
||||
*
|
||||
* The default duration is 43200 seconds (12 hours).
|
||||
* To force a cache refresh call the method with a duration of 0.
|
||||
*/
|
||||
fetch(duration?: number): Promise<string>;
|
||||
|
||||
/**
|
||||
* Fetches the remote config data from Firebase, defined in the dashboard.
|
||||
* The default expiration duration is 43200 seconds (12 hours)
|
||||
*/
|
||||
activateFetched(): Promise<boolean>;
|
||||
|
||||
/**
|
||||
* Gets a config item by key.
|
||||
* Returns a snapshot containing source (default, remote or static) and val function.
|
||||
*/
|
||||
getValue(key: string): Promise<ConfigSnapshot>;
|
||||
|
||||
/**
|
||||
* Gets multiple values by key.
|
||||
* Returns a snapshot object with snapshot keys e.g. snapshots.foo.val().
|
||||
*/
|
||||
getValues(array: Array<string>): Promise<Object<ConfigSnapshot>>;
|
||||
|
||||
/**
|
||||
* Returns all keys as an array by a prefix. If no prefix is defined all keys are returned.
|
||||
*/
|
||||
getKeysByPrefix(prefix?: string): Promise<Array<String>>;
|
||||
|
||||
/**
|
||||
* Sets the default values from a resource:
|
||||
* - Android: Id for the XML resource, which should be in your application's res/xml folder.
|
||||
* - iOS: The plist file name, with no file name extension.
|
||||
*/
|
||||
setDefaultsFromResource(resource: string | number): void;
|
||||
}
|
||||
}
|
||||
|
||||
namespace crash {
|
||||
interface Crash {
|
||||
/** Logs a message that will appear in a subsequent crash report. */
|
||||
@@ -1597,6 +1691,121 @@ declare module 'react-native-firebase' {
|
||||
}
|
||||
}
|
||||
|
||||
// Source: https://github.com/firebase/firebase-js-sdk/blob/master/packages/functions-types/index.d.ts
|
||||
namespace functions {
|
||||
type HttpsErrorCode = { [name: string]: FunctionsErrorCode };
|
||||
|
||||
/**
|
||||
* The set of Firebase Functions status codes. The codes are the same at the
|
||||
* ones exposed by gRPC here:
|
||||
* https://github.com/grpc/grpc/blob/master/doc/statuscodes.md
|
||||
*
|
||||
* Possible values:
|
||||
* - 'cancelled': The operation was cancelled (typically by the caller).
|
||||
* - 'unknown': Unknown error or an error from a different error domain.
|
||||
* - 'invalid-argument': Client specified an invalid argument. Note that this
|
||||
* differs from 'failed-precondition'. 'invalid-argument' indicates
|
||||
* arguments that are problematic regardless of the state of the system
|
||||
* (e.g. an invalid field name).
|
||||
* - 'deadline-exceeded': Deadline expired before operation could complete.
|
||||
* For operations that change the state of the system, this error may be
|
||||
* returned even if the operation has completed successfully. For example,
|
||||
* a successful response from a server could have been delayed long enough
|
||||
* for the deadline to expire.
|
||||
* - 'not-found': Some requested document was not found.
|
||||
* - 'already-exists': Some document that we attempted to create already
|
||||
* exists.
|
||||
* - 'permission-denied': The caller does not have permission to execute the
|
||||
* specified operation.
|
||||
* - 'resource-exhausted': Some resource has been exhausted, perhaps a
|
||||
* per-user quota, or perhaps the entire file system is out of space.
|
||||
* - 'failed-precondition': Operation was rejected because the system is not
|
||||
* in a state required for the operation's execution.
|
||||
* - 'aborted': The operation was aborted, typically due to a concurrency
|
||||
* issue like transaction aborts, etc.
|
||||
* - 'out-of-range': Operation was attempted past the valid range.
|
||||
* - 'unimplemented': Operation is not implemented or not supported/enabled.
|
||||
* - 'internal': Internal errors. Means some invariants expected by
|
||||
* underlying system has been broken. If you see one of these errors,
|
||||
* something is very broken.
|
||||
* - 'unavailable': The service is currently unavailable. This is most likely
|
||||
* a transient condition and may be corrected by retrying with a backoff.
|
||||
* - 'data-loss': Unrecoverable data loss or corruption.
|
||||
* - 'unauthenticated': The request does not have valid authentication
|
||||
* credentials for the operation.
|
||||
*/
|
||||
type FunctionsErrorCode =
|
||||
| 'ok'
|
||||
| 'cancelled'
|
||||
| 'unknown'
|
||||
| 'invalid-argument'
|
||||
| 'deadline-exceeded'
|
||||
| 'not-found'
|
||||
| 'already-exists'
|
||||
| 'permission-denied'
|
||||
| 'resource-exhausted'
|
||||
| 'failed-precondition'
|
||||
| 'aborted'
|
||||
| 'out-of-range'
|
||||
| 'unimplemented'
|
||||
| 'internal'
|
||||
| 'unavailable'
|
||||
| 'data-loss'
|
||||
| 'unauthenticated';
|
||||
|
||||
/**
|
||||
* An HttpsCallableResult wraps a single result from a function call.
|
||||
*/
|
||||
interface HttpsCallableResult {
|
||||
readonly data: any;
|
||||
}
|
||||
|
||||
/**
|
||||
* An HttpsCallable is a reference to a "callable" http trigger in
|
||||
* Google Cloud Functions.
|
||||
*/
|
||||
interface HttpsCallable {
|
||||
(data?: any): Promise<HttpsCallableResult>;
|
||||
}
|
||||
|
||||
/**
|
||||
* `FirebaseFunctions` represents a Functions app, and is the entry point for
|
||||
* all Functions operations.
|
||||
*/
|
||||
interface Functions {
|
||||
/**
|
||||
* Gets an `HttpsCallable` instance that refers to the function with the given
|
||||
* name.
|
||||
*
|
||||
* @param name The name of the https callable function.
|
||||
* @return The `HttpsCallable` instance.
|
||||
*/
|
||||
httpsCallable(name: string): HttpsCallable;
|
||||
}
|
||||
|
||||
/**
|
||||
* firebase.functions.X
|
||||
*/
|
||||
interface FunctionsStatics {
|
||||
/**
|
||||
* Uppercased + underscored variables of @FunctionsErrorCode
|
||||
*/
|
||||
HttpsErrorCode: HttpsErrorCode;
|
||||
}
|
||||
|
||||
interface HttpsError extends Error {
|
||||
/**
|
||||
* A standard error code that will be returned to the client. This also
|
||||
* determines the HTTP status code of the response, as defined in code.proto.
|
||||
*/
|
||||
readonly code: FunctionsErrorCode;
|
||||
/**
|
||||
* Extra data to be converted to JSON and included in the error response.
|
||||
*/
|
||||
readonly details?: any;
|
||||
}
|
||||
}
|
||||
|
||||
namespace firestore {
|
||||
interface Firestore {
|
||||
readonly app: App;
|
||||
@@ -1631,7 +1840,7 @@ declare module 'react-native-firebase' {
|
||||
endAt(...varargs: any[]): Query;
|
||||
endBefore(snapshot: DocumentSnapshot): Query;
|
||||
endBefore(...varargs: any[]): Query;
|
||||
get(): Promise<QuerySnapshot>;
|
||||
get(options?: Types.GetOptions): Promise<QuerySnapshot>;
|
||||
limit(limit: number): Query;
|
||||
onSnapshot(
|
||||
onNext: Query.ObserverOnNext,
|
||||
@@ -1639,12 +1848,12 @@ declare module 'react-native-firebase' {
|
||||
): () => void;
|
||||
onSnapshot(observer: Query.Observer): () => void;
|
||||
onSnapshot(
|
||||
queryListenOptions: Query.QueryListenOptions,
|
||||
metadataChanges: MetadataChanges,
|
||||
onNext: Query.ObserverOnNext,
|
||||
onError?: Query.ObserverOnError
|
||||
): () => void;
|
||||
onSnapshot(
|
||||
queryListenOptions: Query.QueryListenOptions,
|
||||
metadataChanges: MetadataChanges,
|
||||
observer: Query.Observer
|
||||
): () => void;
|
||||
orderBy(
|
||||
@@ -1666,7 +1875,7 @@ declare module 'react-native-firebase' {
|
||||
readonly doc: DocumentSnapshot;
|
||||
readonly newIndex: number;
|
||||
readonly oldIndex: number;
|
||||
readonly type: string;
|
||||
readonly type: 'added' | 'modified' | 'removed';
|
||||
}
|
||||
|
||||
interface DocumentReference {
|
||||
@@ -1676,22 +1885,22 @@ declare module 'react-native-firebase' {
|
||||
readonly path: string;
|
||||
collection(collectionPath: string): CollectionReference;
|
||||
delete(): Promise<void>;
|
||||
get(): Promise<DocumentSnapshot>;
|
||||
get(options?: Types.GetOptions): Promise<DocumentSnapshot>;
|
||||
onSnapshot(
|
||||
onNext: DocumentReference.ObserverOnNext,
|
||||
onError?: DocumentReference.ObserverOnError
|
||||
): () => void;
|
||||
onSnapshot(observer: DocumentReference.Observer): () => void;
|
||||
onSnapshot(
|
||||
documentListenOptions: DocumentReference.DocumentListenOptions,
|
||||
metadataChanges: MetadataChanges,
|
||||
onNext: DocumentReference.ObserverOnNext,
|
||||
onError?: DocumentReference.ObserverOnError
|
||||
): () => void;
|
||||
onSnapshot(
|
||||
documentListenOptions: DocumentReference.DocumentListenOptions,
|
||||
metadataChanges: MetadataChanges,
|
||||
observer: DocumentReference.Observer
|
||||
): () => void;
|
||||
set(data: object, writeOptions?: Types.WriteOptions): Promise<void>;
|
||||
set(data: object, writeOptions?: Types.SetOptions): Promise<void>;
|
||||
update(obj: object): Promise<void>;
|
||||
update(key1: Types.UpdateKey, val1: any): Promise<void>;
|
||||
update(
|
||||
@@ -1732,10 +1941,6 @@ declare module 'react-native-firebase' {
|
||||
): Promise<void>;
|
||||
}
|
||||
namespace DocumentReference {
|
||||
interface DocumentListenOptions {
|
||||
includeMetadataChanges: boolean;
|
||||
}
|
||||
|
||||
type ObserverOnNext = (documentSnapshot: DocumentSnapshot) => void;
|
||||
type ObserverOnError = (err: object) => void;
|
||||
interface Observer {
|
||||
@@ -1788,13 +1993,17 @@ declare module 'react-native-firebase' {
|
||||
parent(): Path | null;
|
||||
}
|
||||
|
||||
type MetadataChanges = {
|
||||
includeMetadataChanges: boolean;
|
||||
};
|
||||
|
||||
interface Query {
|
||||
readonly firestore: Firestore;
|
||||
endAt(snapshot: DocumentSnapshot): Query;
|
||||
endAt(...varargs: any[]): Query;
|
||||
endBefore(snapshot: DocumentSnapshot): Query;
|
||||
endBefore(...varargs: any[]): Query;
|
||||
get(): Promise<QuerySnapshot>;
|
||||
get(options?: Types.GetOptions): Promise<QuerySnapshot>;
|
||||
limit(limit: number): Query;
|
||||
onSnapshot(
|
||||
onNext: Query.ObserverOnNext,
|
||||
@@ -1802,12 +2011,12 @@ declare module 'react-native-firebase' {
|
||||
): () => void;
|
||||
onSnapshot(observer: Query.Observer): () => void;
|
||||
onSnapshot(
|
||||
queryListenOptions: Query.QueryListenOptions,
|
||||
metadataChanges: MetadataChanges,
|
||||
onNext: Query.ObserverOnNext,
|
||||
onError?: Query.ObserverOnError
|
||||
): () => void;
|
||||
onSnapshot(
|
||||
queryListenOptions: Query.QueryListenOptions,
|
||||
metadataChanges: MetadataChanges,
|
||||
observer: Query.Observer
|
||||
): () => void;
|
||||
orderBy(
|
||||
@@ -1852,19 +2061,6 @@ declare module 'react-native-firebase' {
|
||||
startAt?: any[];
|
||||
}
|
||||
|
||||
// The JS code expects at least one of 'includeDocumentMetadataChanges'
|
||||
// or 'includeQueryMetadataChanges' to be defined.
|
||||
interface _IncludeDocumentMetadataChanges {
|
||||
includeDocumentMetadataChanges: boolean;
|
||||
}
|
||||
interface _IncludeQueryMetadataChanges {
|
||||
includeQueryMetadataChanges: boolean;
|
||||
}
|
||||
type QueryListenOptions =
|
||||
| _IncludeDocumentMetadataChanges
|
||||
| _IncludeQueryMetadataChanges
|
||||
| (_IncludeDocumentMetadataChanges & _IncludeQueryMetadataChanges);
|
||||
|
||||
type ObserverOnNext = (querySnapshot: QuerySnapshot) => void;
|
||||
type ObserverOnError = (err: object) => void;
|
||||
interface Observer {
|
||||
@@ -1903,7 +2099,7 @@ declare module 'react-native-firebase' {
|
||||
set(
|
||||
documentRef: DocumentReference,
|
||||
data: Object,
|
||||
options?: Types.WriteOptions
|
||||
options?: Types.SetOptions
|
||||
): Transaction;
|
||||
// multiple overrides for update() to allow strong-typed var_args
|
||||
update(docRef: DocumentReference, obj: object): WriteBatch;
|
||||
@@ -1960,7 +2156,7 @@ declare module 'react-native-firebase' {
|
||||
set(
|
||||
docRef: DocumentReference,
|
||||
data: object,
|
||||
options?: Types.WriteOptions
|
||||
options?: Types.SetOptions
|
||||
): WriteBatch;
|
||||
// multiple overrides for update() to allow strong-typed var_args
|
||||
update(docRef: DocumentReference, obj: object): WriteBatch;
|
||||
@@ -2054,7 +2250,11 @@ declare module 'react-native-firebase' {
|
||||
/** The key in update() function for DocumentReference and WriteBatch. */
|
||||
type UpdateKey = string | FieldPath;
|
||||
|
||||
interface WriteOptions {
|
||||
interface GetOptions {
|
||||
source: 'default' | 'server' | 'cache';
|
||||
}
|
||||
|
||||
interface SetOptions {
|
||||
merge?: boolean;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -39,8 +39,7 @@ export type { default as DataQuery } from './modules/database/Query';
|
||||
* Export Firestore types
|
||||
*/
|
||||
export type {
|
||||
DocumentListenOptions,
|
||||
QueryListenOptions,
|
||||
MetadataChanges,
|
||||
SetOptions,
|
||||
SnapshotMetadata,
|
||||
} from './modules/firestore/types';
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
import User from './User';
|
||||
import ModuleBase from '../../utils/ModuleBase';
|
||||
import { getAppEventName, SharedEventEmitter } from '../../utils/events';
|
||||
import { isAndroid, isBoolean } from '../../utils';
|
||||
import { getLogger } from '../../utils/log';
|
||||
import { getNativeModule } from '../../utils/native';
|
||||
import INTERNALS from '../../utils/internals';
|
||||
@@ -354,7 +355,16 @@ export default class Auth extends ModuleBase {
|
||||
* Asynchronously signs in using a phone number.
|
||||
*
|
||||
*/
|
||||
signInWithPhoneNumber(phoneNumber: string): Promise<ConfirmationResult> {
|
||||
signInWithPhoneNumber(
|
||||
phoneNumber: string,
|
||||
forceResend?: boolean
|
||||
): Promise<ConfirmationResult> {
|
||||
if (isAndroid) {
|
||||
return getNativeModule(this)
|
||||
.signInWithPhoneNumber(phoneNumber, forceResend || false)
|
||||
.then(result => new ConfirmationResult(this, result.verificationId));
|
||||
}
|
||||
|
||||
return getNativeModule(this)
|
||||
.signInWithPhoneNumber(phoneNumber)
|
||||
.then(result => new ConfirmationResult(this, result.verificationId));
|
||||
@@ -366,19 +376,36 @@ export default class Auth extends ModuleBase {
|
||||
* authentication purposes.
|
||||
*
|
||||
* @param phoneNumber
|
||||
* @param autoVerifyTimeout Android Only
|
||||
* @param autoVerifyTimeoutOrForceResend Android Only
|
||||
* @param forceResend Android Only
|
||||
* @returns {PhoneAuthListener}
|
||||
*/
|
||||
verifyPhoneNumber(
|
||||
phoneNumber: string,
|
||||
autoVerifyTimeout?: number
|
||||
autoVerifyTimeoutOrForceResend?: number | boolean,
|
||||
forceResend?: boolean
|
||||
): PhoneAuthListener {
|
||||
return new PhoneAuthListener(this, phoneNumber, autoVerifyTimeout);
|
||||
let _forceResend = forceResend;
|
||||
let _autoVerifyTimeout = 60;
|
||||
|
||||
if (isBoolean(autoVerifyTimeoutOrForceResend)) {
|
||||
_forceResend = autoVerifyTimeoutOrForceResend;
|
||||
} else {
|
||||
_autoVerifyTimeout = autoVerifyTimeoutOrForceResend;
|
||||
}
|
||||
|
||||
return new PhoneAuthListener(
|
||||
this,
|
||||
phoneNumber,
|
||||
_autoVerifyTimeout,
|
||||
_forceResend
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Send reset password instructions via email
|
||||
* @param {string} email The email to send password reset instructions
|
||||
* @param actionCodeSettings
|
||||
*/
|
||||
sendPasswordResetEmail(
|
||||
email: string,
|
||||
@@ -390,6 +417,50 @@ export default class Auth extends ModuleBase {
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends a sign-in email link to the user with the specified email
|
||||
* @param {string} email The email account to sign in with.
|
||||
* @param actionCodeSettings
|
||||
*/
|
||||
sendSignInLinkToEmail(
|
||||
email: string,
|
||||
actionCodeSettings?: ActionCodeSettings
|
||||
): Promise<void> {
|
||||
return getNativeModule(this).sendSignInLinkToEmail(
|
||||
email,
|
||||
actionCodeSettings
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if an incoming link is a sign-in with email link.
|
||||
* @param {string} emailLink Sign-in email link.
|
||||
*/
|
||||
isSignInWithEmailLink(emailLink: string): boolean {
|
||||
return (
|
||||
typeof emailLink === 'string' &&
|
||||
(emailLink.includes('mode=signIn') ||
|
||||
emailLink.includes('mode%3DsignIn')) &&
|
||||
(emailLink.includes('oobCode=') || emailLink.includes('oobCode%3D'))
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Asynchronously signs in using an email and sign-in email link.
|
||||
*
|
||||
* @param {string} email The email account to sign in with.
|
||||
* @param {string} emailLink Sign-in email link.
|
||||
* @return {Promise} A promise resolved upon completion
|
||||
*/
|
||||
signInWithEmailLink(
|
||||
email: string,
|
||||
emailLink: string
|
||||
): Promise<UserCredential> {
|
||||
return getNativeModule(this)
|
||||
.signInWithEmailLink(email, emailLink)
|
||||
.then(userCredential => this._setUserCredential(userCredential));
|
||||
}
|
||||
|
||||
/**
|
||||
* Completes the password reset process, given a confirmation code and new password.
|
||||
*
|
||||
@@ -427,9 +498,21 @@ export default class Auth extends ModuleBase {
|
||||
/**
|
||||
* Returns a list of authentication providers that can be used to sign in a given user (identified by its main email address).
|
||||
* @return {Promise}
|
||||
* @Deprecated
|
||||
*/
|
||||
fetchProvidersForEmail(email: string): Promise<string[]> {
|
||||
return getNativeModule(this).fetchProvidersForEmail(email);
|
||||
console.warn(
|
||||
'Deprecated firebase.auth().fetchProvidersForEmail in favor of firebase.auth().fetchSignInMethodsForEmail()'
|
||||
);
|
||||
return getNativeModule(this).fetchSignInMethodsForEmail(email);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a list of authentication methods that can be used to sign in a given user (identified by its main email address).
|
||||
* @return {Promise}
|
||||
*/
|
||||
fetchSignInMethodsForEmail(email: string): Promise<string[]> {
|
||||
return getNativeModule(this).fetchSignInMethodsForEmail(email);
|
||||
}
|
||||
|
||||
verifyPasswordResetCode(code: string): Promise<string> {
|
||||
|
||||
@@ -32,6 +32,7 @@ export default class PhoneAuthListener {
|
||||
_timeout: number;
|
||||
_publicEvents: Object;
|
||||
_internalEvents: Object;
|
||||
_forceResending: boolean;
|
||||
_reject: Function | null;
|
||||
_resolve: Function | null;
|
||||
_credential: Object | null;
|
||||
@@ -43,8 +44,14 @@ export default class PhoneAuthListener {
|
||||
* @param auth
|
||||
* @param phoneNumber
|
||||
* @param timeout
|
||||
* @param forceResend
|
||||
*/
|
||||
constructor(auth: Auth, phoneNumber: string, timeout?: number) {
|
||||
constructor(
|
||||
auth: Auth,
|
||||
phoneNumber: string,
|
||||
timeout?: number,
|
||||
forceResend?: boolean
|
||||
) {
|
||||
this._auth = auth;
|
||||
this._reject = null;
|
||||
this._resolve = null;
|
||||
@@ -52,6 +59,7 @@ export default class PhoneAuthListener {
|
||||
this._credential = null;
|
||||
|
||||
this._timeout = timeout || 20; // 20 secs
|
||||
this._forceResending = forceResend || false;
|
||||
this._phoneAuthRequestKey = generatePushID();
|
||||
|
||||
// internal events
|
||||
@@ -86,7 +94,8 @@ export default class PhoneAuthListener {
|
||||
getNativeModule(this._auth).verifyPhoneNumber(
|
||||
phoneNumber,
|
||||
this._phoneAuthRequestKey,
|
||||
this._timeout
|
||||
this._timeout,
|
||||
this._forceResending
|
||||
);
|
||||
}
|
||||
|
||||
@@ -284,9 +293,9 @@ export default class PhoneAuthListener {
|
||||
|
||||
on(
|
||||
event: string,
|
||||
observer: () => PhoneAuthSnapshot,
|
||||
errorCb?: () => PhoneAuthError,
|
||||
successCb?: () => PhoneAuthSnapshot
|
||||
observer: PhoneAuthSnapshot => void,
|
||||
errorCb?: PhoneAuthError => void,
|
||||
successCb?: PhoneAuthSnapshot => void
|
||||
): this {
|
||||
if (!isString(event)) {
|
||||
throw new Error(
|
||||
@@ -327,7 +336,7 @@ export default class PhoneAuthListener {
|
||||
* Promise .then proxy
|
||||
* @param fn
|
||||
*/
|
||||
then(fn: () => PhoneAuthSnapshot) {
|
||||
then(fn: PhoneAuthSnapshot => void) {
|
||||
this._promiseDeferred();
|
||||
// $FlowFixMe: Unsure how to annotate `bind` here
|
||||
if (this._promise) return this._promise.then.bind(this._promise)(fn);
|
||||
@@ -338,7 +347,7 @@ export default class PhoneAuthListener {
|
||||
* Promise .catch proxy
|
||||
* @param fn
|
||||
*/
|
||||
catch(fn: () => Error) {
|
||||
catch(fn: Error => void) {
|
||||
this._promiseDeferred();
|
||||
// $FlowFixMe: Unsure how to annotate `bind` here
|
||||
if (this._promise) return this._promise.catch.bind(this._promise)(fn);
|
||||
|
||||
@@ -4,7 +4,8 @@
|
||||
*/
|
||||
import type { AuthCredential } from '../types';
|
||||
|
||||
const providerId = 'password';
|
||||
const linkProviderId = 'emailLink';
|
||||
const passwordProviderId = 'password';
|
||||
|
||||
export default class EmailAuthProvider {
|
||||
constructor() {
|
||||
@@ -13,15 +14,37 @@ export default class EmailAuthProvider {
|
||||
);
|
||||
}
|
||||
|
||||
static get EMAIL_LINK_SIGN_IN_METHOD(): string {
|
||||
return linkProviderId;
|
||||
}
|
||||
|
||||
static get EMAIL_PASSWORD_SIGN_IN_METHOD(): string {
|
||||
return passwordProviderId;
|
||||
}
|
||||
|
||||
static get PROVIDER_ID(): string {
|
||||
return providerId;
|
||||
return passwordProviderId;
|
||||
}
|
||||
|
||||
static credential(email: string, password: string): AuthCredential {
|
||||
return {
|
||||
token: email,
|
||||
secret: password,
|
||||
providerId,
|
||||
providerId: passwordProviderId,
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize an EmailAuthProvider credential using an email and an email link after a sign in with email link operation.
|
||||
* @param email Email address.
|
||||
* @param emailLink Sign-in email link.
|
||||
* @returns {{token: string, secret: string, providerId: string}}
|
||||
*/
|
||||
static credentialWithLink(email: string, emailLink: string): AuthCredential {
|
||||
return {
|
||||
token: email,
|
||||
secret: emailLink,
|
||||
providerId: linkProviderId,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -22,6 +22,11 @@ type NativeValue = {
|
||||
export const MODULE_NAME = 'RNFirebaseRemoteConfig';
|
||||
export const NAMESPACE = 'config';
|
||||
|
||||
type ConfigSnapshot = {
|
||||
source: string,
|
||||
val(): any,
|
||||
};
|
||||
|
||||
/**
|
||||
* @class Config
|
||||
*/
|
||||
@@ -44,7 +49,7 @@ export default class RemoteConfig extends ModuleBase {
|
||||
* @returns {*}
|
||||
* @private
|
||||
*/
|
||||
_nativeValueToJS(nativeValue: NativeValue) {
|
||||
_nativeValueToJS(nativeValue: NativeValue): ConfigSnapshot {
|
||||
return {
|
||||
source: nativeValue.source,
|
||||
val() {
|
||||
@@ -89,7 +94,7 @@ export default class RemoteConfig extends ModuleBase {
|
||||
* Call activateFetched to make fetched data available in app
|
||||
* @returns {*|Promise.<String>}:
|
||||
*/
|
||||
fetch(expiration?: number) {
|
||||
fetch(expiration?: number): Promise<string> {
|
||||
if (expiration !== undefined) {
|
||||
getLogger(this).debug(
|
||||
`Fetching remote config data with expiration ${expiration.toString()}`
|
||||
@@ -106,7 +111,7 @@ export default class RemoteConfig extends ModuleBase {
|
||||
* resolves if there was a Fetched Config, and it was activated,
|
||||
* rejects if no Fetched Config was found, or the Fetched Config was already activated.
|
||||
*/
|
||||
activateFetched() {
|
||||
activateFetched(): Promise<boolean> {
|
||||
getLogger(this).debug('Activating remote config');
|
||||
return getNativeModule(this).activateFetched();
|
||||
}
|
||||
@@ -124,7 +129,7 @@ export default class RemoteConfig extends ModuleBase {
|
||||
* "source" : OneOf<String>(remoteConfigSourceRemote|remoteConfigSourceDefault|remoteConfigSourceStatic)
|
||||
* }
|
||||
*/
|
||||
getValue(key: string) {
|
||||
getValue(key: string): Promise<ConfigSnapshot> {
|
||||
return getNativeModule(this)
|
||||
.getValue(key || '')
|
||||
.then(this._nativeValueToJS);
|
||||
@@ -144,7 +149,7 @@ export default class RemoteConfig extends ModuleBase {
|
||||
* "source" : OneOf<String>(remoteConfigSourceRemote|remoteConfigSourceDefault|remoteConfigSourceStatic)
|
||||
* }
|
||||
*/
|
||||
getValues(keys: Array<string>) {
|
||||
getValues(keys: Array<string>): Promise<{ [string]: ConfigSnapshot }> {
|
||||
return getNativeModule(this)
|
||||
.getValues(keys || [])
|
||||
.then(nativeValues => {
|
||||
@@ -161,7 +166,7 @@ export default class RemoteConfig extends ModuleBase {
|
||||
* @param prefix: The key prefix to look for. If prefix is nil or empty, returns all the keys.
|
||||
* @returns {*|Promise.<Array<String>>}
|
||||
*/
|
||||
getKeysByPrefix(prefix?: string) {
|
||||
getKeysByPrefix(prefix?: string): Promise<string[]> {
|
||||
return getNativeModule(this).getKeysByPrefix(prefix);
|
||||
}
|
||||
|
||||
@@ -169,7 +174,7 @@ export default class RemoteConfig extends ModuleBase {
|
||||
* Sets config defaults for parameter keys and values in the default namespace config.
|
||||
* @param defaults: A dictionary mapping a String key to a Object values.
|
||||
*/
|
||||
setDefaults(defaults: Object) {
|
||||
setDefaults(defaults: Object): void {
|
||||
getNativeModule(this).setDefaults(defaults);
|
||||
}
|
||||
|
||||
@@ -177,7 +182,7 @@ export default class RemoteConfig extends ModuleBase {
|
||||
* Sets default configs from plist for default namespace;
|
||||
* @param resource: The plist file name or resource ID
|
||||
*/
|
||||
setDefaultsFromResource(resource: string | number) {
|
||||
setDefaultsFromResource(resource: string | number): void {
|
||||
getNativeModule(this).setDefaultsFromResource(resource);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -892,3 +892,12 @@ export default class Reference extends ReferenceBase {
|
||||
return SyncTree.removeListenersForRegistrations(registrations);
|
||||
}
|
||||
}
|
||||
|
||||
// eslint-disable-next-line no-unused-vars
|
||||
// class ThenableReference<+R> extends Reference {
|
||||
// then<U>(
|
||||
// onFulfill?: (value: R) => Promise<U> | U,
|
||||
// onReject?: (error: any) => Promise<U> | U
|
||||
// ): Promise<U>;
|
||||
// catch<U>(onReject?: (error: any) => Promise<U> | U): Promise<R | U>;
|
||||
// }
|
||||
|
||||
@@ -8,8 +8,9 @@ import { firestoreAutoId } from '../../utils';
|
||||
|
||||
import type Firestore from './';
|
||||
import type {
|
||||
GetOptions,
|
||||
MetadataChanges,
|
||||
QueryDirection,
|
||||
QueryListenOptions,
|
||||
QueryOperator,
|
||||
} from './types';
|
||||
import type FieldPath from './FieldPath';
|
||||
@@ -71,8 +72,8 @@ export default class CollectionReference {
|
||||
return this._query.endBefore(snapshotOrVarArgs);
|
||||
}
|
||||
|
||||
get(): Promise<QuerySnapshot> {
|
||||
return this._query.get();
|
||||
get(options?: GetOptions): Promise<QuerySnapshot> {
|
||||
return this._query.get(options);
|
||||
}
|
||||
|
||||
limit(limit: number): Query {
|
||||
@@ -80,7 +81,7 @@ export default class CollectionReference {
|
||||
}
|
||||
|
||||
onSnapshot(
|
||||
optionsOrObserverOrOnNext: QueryListenOptions | Observer | ObserverOnNext,
|
||||
optionsOrObserverOrOnNext: MetadataChanges | Observer | ObserverOnNext,
|
||||
observerOrOnNextOrOnError?: Observer | ObserverOnNext | ObserverOnError,
|
||||
onError?: ObserverOnError
|
||||
): () => void {
|
||||
|
||||
@@ -14,7 +14,7 @@ export default class DocumentChange {
|
||||
_document: DocumentSnapshot;
|
||||
_newIndex: number;
|
||||
_oldIndex: number;
|
||||
_type: string;
|
||||
_type: 'added' | 'modified' | 'removed';
|
||||
|
||||
constructor(firestore: Firestore, nativeData: NativeDocumentChange) {
|
||||
this._document = new DocumentSnapshot(firestore, nativeData.document);
|
||||
|
||||
@@ -13,7 +13,8 @@ import { getNativeModule } from '../../utils/native';
|
||||
|
||||
import type Firestore from './';
|
||||
import type {
|
||||
DocumentListenOptions,
|
||||
GetOptions,
|
||||
MetadataChanges,
|
||||
NativeDocumentSnapshot,
|
||||
SetOptions,
|
||||
} from './types';
|
||||
@@ -70,17 +71,34 @@ export default class DocumentReference {
|
||||
return getNativeModule(this._firestore).documentDelete(this.path);
|
||||
}
|
||||
|
||||
get(): Promise<DocumentSnapshot> {
|
||||
get(options?: GetOptions): Promise<DocumentSnapshot> {
|
||||
if (options) {
|
||||
if (!isObject(options)) {
|
||||
return Promise.reject(
|
||||
new Error(
|
||||
'DocumentReference.get failed: First argument must be an object.'
|
||||
)
|
||||
);
|
||||
} else if (
|
||||
options.source &&
|
||||
(options.source !== 'default' &&
|
||||
options.source !== 'server' &&
|
||||
options.source !== 'cache')
|
||||
) {
|
||||
return Promise.reject(
|
||||
new Error(
|
||||
'DocumentReference.get failed: GetOptions.source must be one of `default`, `server` or `cache`.'
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
return getNativeModule(this._firestore)
|
||||
.documentGet(this.path)
|
||||
.documentGet(this.path, options)
|
||||
.then(result => new DocumentSnapshot(this._firestore, result));
|
||||
}
|
||||
|
||||
onSnapshot(
|
||||
optionsOrObserverOrOnNext:
|
||||
| DocumentListenOptions
|
||||
| Observer
|
||||
| ObserverOnNext,
|
||||
optionsOrObserverOrOnNext: MetadataChanges | Observer | ObserverOnNext,
|
||||
observerOrOnNextOrOnError?: Observer | ObserverOnNext | ObserverOnError,
|
||||
onError?: ObserverOnError
|
||||
) {
|
||||
|
||||
@@ -14,9 +14,10 @@ import { getNativeModule } from '../../utils/native';
|
||||
import type Firestore from './';
|
||||
import type Path from './Path';
|
||||
import type {
|
||||
MetadataChanges,
|
||||
QueryDirection,
|
||||
QueryOperator,
|
||||
QueryListenOptions,
|
||||
GetOptions,
|
||||
} from './types';
|
||||
|
||||
const DIRECTIONS: { [QueryDirection]: string } = {
|
||||
@@ -141,13 +142,32 @@ export default class Query {
|
||||
);
|
||||
}
|
||||
|
||||
get(): Promise<QuerySnapshot> {
|
||||
get(options?: GetOptions): Promise<QuerySnapshot> {
|
||||
if (options) {
|
||||
if (!isObject(options)) {
|
||||
return Promise.reject(
|
||||
new Error('Query.get failed: First argument must be an object.')
|
||||
);
|
||||
} else if (
|
||||
options.source &&
|
||||
(options.source !== 'default' &&
|
||||
options.source !== 'server' &&
|
||||
options.source !== 'cache')
|
||||
) {
|
||||
return Promise.reject(
|
||||
new Error(
|
||||
'Query.get failed: GetOptions.source must be one of `default`, `server` or `cache`.'
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
return getNativeModule(this._firestore)
|
||||
.collectionGet(
|
||||
this._referencePath.relativeName,
|
||||
this._fieldFilters,
|
||||
this._fieldOrders,
|
||||
this._queryOptions
|
||||
this._queryOptions,
|
||||
options
|
||||
)
|
||||
.then(nativeData => new QuerySnapshot(this._firestore, this, nativeData));
|
||||
}
|
||||
@@ -170,12 +190,12 @@ export default class Query {
|
||||
}
|
||||
|
||||
onSnapshot(
|
||||
optionsOrObserverOrOnNext: QueryListenOptions | Observer | ObserverOnNext,
|
||||
optionsOrObserverOrOnNext: MetadataChanges | Observer | ObserverOnNext,
|
||||
observerOrOnNextOrOnError?: Observer | ObserverOnNext | ObserverOnError,
|
||||
onError?: ObserverOnError
|
||||
) {
|
||||
let observer: Observer;
|
||||
let queryListenOptions = {};
|
||||
let metadataChanges = {};
|
||||
// Called with: onNext, ?onError
|
||||
if (isFunction(optionsOrObserverOrOnNext)) {
|
||||
if (observerOrOnNextOrOnError && !isFunction(observerOrOnNextOrOnError)) {
|
||||
@@ -216,14 +236,10 @@ export default class Query {
|
||||
} else if (
|
||||
Object.prototype.hasOwnProperty.call(
|
||||
optionsOrObserverOrOnNext,
|
||||
'includeDocumentMetadataChanges'
|
||||
) ||
|
||||
Object.prototype.hasOwnProperty.call(
|
||||
optionsOrObserverOrOnNext,
|
||||
'includeQueryMetadataChanges'
|
||||
'includeMetadataChanges'
|
||||
)
|
||||
) {
|
||||
queryListenOptions = optionsOrObserverOrOnNext;
|
||||
metadataChanges = optionsOrObserverOrOnNext;
|
||||
// Called with: Options, onNext, ?onError
|
||||
if (isFunction(observerOrOnNextOrOnError)) {
|
||||
if (onError && !isFunction(onError)) {
|
||||
@@ -307,7 +323,7 @@ export default class Query {
|
||||
this._fieldOrders,
|
||||
this._queryOptions,
|
||||
listenerId,
|
||||
queryListenOptions
|
||||
metadataChanges
|
||||
);
|
||||
|
||||
// Return an unsubscribe method
|
||||
|
||||
@@ -2,19 +2,18 @@
|
||||
* @flow
|
||||
*/
|
||||
|
||||
export type DocumentListenOptions = {
|
||||
export type MetadataChanges = {|
|
||||
includeMetadataChanges: boolean,
|
||||
};
|
||||
|};
|
||||
|
||||
export type QueryDirection = 'DESC' | 'desc' | 'ASC' | 'asc';
|
||||
|
||||
export type QueryListenOptions = {|
|
||||
includeDocumentMetadataChanges: boolean,
|
||||
includeQueryMetadataChanges: boolean,
|
||||
|};
|
||||
|
||||
export type QueryOperator = '<' | '<=' | '=' | '==' | '>' | '>=';
|
||||
|
||||
export type GetOptions = {
|
||||
source: 'default' | 'server' | 'cache',
|
||||
};
|
||||
|
||||
export type SetOptions = {
|
||||
merge?: boolean,
|
||||
};
|
||||
@@ -28,7 +27,7 @@ export type NativeDocumentChange = {
|
||||
document: NativeDocumentSnapshot,
|
||||
newIndex: number,
|
||||
oldIndex: number,
|
||||
type: string,
|
||||
type: 'added' | 'modified' | 'removed',
|
||||
};
|
||||
|
||||
export type NativeDocumentSnapshot = {
|
||||
|
||||
@@ -18,6 +18,26 @@ import type {
|
||||
export const NAMESPACE = 'functions';
|
||||
export const MODULE_NAME = 'RNFirebaseFunctions';
|
||||
|
||||
/**
|
||||
* -------------
|
||||
* INTERNALS
|
||||
* -------------
|
||||
*/
|
||||
function errorOrResult(possibleError): HttpsCallablePromise {
|
||||
if (isObject(possibleError) && possibleError.__error) {
|
||||
const { code, message, details } = possibleError;
|
||||
return Promise.reject(
|
||||
new HttpsError(
|
||||
statics.HttpsErrorCode[code] || statics.HttpsErrorCode.UNKNOWN,
|
||||
message,
|
||||
details
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
return Promise.resolve(possibleError);
|
||||
}
|
||||
|
||||
export default class Functions extends ModuleBase {
|
||||
constructor(app: App) {
|
||||
super(app, {
|
||||
@@ -41,29 +61,9 @@ export default class Functions extends ModuleBase {
|
||||
httpsCallable(name: string): HttpsCallable {
|
||||
return (data?: any): HttpsCallablePromise => {
|
||||
const promise = getNativeModule(this).httpsCallable(name, { data });
|
||||
return promise.then(this._errorOrResult);
|
||||
return promise.then(errorOrResult);
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* -------------
|
||||
* INTERNALS
|
||||
* -------------
|
||||
*/
|
||||
_errorOrResult(possibleError): HttpsCallablePromise {
|
||||
if (isObject(possibleError) && possibleError.__error) {
|
||||
const { code, message, details } = possibleError;
|
||||
return Promise.reject(
|
||||
new HttpsError(
|
||||
statics.HttpsErrorCode[code] || statics.HttpsErrorCode.UNKNOWN,
|
||||
message,
|
||||
details
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
return Promise.resolve(possibleError);
|
||||
}
|
||||
}
|
||||
|
||||
export const statics: { HttpsErrorCode: HttpsErrorCode } = {
|
||||
|
||||
@@ -27,6 +27,14 @@ export default class InstanceId extends ModuleBase {
|
||||
get(): Promise<string> {
|
||||
return getNativeModule(this).get();
|
||||
}
|
||||
|
||||
getToken(authorizedEntity: string, scope: string): Promise<string> {
|
||||
return getNativeModule(this).getToken(authorizedEntity, scope);
|
||||
}
|
||||
|
||||
deleteToken(authorizedEntity: string, scope: string): Promise<void> {
|
||||
return getNativeModule(this).deleteToken(authorizedEntity, scope);
|
||||
}
|
||||
}
|
||||
|
||||
export const statics = {};
|
||||
|
||||
@@ -21,6 +21,7 @@ export default class AndroidAction {
|
||||
this._action = action;
|
||||
this._icon = icon;
|
||||
this._remoteInputs = [];
|
||||
this._showUserInterface = true;
|
||||
this._title = title;
|
||||
}
|
||||
|
||||
|
||||
@@ -671,6 +671,16 @@ export default class AndroidNotification {
|
||||
return this._notification;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param visibility
|
||||
* @returns {Notification}
|
||||
*/
|
||||
setVisibility(visibility: VisibilityType): Notification {
|
||||
this._visibility = visibility;
|
||||
return this._notification;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param when
|
||||
|
||||
@@ -92,20 +92,41 @@ export default class AndroidNotifications {
|
||||
return Promise.resolve();
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove a delivered notifications by tag.
|
||||
* @param tag
|
||||
*/
|
||||
removeDeliveredNotificationsByTag(tag: string): Promise<void> {
|
||||
if (!tag) {
|
||||
return Promise.reject(
|
||||
new Error(
|
||||
'Notifications: removeDeliveredNotificationsByTag expects a `tag`'
|
||||
)
|
||||
);
|
||||
if (Platform.OS === 'android') {
|
||||
if (typeof tag !== 'string') {
|
||||
throw new Error(
|
||||
`AndroidNotifications:removeDeliveredNotificationsByTag expects an 'string' but got type ${typeof tag}`
|
||||
);
|
||||
}
|
||||
return getNativeModule(
|
||||
this._notifications
|
||||
).removeDeliveredNotificationsByTag(tag);
|
||||
}
|
||||
return getNativeModule(
|
||||
this._notifications
|
||||
).removeDeliveredNotificationsByTag(tag);
|
||||
return Promise.resolve();
|
||||
}
|
||||
|
||||
deleteChannelGroup(groupId: string): Promise<void> {
|
||||
if (Platform.OS === 'android') {
|
||||
if (typeof groupId !== 'string') {
|
||||
throw new Error(
|
||||
`AndroidNotifications:deleteChannelGroup expects an 'string' but got type ${typeof groupId}`
|
||||
);
|
||||
}
|
||||
return getNativeModule(this._notifications).deleteChannelGroup(groupId);
|
||||
}
|
||||
return Promise.resolve();
|
||||
}
|
||||
|
||||
deleteChannel(channelId: string): Promise<void> {
|
||||
if (Platform.OS === 'android') {
|
||||
if (typeof channelId !== 'string') {
|
||||
throw new Error(
|
||||
`AndroidNotifications:deleteChannel expects an 'string' but got type ${typeof channelId}`
|
||||
);
|
||||
}
|
||||
return getNativeModule(this._notifications).deleteChannel(channelId);
|
||||
}
|
||||
return Promise.resolve();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -44,7 +44,7 @@ export const Importance = {
|
||||
Low: 2,
|
||||
Max: 5,
|
||||
Min: 1,
|
||||
None: 3,
|
||||
None: 0,
|
||||
Unspecified: -1000,
|
||||
};
|
||||
|
||||
|
||||
@@ -7,6 +7,7 @@ import { NativeModules } from 'react-native';
|
||||
import StorageRef from './reference';
|
||||
import { getAppEventName, SharedEventEmitter } from '../../utils/events';
|
||||
import { getLogger } from '../../utils/log';
|
||||
import { stripTrailingSlash } from '../../utils';
|
||||
import ModuleBase from '../../utils/ModuleBase';
|
||||
import { getNativeModule } from '../../utils/native';
|
||||
|
||||
@@ -149,16 +150,29 @@ export const statics = {
|
||||
},
|
||||
Native: FirebaseStorage
|
||||
? {
|
||||
MAIN_BUNDLE_PATH: FirebaseStorage.MAIN_BUNDLE_PATH,
|
||||
CACHES_DIRECTORY_PATH: FirebaseStorage.CACHES_DIRECTORY_PATH,
|
||||
DOCUMENT_DIRECTORY_PATH: FirebaseStorage.DOCUMENT_DIRECTORY_PATH,
|
||||
EXTERNAL_DIRECTORY_PATH: FirebaseStorage.EXTERNAL_DIRECTORY_PATH,
|
||||
EXTERNAL_STORAGE_DIRECTORY_PATH:
|
||||
FirebaseStorage.EXTERNAL_STORAGE_DIRECTORY_PATH,
|
||||
TEMP_DIRECTORY_PATH: FirebaseStorage.TEMP_DIRECTORY_PATH,
|
||||
LIBRARY_DIRECTORY_PATH: FirebaseStorage.LIBRARY_DIRECTORY_PATH,
|
||||
FILETYPE_REGULAR: FirebaseStorage.FILETYPE_REGULAR,
|
||||
FILETYPE_DIRECTORY: FirebaseStorage.FILETYPE_DIRECTORY,
|
||||
MAIN_BUNDLE_PATH: stripTrailingSlash(FirebaseStorage.MAIN_BUNDLE_PATH),
|
||||
CACHES_DIRECTORY_PATH: stripTrailingSlash(
|
||||
FirebaseStorage.CACHES_DIRECTORY_PATH
|
||||
),
|
||||
DOCUMENT_DIRECTORY_PATH: stripTrailingSlash(
|
||||
FirebaseStorage.DOCUMENT_DIRECTORY_PATH
|
||||
),
|
||||
EXTERNAL_DIRECTORY_PATH: stripTrailingSlash(
|
||||
FirebaseStorage.EXTERNAL_DIRECTORY_PATH
|
||||
),
|
||||
EXTERNAL_STORAGE_DIRECTORY_PATH: stripTrailingSlash(
|
||||
FirebaseStorage.EXTERNAL_STORAGE_DIRECTORY_PATH
|
||||
),
|
||||
TEMP_DIRECTORY_PATH: stripTrailingSlash(
|
||||
FirebaseStorage.TEMP_DIRECTORY_PATH
|
||||
),
|
||||
LIBRARY_DIRECTORY_PATH: stripTrailingSlash(
|
||||
FirebaseStorage.LIBRARY_DIRECTORY_PATH
|
||||
),
|
||||
FILETYPE_REGULAR: stripTrailingSlash(FirebaseStorage.FILETYPE_REGULAR),
|
||||
FILETYPE_DIRECTORY: stripTrailingSlash(
|
||||
FirebaseStorage.FILETYPE_DIRECTORY
|
||||
),
|
||||
}
|
||||
: {},
|
||||
};
|
||||
|
||||
@@ -96,7 +96,8 @@ export default class StorageReference extends ReferenceBase {
|
||||
* @return {Promise}
|
||||
*/
|
||||
putFile(filePath: Object, metadata: Object = {}): Promise<Object> {
|
||||
const _filePath = filePath.replace('file://', '');
|
||||
let _filePath = filePath.replace('file://', '');
|
||||
if (_filePath.includes('%')) _filePath = decodeURI(_filePath);
|
||||
return new StorageTask(
|
||||
UPLOAD_TASK,
|
||||
getNativeModule(this._storage).putFile(this.path, _filePath, metadata),
|
||||
|
||||
@@ -190,63 +190,15 @@ export function tryJSONStringify(data: mixed): string | null {
|
||||
*/
|
||||
export function noop(): void {}
|
||||
|
||||
// /**
|
||||
// * Delays chunks based on sizes per event loop.
|
||||
// * @param collection
|
||||
// * @param chunkSize
|
||||
// * @param operation
|
||||
// * @param callback
|
||||
// * @private
|
||||
// */
|
||||
// function _delayChunk(collection: Array<*>,
|
||||
// chunkSize: number,
|
||||
// operation: Function,
|
||||
// callback: Function): void {
|
||||
// const length = collection.length;
|
||||
// const iterations = Math.ceil(length / chunkSize);
|
||||
//
|
||||
// // noinspection ES6ConvertVarToLetConst
|
||||
// let thisIteration = 0;
|
||||
//
|
||||
// setImmediate(function next() {
|
||||
// const start = thisIteration * chunkSize;
|
||||
// const _end = start + chunkSize;
|
||||
// const end = _end >= length ? length : _end;
|
||||
// const result = operation(collection.slice(start, end), start, end);
|
||||
//
|
||||
// if (thisIteration++ > iterations) {
|
||||
// callback(null, result);
|
||||
// } else {
|
||||
// setImmediate(next);
|
||||
// }
|
||||
// });
|
||||
// }
|
||||
//
|
||||
// /**
|
||||
// * Async each with optional chunk size limit
|
||||
// * @param array
|
||||
// * @param chunkSize
|
||||
// * @param iterator
|
||||
// * @param cb
|
||||
// */
|
||||
// export function each(array: Array<*>,
|
||||
// chunkSize: number | Function,
|
||||
// iterator: Function,
|
||||
// cb?: Function): void {
|
||||
// if (typeof chunkSize === 'function') {
|
||||
// cb = iterator;
|
||||
// iterator = chunkSize;
|
||||
// chunkSize = DEFAULT_CHUNK_SIZE;
|
||||
// }
|
||||
//
|
||||
// if (cb) {
|
||||
// _delayChunk(array, chunkSize, (slice, start) => {
|
||||
// for (let ii = 0, jj = slice.length; ii < jj; ii += 1) {
|
||||
// iterator(slice[ii], start + ii);
|
||||
// }
|
||||
// }, cb);
|
||||
// }
|
||||
// }
|
||||
/**
|
||||
* Remove a trailing forward slash from a string
|
||||
* @param str
|
||||
* @returns {*}
|
||||
*/
|
||||
export function stripTrailingSlash(str: string): string {
|
||||
if (!isString(str)) return str;
|
||||
return str.endsWith('/') ? str.slice(0, -1) : str;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a string typeof that's valid for Firebase usage
|
||||
@@ -259,42 +211,6 @@ export function typeOf(value: any): string {
|
||||
return typeof value;
|
||||
}
|
||||
|
||||
// /**
|
||||
// * Async map with optional chunk size limit
|
||||
// * @param array
|
||||
// * @param chunkSize
|
||||
// * @param iterator
|
||||
// * @param cb
|
||||
// * @returns {*}
|
||||
// */
|
||||
// export function map(array: Array<*>,
|
||||
// chunkSize: number | Function,
|
||||
// iterator: Function,
|
||||
// cb?: Function): void {
|
||||
// if (typeof chunkSize === 'function') {
|
||||
// cb = iterator;
|
||||
// iterator = chunkSize;
|
||||
// chunkSize = DEFAULT_CHUNK_SIZE;
|
||||
// }
|
||||
//
|
||||
// const result = [];
|
||||
// _delayChunk(array, chunkSize, (slice, start) => {
|
||||
// for (let ii = 0, jj = slice.length; ii < jj; ii += 1) {
|
||||
// result.push(iterator(slice[ii], start + ii, array));
|
||||
// }
|
||||
// return result;
|
||||
// }, () => cb && cb(result));
|
||||
// }
|
||||
|
||||
// /**
|
||||
// *
|
||||
// * @param string
|
||||
// * @return {string}
|
||||
// */
|
||||
// export function capitalizeFirstLetter(string: string) {
|
||||
// return `${string.charAt(0).toUpperCase()}${string.slice(1)}`;
|
||||
// }
|
||||
|
||||
// timestamp of last push, used to prevent local collisions if you push twice in one ms.
|
||||
let lastPushTime = 0;
|
||||
|
||||
|
||||
3778
package-lock.json
generated
3778
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
13
package.json
13
package.json
@@ -1,8 +1,8 @@
|
||||
{
|
||||
"name": "react-native-firebase",
|
||||
"version": "4.0.7",
|
||||
"version": "4.3.5",
|
||||
"author": "Invertase <contact@invertase.io> (http://invertase.io)",
|
||||
"description": "A well tested, feature rich Firebase implementation for React Native, supporting iOS & Android. Individual module support for Admob, Analytics, Auth, Crash Reporting, Cloud Firestore, Database, Dynamic Links, Messaging (FCM), Remote Config, Storage and Performance.",
|
||||
"description": "A well tested, feature rich Firebase implementation for React Native, supporting iOS & Android. Individual module support for Admob, Analytics, Auth, Crash Reporting, Cloud Firestore, Database, Dynamic Links, Functions, Messaging (FCM), Remote Config, Storage and more.",
|
||||
"main": "dist/index.js",
|
||||
"types": "dist/index.d.ts",
|
||||
"scripts": {
|
||||
@@ -35,8 +35,8 @@
|
||||
"setupFiles": [],
|
||||
"unmockedModulePathPatterns": ["./node_modules/react", "./node_modules/react-native", "./node_modules/react-native-mock", "./node_modules/react-addons-test-utils"]
|
||||
},
|
||||
"license": "APACHE-2.0",
|
||||
"keywords": ["react", "admob", "auth", "config", "digits", "fabric", "phone-auth", "sms", "firestore", "cloud-firestore", "datastore", "remote-config", "transactions", "react-native", "react-native-firebase", "firebase", "fcm", "apn", "gcm", "analytics", "messaging", "database", "android", "ios", "crash", "firestack", "performance", "firestore", "dynamic-links", "crashlytics"],
|
||||
"license": "Apache-2.0",
|
||||
"keywords": ["react", "admob", "auth", "config", "digits", "fabric", "functions", "phone-auth", "sms", "firestore", "cloud-firestore", "datastore", "remote-config", "transactions", "react-native", "react-native-firebase", "firebase", "fcm", "apn", "gcm", "analytics", "messaging", "database", "android", "ios", "crash", "firestack", "performance", "firestore", "dynamic-links", "crashlytics"],
|
||||
"peerDependencies": {
|
||||
"react": "*",
|
||||
"react-native": ">= 0.48.0",
|
||||
@@ -79,12 +79,9 @@
|
||||
},
|
||||
"rnpm": {
|
||||
"android": {
|
||||
"buildPatch": " compile(project(':react-native-firebase')) {\n transitive = false\n }\n",
|
||||
"buildPatch": " implementation project(':react-native-firebase')",
|
||||
"packageImportPath": "import io.invertase.firebase.RNFirebasePackage;",
|
||||
"packageInstance": "new RNFirebasePackage()"
|
||||
},
|
||||
"commands": {
|
||||
"postlink": "node node_modules/react-native-firebase/scripts/rnpm-postlink"
|
||||
}
|
||||
},
|
||||
"collective": {
|
||||
|
||||
@@ -4,7 +4,8 @@ const path = require('path');
|
||||
const appBuildGradlePath = path.join('android', 'app', 'build.gradle');
|
||||
|
||||
const defaultCompileStatement = "compile project(':react-native-firebase')";
|
||||
const requiredCompileStatement = "compile(project(':react-native-firebase')) {\n transitive = false\n }";
|
||||
const requiredCompileStatement =
|
||||
"compile(project(':react-native-firebase')) {\n transitive = false\n }";
|
||||
|
||||
// android/build.gradle
|
||||
// 1) TODO: Add Google Play maven repository
|
||||
@@ -16,7 +17,10 @@ const requiredCompileStatement = "compile(project(':react-native-firebase')) {\n
|
||||
let buildGradleContents = fs.readFileSync(appBuildGradlePath, 'utf8');
|
||||
|
||||
// 1) Check that react-native-firebase compile statement is the correct format
|
||||
buildGradleContents = buildGradleContents.replace(defaultCompileStatement, requiredCompileStatement);
|
||||
buildGradleContents = buildGradleContents.replace(
|
||||
defaultCompileStatement,
|
||||
requiredCompileStatement
|
||||
);
|
||||
|
||||
// 2) TODO: Add firebase-core and play-services-base dependencies
|
||||
|
||||
|
||||
@@ -70,29 +70,31 @@ android {
|
||||
}
|
||||
}
|
||||
|
||||
project.ext.firebaseVersion = '12.0.0'
|
||||
|
||||
dependencies {
|
||||
implementation project(':react-native-vector-icons')
|
||||
implementation(project(':react-native-firebase')) {
|
||||
transitive = false
|
||||
}
|
||||
implementation project(':react-native-firebase')
|
||||
implementation fileTree(dir: "libs", include: ["*.jar"])
|
||||
implementation "com.google.android.gms:play-services-base:$firebaseVersion"
|
||||
implementation "com.google.firebase:firebase-ads:$firebaseVersion"
|
||||
implementation "com.google.firebase:firebase-auth:$firebaseVersion"
|
||||
implementation "com.google.firebase:firebase-config:$firebaseVersion"
|
||||
implementation "com.google.firebase:firebase-core:$firebaseVersion"
|
||||
implementation "com.google.firebase:firebase-crash:$firebaseVersion"
|
||||
implementation "com.google.firebase:firebase-database:$firebaseVersion"
|
||||
implementation "com.google.firebase:firebase-messaging:$firebaseVersion"
|
||||
implementation "com.google.firebase:firebase-perf:$firebaseVersion"
|
||||
implementation "com.google.firebase:firebase-storage:$firebaseVersion"
|
||||
implementation "com.google.firebase:firebase-firestore:$firebaseVersion"
|
||||
implementation "com.google.firebase:firebase-invites:$firebaseVersion"
|
||||
implementation('com.crashlytics.sdk.android:crashlytics:2.9.1@aar') {
|
||||
implementation('com.crashlytics.sdk.android:crashlytics:2.9.3@aar') {
|
||||
transitive = true
|
||||
}
|
||||
|
||||
// RNFirebase required dependencies
|
||||
implementation "com.google.firebase:firebase-core:16.0.1"
|
||||
implementation "com.google.android.gms:play-services-base:15.0.1"
|
||||
|
||||
// RNFirebase optional dependencies
|
||||
implementation "com.google.firebase:firebase-ads:15.0.1"
|
||||
implementation "com.google.firebase:firebase-auth:16.0.2"
|
||||
implementation "com.google.firebase:firebase-config:16.0.0"
|
||||
implementation "com.google.firebase:firebase-crash:16.0.1"
|
||||
implementation "com.google.firebase:firebase-database:16.0.1"
|
||||
implementation "com.google.firebase:firebase-firestore:17.0.2"
|
||||
implementation "com.google.firebase:firebase-functions:16.0.1"
|
||||
implementation "com.google.firebase:firebase-invites:16.0.1"
|
||||
implementation "com.google.firebase:firebase-storage:16.0.1"
|
||||
implementation "com.google.firebase:firebase-messaging:17.0.0"
|
||||
implementation "com.google.firebase:firebase-perf:16.0.0"
|
||||
|
||||
implementation "com.android.support:appcompat-v7:27.0.2"
|
||||
implementation "com.facebook.react:react-native:+" // From node_modules
|
||||
}
|
||||
|
||||
@@ -2,29 +2,29 @@
|
||||
|
||||
buildscript {
|
||||
repositories {
|
||||
jcenter()
|
||||
google()
|
||||
jcenter()
|
||||
maven {
|
||||
url 'https://maven.fabric.io/public'
|
||||
}
|
||||
}
|
||||
dependencies {
|
||||
classpath 'com.android.tools.build:gradle:3.1.0'
|
||||
classpath 'com.google.gms:google-services:3.1.2'
|
||||
classpath 'com.android.tools.build:gradle:3.1.2'
|
||||
classpath 'com.google.gms:google-services:4.0.1'
|
||||
classpath 'com.google.firebase:firebase-plugins:1.1.1'
|
||||
classpath 'io.fabric.tools:gradle:1.25.1'
|
||||
classpath 'io.fabric.tools:gradle:1.25.4'
|
||||
}
|
||||
}
|
||||
|
||||
allprojects {
|
||||
repositories {
|
||||
mavenLocal()
|
||||
google()
|
||||
jcenter()
|
||||
maven {
|
||||
// All of React Native (JS, Obj-C sources, Android binaries) is installed from npm
|
||||
url "$rootDir/../node_modules/react-native/android"
|
||||
}
|
||||
mavenLocal()
|
||||
google()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,88 +1,93 @@
|
||||
PODS:
|
||||
- boost-for-react-native (1.63.0)
|
||||
- BoringSSL (10.0.2):
|
||||
- BoringSSL/Implementation (= 10.0.2)
|
||||
- BoringSSL/Interface (= 10.0.2)
|
||||
- BoringSSL/Implementation (10.0.2):
|
||||
- BoringSSL/Interface (= 10.0.2)
|
||||
- BoringSSL/Interface (10.0.2)
|
||||
- Crashlytics (3.10.1):
|
||||
- Fabric (~> 1.7.5)
|
||||
- BoringSSL (10.0.5):
|
||||
- BoringSSL/Implementation (= 10.0.5)
|
||||
- BoringSSL/Interface (= 10.0.5)
|
||||
- BoringSSL/Implementation (10.0.5):
|
||||
- BoringSSL/Interface (= 10.0.5)
|
||||
- BoringSSL/Interface (10.0.5)
|
||||
- Crashlytics (3.10.2):
|
||||
- Fabric (~> 1.7.7)
|
||||
- DoubleConversion (1.1.5)
|
||||
- Fabric (1.7.6)
|
||||
- Firebase/AdMob (4.12.0):
|
||||
- Fabric (1.7.7)
|
||||
- Firebase/AdMob (5.3.0):
|
||||
- Firebase/Core
|
||||
- Google-Mobile-Ads-SDK (= 7.30.0)
|
||||
- Firebase/Auth (4.12.0):
|
||||
- Google-Mobile-Ads-SDK (= 7.31.0)
|
||||
- Firebase/Auth (5.3.0):
|
||||
- Firebase/CoreOnly
|
||||
- FirebaseAuth (= 5.0.1)
|
||||
- Firebase/Core (5.3.0):
|
||||
- Firebase/CoreOnly
|
||||
- FirebaseAnalytics (= 5.0.1)
|
||||
- Firebase/CoreOnly (5.3.0):
|
||||
- FirebaseCore (= 5.0.4)
|
||||
- Firebase/Crash (5.3.0):
|
||||
- Firebase/Core
|
||||
- FirebaseAuth (= 4.6.0)
|
||||
- Firebase/Core (4.12.0):
|
||||
- FirebaseAnalytics (= 4.1.0)
|
||||
- FirebaseCore (= 4.0.19)
|
||||
- Firebase/Crash (4.12.0):
|
||||
- FirebaseCrash (= 3.0.0)
|
||||
- Firebase/Database (5.3.0):
|
||||
- Firebase/CoreOnly
|
||||
- FirebaseDatabase (= 5.0.1)
|
||||
- Firebase/DynamicLinks (5.3.0):
|
||||
- Firebase/Core
|
||||
- FirebaseCrash (= 2.0.2)
|
||||
- Firebase/Database (4.12.0):
|
||||
- FirebaseDynamicLinks (= 3.0.1)
|
||||
- Firebase/Firestore (5.3.0):
|
||||
- Firebase/CoreOnly
|
||||
- FirebaseFirestore (= 0.12.4)
|
||||
- Firebase/Invites (5.3.0):
|
||||
- Firebase/Core
|
||||
- FirebaseDatabase (= 4.1.5)
|
||||
- Firebase/DynamicLinks (4.12.0):
|
||||
- FirebaseInvites (= 3.0.0)
|
||||
- Firebase/Messaging (5.3.0):
|
||||
- Firebase/CoreOnly
|
||||
- FirebaseMessaging (= 3.0.2)
|
||||
- Firebase/Performance (5.3.0):
|
||||
- Firebase/Core
|
||||
- FirebaseDynamicLinks (= 2.3.2)
|
||||
- Firebase/Firestore (4.12.0):
|
||||
- FirebasePerformance (= 2.0.1)
|
||||
- Firebase/RemoteConfig (5.3.0):
|
||||
- Firebase/Core
|
||||
- FirebaseFirestore (= 0.11.0)
|
||||
- Firebase/Invites (4.12.0):
|
||||
- Firebase/Core
|
||||
- FirebaseInvites (= 2.0.2)
|
||||
- Firebase/Messaging (4.12.0):
|
||||
- Firebase/Core
|
||||
- FirebaseMessaging (= 2.2.0)
|
||||
- Firebase/Performance (4.12.0):
|
||||
- Firebase/Core
|
||||
- FirebasePerformance (= 1.1.3)
|
||||
- Firebase/RemoteConfig (4.12.0):
|
||||
- Firebase/Core
|
||||
- FirebaseRemoteConfig (= 2.1.3)
|
||||
- Firebase/Storage (4.12.0):
|
||||
- Firebase/Core
|
||||
- FirebaseStorage (= 2.2.0)
|
||||
- FirebaseABTesting (1.0.0):
|
||||
- FirebaseCore (~> 4.0)
|
||||
- Protobuf (~> 3.1)
|
||||
- FirebaseAnalytics (4.1.0):
|
||||
- FirebaseCore (~> 4.0)
|
||||
- FirebaseInstanceID (~> 2.0)
|
||||
- FirebaseRemoteConfig (= 3.0.0)
|
||||
- Firebase/Storage (5.3.0):
|
||||
- Firebase/CoreOnly
|
||||
- FirebaseStorage (= 3.0.0)
|
||||
- FirebaseABTesting (2.0.0):
|
||||
- FirebaseCore (~> 5.0)
|
||||
- Protobuf (~> 3.5)
|
||||
- FirebaseAnalytics (5.0.1):
|
||||
- FirebaseCore (~> 5.0)
|
||||
- FirebaseInstanceID (~> 3.0)
|
||||
- GoogleToolboxForMac/NSData+zlib (~> 2.1)
|
||||
- nanopb (~> 0.3)
|
||||
- FirebaseAuth (4.6.0):
|
||||
- FirebaseAnalytics (~> 4.1)
|
||||
- GoogleToolboxForMac/NSDictionary+URLArguments (~> 2.1)
|
||||
- FirebaseAuth (5.0.1):
|
||||
- FirebaseCore (~> 5.0)
|
||||
- GTMSessionFetcher/Core (~> 1.1)
|
||||
- FirebaseCore (4.0.19):
|
||||
- FirebaseCore (5.0.4):
|
||||
- GoogleToolboxForMac/NSData+zlib (~> 2.1)
|
||||
- FirebaseCrash (2.0.2):
|
||||
- FirebaseAnalytics (~> 4.0)
|
||||
- FirebaseInstanceID (~> 2.0)
|
||||
- FirebaseCrash (3.0.0):
|
||||
- FirebaseAnalytics (~> 5.0)
|
||||
- FirebaseInstanceID (~> 3.0)
|
||||
- GoogleToolboxForMac/Logger (~> 2.1)
|
||||
- GoogleToolboxForMac/NSData+zlib (~> 2.1)
|
||||
- Protobuf (~> 3.1)
|
||||
- FirebaseDatabase (4.1.5):
|
||||
- FirebaseAnalytics (~> 4.1)
|
||||
- FirebaseCore (~> 4.0)
|
||||
- Protobuf (~> 3.5)
|
||||
- FirebaseDatabase (5.0.1):
|
||||
- FirebaseCore (~> 5.0)
|
||||
- leveldb-library (~> 1.18)
|
||||
- FirebaseDynamicLinks (2.3.2):
|
||||
- FirebaseAnalytics (~> 4.0)
|
||||
- FirebaseFirestore (0.11.0):
|
||||
- FirebaseAnalytics (~> 4.1)
|
||||
- FirebaseCore (~> 4.0)
|
||||
- FirebaseDynamicLinks (3.0.1):
|
||||
- FirebaseAnalytics (~> 5.0)
|
||||
- FirebaseFirestore (0.12.4):
|
||||
- FirebaseCore (~> 5.0)
|
||||
- FirebaseFirestore/abseil-cpp (= 0.12.4)
|
||||
- gRPC-ProtoRPC (~> 1.0)
|
||||
- leveldb-library (~> 1.18)
|
||||
- Protobuf (~> 3.5)
|
||||
- FirebaseInstanceID (2.0.10):
|
||||
- FirebaseCore (~> 4.0)
|
||||
- FirebaseInvites (2.0.2):
|
||||
- FirebaseAnalytics (~> 4.0)
|
||||
- FirebaseDynamicLinks (~> 2.2)
|
||||
- Protobuf (~> 3.1)
|
||||
- FirebaseFirestore/abseil-cpp (0.12.4):
|
||||
- FirebaseCore (~> 5.0)
|
||||
- gRPC-ProtoRPC (~> 1.0)
|
||||
- leveldb-library (~> 1.18)
|
||||
- Protobuf (~> 3.1)
|
||||
- FirebaseInstanceID (3.1.1):
|
||||
- FirebaseCore (~> 5.0)
|
||||
- FirebaseInvites (3.0.0):
|
||||
- FirebaseAnalytics (~> 5.0)
|
||||
- FirebaseDynamicLinks (~> 3.0)
|
||||
- GoogleAPIClientForREST (~> 1.0)
|
||||
- GoogleSignIn (~> 4.1)
|
||||
- GoogleToolboxForMac/Logger (~> 2.1)
|
||||
@@ -93,42 +98,40 @@ PODS:
|
||||
- GTMOAuth2 (~> 1.0)
|
||||
- GTMSessionFetcher/Core (~> 1.1)
|
||||
- GTMSessionFetcher/Full (~> 1.1)
|
||||
- Protobuf (~> 3.5)
|
||||
- FirebaseMessaging (3.0.2):
|
||||
- FirebaseCore (~> 5.0)
|
||||
- FirebaseInstanceID (~> 3.0)
|
||||
- GoogleToolboxForMac/Logger (~> 2.1)
|
||||
- Protobuf (~> 3.1)
|
||||
- FirebaseMessaging (2.2.0):
|
||||
- FirebaseAnalytics (~> 4.1)
|
||||
- FirebaseCore (~> 4.0)
|
||||
- FirebaseInstanceID (~> 2.0)
|
||||
- GoogleToolboxForMac/Logger (~> 2.1)
|
||||
- Protobuf (~> 3.5)
|
||||
- FirebasePerformance (1.1.3):
|
||||
- FirebaseAnalytics (~> 4.1)
|
||||
- FirebaseInstanceID (~> 2.0)
|
||||
- FirebaseSwizzlingUtilities/ISASwizzling (~> 1.0)
|
||||
- FirebaseSwizzlingUtilities/MethodSwizzling (~> 1.0)
|
||||
- FirebasePerformance (2.0.1):
|
||||
- FirebaseAnalytics (~> 5.0)
|
||||
- FirebaseInstanceID (~> 3.1)
|
||||
- FirebaseSwizzlingUtilities/ISASwizzling (~> 2.0)
|
||||
- FirebaseSwizzlingUtilities/MethodSwizzling (~> 2.0)
|
||||
- GoogleToolboxForMac/Logger (~> 2.1)
|
||||
- GoogleToolboxForMac/NSData+zlib (~> 2.1)
|
||||
- GTMSessionFetcher/Core (~> 1.1)
|
||||
- Protobuf (~> 3.5)
|
||||
- FirebaseRemoteConfig (2.1.3):
|
||||
- FirebaseABTesting (~> 1.0)
|
||||
- FirebaseAnalytics (~> 4.1)
|
||||
- FirebaseCore (~> 4.0)
|
||||
- FirebaseInstanceID (~> 2.0)
|
||||
- FirebaseRemoteConfig (3.0.0):
|
||||
- FirebaseABTesting (~> 2.0)
|
||||
- FirebaseAnalytics (~> 5.0)
|
||||
- FirebaseCore (~> 5.0)
|
||||
- FirebaseInstanceID (~> 3.0)
|
||||
- GoogleToolboxForMac/NSData+zlib (~> 2.1)
|
||||
- Protobuf (~> 3.5)
|
||||
- FirebaseStorage (2.2.0):
|
||||
- FirebaseAnalytics (~> 4.1)
|
||||
- FirebaseCore (~> 4.0)
|
||||
- FirebaseStorage (3.0.0):
|
||||
- FirebaseCore (~> 5.0)
|
||||
- GTMSessionFetcher/Core (~> 1.1)
|
||||
- FirebaseSwizzlingUtilities/ISASwizzling (1.0.1)
|
||||
- FirebaseSwizzlingUtilities/MethodSwizzling (1.0.1):
|
||||
- FirebaseCore (~> 4.0)
|
||||
- FirebaseSwizzlingUtilities/ISASwizzling (2.0.0)
|
||||
- FirebaseSwizzlingUtilities/MethodSwizzling (2.0.0):
|
||||
- FirebaseCore (~> 5.0)
|
||||
- Folly (2016.09.26.00):
|
||||
- boost-for-react-native
|
||||
- DoubleConversion
|
||||
- glog
|
||||
- glog (0.3.4)
|
||||
- Google-Mobile-Ads-SDK (7.30.0)
|
||||
- Google-Mobile-Ads-SDK (7.31.0)
|
||||
- GoogleAPIClientForREST (1.3.4):
|
||||
- GoogleAPIClientForREST/Core (= 1.3.4)
|
||||
- GTMSessionFetcher (>= 1.1.7)
|
||||
@@ -139,46 +142,46 @@ PODS:
|
||||
- GoogleToolboxForMac/NSString+URLArguments (~> 2.1)
|
||||
- GTMOAuth2 (~> 1.0)
|
||||
- GTMSessionFetcher/Core (~> 1.1)
|
||||
- GoogleToolboxForMac/Core (2.1.3):
|
||||
- GoogleToolboxForMac/Defines (= 2.1.3)
|
||||
- GoogleToolboxForMac/DebugUtils (2.1.3):
|
||||
- GoogleToolboxForMac/Defines (= 2.1.3)
|
||||
- GoogleToolboxForMac/Defines (2.1.3)
|
||||
- GoogleToolboxForMac/Logger (2.1.3):
|
||||
- GoogleToolboxForMac/Defines (= 2.1.3)
|
||||
- GoogleToolboxForMac/NSData+zlib (2.1.3):
|
||||
- GoogleToolboxForMac/Defines (= 2.1.3)
|
||||
- GoogleToolboxForMac/NSDictionary+URLArguments (2.1.3):
|
||||
- GoogleToolboxForMac/DebugUtils (= 2.1.3)
|
||||
- GoogleToolboxForMac/Defines (= 2.1.3)
|
||||
- GoogleToolboxForMac/NSString+URLArguments (= 2.1.3)
|
||||
- GoogleToolboxForMac/NSString+URLArguments (2.1.3)
|
||||
- GoogleToolboxForMac/StringEncoding (2.1.3):
|
||||
- GoogleToolboxForMac/Defines (= 2.1.3)
|
||||
- GoogleToolboxForMac/URLBuilder (2.1.3):
|
||||
- GoogleToolboxForMac/Core (= 2.1.3)
|
||||
- GoogleToolboxForMac/Defines (= 2.1.3)
|
||||
- GoogleToolboxForMac/NSDictionary+URLArguments (= 2.1.3)
|
||||
- GoogleToolboxForMac/NSString+URLArguments (= 2.1.3)
|
||||
- gRPC (1.10.0):
|
||||
- gRPC-RxLibrary (= 1.10.0)
|
||||
- gRPC/Main (= 1.10.0)
|
||||
- gRPC-Core (1.10.0):
|
||||
- gRPC-Core/Implementation (= 1.10.0)
|
||||
- gRPC-Core/Interface (= 1.10.0)
|
||||
- gRPC-Core/Implementation (1.10.0):
|
||||
- GoogleToolboxForMac/Core (2.1.4):
|
||||
- GoogleToolboxForMac/Defines (= 2.1.4)
|
||||
- GoogleToolboxForMac/DebugUtils (2.1.4):
|
||||
- GoogleToolboxForMac/Defines (= 2.1.4)
|
||||
- GoogleToolboxForMac/Defines (2.1.4)
|
||||
- GoogleToolboxForMac/Logger (2.1.4):
|
||||
- GoogleToolboxForMac/Defines (= 2.1.4)
|
||||
- GoogleToolboxForMac/NSData+zlib (2.1.4):
|
||||
- GoogleToolboxForMac/Defines (= 2.1.4)
|
||||
- GoogleToolboxForMac/NSDictionary+URLArguments (2.1.4):
|
||||
- GoogleToolboxForMac/DebugUtils (= 2.1.4)
|
||||
- GoogleToolboxForMac/Defines (= 2.1.4)
|
||||
- GoogleToolboxForMac/NSString+URLArguments (= 2.1.4)
|
||||
- GoogleToolboxForMac/NSString+URLArguments (2.1.4)
|
||||
- GoogleToolboxForMac/StringEncoding (2.1.4):
|
||||
- GoogleToolboxForMac/Defines (= 2.1.4)
|
||||
- GoogleToolboxForMac/URLBuilder (2.1.4):
|
||||
- GoogleToolboxForMac/Core (= 2.1.4)
|
||||
- GoogleToolboxForMac/Defines (= 2.1.4)
|
||||
- GoogleToolboxForMac/NSDictionary+URLArguments (= 2.1.4)
|
||||
- GoogleToolboxForMac/NSString+URLArguments (= 2.1.4)
|
||||
- gRPC (1.12.0):
|
||||
- gRPC-RxLibrary (= 1.12.0)
|
||||
- gRPC/Main (= 1.12.0)
|
||||
- gRPC-Core (1.12.0):
|
||||
- gRPC-Core/Implementation (= 1.12.0)
|
||||
- gRPC-Core/Interface (= 1.12.0)
|
||||
- gRPC-Core/Implementation (1.12.0):
|
||||
- BoringSSL (~> 10.0)
|
||||
- gRPC-Core/Interface (= 1.10.0)
|
||||
- gRPC-Core/Interface (= 1.12.0)
|
||||
- nanopb (~> 0.3)
|
||||
- gRPC-Core/Interface (1.10.0)
|
||||
- gRPC-ProtoRPC (1.10.0):
|
||||
- gRPC (= 1.10.0)
|
||||
- gRPC-RxLibrary (= 1.10.0)
|
||||
- gRPC-Core/Interface (1.12.0)
|
||||
- gRPC-ProtoRPC (1.12.0):
|
||||
- gRPC (= 1.12.0)
|
||||
- gRPC-RxLibrary (= 1.12.0)
|
||||
- Protobuf (~> 3.0)
|
||||
- gRPC-RxLibrary (1.10.0)
|
||||
- gRPC/Main (1.10.0):
|
||||
- gRPC-Core (= 1.10.0)
|
||||
- gRPC-RxLibrary (= 1.10.0)
|
||||
- gRPC-RxLibrary (1.12.0)
|
||||
- gRPC/Main (1.12.0):
|
||||
- gRPC-Core (= 1.12.0)
|
||||
- gRPC-RxLibrary (= 1.12.0)
|
||||
- GTMOAuth2 (1.1.6):
|
||||
- GTMSessionFetcher (~> 1.1)
|
||||
- GTMSessionFetcher (1.1.15):
|
||||
@@ -192,7 +195,7 @@ PODS:
|
||||
- nanopb/encode (= 0.3.8)
|
||||
- nanopb/decode (0.3.8)
|
||||
- nanopb/encode (0.3.8)
|
||||
- Protobuf (3.5.0)
|
||||
- Protobuf (3.6.0)
|
||||
- React (0.54.4):
|
||||
- React/Core (= 0.54.4)
|
||||
- React/Core (0.54.4):
|
||||
@@ -222,7 +225,8 @@ PODS:
|
||||
- React/Core
|
||||
- React/fishhook
|
||||
- React/RCTBlob
|
||||
- RNFirebase (4.0.2):
|
||||
- RNFirebase (4.2.0):
|
||||
- Firebase/Core
|
||||
- React
|
||||
- yoga (0.54.4.React)
|
||||
|
||||
@@ -259,43 +263,43 @@ EXTERNAL SOURCES:
|
||||
|
||||
SPEC CHECKSUMS:
|
||||
boost-for-react-native: 39c7adb57c4e60d6c5479dd8623128eb5b3f0f2c
|
||||
BoringSSL: 60dd24df4af296bf41d78e5841dbb95d75f88c0d
|
||||
Crashlytics: aee1a064cbbf99b32efa3f056a5f458d846bc8ff
|
||||
BoringSSL: cf3f1793eb6e3c445c4d150456341f149c268a35
|
||||
Crashlytics: 0360624eea1c978a743feddb2fb1ef8b37fb7a0d
|
||||
DoubleConversion: e22e0762848812a87afd67ffda3998d9ef29170c
|
||||
Fabric: f8d42c893bb187326a7968b62abe55c36a987a46
|
||||
Firebase: d7fdf40e4d6c841849c52919f437fd3a0009ded0
|
||||
FirebaseABTesting: d07d0ee833b842d5153549e4c7e2e2cb1c23a3f9
|
||||
FirebaseAnalytics: 3dfae28d4a5e06f86c4fae830efc2ad3fadb19bc
|
||||
FirebaseAuth: 85a1b118a89838efc6f6ab3f2b1f94747d72a915
|
||||
FirebaseCore: ff49ebb37e0f63a570d78c4f1c1c0befe8659d5c
|
||||
FirebaseCrash: a7d980468dc8aa2db9792493c3e02722d601f6ab
|
||||
FirebaseDatabase: 5f0bc6134c5c237cf55f9e1249d406770a75eafd
|
||||
FirebaseDynamicLinks: 38b68641d24e78d0277a9205d988ce22875d5a25
|
||||
FirebaseFirestore: e92a096ce80c7b4b905d4e9d41dbd944adc9d2a5
|
||||
FirebaseInstanceID: 8d20d890d65c917f9f7d9950b6e10a760ad34321
|
||||
FirebaseInvites: ae15e0636f9eb42bdf5c1ef4c8f7bd4a88f9878b
|
||||
FirebaseMessaging: 75cdb862e86c30e0913a2ff307e48d49357c5b73
|
||||
FirebasePerformance: 85bdc3f3d630deb629e85695fcab23364d68f5db
|
||||
FirebaseRemoteConfig: 3e95fb7c072308492e85fa41d59d38b3d6fd2372
|
||||
FirebaseStorage: 0c223481c8f89ed300cf1239ddd2d9833622c65f
|
||||
FirebaseSwizzlingUtilities: 6006111d30248d2321ffac0231e246663e704ea3
|
||||
Fabric: bda89e242bce1b7b8ab264248cf3407774ce0095
|
||||
Firebase: 68afeeb05461db02d7c9e3215cda28068670f4aa
|
||||
FirebaseABTesting: 1f50b8d50f5e3469eea54e7463a7b7fe221d1f5e
|
||||
FirebaseAnalytics: b3628aea54c50464c32c393fb2ea032566e7ecc2
|
||||
FirebaseAuth: 463b8ce33bd5d05f706dcd4615499e3212b4132b
|
||||
FirebaseCore: 62f1b792a49bb9e8b4073f24606d2c93ffc352f0
|
||||
FirebaseCrash: 8900571fd763fd5bdda04522ec53da979456e3ce
|
||||
FirebaseDatabase: 482bad9c2abd422bb2321194fb8c937e67426a89
|
||||
FirebaseDynamicLinks: d624a7adc81a8fd70d52be5a6a47a2bc0644b923
|
||||
FirebaseFirestore: 53f6fe858494c39dbfd5237655e0641152a88c89
|
||||
FirebaseInstanceID: f3f0657372592ecdfdfe2cac604a5a75758376a6
|
||||
FirebaseInvites: d7534f94d0610b892bac8ee0cf4218a14be46c28
|
||||
FirebaseMessaging: 6894b8fe0a0cf26c3b13dad729f1131654ae0bdb
|
||||
FirebasePerformance: 1ebd87ffee5ca814582db1dc9e25651792ba02db
|
||||
FirebaseRemoteConfig: 3c57e4644bd6976b671ae0b725cd709f198bd1f5
|
||||
FirebaseStorage: 7ca4bb7b58a25fa647b04f524033fc7cb7eb272b
|
||||
FirebaseSwizzlingUtilities: 6c22677c50d0b6f5f0dc637c1233f13694a3003f
|
||||
Folly: 211775e49d8da0ca658aebc8eab89d642935755c
|
||||
glog: 1de0bb937dccdc981596d3b5825ebfb765017ded
|
||||
Google-Mobile-Ads-SDK: 7404f68120ae8682afeb5af001fbf4aad731c78e
|
||||
Google-Mobile-Ads-SDK: 6e529e748b45507a2ca904e0b5a52669ba3920c4
|
||||
GoogleAPIClientForREST: f7951c455df271bc6259b3ddb4073d0026475ccf
|
||||
GoogleSignIn: d9ef55b10f0aa401a5de2747f59b725e4b9732ac
|
||||
GoogleToolboxForMac: 2501e2ad72a52eb3dfe7bd9aee7dad11b858bd20
|
||||
gRPC: f54f0e6d603052b4562447da442ce2ff30bcdacc
|
||||
gRPC-Core: a030b1678ded49c88ec5ba7c90ee8ee5f47ec6e1
|
||||
gRPC-ProtoRPC: 22712b23eb1bda656a59715fa5c1da0ea1493ea4
|
||||
gRPC-RxLibrary: a41a4652d220f230ba1c0491a94ce2ee04c6180a
|
||||
GoogleToolboxForMac: 91c824d21e85b31c2aae9bb011c5027c9b4e738f
|
||||
gRPC: 9362451032695e2dfb7bafcd3740e3a27939e4ff
|
||||
gRPC-Core: 9696b220565b283e021cf2722d473a4a74b7622a
|
||||
gRPC-ProtoRPC: a1bd56fb1991a8dae4581250d7259eddabb66779
|
||||
gRPC-RxLibrary: 1ed5314e8b38cd6e55c9bfa048387136ae925ce9
|
||||
GTMOAuth2: c77fe325e4acd453837e72d91e3b5f13116857b2
|
||||
GTMSessionFetcher: 5fa5b80fd20e439ef5f545fb2cb3ca6c6714caa2
|
||||
leveldb-library: 08cba283675b7ed2d99629a4bc5fd052cd2bb6a5
|
||||
nanopb: 5601e6bca2dbf1ed831b519092ec110f66982ca3
|
||||
Protobuf: 8a9838fba8dae3389230e1b7f8c104aa32389c03
|
||||
Protobuf: 0fc0ad8bec688b2a3017a139953e01374fedbd5f
|
||||
React: c237e42de9c70e5cac6eeb52b4cfd3a0910c1f00
|
||||
RNFirebase: dff98ceb517ef0b5e1858deb59eca186acc6edb0
|
||||
RNFirebase: 2b25fd2e60269f26bb0a76c71dcc942b35a77df0
|
||||
yoga: 55da126afc384965b96bff46652464373b330add
|
||||
|
||||
PODFILE CHECKSUM: b776d6f4d08bbd51cda6d929b57bfaa8031e7ead
|
||||
|
||||
4768
tests/package-lock.json
generated
4768
tests/package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@@ -389,8 +389,7 @@ function collectionReferenceTests({
|
||||
await new Promise(resolve2 => {
|
||||
unsubscribe = collectionRef.onSnapshot(
|
||||
{
|
||||
includeQueryMetadataChanges: true,
|
||||
includeDocumentMetadataChanges: true,
|
||||
includeMetadataChanges: true,
|
||||
},
|
||||
snapshot => {
|
||||
snapshot.forEach(doc => callback(doc.data()));
|
||||
@@ -478,8 +477,7 @@ function collectionReferenceTests({
|
||||
};
|
||||
unsubscribe = collectionRef.onSnapshot(
|
||||
{
|
||||
includeQueryMetadataChanges: true,
|
||||
includeDocumentMetadataChanges: true,
|
||||
includeMetadataChanges: true,
|
||||
},
|
||||
observer
|
||||
);
|
||||
@@ -531,7 +529,7 @@ function collectionReferenceTests({
|
||||
(() => {
|
||||
colRef.onSnapshot(
|
||||
{
|
||||
includeQueryMetadataChanges: true,
|
||||
includeMetadataChanges: true,
|
||||
},
|
||||
() => {},
|
||||
'error'
|
||||
@@ -542,7 +540,7 @@ function collectionReferenceTests({
|
||||
(() => {
|
||||
colRef.onSnapshot(
|
||||
{
|
||||
includeQueryMetadataChanges: true,
|
||||
includeMetadataChanges: true,
|
||||
},
|
||||
{
|
||||
next: () => {},
|
||||
@@ -555,7 +553,7 @@ function collectionReferenceTests({
|
||||
(() => {
|
||||
colRef.onSnapshot(
|
||||
{
|
||||
includeQueryMetadataChanges: true,
|
||||
includeMetadataChanges: true,
|
||||
},
|
||||
{
|
||||
next: 'error',
|
||||
@@ -567,7 +565,7 @@ function collectionReferenceTests({
|
||||
(() => {
|
||||
colRef.onSnapshot(
|
||||
{
|
||||
includeQueryMetadataChanges: true,
|
||||
includeMetadataChanges: true,
|
||||
},
|
||||
'error'
|
||||
);
|
||||
|
||||
@@ -93,6 +93,26 @@ function documentReferenceTests({
|
||||
snapshot.id.should.equal('doc1');
|
||||
snapshot.metadata.should.be.an.Object();
|
||||
});
|
||||
|
||||
it('should support GetOptions source=`default`', async () => {
|
||||
const snapshot = await firebase.native
|
||||
.firestore()
|
||||
.doc('document-tests/doc1')
|
||||
.get({ source: 'default' });
|
||||
snapshot.id.should.equal('doc1');
|
||||
snapshot.metadata.should.be.an.Object();
|
||||
should.equal(snapshot.metadata.fromCache, false);
|
||||
});
|
||||
|
||||
it('should support GetOptions source=`cache`', async () => {
|
||||
const snapshot = await firebase.native
|
||||
.firestore()
|
||||
.doc('document-tests/doc1')
|
||||
.get({ source: 'cache' });
|
||||
snapshot.id.should.equal('doc1');
|
||||
snapshot.metadata.should.be.an.Object();
|
||||
should.equal(snapshot.metadata.fromCache, true);
|
||||
});
|
||||
});
|
||||
|
||||
context('onSnapshot()', () => {
|
||||
|
||||
35
tests/src/tests/iid/iidTests.js
Normal file
35
tests/src/tests/iid/iidTests.js
Normal file
@@ -0,0 +1,35 @@
|
||||
import should from 'should';
|
||||
|
||||
function iidTests({ describe, it, firebase }) {
|
||||
describe('iid', () => {
|
||||
it('should delete the iid token', async () => {
|
||||
await firebase.native.iid().delete();
|
||||
});
|
||||
|
||||
it('it should return iid token from get', async () => {
|
||||
const token = await firebase.native.iid().get();
|
||||
|
||||
token.should.be.a.String();
|
||||
});
|
||||
|
||||
it('should return an FCM token from getToken with arguments', async () => {
|
||||
await firebase.native.iid().delete();
|
||||
|
||||
const otherSenderIdToken = await firebase.native
|
||||
.iid()
|
||||
.getToken('305229645282', '*');
|
||||
|
||||
otherSenderIdToken.should.be.a.String();
|
||||
});
|
||||
|
||||
it('should return nil from deleteToken', async () => {
|
||||
const token = await firebase.native
|
||||
.iid()
|
||||
.deleteToken('305229645282', '*');
|
||||
|
||||
should.not.exist(token);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
export default iidTests;
|
||||
10
tests/src/tests/iid/index.js
Normal file
10
tests/src/tests/iid/index.js
Normal file
@@ -0,0 +1,10 @@
|
||||
import firebase from '../../firebase';
|
||||
import TestSuite from '../../../lib/TestSuite';
|
||||
|
||||
import iidTests from './iidTests';
|
||||
|
||||
const suite = new TestSuite('Iid', 'firebase.id()', firebase);
|
||||
|
||||
suite.addTests(iidTests);
|
||||
|
||||
export default suite;
|
||||
@@ -12,6 +12,7 @@ import performance from './perf';
|
||||
import admob from './admob';
|
||||
import firestore from './firestore';
|
||||
import links from './links/index';
|
||||
import iid from './iid';
|
||||
|
||||
window.getCoverage = function getCoverage() {
|
||||
return JSON.stringify(global.__coverage__);
|
||||
@@ -31,6 +32,7 @@ const testSuiteInstances = [
|
||||
performance,
|
||||
storage,
|
||||
links,
|
||||
iid,
|
||||
];
|
||||
|
||||
/*
|
||||
|
||||
Reference in New Issue
Block a user