@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.
487 lines (481 loc) • 19 kB
JavaScript
var _DirectCall;
function _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; }
function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == typeof i ? i : i + ""; }
function _toPrimitive(t, r) { if ("object" != typeof t || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != typeof i) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); }
import { Platform } from 'react-native';
import { ControllableModuleType, RouteChangeReason } from '../types';
import { Logger } from '../utils/logger';
import { CallsEvent, DirectCallEventType } from './NativeBinder';
export class DirectCall {
/** @internal **/
static poolRelease() {
DirectCall.pool = {};
}
/** @internal **/
static get(binder, props) {
if (!DirectCall.pool[props.callId]) DirectCall.pool[props.callId] = new DirectCall(binder, props);
const directCall = DirectCall.pool[props.callId];
return directCall._updateInternal(props);
}
/** @internal **/
static updateCustomItems(callId, customItems) {
const directCall = DirectCall.pool[callId];
if (directCall) {
directCall._updateCustomItems(customItems);
}
}
constructor(binder, props) {
_defineProperty(this, "_binder", void 0);
_defineProperty(this, "_props", void 0);
_defineProperty(this, "_internalEvents", {
pool: [],
emit: (event, ...args) => {
// @ts-ignore
this._internalEvents.pool.forEach(listener => {
var _listener$event;
return (_listener$event = listener[event]) === null || _listener$event === void 0 ? void 0 : _listener$event.call(listener, ...args);
});
},
add: listener => {
this._internalEvents.pool.push(listener);
return () => {
const index = this._internalEvents.pool.indexOf(listener);
if (index > -1) delete this._internalEvents.pool[index];
};
}
});
/**
* Add DirectCall listener.
* supports multiple listeners.
*
* @since 1.0.0
*/
_defineProperty(this, "addListener", listener => {
Logger.info('[DirectCall]', 'addListener', this.callId);
const unsubscribes = [];
const disposeInternal = this._internalEvents.add(listener);
const disposeNative = this._binder.addListener(CallsEvent.DIRECT_CALL, ({
type,
data,
additionalData
}) => {
if (data.callId !== this.callId) return;
this._updateInternal(data);
switch (type) {
case DirectCallEventType.ON_ESTABLISHED:
{
var _listener$onEstablish;
(_listener$onEstablish = listener.onEstablished) === null || _listener$onEstablish === void 0 || _listener$onEstablish.call(listener, this);
break;
}
case DirectCallEventType.ON_CONNECTED:
{
var _listener$onConnected;
(_listener$onConnected = listener.onConnected) === null || _listener$onConnected === void 0 || _listener$onConnected.call(listener, this);
break;
}
case DirectCallEventType.ON_RECONNECTING:
{
var _listener$onReconnect;
(_listener$onReconnect = listener.onReconnecting) === null || _listener$onReconnect === void 0 || _listener$onReconnect.call(listener, this);
break;
}
case DirectCallEventType.ON_RECONNECTED:
{
var _listener$onReconnect2;
(_listener$onReconnect2 = listener.onReconnected) === null || _listener$onReconnect2 === void 0 || _listener$onReconnect2.call(listener, this);
break;
}
case DirectCallEventType.ON_ENDED:
{
var _listener$onEnded;
(_listener$onEnded = listener.onEnded) === null || _listener$onEnded === void 0 || _listener$onEnded.call(listener, this);
break;
}
case DirectCallEventType.ON_REMOTE_AUDIO_SETTINGS_CHANGED:
{
var _listener$onRemoteAud;
(_listener$onRemoteAud = listener.onRemoteAudioSettingsChanged) === null || _listener$onRemoteAud === void 0 || _listener$onRemoteAud.call(listener, this);
break;
}
case DirectCallEventType.ON_REMOTE_VIDEO_SETTINGS_CHANGED:
{
var _listener$onRemoteVid;
(_listener$onRemoteVid = listener.onRemoteVideoSettingsChanged) === null || _listener$onRemoteVid === void 0 || _listener$onRemoteVid.call(listener, this);
break;
}
case DirectCallEventType.ON_LOCAL_VIDEO_SETTINGS_CHANGED:
{
var _listener$onLocalVide;
(_listener$onLocalVide = listener.onLocalVideoSettingsChanged) === null || _listener$onLocalVide === void 0 || _listener$onLocalVide.call(listener, this);
break;
}
case DirectCallEventType.ON_REMOTE_RECORDING_STATUS_CHANGED:
{
var _listener$onRemoteRec;
(_listener$onRemoteRec = listener.onRemoteRecordingStatusChanged) === null || _listener$onRemoteRec === void 0 || _listener$onRemoteRec.call(listener, this);
break;
}
case DirectCallEventType.ON_CUSTOM_ITEMS_UPDATED:
{
var _listener$onCustomIte;
(_listener$onCustomIte = listener.onCustomItemsUpdated) === null || _listener$onCustomIte === void 0 || _listener$onCustomIte.call(listener, this, (additionalData === null || additionalData === void 0 ? void 0 : additionalData.updatedKeys) ?? []);
break;
}
case DirectCallEventType.ON_CUSTOM_ITEMS_DELETED:
{
var _listener$onCustomIte2;
(_listener$onCustomIte2 = listener.onCustomItemsDeleted) === null || _listener$onCustomIte2 === void 0 || _listener$onCustomIte2.call(listener, this, (additionalData === null || additionalData === void 0 ? void 0 : additionalData.deletedKeys) ?? []);
break;
}
case DirectCallEventType.ON_USER_HOLD_STATUS_CHANGED:
{
var _listener$onUserHoldS;
(_listener$onUserHoldS = listener.onUserHoldStatusChanged) === null || _listener$onUserHoldS === void 0 || _listener$onUserHoldS.call(listener, this, (additionalData === null || additionalData === void 0 ? void 0 : additionalData.isLocalUser) ?? false, (additionalData === null || additionalData === void 0 ? void 0 : additionalData.isUserOnHold) ?? false);
break;
}
case DirectCallEventType.ON_AUDIO_DEVICE_CHANGED:
{
if (Platform.OS === 'android') {
var _listener$onAudioDevi;
(_listener$onAudioDevi = listener.onAudioDeviceChanged) === null || _listener$onAudioDevi === void 0 || _listener$onAudioDevi.call(listener, this, {
platform: 'android',
data: {
currentAudioDevice: (additionalData === null || additionalData === void 0 ? void 0 : additionalData.currentAudioDevice) ?? null,
availableAudioDevices: (additionalData === null || additionalData === void 0 ? void 0 : additionalData.availableAudioDevices) ?? []
}
});
}
if (Platform.OS === 'ios') {
var _listener$onAudioDevi2;
(_listener$onAudioDevi2 = listener.onAudioDeviceChanged) === null || _listener$onAudioDevi2 === void 0 || _listener$onAudioDevi2.call(listener, this, {
platform: 'ios',
data: {
reason: (additionalData === null || additionalData === void 0 ? void 0 : additionalData.reason) ?? RouteChangeReason.unknown,
currentRoute: (additionalData === null || additionalData === void 0 ? void 0 : additionalData.currentRoute) ?? {
inputs: [],
outputs: []
},
previousRoute: (additionalData === null || additionalData === void 0 ? void 0 : additionalData.previousRoute) ?? {
inputs: [],
outputs: []
}
}
});
}
break;
}
}
});
unsubscribes.push(disposeNative, disposeInternal);
return () => unsubscribes.forEach(fn => fn());
});
/**
* Accepts call.
*
* @since 1.0.0
*/
_defineProperty(this, "accept", async (options = {
audioEnabled: true,
frontCamera: true,
videoEnabled: true
}, holdActiveCall = false) => {
await this._binder.nativeModule.accept(this.callId, options, holdActiveCall);
});
/**
* Ends the call.
* {@link DirectCallListener.onEnded} will be called after successful ending.
* This listener will also be called when the remote user ends the call.
*
* @since 1.0.0
*/
_defineProperty(this, "end", async () => {
await this._binder.nativeModule.end(this.callId);
});
/**
* Selects video device.
* Changes current video device asynchronously.
*
* @since 1.0.0
*/
_defineProperty(this, "selectVideoDevice", async device => {
await this._binder.nativeModule.selectVideoDevice(ControllableModuleType.DIRECT_CALL, this.callId, device);
});
/**
* Selects audio device.
*
* @platform Android
* @since 1.0.0
*/
_defineProperty(this, "android_selectAudioDevice", async device => {
if (Platform.OS !== 'android') return;
await this._binder.nativeModule.selectAudioDevice(ControllableModuleType.DIRECT_CALL, this.callId, device);
});
/**
* Connects the device camera and Sendbird Calls SDK to stream video.
*
* @platform Android
* @since 1.1.3
* */
_defineProperty(this, "android_resumeVideoCapturer", () => {
if (Platform.OS !== 'android') return;
this._binder.nativeModule.resumeVideoCapturer(ControllableModuleType.DIRECT_CALL, this.callId);
});
/**
* Connects the device audio and Sendbird Calls SDK to stream audio.
*
* @platform Android
* @since 1.1.5
* */
_defineProperty(this, "android_resumeAudioTrack", () => {
if (Platform.OS !== 'android') return;
this._binder.nativeModule.resumeAudioTrack(ControllableModuleType.DIRECT_CALL, this.callId);
});
/**
* Mutes the audio of local user.
* Will trigger {@link DirectCallListener.onRemoteAudioSettingsChanged} method of the remote user.
* If the remote user changes their audio settings, local user will be notified via same delegate method.
*
* @since 1.0.0
*/
_defineProperty(this, "muteMicrophone", () => {
this._binder.nativeModule.muteMicrophone(ControllableModuleType.DIRECT_CALL, this.callId);
// NOTE: native doesn't have onLocalAudioSettingsChanged event
this._props.isLocalAudioEnabled = false;
this._internalEvents.emit('onPropertyUpdatedManually', this);
});
/**
* Unmutes the audio of local user.
* Will trigger {@link DirectCallListener.onRemoteAudioSettingsChanged} method of the remote user.
* If the remote user changes their audio settings, local user will be notified via same delegate method.
*
* @since 1.0.0
*/
_defineProperty(this, "unmuteMicrophone", () => {
this._binder.nativeModule.unmuteMicrophone(ControllableModuleType.DIRECT_CALL, this.callId);
// NOTE: native doesn't have onLocalAudioSettingsChanged event
this._props.isLocalAudioEnabled = true;
this._internalEvents.emit('onPropertyUpdatedManually', this);
});
/**
* Starts local video.
* If the callee changes video settings,
* the caller is notified via the {@link DirectCallListener.onRemoteVideoSettingsChanged} listener.
*
* @since 1.0.0
*/
_defineProperty(this, "startVideo", () => {
this._binder.nativeModule.startVideo(ControllableModuleType.DIRECT_CALL, this.callId);
this._props.isLocalVideoEnabled = true;
// NOTE: ios native doesn't have onLocalAudioSettingsChanged event
Platform.OS === 'ios' && this._internalEvents.emit('onLocalVideoSettingsChanged', this);
});
/**
* Stops local video.
* If the callee changes video settings,
* the caller is notified via the {@link DirectCallListener.onRemoteVideoSettingsChanged} listener.
*
* @since 1.0.0
*/
_defineProperty(this, "stopVideo", () => {
this._binder.nativeModule.stopVideo(ControllableModuleType.DIRECT_CALL, this.callId);
this._props.isLocalVideoEnabled = false;
// NOTE: ios native doesn't have onLocalAudioSettingsChanged event
Platform.OS === 'ios' && this._internalEvents.emit('onLocalVideoSettingsChanged', this);
});
/**
* Starts sharing the local user's screen.
* The local camera video will be replaced with the screen share stream.
*
* On iOS, this starts RPScreenRecorder capture internally.
* On Android, this triggers MediaProjection permission dialog
* and manages ForegroundService lifecycle internally.
*
* @since 1.2.0
*/
_defineProperty(this, "startScreenShare", async () => {
await this._binder.nativeModule.startScreenShare(this.callId);
});
/**
* Stops sharing the local user's screen and returns to the camera video.
*
* @since 1.2.0
*/
_defineProperty(this, "stopScreenShare", async () => {
await this._binder.nativeModule.stopScreenShare(this.callId);
});
/**
* Toggles the selection between the front and the back camera.
*
* on Android, In case of more than two cameras, the next camera will be selected.
* If the last camera is already selected, the first one will be selected again.
*
* @since 1.0.0
*/
_defineProperty(this, "switchCamera", async () => {
await this._binder.nativeModule.switchCamera(ControllableModuleType.DIRECT_CALL, this.callId);
});
/**
* Update local video view.
* @see DirectCallVideoView.videoViewId
*
* @since 1.0.0
*/
_defineProperty(this, "updateLocalVideoView", videoViewId => {
this._binder.nativeModule.updateLocalVideoView(this.callId, videoViewId);
});
/**
* Update remote video view.
* @see DirectCallVideoView.videoViewId
*
* @since 1.0.0
*/
_defineProperty(this, "updateRemoteVideoView", videoViewId => {
this._binder.nativeModule.updateRemoteVideoView(this.callId, videoViewId);
});
/**
* Updates custom items for this call.
*
* @param customItems Custom items of [String: String] to be updated or inserted.
* @returns Promise that resolves with CustomItemUpdateResult containing updated items and affected keys.
* @since 1.1.9
*/
_defineProperty(this, "updateCustomItems", async customItems => {
const result = await this._binder.nativeModule.directCallUpdateCustomItems(this.callId, customItems);
if (result && result.updatedItems) {
this._updateCustomItems(result.updatedItems);
}
return result;
});
/**
* Deletes custom items for this call.
*
* @param customItemKeys Custom item keys which you want to delete.
* @returns Promise that resolves with CustomItemUpdateResult containing updated items and affected keys.
* @since 1.1.9
*/
_defineProperty(this, "deleteCustomItems", async customItemKeys => {
const result = await this._binder.nativeModule.directCallDeleteCustomItems(this.callId, customItemKeys);
if (result && result.updatedItems) {
this._updateCustomItems(result.updatedItems);
}
return result;
});
/**
* Deletes all custom items for this call.
*
* @returns Promise that resolves with CustomItemUpdateResult containing updated items and affected keys.
* @since 1.1.9
*/
_defineProperty(this, "deleteAllCustomItems", async () => {
const result = await this._binder.nativeModule.directCallDeleteAllCustomItems(this.callId);
if (result && result.updatedItems) {
this._updateCustomItems(result.updatedItems);
}
return result;
});
this._binder = binder;
this._props = props;
}
_updateInternal(props) {
this._props = props;
return this;
}
_updateCustomItems(customItems) {
this._props.customItems = customItems;
}
get ios_callUUID() {
return this._props.ios_callUUID;
}
get android_availableAudioDevices() {
return this._props.android_availableAudioDevices;
}
get android_currentAudioDevice() {
return this._props.android_currentAudioDevice;
}
get availableVideoDevices() {
return this._props.availableVideoDevices;
}
get callId() {
return this._props.callId;
}
get callLog() {
return this._props.callLog;
}
get callee() {
return this._props.callee;
}
get caller() {
return this._props.caller;
}
get currentVideoDevice() {
return this._props.currentVideoDevice;
}
get customItems() {
return this._props.customItems;
}
get startedAt() {
return this._props.startedAt;
}
get duration() {
if (this.startedAt > 0) {
return Math.max(0, Date.now() - this.startedAt);
} else if (this._props.duration > 0) {
return this._props.duration;
} else {
return 0;
}
}
get endedBy() {
return this._props.endedBy;
}
get isEnded() {
return this._props.isEnded;
}
get isLocalAudioEnabled() {
return this._props.isLocalAudioEnabled;
}
get isLocalScreenShareEnabled() {
return this._props.isLocalScreenShareEnabled;
}
get isLocalVideoEnabled() {
return this._props.isLocalVideoEnabled;
}
get isOnHold() {
return this._props.isOnHold;
}
get isOngoing() {
return this._props.isOngoing;
}
get isRemoteAudioEnabled() {
return this._props.isRemoteAudioEnabled;
}
get isRemoteVideoEnabled() {
return this._props.isRemoteVideoEnabled;
}
get isVideoCall() {
return this._props.isVideoCall;
}
get localRecordingStatus() {
return this._props.localRecordingStatus;
}
get localUser() {
return this._props.localUser;
}
get myRole() {
return this._props.myRole;
}
get remoteRecordingStatus() {
return this._props.remoteRecordingStatus;
}
get remoteUser() {
return this._props.remoteUser;
}
get endResult() {
return this._props.endResult;
}
}
_DirectCall = DirectCall;
/** @internal **/
_defineProperty(DirectCall, "pool", {});
//# sourceMappingURL=DirectCall.js.map