@bigin/ns-firebase
Version:
1,185 lines (1,181 loc) • 91.9 kB
JavaScript
import { Application, Utils, AndroidApplication } from '@nativescript/core';
import lazy from '@nativescript/core/utils/lazy';
import { DocumentSnapshot as DocumentSnapshotBase, FieldValue, firebase, GeoPoint, isDocumentReference } from './firebase-common';
import * as firebaseFunctions from './functions/functions';
import * as firebaseMessaging from './messaging/messaging';
export var QueryOrderByType;
(function (QueryOrderByType) {
QueryOrderByType[(QueryOrderByType['KEY'] = 0)] = 'KEY';
QueryOrderByType[(QueryOrderByType['VALUE'] = 1)] = 'VALUE';
QueryOrderByType[(QueryOrderByType['CHILD'] = 2)] = 'CHILD';
QueryOrderByType[(QueryOrderByType['PRIORITY'] = 3)] = 'PRIORITY';
})(QueryOrderByType || (QueryOrderByType = {}));
export var QueryRangeType;
(function (QueryRangeType) {
QueryRangeType[(QueryRangeType['START_AT'] = 0)] = 'START_AT';
QueryRangeType[(QueryRangeType['END_AT'] = 1)] = 'END_AT';
QueryRangeType[(QueryRangeType['EQUAL_TO'] = 2)] = 'EQUAL_TO';
})(QueryRangeType || (QueryRangeType = {}));
export var QueryLimitType;
(function (QueryLimitType) {
QueryLimitType[(QueryLimitType['FIRST'] = 0)] = 'FIRST';
QueryLimitType[(QueryLimitType['LAST'] = 1)] = 'LAST';
})(QueryLimitType || (QueryLimitType = {}));
const gmsAds = com.google.android.gms.ads;
const gmsTasks = com.google.android.gms.tasks;
class DocumentSnapshot extends DocumentSnapshotBase {
constructor(snapshot) {
super(snapshot ? snapshot.getId() : null, snapshot.exists(), firebase.toJsObject(snapshot.getData()), firebase.firestore._getDocumentReference(snapshot.getReference()));
this.snapshot = snapshot;
this.metadata = {
fromCache: this.snapshot.getMetadata().isFromCache(),
hasPendingWrites: this.snapshot.getMetadata().hasPendingWrites(),
};
this.android = snapshot;
}
}
firebase._launchNotification = null;
firebase._cachedDynamicLink = null;
firebase._googleSignInIdToken = null;
firebase._googleSignInAuthCode = null;
firebase._facebookAccessToken = null;
firebase._appleSignInIdToken = null;
let fbCallbackManager = null;
let initializeArguments;
const GOOGLE_SIGNIN_INTENT_ID = 123;
const authEnabled = lazy(() => typeof com.google.firebase.auth !== 'undefined' && typeof com.google.firebase.auth.FirebaseAuth !== 'undefined');
const messagingEnabled = lazy(() => typeof com.google.firebase.messaging !== 'undefined');
const dynamicLinksEnabled = lazy(() => typeof com.google.firebase.dynamiclinks !== 'undefined');
(() => {
Application.android.on(AndroidApplication.activityCreatedEvent, (args) => {
if (messagingEnabled()) {
firebaseMessaging.onAppModuleLaunchEvent(args.activity.getIntent());
}
// if (dynamicLinksEnabled()) {
// const emailLink = '' + args.activity.getIntent().getData();
// if (authEnabled() && com.google.firebase.auth.FirebaseAuth.getInstance().isSignInWithEmailLink(emailLink)) {
// const rememberedEmail = firebase.getRememberedEmailForEmailLinkLogin();
// if (rememberedEmail !== undefined) {
// const emailLinkOnCompleteListener = new gmsTasks.OnCompleteListener({
// onComplete: (task) => {
// if (task.isSuccessful()) {
// const authResult = task.getResult();
// firebase.notifyAuthStateListeners({
// loggedIn: true,
// user: toLoginResult(authResult.getUser(), authResult.getAdditionalUserInfo()),
// });
// }
// },
// });
// const user = com.google.firebase.auth.FirebaseAuth.getInstance().getCurrentUser();
// if (user) {
// const authCredential = com.google.firebase.auth.EmailAuthProvider.getCredentialWithLink(rememberedEmail, emailLink);
// user.linkWithCredential(authCredential).addOnCompleteListener(emailLinkOnCompleteListener);
// } else {
// com.google.firebase.auth.FirebaseAuth.getInstance().signInWithEmailLink(rememberedEmail, emailLink).addOnCompleteListener(emailLinkOnCompleteListener);
// }
// }
// } else {
// const getDynamicLinksCallback = new gmsTasks.OnSuccessListener({
// onSuccess: (pendingDynamicLinkData) => {
// if (pendingDynamicLinkData != null) {
// const deepLink = pendingDynamicLinkData.getLink().toString();
// const minimumAppVersion = pendingDynamicLinkData.getMinimumAppVersion();
// if (firebase._dynamicLinkCallback === null) {
// firebase._cachedDynamicLink = {
// url: deepLink,
// minimumAppVersion: minimumAppVersion,
// };
// } else {
// setTimeout(function () {
// firebase._dynamicLinkCallback({
// url: deepLink,
// minimumAppVersion: minimumAppVersion,
// });
// });
// }
// }
// },
// });
// const firebaseDynamicLinks = com.google.firebase.dynamiclinks.FirebaseDynamicLinks.getInstance();
// firebaseDynamicLinks.getDynamicLink(args.activity.getIntent()).addOnSuccessListener(getDynamicLinksCallback);
// }
// }
});
Application.android.on(AndroidApplication.activityResumedEvent, (args) => {
if (dynamicLinksEnabled()) {
const emailLink = '' + args.activity.getIntent().getData();
if (authEnabled() && com.google.firebase.auth.FirebaseAuth.getInstance().isSignInWithEmailLink(emailLink)) {
const rememberedEmail = firebase.getRememberedEmailForEmailLinkLogin();
if (rememberedEmail !== undefined) {
const emailLinkOnCompleteListener = new gmsTasks.OnCompleteListener({
onComplete: (task) => {
if (task.isSuccessful()) {
const authResult = task.getResult();
firebase.notifyAuthStateListeners({
loggedIn: true,
user: toLoginResult(authResult.getUser(), authResult.getAdditionalUserInfo()),
});
}
},
});
const user = com.google.firebase.auth.FirebaseAuth.getInstance().getCurrentUser();
if (user) {
const authCredential = com.google.firebase.auth.EmailAuthProvider.getCredentialWithLink(rememberedEmail, emailLink);
user.linkWithCredential(authCredential).addOnCompleteListener(emailLinkOnCompleteListener);
} else {
com.google.firebase.auth.FirebaseAuth.getInstance().signInWithEmailLink(rememberedEmail, emailLink).addOnCompleteListener(emailLinkOnCompleteListener);
}
}
} else {
const getDynamicLinksCallback = new gmsTasks.OnSuccessListener({
onSuccess: (pendingDynamicLinkData) => {
if (pendingDynamicLinkData != null) {
const deepLink = pendingDynamicLinkData.getLink().toString();
const minimumAppVersion = pendingDynamicLinkData.getMinimumAppVersion();
// if (!firebase._cachedDynamicLink) {
// firebase._cachedDynamicLink = {
// url: '',
// minimumAppVersion: '',
// };
// }
if (firebase._dynamicLinkCallback === null) {
firebase._cachedDynamicLink = {
url: deepLink,
minimumAppVersion: minimumAppVersion,
};
} else {
if (firebase._cachedDynamicLink === null || firebase._cachedDynamicLink.url !== deepLink) {
setTimeout(function () {
firebase._cachedDynamicLink = {
url: deepLink,
minimumAppVersion: minimumAppVersion,
};
firebase._dynamicLinkCallback({
url: deepLink,
minimumAppVersion: minimumAppVersion,
});
});
}
}
}
},
});
const firebaseDynamicLinks = com.google.firebase.dynamiclinks.FirebaseDynamicLinks.getInstance();
firebaseDynamicLinks.getDynamicLink(args.activity.getIntent()).addOnSuccessListener(getDynamicLinksCallback);
}
}
});
Application.on(Application.resumeEvent, (args) => {
if (messagingEnabled()) {
firebaseMessaging.onAppModuleResumeEvent(args);
}
});
})();
firebase.toHashMap = (obj) => {
const node = new java.util.HashMap();
for (const property in obj) {
if (obj.hasOwnProperty(property)) {
if (obj[property] === null) {
node.put(property, null);
} else {
if (obj[property] === 'SERVER_TIMESTAMP') {
node.put(property, com.google.firebase.firestore.FieldValue.serverTimestamp());
} else if (obj[property] === 'DELETE_FIELD') {
node.put(property, com.google.firebase.firestore.FieldValue.delete());
} else if (obj[property] instanceof FieldValue) {
const fieldValue = obj[property];
if (fieldValue.type === 'ARRAY_UNION') {
let values = Array.isArray(fieldValue.value[0]) ? fieldValue.value[0] : fieldValue.value;
values = values.map((v) => (typeof v === 'object' ? firebase.toHashMap(v) : v));
node.put(property, com.google.firebase.firestore.FieldValue.arrayUnion(values));
} else if (fieldValue.type === 'ARRAY_REMOVE') {
let values = Array.isArray(fieldValue.value[0]) ? fieldValue.value[0] : fieldValue.value;
values = values.map((v) => (typeof v === 'object' ? firebase.toHashMap(v) : v));
node.put(property, com.google.firebase.firestore.FieldValue.arrayRemove(values));
} else if (fieldValue.type === 'INCREMENT') {
node.put(property, com.google.firebase.firestore.FieldValue.increment(fieldValue.value));
} else {
console.log("You found a bug! Please report an issue at https://github.com/EddyVerbruggen/nativescript-plugin-firebase/issues, mention fieldValue.type = '" + fieldValue.type + "'. Thanks!");
}
} else if (obj[property] instanceof Date) {
node.put(property, new java.util.Date(obj[property].getTime()));
} else if (obj[property] instanceof GeoPoint) {
const geo = obj[property];
node.put(property, new com.google.firebase.firestore.GeoPoint(geo.latitude, geo.longitude));
} else if (isDocumentReference(obj[property])) {
node.put(property, obj[property].android);
} else if (Array.isArray(obj[property])) {
node.put(property, firebase.toJavaArray(obj[property]));
} else {
switch (typeof obj[property]) {
case 'object':
node.put(property, firebase.toHashMap(obj[property], node));
break;
case 'boolean':
node.put(property, java.lang.Boolean.valueOf(String(obj[property])));
break;
case 'number':
if (Number(obj[property]) === obj[property] && obj[property] % 1 === 0) node.put(property, java.lang.Long.valueOf(String(obj[property])));
else node.put(property, java.lang.Double.valueOf(String(obj[property])));
break;
case 'string':
node.put(property, String(obj[property]));
break;
}
}
}
}
}
return node;
};
firebase.toJavaArray = (val) => {
const javaArray = new java.util.ArrayList();
for (let i = 0; i < val.length; i++) {
javaArray.add(firebase.toValue(val[i]));
}
return javaArray;
};
firebase.toValue = (val) => {
let returnVal = null;
if (val !== null) {
if (val instanceof Date) {
returnVal = new java.util.Date(val.getTime());
} else if (Array.isArray(val)) {
returnVal = firebase.toJavaArray(val);
} else if (val instanceof GeoPoint) {
returnVal = new com.google.firebase.firestore.GeoPoint(val.latitude, val.longitude);
} else if (isDocumentReference(val)) {
returnVal = val.android;
} else {
switch (typeof val) {
case 'object':
returnVal = firebase.toHashMap(val);
break;
case 'boolean':
returnVal = java.lang.Boolean.valueOf(String(val));
break;
case 'number':
if (Number(val) === val && val % 1 === 0) returnVal = java.lang.Long.valueOf(String(val));
else returnVal = java.lang.Double.valueOf(String(val));
break;
case 'string':
returnVal = String(val);
break;
}
}
}
return returnVal;
};
firebase.toJsObject = (javaObj) => {
if (javaObj === null || typeof javaObj !== 'object') {
return javaObj;
}
let node;
switch (javaObj.getClass().getName()) {
case 'java.lang.Boolean':
const str = String(javaObj);
return Boolean(!!(str === 'True' || str === 'true'));
case 'java.lang.String':
return String(javaObj);
case 'java.lang.Integer':
case 'java.lang.Long':
case 'java.lang.Double':
return Number(String(javaObj));
case 'java.util.Date':
return new Date(javaObj.getTime());
case 'com.google.firebase.Timestamp':
return new Date(javaObj.toDate().getTime());
case 'com.google.firebase.firestore.GeoPoint':
return {
latitude: javaObj.getLatitude(),
longitude: javaObj.getLongitude(),
};
case 'com.google.firebase.firestore.DocumentReference':
const path = javaObj.getPath();
const lastSlashIndex = path.lastIndexOf('/');
return firebase.firestore._getDocumentReference(javaObj, path.substring(0, lastSlashIndex), path.substring(lastSlashIndex + 1));
case 'java.util.ArrayList':
node = [];
for (let i = 0; i < javaObj.size(); i++) {
node[i] = firebase.toJsObject(javaObj.get(i));
}
break;
case 'android.util.ArrayMap':
case 'android.support.v4.util.ArrayMap':
case 'androidx.collection.ArrayMap':
node = {};
for (let i = 0; i < javaObj.size(); i++) {
node[javaObj.keyAt(i)] = firebase.toJsObject(javaObj.valueAt(i));
}
break;
default:
try {
node = {};
const iterator = javaObj.entrySet().iterator();
while (iterator.hasNext()) {
const item = iterator.next();
node[item.getKey()] = firebase.toJsObject(item.getValue());
}
} catch (e) {
if (JSON.stringify(e).includes('Attempt to use cleared object reference')) {
console.log('Error while transforming Java to Js: ' + e);
} else {
console.log('PLEASE REPORT THIS AT https://github.com/EddyVerbruggen/nativescript-plugin-firebase/issues: Tried to serialize an unsupported type: ' + javaObj.getClass().getName() + ', error: ' + e);
}
}
}
return node;
};
firebase.getCallbackData = (type, snapshot) => {
return {
type: type,
key: snapshot.getKey(),
value: firebase.toJsObject(snapshot.getValue()),
};
};
firebase.authStateListener = null;
firebase.init = (arg) => {
return new Promise((resolve, reject) => {
if (firebase.initialized) {
reject('Firebase already initialized');
return;
}
firebase.initialized = true;
const runInit = () => {
arg = arg || {};
initializeArguments = arg;
if (typeof com.google.firebase.analytics !== 'undefined' && typeof com.google.firebase.analytics.FirebaseAnalytics !== 'undefined') {
com.google.firebase.analytics.FirebaseAnalytics.getInstance(Application.android.context || Application.getNativeApplication()).setAnalyticsCollectionEnabled(arg.analyticsCollectionEnabled !== false);
}
if (arg.crashlyticsCollectionEnabled && typeof com.crashlytics !== 'undefined' && typeof com.crashlytics.android.Crashlytics !== 'undefined') {
io.fabric.sdk.android.Fabric.with(Application.android.context || Application.getNativeApplication(), [new com.crashlytics.android.Crashlytics()]);
}
if (typeof com.google.firebase.database !== 'undefined' && typeof com.google.firebase.database.ServerValue !== 'undefined') {
firebase.ServerValue = {
TIMESTAMP: firebase.toJsObject(com.google.firebase.database.ServerValue.TIMESTAMP),
};
const fDatabase = com.google.firebase.database.FirebaseDatabase;
if (arg.persist) {
try {
fDatabase.getInstance().setPersistenceEnabled(true);
} catch (ignore) {}
}
firebase.instance = fDatabase.getInstance().getReference();
}
if (arg.persist === false && typeof com.google.firebase.firestore !== 'undefined') {
try {
com.google.firebase.firestore.FirebaseFirestore.getInstance().setFirestoreSettings(new com.google.firebase.firestore.FirebaseFirestoreSettings.Builder().setPersistenceEnabled(false).build());
} catch (ignore) {}
}
if (authEnabled()) {
const firebaseAuth = com.google.firebase.auth.FirebaseAuth.getInstance();
if (arg.onAuthStateChanged) {
firebase.addAuthStateListener(arg.onAuthStateChanged);
}
if (!firebase.authStateListener) {
firebase.authStateListener = new com.google.firebase.auth.FirebaseAuth.AuthStateListener({
onAuthStateChanged: (fbAuth) => {
const user = fbAuth.getCurrentUser();
firebase.notifyAuthStateListeners({
loggedIn: user !== null,
user: toLoginResult(user),
});
},
});
firebaseAuth.addAuthStateListener(firebase.authStateListener);
}
}
if (messagingEnabled()) {
firebaseMessaging.initFirebaseMessaging(arg);
}
if (arg.onDynamicLinkCallback !== undefined) {
firebase.addOnDynamicLinkReceivedCallback(arg.onDynamicLinkCallback);
}
if (arg.storageBucket) {
if (typeof com.google.firebase.storage === 'undefined') {
reject("Uncomment firebase-storage in the plugin's include.gradle first");
return;
}
firebase.storageBucket = com.google.firebase.storage.FirebaseStorage.getInstance().getReferenceFromUrl(arg.storageBucket);
}
if (typeof gmsAds !== 'undefined' && typeof gmsAds.MobileAds !== 'undefined') {
gmsAds.MobileAds.initialize(Application.android.context);
}
resolve(firebase.instance);
};
try {
if (Application.android.startActivity) {
runInit();
} else {
Application.on(Application.launchEvent, runInit);
}
} catch (ex) {
console.log('Error in firebase.init: ' + ex);
reject(ex);
}
});
};
firebase.fetchSignInMethodsForEmail = (email) => {
return new Promise((resolve, reject) => {
try {
if (typeof email !== 'string') {
reject('A parameter representing an email address is required.');
return;
}
const onCompleteListener = new gmsTasks.OnCompleteListener({
onComplete: (task) => {
if (!task.isSuccessful()) {
reject(task.getException() && task.getException().getReason ? task.getException().getReason() : task.getException());
} else {
const signInMethods = task.getResult().getSignInMethods();
resolve(firebase.toJsObject(signInMethods));
}
},
});
com.google.firebase.auth.FirebaseAuth.getInstance().fetchSignInMethodsForEmail(email).addOnCompleteListener(onCompleteListener);
} catch (ex) {
console.log('Error in firebase.fetchSignInMethodsForEmail: ' + ex);
reject(ex);
}
});
};
firebase.getCurrentPushToken = firebaseMessaging.getCurrentPushToken;
firebase.addOnMessageReceivedCallback = firebaseMessaging.addOnMessageReceivedCallback;
firebase.addOnPushTokenReceivedCallback = firebaseMessaging.addOnPushTokenReceivedCallback;
firebase.registerForPushNotifications = firebaseMessaging.registerForPushNotifications;
firebase.unregisterForPushNotifications = firebaseMessaging.unregisterForPushNotifications;
firebase.subscribeToTopic = firebaseMessaging.subscribeToTopic;
firebase.unsubscribeFromTopic = firebaseMessaging.unsubscribeFromTopic;
firebase.areNotificationsEnabled = firebaseMessaging.areNotificationsEnabled;
firebase.functions = firebaseFunctions;
firebase.addOnDynamicLinkReceivedCallback = (callback) => {
return new Promise((resolve, reject) => {
try {
if (typeof com.google.firebase.dynamiclinks === 'undefined') {
reject("Uncomment dynamic links in the plugin's include.gradle first");
return;
}
firebase._dynamicLinkCallback = callback;
if (firebase._cachedDynamicLink !== null) {
callback(firebase._cachedDynamicLink);
// firebase._cachedDynamicLink = null;
}
resolve();
} catch (ex) {
console.log('Error in firebase.addOnDynamicLinkReceivedCallback: ' + ex);
reject(ex);
}
});
};
firebase.getRemoteConfigDefaults = (properties) => {
let defaults = {};
for (const p in properties) {
const prop = properties[p];
if (prop.default !== undefined) {
defaults[prop.key] = prop.default;
}
}
return defaults;
};
firebase._isGooglePlayServicesAvailable = () => {
const ctx = Application.android.foregroundActivity || Application.android.startActivity || Application.getNativeApplication();
const googleApiAvailability = com.google.android.gms.common.GoogleApiAvailability.getInstance();
const playServiceStatusSuccess = 0;
const playServicesStatus = googleApiAvailability.isGooglePlayServicesAvailable(ctx);
const available = playServicesStatus === playServiceStatusSuccess;
if (!available && googleApiAvailability.isUserResolvableError(playServicesStatus)) {
googleApiAvailability.showErrorDialogFragment(
ctx,
playServicesStatus,
1,
new android.content.DialogInterface.OnCancelListener({
onCancel: (dialogInterface) => {
console.log('Canceled');
},
})
);
}
return available;
};
firebase.getRemoteConfig = (arg) => {
return new Promise((resolve, reject) => {
if (typeof com.google.firebase.remoteconfig === 'undefined') {
reject("Uncomment firebase-config in the plugin's include.gradle first");
return;
}
if (arg.properties === undefined) {
reject("Argument 'properties' is missing");
return;
}
const runGetRemoteConfig = () => {
if (!firebase._isGooglePlayServicesAvailable()) {
reject('Google Play services is required for this feature, but not available on this device');
return;
}
const firebaseRemoteConfig = com.google.firebase.remoteconfig.FirebaseRemoteConfig.getInstance();
const remoteConfigSettingsBuilder = new com.google.firebase.remoteconfig.FirebaseRemoteConfigSettings.Builder();
if (arg.developerMode === true) {
remoteConfigSettingsBuilder.setFetchTimeoutInSeconds(0);
}
const onSetConfigSettingsCompleteListener = new gmsTasks.OnCompleteListener({
onComplete: (task) => {
if (!task.isSuccessful()) {
reject(task.getException() && task.getException().getReason ? task.getException().getReason() : task.getException());
} else {
const defaults = firebase.getRemoteConfigDefaults(arg.properties);
firebaseRemoteConfig.setDefaultsAsync(firebase.toHashMap(defaults)).addOnCompleteListener(
new gmsTasks.OnCompleteListener({
onComplete: (task) => {
if (!task.isSuccessful()) {
reject(task.getException() && task.getException().getReason ? task.getException().getReason() : task.getException());
} else {
const returnMethod = (throttled) => {
const addOnCompleteActivateListener = new gmsTasks.OnCompleteListener({
onComplete: (task) => {
if (!task.isSuccessful()) {
reject(task.getException() && task.getException().getReason ? task.getException().getReason() : task.getException());
} else {
const lastFetchTime = firebaseRemoteConfig.getInfo().getFetchTimeMillis();
const lastFetch = new Date(lastFetchTime);
const result = {
lastFetch,
throttled,
properties: {},
};
for (const p in arg.properties) {
const prop = arg.properties[p];
const key = prop.key;
const value = firebaseRemoteConfig.getString(key);
result.properties[key] = firebase.strongTypeify(value);
}
resolve(result);
}
},
});
firebaseRemoteConfig.activate().addOnCompleteListener(addOnCompleteActivateListener);
};
const onSuccessListener = new gmsTasks.OnSuccessListener({
onSuccess: () => returnMethod(false),
});
const onFailureListener = new gmsTasks.OnFailureListener({
onFailure: (exception) => {
if (exception.getMessage() === 'com.google.firebase.remoteconfig.FirebaseRemoteConfigFetchThrottledException') {
returnMethod(true);
} else {
reject('Retrieving remote config data failed. ' + exception);
}
},
});
const expirationDuration = arg.cacheExpirationSeconds || 43200;
firebaseRemoteConfig.fetch(expirationDuration).addOnSuccessListener(onSuccessListener).addOnFailureListener(onFailureListener);
}
},
})
);
}
},
});
firebaseRemoteConfig.setConfigSettingsAsync(remoteConfigSettingsBuilder.build()).addOnCompleteListener(onSetConfigSettingsCompleteListener);
};
try {
if (Application.android.foregroundActivity) {
runGetRemoteConfig();
} else {
const callback = () => {
runGetRemoteConfig();
Application.off(Application.resumeEvent, callback);
};
Application.on(Application.resumeEvent, callback);
}
} catch (ex) {
console.log('Error in firebase.getRemoteConfig: ' + ex);
reject(ex);
}
});
};
firebase.getCurrentUser = (arg) => {
return new Promise((resolve, reject) => {
try {
const firebaseAuth = com.google.firebase.auth.FirebaseAuth.getInstance();
const user = firebaseAuth.getCurrentUser();
if (user !== null) {
resolve(toLoginResult(user));
} else {
reject();
}
} catch (ex) {
console.log('Error in firebase.getCurrentUser: ' + ex);
reject(ex);
}
});
};
firebase.sendEmailVerification = (actionCodeSettings) => {
return new Promise((resolve, reject) => {
try {
const firebaseAuth = com.google.firebase.auth.FirebaseAuth.getInstance();
const user = firebaseAuth.getCurrentUser();
if (user !== null) {
const addOnCompleteListener = new gmsTasks.OnCompleteListener({
onComplete: (task) => {
if (!task.isSuccessful()) {
reject(task.getException() && task.getException().getReason ? task.getException().getReason() : task.getException());
} else {
resolve();
}
},
});
if (actionCodeSettings) {
const settingsBuilder = new com.google.firebase.auth.ActionCodeSettings.newBuilder();
if (actionCodeSettings.handleCodeInApp !== undefined) {
settingsBuilder.setHandleCodeInApp(actionCodeSettings.handleCodeInApp);
}
if (actionCodeSettings.url) {
settingsBuilder.setUrl(actionCodeSettings.url);
}
if (actionCodeSettings.iOS && actionCodeSettings.iOS.bundleId) {
settingsBuilder.setIOSBundleId(actionCodeSettings.iOS.bundleId);
}
if (actionCodeSettings.android && actionCodeSettings.android.packageName) {
settingsBuilder.setAndroidPackageName(actionCodeSettings.android.packageName, actionCodeSettings.android.installApp, actionCodeSettings.android.minimumVersion || null);
}
user.sendEmailVerification(settingsBuilder.build()).addOnCompleteListener(addOnCompleteListener);
} else {
user.sendEmailVerification().addOnCompleteListener(addOnCompleteListener);
}
} else {
reject('Log in first');
}
} catch (ex) {
console.log('Error in firebase.sendEmailVerification: ' + ex);
reject(ex);
}
});
};
firebase.logout = (arg) => {
return new Promise((resolve, reject) => {
try {
com.google.firebase.auth.FirebaseAuth.getInstance().signOut();
firebase.currentAdditionalUserInfo = null;
if (firebase._mGoogleApiClient && firebase._mGoogleApiClient.isConnected()) {
com.google.android.gms.auth.api.Auth.GoogleSignInApi.revokeAccess(firebase._mGoogleApiClient);
}
if (typeof com.facebook !== 'undefined' && typeof com.facebook.login !== 'undefined') {
com.facebook.login.LoginManager.getInstance().logOut();
}
resolve();
} catch (ex) {
console.log('Error in firebase.logout: ' + ex);
reject(ex);
}
});
};
firebase.unlink = (providerId) => {
return new Promise((resolve, reject) => {
try {
const user = com.google.firebase.auth.FirebaseAuth.getInstance().getCurrentUser();
if (!user) {
reject('Not logged in');
return;
}
user.unlink(providerId).addOnCompleteListener(
new gmsTasks.OnCompleteListener({
onComplete: (task) => {
if (task.isSuccessful()) {
resolve();
} else {
reject(task.getException() && task.getException().getReason ? task.getException().getReason() : task.getException());
}
},
})
);
} catch (ex) {
console.log('Error in firebase.unlink: ' + ex);
reject(ex);
}
});
};
firebase.getAuthToken = (arg) => {
return new Promise((resolve, reject) => {
try {
const firebaseAuth = com.google.firebase.auth.FirebaseAuth.getInstance();
const user = firebaseAuth.getCurrentUser();
if (user !== null) {
const onSuccessListener = new gmsTasks.OnSuccessListener({
onSuccess: (tokenResult) => {
resolve({
token: tokenResult.getToken(),
claims: firebase.toJsObject(tokenResult.getClaims()),
signInProvider: tokenResult.getSignInProvider(),
expirationTime: tokenResult.getExpirationTimestamp(),
issuedAtTime: tokenResult.getIssuedAtTimestamp(),
authTime: tokenResult.getAuthTimestamp(),
});
},
});
const onFailureListener = new gmsTasks.OnFailureListener({
onFailure: (exception) => {
reject(exception);
},
});
user.getIdToken(arg.forceRefresh).addOnSuccessListener(onSuccessListener).addOnFailureListener(onFailureListener);
} else {
reject('Log in first');
}
} catch (ex) {
console.log('Error in firebase.getAuthToken: ' + ex);
reject(ex);
}
});
};
function toLoginResult(user, additionalUserInfo) {
if (user === null) {
return null;
}
if (additionalUserInfo) {
firebase.currentAdditionalUserInfo = additionalUserInfo;
}
const providers = [];
const providerData = user.getProviderData();
for (let i = 0; i < providerData.size(); i++) {
const pid = providerData.get(i).getProviderId();
if (pid === 'facebook.com') {
providers.push({ id: pid, token: firebase._facebookAccessToken });
} else if (pid === 'google.com') {
providers.push({ id: pid, token: firebase._googleSignInAuthCode });
} else if (pid === 'apple.com') {
providers.push({ id: pid, token: firebase._appleSignInIdToken });
} else {
providers.push({ id: pid });
}
}
const loginResult = {
uid: user.getUid(),
displayName: user.getDisplayName(),
email: user.getEmail(),
emailVerified: user.isEmailVerified(),
providers: providers,
anonymous: user.isAnonymous(),
isAnonymous: user.isAnonymous(),
phoneNumber: user.getPhoneNumber(),
photoURL: user.getPhotoUrl() ? user.getPhotoUrl().toString() : null,
metadata: {
creationTimestamp: user.getMetadata() ? new Date(user.getMetadata().getCreationTimestamp()) : null,
lastSignInTimestamp: user.getMetadata() ? new Date(user.getMetadata().getLastSignInTimestamp()) : null,
},
getIdToken: (forceRefresh) =>
new Promise((resolve, reject) => {
firebase
.getAuthToken({ forceRefresh })
.then((result) => resolve(result.token))
.catch(reject);
}),
getIdTokenResult: (forceRefresh) =>
new Promise((resolve, reject) => {
firebase
.getAuthToken({ forceRefresh })
.then((result) => resolve(result))
.catch(reject);
}),
sendEmailVerification: (actionCodeSettings) => firebase.sendEmailVerification(actionCodeSettings),
};
if (firebase.currentAdditionalUserInfo) {
loginResult.additionalUserInfo = {
providerId: firebase.currentAdditionalUserInfo.getProviderId(),
username: firebase.currentAdditionalUserInfo.getUsername(),
isNewUser: firebase.currentAdditionalUserInfo.isNewUser(),
profile: firebase.toJsObject(firebase.currentAdditionalUserInfo.getProfile()),
};
}
return loginResult;
}
firebase.login = (arg) => {
return new Promise((resolve, reject) => {
try {
firebase.resolve = resolve;
firebase.reject = reject;
if (!firebase._isGooglePlayServicesAvailable()) {
reject('Google Play services is required for this feature, but not available on this device');
return;
}
firebase.moveLoginOptionsToObjects(arg);
const firebaseAuth = com.google.firebase.auth.FirebaseAuth.getInstance();
const onCompleteListener = new gmsTasks.OnCompleteListener({
onComplete: (task) => {
if (!task.isSuccessful()) {
console.log('Logging in the user failed. ' + (task.getException() && task.getException().getReason ? task.getException().getReason() : task.getException()));
if (firebase._mGoogleApiClient) {
com.google.android.gms.auth.api.Auth.GoogleSignInApi.revokeAccess(firebase._mGoogleApiClient);
}
if (firebase.reject) {
firebase.reject('Logging in the user failed. ' + (task.getException() && task.getException().getReason ? task.getException().getReason() : task.getException()));
}
} else {
const user = task.getResult().getUser();
let additionalUserInfo = task.getResult().getAdditionalUserInfo();
if (firebase.resolve) {
firebase.resolve(toLoginResult(user, additionalUserInfo));
}
}
},
});
if (arg.type === firebase.LoginType.ANONYMOUS) {
firebaseAuth.signInAnonymously().addOnCompleteListener(onCompleteListener);
} else if (arg.type === firebase.LoginType.PASSWORD) {
if (!arg.passwordOptions || !arg.passwordOptions.email || !arg.passwordOptions.password) {
reject("Auth type PASSWORD requires an 'passwordOptions.email' and 'passwordOptions.password' argument");
return;
}
const user = com.google.firebase.auth.FirebaseAuth.getInstance().getCurrentUser();
if (user) {
if (firebase._alreadyLinkedToAuthProvider(user, 'password')) {
firebaseAuth.signInWithEmailAndPassword(arg.passwordOptions.email, arg.passwordOptions.password).addOnCompleteListener(onCompleteListener);
} else {
const authCredential = com.google.firebase.auth.EmailAuthProvider.getCredential(arg.passwordOptions.email, arg.passwordOptions.password);
user.linkWithCredential(authCredential).addOnCompleteListener(onCompleteListener);
}
} else {
firebaseAuth.signInWithEmailAndPassword(arg.passwordOptions.email, arg.passwordOptions.password).addOnCompleteListener(onCompleteListener);
}
} else if (arg.type === firebase.LoginType.EMAIL_LINK) {
if (!arg.emailLinkOptions || !arg.emailLinkOptions.email) {
reject("Auth type EMAIL_LINK requires an 'emailLinkOptions.email' argument");
return;
}
if (!arg.emailLinkOptions.url) {
reject("Auth type EMAIL_LINK requires an 'emailLinkOptions.url' argument");
return;
}
const actionCodeSettings = com.google.firebase.auth.ActionCodeSettings.newBuilder()
.setUrl(arg.emailLinkOptions.url)
.setHandleCodeInApp(true)
.setIOSBundleId(arg.emailLinkOptions.iOS ? arg.emailLinkOptions.iOS.bundleId : Application.android.context.getPackageName())
.setAndroidPackageName(arg.emailLinkOptions.android ? arg.emailLinkOptions.android.packageName : Application.android.context.getPackageName(), arg.emailLinkOptions.android ? arg.emailLinkOptions.android.installApp || false : false, arg.emailLinkOptions.android ? arg.emailLinkOptions.android.minimumVersion || '1' : '1')
.build();
const onEmailLinkCompleteListener = new gmsTasks.OnCompleteListener({
onComplete: (task) => {
if (!task.isSuccessful()) {
reject(task.getException() && task.getException().getReason ? task.getException().getReason() : task.getException());
} else {
firebase.rememberEmailForEmailLinkLogin(arg.emailLinkOptions.email);
resolve();
}
},
});
firebaseAuth.sendSignInLinkToEmail(arg.emailLinkOptions.email, actionCodeSettings).addOnCompleteListener(onEmailLinkCompleteListener);
} else if (arg.type === firebase.LoginType.PHONE) {
if (!arg.phoneOptions || !arg.phoneOptions.phoneNumber) {
reject("Auth type PHONE requires a 'phoneOptions.phoneNumber' argument");
return;
}
const user = com.google.firebase.auth.FirebaseAuth.getInstance().getCurrentUser();
if (user && firebase._alreadyLinkedToAuthProvider(user, 'phone')) {
resolve(toLoginResult(user));
return;
}
const OnVerificationStateChangedCallbacks = com.google.firebase.auth.PhoneAuthProvider.OnVerificationStateChangedCallbacks.extend({
onVerificationCompleted: (phoneAuthCredential) => {
firebase._verifyPhoneNumberInProgress = false;
const user = com.google.firebase.auth.FirebaseAuth.getInstance().getCurrentUser();
if (!user || firebase._alreadyLinkedToAuthProvider(user, 'phone')) {
firebaseAuth.signInWithCredential(phoneAuthCredential).addOnCompleteListener(onCompleteListener);
} else {
user.linkWithCredential(phoneAuthCredential).addOnCompleteListener(onCompleteListener);
}
},
onVerificationFailed: (firebaseException) => {
firebase._verifyPhoneNumberInProgress = false;
const errorMessage = firebaseException.getMessage();
if (errorMessage.includes('INVALID_APP_CREDENTIAL')) {
if (firebase.reject) {
firebase.reject('Please upload the SHA1 fingerprint of your debug and release keystores to the Firebase console, see https://github.com/EddyVerbruggen/nativescript-plugin-firebase/blob/master/docs/AUTHENTICATION.md#phone-verification');
}
} else {
if (firebase.reject) {
firebase.reject(errorMessage);
}
}
},
onCodeSent: (verificationId, forceResendingToken) => {
setTimeout(() => {
if (firebase._verifyPhoneNumberInProgress) {
firebase._verifyPhoneNumberInProgress = false;
firebase.requestPhoneAuthVerificationCode((userResponse) => {
if (userResponse === undefined && firebase.reject) {
firebase.reject('Prompt was canceled');
return;
}
const authCredential = com.google.firebase.auth.PhoneAuthProvider.getCredential(verificationId, userResponse);
const user = com.google.firebase.auth.FirebaseAuth.getInstance().getCurrentUser();
if (!user || firebase._alreadyLinkedToAuthProvider(user, 'phone')) {
firebaseAuth.signInWithCredential(authCredential).addOnCompleteListener(onCompleteListener);
} else {
user.linkWithCredential(authCredential).addOnCompleteListener(onCompleteListener);
}
}, arg.phoneOptions.verificationPrompt);
}
}, 3000);
},
});
firebase._verifyPhoneNumberInProgress = true;
let timeout = arg.phoneOptions.android ? arg.phoneOptions.android.timeout : 60;
com.google.firebase.auth.PhoneAuthProvider.getInstance().verifyPhoneNumber(arg.phoneOptions.phoneNumber, timeout, java.util.concurrent.TimeUnit.SECONDS, Application.android.foregroundActivity, new OnVerificationStateChangedCallbacks());
} else if (arg.type === firebase.LoginType.CUSTOM) {
if (!arg.customOptions || (!arg.customOptions.token && !arg.customOptions.tokenProviderFn)) {
reject("Auth type CUSTOM requires a 'customOptions.token' or 'customOptions.tokenProviderFn' argument");
return;
}
if (arg.customOptions.token) {
firebaseAuth.signInWithCustomToken(arg.customOptions.token).addOnCompleteListener(onCompleteListener);
} else if (arg.customOptions.tokenProviderFn) {
arg.customOptions.tokenProviderFn().then(
(token) => {
firebaseAuth.signInWithCustomToken(token).addOnCompleteListener(onCompleteListener);
},
(error) => {
reject(error);
}
);
}
} else if (arg.type === firebase.LoginType.FACEBOOK) {
if (typeof com.facebook === 'undefined' || typeof com.facebook.FacebookSdk === 'undefined') {
reject('Facebook SDK not installed - see gradle config');
return;
}
if (!fbCallbackManager) {
com.facebook.FacebookSdk.sdkInitialize(Application.getNativeApplication());
fbCallbackManager = com.facebook.CallbackManager.Factory.create();
}
const callback = (eventData) => {
Application.android.off(AndroidApplication.activityResultEvent, callback);
fbCallbackManager.onActivityResult(eventData.requestCode, eventData.resultCode, eventData.intent);
};
Application.android.on(AndroidApplication.activityResultEvent, callback);
const fbLoginManager = com.facebook.login.LoginManager.getInstance();
fbLoginManager.registerCallback(
fbCallbackManager,
new com.facebook.FacebookCallback({
onSuccess: (loginResult) => {
firebase._facebookAccessToken = loginResult.getAccessToken().getToken();
const authCredential = com.google.firebase.auth.FacebookAuthProvider.getCredential(firebase._facebookAccessToken);
const user = com.google.firebase.auth.FirebaseAuth.getInstance().getCurrentUser();
if (user) {
if (firebase._alreadyLinkedToAuthProvider(user, 'facebook.com')) {
firebaseAuth.signInWithCredential(authCredential).addOnCompleteListener(onCompleteListener);
} else {
user.linkWithCredential(authCredential).addOnCompleteListener(onCompleteListener);
}
} else {
firebaseAuth.signInWithCredential(authCredential).addOnCompleteListener(onCompleteListener);
}
},
onCancel: () => reject('Facebook Login canceled'),
onError: (ex) => reject('Error while trying to login with Fb ' + ex),
})
);
let scopes = ['public_profile', 'email'];
if (arg.facebookOptions && arg.facebookOptions.scopes) {
scopes = arg.facebookOptions.scopes;
}
const permissions = Utils.android.collections.stringArrayToStringSet(scopes);
const activity = Application.android.foregroundActivity;
fbLoginManager.logInWithReadPermissions(activity, permissions);
} else if (arg.type === firebase.LoginType.APPLE) {
const onSuccessListener = new gmsTasks.OnSuccessListener({
onSuccess: (authResult) => {
firebase._appleSignInIdToken = authResult.getCredential().getIdToken();
const loginResult = toLoginResult(authResult.getUser(), authResult.getAdditionalUserInfo());
firebase.notifyAuthStateListeners({
loggedIn: true,
user: loginResult,
});
resolve(loginResult);
},
});
const onFailureListener = new gmsTasks.OnFailureListener({
onFailure: (exception) => {
reject(exception.getMessage());
},
});
const pendingAuthResult = firebaseAuth.getPendingAuthResult();
if (pendingAuthResult) {
pendingAuthResult.addOnSuccessListener(onSuccessListener).addOnFailureListener(onFailureListener);
} else {
const oAuthProviderBuilder = com.google.firebase.auth.OAuthProvider.newBuilder('apple.com');
let scopes = ['name', 'email'];
if (arg.appleOptions && arg.appleOptions.scopes) {
scopes = arg.appleOptions.scopes;
}
oAuthProviderBuilder.setScopes(firebase.toJavaArray(scopes));
if (arg.appleOptions && arg.appleOptions.locale) {
oAuthProviderBuilder.addCustomParameter('locale', arg.appleOptions.locale);
}
const provider = oAuthProviderBuilder.build();
firebaseAuth
.startActivityForSignInWithProvider(Application.android.foregroundActivity || Application.android.startActivity, provider)
.addOnSuccessListener(onSuccessListener)
.addOnFailureListener(onFailureListener);
}
} else if (arg.type === firebase.LoginType.GOOGLE) {
if (typeof com.google.android.gms.auth.api.Auth === 'undefined') {
reject('Google Sign In not installed - see gradle config');
return;
}
const clientStringId = Utils.android.resources.getStringId('default_web_client_id');
const clientId = Utils.android.getApplicationContext().getResources().getString(clientStringId);
const googleSignInOptionsBuilder = new com.google.android.gms.auth.api.signin.GoogleSignInOptions.Builder(com.google.android.gms.auth.api.signin.GoogleSignInOptions.DEFAULT_SIGN_IN).requestServerAuthCode(clientId).requestIdToken(clientId).requestEmail();
if (arg.googleOptions && arg.googleOptions.hostedDomain) {
googleSignInOptionsBuilder.setHostedDomain(arg.googleOptions.hostedDomain);
}
if (arg.googleOptions && arg.googleOptions.scopes) {
const scopesArray = [];
if (arg.googleOptions.scopes.length > 1) {
arg.googleOptions.scopes.forEach((s) => scopesArray.push(new com.google.android.gms.common.api.Scope(s)));
}
googleSignInOptionsBuilder.requestScopes(new com.google.android.gms.common.api.Scope(arg.googleOptions.scopes[0]), scopesArray);
}
const googleSignInOptions = googleSignInOptionsBuilder.build();
const onConnectionFailedListener = new com.google.android.gms.common.api.GoogleApiClient.OnConnectionFailedListener({
onConnectionFailed: (connectionResult) => {
reject(connectionResult.getErrorMessage());
},
});
firebase._mGoogleApiClient = new com.google.android.gms.common.api.GoogleApiClient.Builder(Application.getNativeApplication()).addOnConnectionFailedListener(onConnectionFailedListener).addApi(com.google.android.gms.auth.api.Auth.GOOGLE_SIGN_IN_API, googleSignInOptions).build();
const signInIntent = com.google.android.gms.auth.api.Auth.GoogleSignInApi.getSignInIntent(firebase._mGoogleApiClient);
(Application.android.foregroundActivity || Application.android.startActivity).startActivityForResult(signInIntent, GOOGLE_SIGNIN_INTENT_ID);
const callback = (eventData) => {
if (eventData.requestCode === GOOGLE_SIGNIN_INTENT_ID) {
Application.android.off(AndroidApplication.activityResultEvent, callback);
const googleSignInResult = com.google.android.gms.auth.api.Auth.GoogleSignInApi.getSignInResultFromIntent(eventData.intent);
if (googleSignInResult === null) {
reject('No googleSignInResult, eventData.intent seems to be invalid');
return;
}
const success = googleSignInResult.isSuccess();
if (success) {
const googleSignInAccount = googleSignInResult.getSignInAccount();
firebase._googleSignInIdToken = googleSignInAccount.getIdToken();
firebase._googleSignInAuthCode = googleSignInAccount.getServerAuthCode();
const accessToken = null;
const authCredential = com.google.firebase.auth.GoogleAuthProvider.getCredential(firebase._googleSignInIdToken, accessToken);
firebase._mGoogleApiClient.connect();
const user = com.google.firebase.auth.FirebaseAuth.getInstance().getCurrentUser();
if (user) {
if (firebase._alreadyLinkedToAuthProvider(user, 'google.com')) {
firebaseAuth.signInWithCredential(authCredential).addOnCompleteListener(onCompleteListener);
} else {
user.linkWithCredential(authCredential).addOnCompleteListener(onCompleteListener);
}
} else {
firebaseAuth.signInWithCredential(authCredential).addOnCompleteListener(onCompleteListener);
}
} else {
console.log("Make sure you've uploaded your SHA1 fingerprint(s) to the Firebase console. Status: " + googleSignInResult.getStatus());
reject('Has the SHA1 fingerprint been uploaded? Sign-in status: ' + googleSignInResult.getStatus());
}
}
};
Application.android.on(AndroidApplication.activityResultEvent, callback);
} else {
reject('Unsupported auth type: ' + arg.type);
}
} catch (ex) {
console.log('Error in firebase.login: ' + ex);
reject(ex);
}
});
};
firebase._alreadyLinkedToAuthProvider = (user, providerId) => {
const providerData = user.getProviderData();
for (let i = 0; i < providerData.size(); i++) {
const profile = providerData.get(i);
if (profile.getProviderId() === providerId) {
return true;
}
}
return false;
};
firebase.reauthenticate = (arg) => {
return new Promise((resolve, reject) => {
try {
const user = com.google.firebase.auth.FirebaseAuth.getInstance().getCurrentUser();
if (user === null) {
reject('no current user');
return;
}
firebase.moveLoginOptionsToObjects(arg);
let authCredential = null;
if (arg.type === firebase.LoginType.PASSWORD) {
if (!arg.passwordOptions || !arg.passwordOptions.email || !arg.passwordOptions.password) {
reject("Auth type PASSWORD requires an 'passwordOptions.email' and 'passwordOptions.password' argument");
return;
}
authCredential = com.google.firebase.auth.EmailAuthProvider.getCredential(arg.passwordOptions.email, arg.passwordOptions.password);
} else if (arg.type === firebase.LoginType.GOOGLE) {
if (!firebase._googleSignInIdToken) {
reject('Not currently logged in with Google');
return;
}
authCredential = com.google.firebase.auth.GoogleAuthProvider.getCredential(firebase._googleSignInIdToken, null);
} else if (arg.type === firebase.LoginType.FACEBOOK) {
if (!firebase._facebookAccessToken) {
reject('Not currently logged in with Facebook');
return;
}
authCredential = com.google.firebase.auth.FacebookAuthProvider.getCredential(firebase._facebookAccessToken);
}
if (authCredential === null) {
reject('arg.type should be one of LoginType.PASSWORD | LoginType.GOOGLE | LoginType.FACEBOOK');
return;
}
const onCompleteListener = new gmsTasks.OnCompleteListener({
onComplete: (task) => {
if (task.isSuccessful()) {
const user = com.google.firebase.auth.FirebaseAuth.getInstance().getCurrentUser();
const loginResult = toLoginResult(user);
firebase.notifyAuthStateListeners({
loggedIn: true,
user: loginResult,
});
resolve(loginResult);
} else {
reject(task.getException() && task.getException().getReason ? task.getException().getReason() : task.getException());
}
},
});
user.reauthenticate(authCredential).addOnCompleteListener(onCompleteListener);
} catch (ex) {
console.log('Error in firebase.reauthenticate: ' + ex);
reject(ex);
}
});
};
firebase.reloadUser = () => {
return new Promise((resolve, reject) => {
try {
const user = com.google.firebase.auth.FirebaseAuth.getInstance().getCurrentUser();
if (user === null) {
reject('no current user');
return;
}
const onCompleteListener = new gmsTasks.OnCompleteListener({
onComplete: (task) => {
if (task.isSuccessful()) {
resolve();
} else {
reject('Reload failed ' + task.getException());
}
},
});
user.reload().addOnCompleteListener(onCompleteListener);
} catch (ex) {
reject(ex);
}
});
};
firebase.sendPasswordResetEmail = (email) => {
return new Promise((resolve, reject) => {
try {
const onCompleteListener = new gmsTasks.OnCompleteListener({
onComplete: (task) => {
if (task.isS