UNPKG

@sendbird/calls-react-native

Version:

Sendbird Calls SDK for React Native: Empower React Native apps with seamless audio, video, and group calling. Build interactive communication easily.

148 lines (129 loc) 6.04 kB
/* eslint-disable */ import { NativeEventEmitter, NativeModules } from 'react-native'; import type { AsNativeInterface, DirectCallProperties, RoomProperties, SendbirdCallsNativeSpec } from '../types'; import { LINKING_ERROR } from '../utils/constants'; import { convertDirectCallPropsNTJ, convertGroupCallPropsNTJ } from '../utils/converter'; import { Logger } from '../utils/logger'; import JSEventEmitter from './JSEventEmitter'; const MODULE_NAME = 'RNSendbirdCalls'; const NativeModule = NativeModules[MODULE_NAME]; //TurboModuleRegistry.get<SendbirdCallsSpec>(MODULE_NAME); const NoopModuleProxy = new Proxy( {}, { get() { throw new Error(LINKING_ERROR); }, }, ); export enum CallsEvent { DEFAULT = 'sendbird.call.default', DIRECT_CALL = 'sendbird.call.direct', GROUP_CALL = 'sendbird.call.group', } export enum DefaultEventType { ON_RINGING = 'sendbird.call.default.onRinging', } export enum DirectCallEventType { ON_ESTABLISHED = 'sendbird.call.direct.onEstablished', ON_CONNECTED = 'sendbird.call.direct.onConnected', ON_RECONNECTING = 'sendbird.call.direct.onReconnecting', ON_RECONNECTED = 'sendbird.call.direct.onReconnected', ON_ENDED = 'sendbird.call.direct.onEnded', ON_REMOTE_AUDIO_SETTINGS_CHANGED = 'sendbird.call.direct.onRemoteAudioSettingsChanged', ON_REMOTE_VIDEO_SETTINGS_CHANGED = 'sendbird.call.direct.onRemoteVideoSettingsChanged', ON_LOCAL_VIDEO_SETTINGS_CHANGED = 'sendbird.call.direct.onLocalVideoSettingsChanged', ON_REMOTE_RECORDING_STATUS_CHANGED = 'sendbird.call.direct.onRemoteRecordingStatusChanged', ON_AUDIO_DEVICE_CHANGED = 'sendbird.call.direct.onAudioDeviceChanged', ON_CUSTOM_ITEMS_UPDATED = 'sendbird.call.direct.onCustomItemsUpdated', ON_CUSTOM_ITEMS_DELETED = 'sendbird.call.direct.onCustomItemsDeleted', ON_USER_HOLD_STATUS_CHANGED = 'sendbird.call.direct.onUserHoldStatusChanged', } export enum GroupCallEventType { ON_DELETED = 'sendbird.call.group.onDeleted', ON_ERROR = 'sendbird.call.group.onError', ON_LOCAL_PARTICIPANT_DISCONNECTED = 'sendbird.call.group.onLocalParticipantDisconnected', ON_LOCAL_PARTICIPANT_RECONNECTED = 'sendbird.call.group.onLocalParticipantReconnected', ON_REMOTE_PARTICIPANT_ENTERED = 'sendbird.call.group.onRemoteParticipantEntered', ON_REMOTE_PARTICIPANT_EXITED = 'sendbird.call.group.onRemoteParticipantExited', ON_REMOTE_PARTICIPANT_STREAM_STARTED = 'sendbird.call.group.onRemoteParticipantStreamStarted', ON_AUDIO_DEVICE_CHANGED = 'sendbird.call.group.onAudioDeviceChanged', ON_REMOTE_VIDEO_SETTINGS_CHANGED = 'sendbird.call.group.onRemoteVideoSettingsChanged', ON_REMOTE_AUDIO_SETTINGS_CHANGED = 'sendbird.call.group.onRemoteAudioSettingsChanged', ON_CUSTOM_ITEMS_UPDATED = 'sendbird.call.group.onCustomItemsUpdated', ON_CUSTOM_ITEMS_DELETED = 'sendbird.call.group.onCustomItemsDeleted', } type MakeEventUnionMember<Type, Data> = { eventType: Type; data: AsNativeInterface<Data>; convertedData: Data; additionalData?: Record<string, any>; }; type EventUnion = | MakeEventUnionMember<DefaultEventType, DirectCallProperties> | MakeEventUnionMember<DirectCallEventType, DirectCallProperties> | MakeEventUnionMember<GroupCallEventType, RoomProperties>; type EventType = EventUnion['eventType']; type ExtractData<T extends EventType, U extends EventUnion = EventUnion> = U extends { eventType: T } ? U['convertedData'] : never; export default class NativeBinder { private _nativeModule: SendbirdCallsNativeSpec = NativeModule ?? NoopModuleProxy; private _nativeEventEmitter = new NativeEventEmitter(this._nativeModule); private _jsEventEmitter = new JSEventEmitter(); private _supportedNativeEvents = [CallsEvent.DEFAULT, CallsEvent.DIRECT_CALL, CallsEvent.GROUP_CALL]; public get nativeModule() { return this._nativeModule; } public get jsEventEmitter() { return this._jsEventEmitter; } constructor() { /* for reduce redundant native event listeners */ this._supportedNativeEvents.forEach((event) => { Logger.info('[NativeBinder] Add native event listener:', event); // Native -> JS this._nativeEventEmitter.addListener( event, ({ eventType, data, additionalData }: Omit<EventUnion, 'convertedData'>) => { Logger.info( '[NativeBinder] Receive events from native module: ', [ event, eventType, event === CallsEvent.GROUP_CALL ? (data as AsNativeInterface<RoomProperties>).roomId : (data as AsNativeInterface<DirectCallProperties>).callId, additionalData && JSON.stringify(additionalData).slice(0, 30) + '...', ].join(' ++ '), ); if (event === CallsEvent.DIRECT_CALL || event === CallsEvent.DEFAULT) { this.jsEventEmitter.emit(event, { type: eventType, data: convertDirectCallPropsNTJ(data as AsNativeInterface<DirectCallProperties>), additionalData, }); } if (event === CallsEvent.GROUP_CALL) { this.jsEventEmitter.emit(event, { type: eventType, data: convertGroupCallPropsNTJ(data as AsNativeInterface<RoomProperties>), additionalData, }); } }, ); }); } public addListener(eventName: CallsEvent.DEFAULT, callback: EventCallback<DefaultEventType>): () => void; public addListener(eventName: CallsEvent.DIRECT_CALL, callback: EventCallback<DirectCallEventType>): () => void; public addListener(eventName: CallsEvent.GROUP_CALL, callback: EventCallback<GroupCallEventType>): () => void; public addListener(eventName: string, callback: (event: any) => void) { Logger.info('[NativeBinder] Add javascript event listener:', eventName); return this.jsEventEmitter.addListener(eventName, callback); } } type EventCallback<T extends EventType> = (data: { type: T; data: ExtractData<T>; additionalData?: Record<string, any>; }) => void;