UNPKG

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
"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;