react-native-firebase-compiled
Version:
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, Sto
343 lines (260 loc) • 8.85 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = void 0;
var _internals = _interopRequireDefault(require("../../../utils/internals"));
var _events = require("../../../utils/events");
var _utils = require("../../../utils");
var _native = require("../../../utils/native");
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
class PhoneAuthListener {
/**
*
* @param auth
* @param phoneNumber
* @param timeout
* @param forceResend
*/
constructor(auth, phoneNumber, timeout, forceResend) {
_defineProperty(this, "_auth", void 0);
_defineProperty(this, "_timeout", void 0);
_defineProperty(this, "_publicEvents", void 0);
_defineProperty(this, "_internalEvents", void 0);
_defineProperty(this, "_forceResending", void 0);
_defineProperty(this, "_reject", void 0);
_defineProperty(this, "_resolve", void 0);
_defineProperty(this, "_credential", void 0);
_defineProperty(this, "_promise", void 0);
_defineProperty(this, "_phoneAuthRequestKey", void 0);
this._auth = auth;
this._reject = null;
this._resolve = null;
this._promise = null;
this._credential = null;
this._timeout = timeout || 20; // 20 secs
this._forceResending = forceResend || false;
this._phoneAuthRequestKey = (0, _utils.generatePushID)(); // internal events
this._internalEvents = {
codeSent: `phone:auth:${this._phoneAuthRequestKey}:onCodeSent`,
verificationFailed: `phone:auth:${this._phoneAuthRequestKey}:onVerificationFailed`,
verificationComplete: `phone:auth:${this._phoneAuthRequestKey}:onVerificationComplete`,
codeAutoRetrievalTimeout: `phone:auth:${this._phoneAuthRequestKey}:onCodeAutoRetrievalTimeout`
}; // user observer events
this._publicEvents = {
// error cb
error: `phone:auth:${this._phoneAuthRequestKey}:error`,
// observer
event: `phone:auth:${this._phoneAuthRequestKey}:event`,
// success cb
success: `phone:auth:${this._phoneAuthRequestKey}:success`
}; // setup internal event listeners
this._subscribeToEvents(); // start verification flow natively
if (_utils.isAndroid) {
(0, _native.getNativeModule)(this._auth).verifyPhoneNumber(phoneNumber, this._phoneAuthRequestKey, this._timeout, this._forceResending);
}
if (_utils.isIOS) {
(0, _native.getNativeModule)(this._auth).verifyPhoneNumber(phoneNumber, this._phoneAuthRequestKey);
}
}
/**
* Subscribes to all EE events on this._internalEvents
* @private
*/
_subscribeToEvents() {
const events = Object.keys(this._internalEvents);
for (let i = 0, len = events.length; i < len; i++) {
const type = events[i];
_events.SharedEventEmitter.once(this._internalEvents[type], // $FlowExpectedError: Flow doesn't support indexable signatures on classes: https://github.com/facebook/flow/issues/1323
this[`_${type}Handler`].bind(this));
}
}
/**
* Subscribe a users listener cb to the snapshot events.
* @param observer
* @private
*/
_addUserObserver(observer) {
_events.SharedEventEmitter.addListener(this._publicEvents.event, observer);
}
/**
* Send a snapshot event to users event observer.
* @param snapshot PhoneAuthSnapshot
* @private
*/
_emitToObservers(snapshot) {
_events.SharedEventEmitter.emit(this._publicEvents.event, snapshot);
}
/**
* Send a error snapshot event to any subscribed errorCb's
* @param snapshot
* @private
*/
_emitToErrorCb(snapshot) {
const error = snapshot.error;
if (this._reject) this._reject(error);
_events.SharedEventEmitter.emit(this._publicEvents.error, error);
}
/**
* Send a success snapshot event to any subscribed completeCb's
* @param snapshot
* @private
*/
_emitToSuccessCb(snapshot) {
if (this._resolve) this._resolve(snapshot);
_events.SharedEventEmitter.emit(this._publicEvents.success, snapshot);
}
/**
* Removes all listeners for this phone auth instance
* @private
*/
_removeAllListeners() {
setTimeout(() => {
// move to next event loop - not sure if needed
// internal listeners
Object.values(this._internalEvents).forEach(event => {
_events.SharedEventEmitter.removeAllListeners(event);
}); // user observer listeners
Object.values(this._publicEvents).forEach(publicEvent => {
_events.SharedEventEmitter.removeAllListeners(publicEvent);
});
}, 0);
}
/**
* Create a new internal deferred promise, if not already created
* @private
*/
_promiseDeferred() {
if (!this._promise) {
this._promise = new Promise((resolve, reject) => {
this._resolve = result => {
this._resolve = null;
return resolve(result);
};
this._reject = possibleError => {
this._reject = null;
return reject(possibleError);
};
});
}
}
/* --------------------------
--- INTERNAL EVENT HANDLERS
---------------------------- */
/**
* Internal code sent event handler
* @private
* @param credential
*/
_codeSentHandler(credential) {
const snapshot = {
verificationId: credential.verificationId,
code: null,
error: null,
state: 'sent'
};
this._emitToObservers(snapshot);
if (_utils.isIOS) {
this._emitToSuccessCb(snapshot);
}
if (_utils.isAndroid) {// android can auto retrieve so we don't emit to successCb immediately,
// if auto retrieve times out then that will emit to successCb
}
}
/**
* Internal code auto retrieve timeout event handler
* @private
* @param credential
*/
_codeAutoRetrievalTimeoutHandler(credential) {
const snapshot = {
verificationId: credential.verificationId,
code: null,
error: null,
state: 'timeout'
};
this._emitToObservers(snapshot);
this._emitToSuccessCb(snapshot);
}
/**
* Internal verification complete event handler
* @param credential
* @private
*/
_verificationCompleteHandler(credential) {
const snapshot = {
verificationId: credential.verificationId,
code: credential.code || null,
error: null,
state: 'verified'
};
this._emitToObservers(snapshot);
this._emitToSuccessCb(snapshot);
this._removeAllListeners();
}
/**
* Internal verification failed event handler
* @param state
* @private
*/
_verificationFailedHandler(state) {
const snapshot = {
verificationId: state.verificationId,
code: null,
error: null,
state: 'error'
};
const _state$error = state.error,
code = _state$error.code,
message = _state$error.message,
nativeErrorMessage = _state$error.nativeErrorMessage;
snapshot.error = (0, _utils.nativeToJSError)(code, message, {
nativeErrorMessage
});
this._emitToObservers(snapshot);
this._emitToErrorCb(snapshot);
this._removeAllListeners();
}
/* -------------
-- PUBLIC API
--------------*/
on(event, observer, errorCb, successCb) {
if (!(0, _utils.isString)(event)) {
throw new Error(_internals.default.STRINGS.ERROR_MISSING_ARG_NAMED('event', 'string', 'on'));
}
if (event !== 'state_changed') {
throw new Error(_internals.default.STRINGS.ERROR_ARG_INVALID_VALUE('event', 'state_changed', event));
}
if (!(0, _utils.isFunction)(observer)) {
throw new Error(_internals.default.STRINGS.ERROR_MISSING_ARG_NAMED('observer', 'function', 'on'));
}
this._addUserObserver(observer);
if ((0, _utils.isFunction)(errorCb)) {
_events.SharedEventEmitter.once(this._publicEvents.error, errorCb);
}
if ((0, _utils.isFunction)(successCb)) {
_events.SharedEventEmitter.once(this._publicEvents.success, successCb);
}
return this;
}
/**
* Promise .then proxy
* @param fn
*/
then(fn) {
this._promiseDeferred(); // $FlowFixMe: Unsure how to annotate `bind` here
if (this._promise) return this._promise.then.bind(this._promise)(fn);
return undefined; // will never get here - just to keep flow happy
}
/**
* Promise .catch proxy
* @param fn
*/
catch(fn) {
this._promiseDeferred(); // $FlowFixMe: Unsure how to annotate `bind` here
if (this._promise) return this._promise.catch.bind(this._promise)(fn);
return undefined; // will never get here - just to keep flow happy
}
}
exports.default = PhoneAuthListener;