UNPKG

create-expo-cljs-app

Version:

Create a react native application with Expo and Shadow-CLJS!

96 lines (80 loc) 3.16 kB
import invariant from 'invariant'; import { NativeEventEmitter, Platform } from 'react-native'; const nativeEmitterSubscriptionKey = '@@nativeEmitterSubscription@@'; type NativeModule = { startObserving?: () => void; stopObserving?: () => void; addListener: (eventName: string) => void; removeListeners: (count: number) => void; }; // @needsAudit export type Subscription = { /** * A method to unsubscribe the listener. */ remove: () => void; }; export class EventEmitter { _listenerCount = 0; _nativeModule: NativeModule; _eventEmitter: NativeEventEmitter; constructor(nativeModule: NativeModule) { this._nativeModule = nativeModule; this._eventEmitter = new NativeEventEmitter(nativeModule as any); } addListener<T>(eventName: string, listener: (event: T) => void): Subscription { if (!this._listenerCount && Platform.OS !== 'ios' && this._nativeModule.startObserving) { this._nativeModule.startObserving(); } this._listenerCount++; const nativeEmitterSubscription = this._eventEmitter.addListener(eventName, listener); const subscription = { [nativeEmitterSubscriptionKey]: nativeEmitterSubscription, remove: () => { this.removeSubscription(subscription); }, }; return subscription; } removeAllListeners(eventName: string): void { // @ts-ignore: the EventEmitter interface has been changed in react-native@0.64.0 const removedListenerCount = this._eventEmitter.listenerCount ? // @ts-ignore: this is available since 0.64 this._eventEmitter.listenerCount(eventName) : // @ts-ignore: this is available in older versions this._eventEmitter.listeners(eventName).length; this._eventEmitter.removeAllListeners(eventName); this._listenerCount -= removedListenerCount; invariant( this._listenerCount >= 0, `EventEmitter must have a non-negative number of listeners` ); if (!this._listenerCount && Platform.OS !== 'ios' && this._nativeModule.stopObserving) { this._nativeModule.stopObserving(); } } removeSubscription(subscription: Subscription): void { const nativeEmitterSubscription = subscription[nativeEmitterSubscriptionKey]; if (!nativeEmitterSubscription) { return; } if ('remove' in nativeEmitterSubscription) { // `react-native-web@0.17.1` doesn't support `removeSubscription` nativeEmitterSubscription.remove(); } else if ('removeSubscription' in this._eventEmitter) { this._eventEmitter.removeSubscription(nativeEmitterSubscription!); } this._listenerCount--; // Ensure that the emitter's internal state remains correct even if `removeSubscription` is // called again with the same subscription delete subscription[nativeEmitterSubscriptionKey]; // Release closed-over references to the emitter subscription.remove = () => {}; if (!this._listenerCount && Platform.OS !== 'ios' && this._nativeModule.stopObserving) { this._nativeModule.stopObserving(); } } emit(eventName: string, ...params: any[]): void { this._eventEmitter.emit(eventName, ...params); } }