1import { DeviceEventEmitter } from 'expo-modules-core'; 2import { EventEmitter, EventSubscription } from 'fbemitter'; 3 4import { transformNativeStateMachineContext } from './Updates'; 5import type { UpdateEvent, UpdatesNativeStateChangeEvent } from './Updates.types'; 6 7let _emitter: EventEmitter | null; 8 9function _getEmitter(): EventEmitter { 10 if (!_emitter) { 11 _emitter = new EventEmitter(); 12 DeviceEventEmitter.addListener('Expo.nativeUpdatesEvent', _emitEvent); 13 DeviceEventEmitter.addListener( 14 'Expo.nativeUpdatesStateChangeEvent', 15 _emitNativeStateChangeEvent 16 ); 17 } 18 return _emitter; 19} 20 21// Reemits native UpdateEvents sent during the startup update check 22function _emitEvent(params): void { 23 if (!_emitter) { 24 throw new Error(`EventEmitter must be initialized to use from its listener`); 25 } 26 let newParams = { ...params }; 27 if (typeof params === 'string') { 28 newParams = JSON.parse(params); 29 } 30 if (newParams.manifestString) { 31 newParams.manifest = JSON.parse(newParams.manifestString); 32 delete newParams.manifestString; 33 } 34 _emitter.emit('Expo.updatesEvent', newParams); 35} 36 37// Reemits native state change events 38function _emitNativeStateChangeEvent(params: any) { 39 if (!_emitter) { 40 throw new Error(`EventEmitter must be initialized to use from its listener`); 41 } 42 let newParams = { ...params }; 43 if (typeof params === 'string') { 44 newParams = JSON.parse(params); 45 } 46 newParams.context = transformNativeStateMachineContext(newParams.context); 47 _emitter.emit('Expo.updatesStateChangeEvent', newParams); 48} 49 50/** 51 * Adds a callback to be invoked when updates-related events occur (such as upon the initial app 52 * load) due to auto-update settings chosen at build-time. See also the 53 * [`useUpdateEvents`](#useupdateeventslistener) React hook. 54 * 55 * @param listener A function that will be invoked with an [`UpdateEvent`](#updateevent) instance 56 * and should not return any value. 57 * @return An `EventSubscription` object on which you can call `remove()` to unsubscribe the 58 * listener. 59 */ 60export function addListener(listener: (event: UpdateEvent) => void): EventSubscription { 61 const emitter = _getEmitter(); 62 return emitter.addListener('Expo.updatesEvent', listener); 63} 64 65// Internal methods 66 67/** 68 * @hidden 69 */ 70export const addUpdatesStateChangeListener = ( 71 listener: (event: UpdatesNativeStateChangeEvent) => void 72) => { 73 // Add listener for state change events 74 const emitter = _getEmitter(); 75 return emitter.addListener('Expo.updatesStateChangeEvent', listener); 76}; 77 78/** 79 * @hidden 80 */ 81export const emitStateChangeEvent = (event: UpdatesNativeStateChangeEvent) => { 82 // Allows JS to emit a state change event (used in testing) 83 _emitNativeStateChangeEvent(event); 84}; 85