all files / firebase/utils/ events.js

100% Statements 24/24
100% Branches 10/10
100% Functions 5/5
100% Lines 24/24
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74                          1428×         31× 31× 31× 15×   31×                                 37× 31× 31× 718×   716×           31×             30× 30× 17× 37×        
/**
 * @flow
 */
import { NativeEventEmitter, NativeModules } from 'react-native';
import EventEmitter from './emitter/EventEmitter';
 
import type ModuleBase from './ModuleBase';
import type { FirebaseModuleConfig, FirebaseModuleName } from '../types';
 
const NATIVE_EMITTERS: { [string]: NativeEventEmitter } = {};
const NATIVE_SUBSCRIPTIONS: { [string]: boolean } = {};
 
export const SharedEventEmitter = new EventEmitter();
 
export const getAppEventName = (
  module: ModuleBase,
  eventName: string
): string => `${module.app.name}-${eventName}`;
 
const getNativeEmitter = (
  moduleName: FirebaseModuleName,
  module: ModuleBase
): NativeEventEmitter => {
  const name = `${module.app.name}-${moduleName}`;
  const nativeModule = NativeModules[moduleName];
  if (!NATIVE_EMITTERS[name]) {
    NATIVE_EMITTERS[name] = new NativeEventEmitter(nativeModule);
  }
  return NATIVE_EMITTERS[name];
};
 
/**
 * Subscribe to a native event for js side distribution by appName
 *    React Native events are hard set at compile - cant do dynamic event names
 *    so we use a single event send it to js and js then internally can prefix it
 *    and distribute dynamically.
 *
 * @param module
 * @param eventName
 * @private
 */
const subscribeToNativeModuleEvents = (
  moduleName: FirebaseModuleName,
  module: ModuleBase,
  eventName: string
): void => {
  if (!NATIVE_SUBSCRIPTIONS[eventName]) {
    const nativeEmitter = getNativeEmitter(moduleName, module);
    nativeEmitter.addListener(eventName, event => {
      if (event.appName) {
        // native event has an appName property - auto prefix and internally emit
        SharedEventEmitter.emit(`${event.appName}-${eventName}`, event);
      } else {
        // standard event - no need to prefix
        SharedEventEmitter.emit(eventName, event);
      }
    });
 
    NATIVE_SUBSCRIPTIONS[eventName] = true;
  }
};
 
export const initialiseNativeModuleEventEmitter = (
  module: ModuleBase,
  config: FirebaseModuleConfig
): void => {
  const { events, moduleName } = config;
  if (events && events.length) {
    for (let i = 0, len = events.length; i < len; i++) {
      subscribeToNativeModuleEvents(moduleName, module, events[i]);
    }
  }
};