@salutejs/jazz-sdk-web
Version:
Jazz SDK for web applications
1,919 lines (1,649 loc) • 95.8 kB
TypeScript
import { Container, Module, ModuleDeclaration } from 'ditox';
import { Query as Query$1, Controller } from 'rx-effects';
import { Observable } from 'rxjs';
import { Signal, Atom, Scope } from 'nrgy';
type EventLike = {
type: string;
};
/**
* This is a subset of Web Storage API
*/
type KeyValueStorage = Readonly<{
/**
* Returns the current value associated with the given key, or null if the
* given key does not exist in the list associated with the object.
*/
getItem: (key: string) => string | undefined;
/**
* Sets the value of the pair identified by key to value, creating a new
* key/value pair if none existed for key previously.
*
* Throws a "QuotaExceededError" DOMException exception if the new value
* couldn't be set. (Setting could fail if, e.g., the user has disabled
* storage for the site, or if the quota has been exceeded.)
*/
setItem: (key: string, value: string) => void;
/**
* Removes the key/value pair with the given key from the list associated
* with the object, if a key/value pair with the given key exists.
*/
removeItem: (key: string) => void;
/**
* Empties the list associated with the object of all key/value pairs, if
* there are any.
*/
clear: () => void;
getKeys: () => ReadonlyArray<string>;
}>;
type AnyObject = Record<string, any>;
type Timestamp = number;
/** Autocomplete for string union with ability use any string
* e.g. 'apple' | 'banana' | string
*
* WARNING: doesn't work as object key with empty default value
* following code will throw type error:
* const obj1: Record<Autocomplete<'foo' | 'bar'>, any> = {}
*/
type StringEnum<Enum extends string> = Enum | (string & Record<never, never>);
type ResultFailure<Error> = {
readonly type: 'failure';
readonly error: Error;
};
type ResultSuccess<Value> = {
readonly type: 'success';
readonly value: Value;
};
type SyncResult<Value, Error = unknown> =
| ResultSuccess<Value>
| ResultFailure<Error>;
type LogLevel = 'debug' | 'info' | 'warn' | 'error';
type LogMetadata = Readonly<Record<string, string>>;
type LogEvent = Readonly<{
timestamp: number;
level: LogLevel;
tag: string;
messages: ReadonlyArray<unknown>;
meta?: LogMetadata;
}>;
type BaseRequestQuery = Record<
string,
string | boolean | number | (string | boolean | number)[]
>;
declare class HttpClientResponseError<
ResponseError,
RequestBody,
RequestQuery extends BaseRequestQuery | void,
> extends Error {
type: 'HttpClientResponseError';
readonly request: HttpClientRequest<RequestBody, RequestQuery>;
readonly status: number;
readonly headers: Headers;
readonly ok: false;
readonly redirected: boolean;
readonly statusText: string;
readonly data: ResponseError;
readonly originalResponse: Response;
constructor(
message: string,
response: HttpClientResponseFailure<
ResponseError,
RequestBody,
RequestQuery
>,
replaceResponseData?: ResponseError,
);
}
declare class HttpClientFetchError<
RequestBody = void,
RequestQuery extends BaseRequestQuery | void = void,
> extends Error {
type: 'HttpClientFetchError';
readonly request: HttpClientRequest<RequestBody, RequestQuery>;
constructor(
message: string,
response: HttpClientErrorResponse<RequestBody, RequestQuery>,
);
}
type HttpClientRequest<
RequestBody,
RequestQuery extends BaseRequestQuery | void,
> = {
body: RequestBody;
url: string;
method: string;
credentials: string;
mode: string;
headers: HeadersInit;
query: RequestQuery;
};
type HttpClientResponseFailure<
ResponseError,
RequestBody,
RequestQuery extends BaseRequestQuery | void,
> = {
originalResponse: Response;
status: number;
headers: Headers;
redirected: boolean;
statusText: string;
request: HttpClientRequest<RequestBody, RequestQuery>;
ok: false;
data: ResponseError;
};
type HttpClientErrorResponse<
RequestBody,
RequestQuery extends BaseRequestQuery | void,
> = {
request: HttpClientRequest<RequestBody, RequestQuery>;
};
type ApiAuthErrorResolution = 'retry' | 'fail';
type ConferenceId = string;
type ReactionType = 'applause' | 'surprise' | 'smile' | 'like' | 'dislike';
/**
* @example b2b_13ne6i_2tm8gv
*/
type RoomId = string;
/**
* @deprecated use JazzRoomUserPermissionKey из @salutejs/jazz-sdk-web
*/
type UserPermissionKey =
| 'canEditOwnName'
| 'canEditRoomPolicy'
| 'canEditRoomTitle'
| 'canFinishCall'
| 'canGrantPermission'
| 'canInvite'
| 'canKickUser'
| 'canMuteUser'
| 'canRequestPermission'
| 'canShareAudio'
| 'canShareCamera'
| 'canShareMedia'
| 'canViewModerators'
| 'canViewAsr'
| 'canManageAsr'
| 'canManageWatermark'
| 'canManageLobby'
| 'canToggleLobby'
| 'canManageDenoiser'
| 'canRecordScreen'
| 'canStartServerVideoRecord'
| 'canSendReaction'
| 'canManageSessionGroups'
| 'canLeaveSessionGroups'
| 'canViewMessage'
| 'canViewTranscription'
| 'canStartTranscription'
| 'canToggleGuestEnabled'
| 'canSendMessage'
| 'canStartPoll'
| 'canManagePoll'
| 'canUpdateRoleMemberToModerator'
| 'canUpdateRoleModeratorToMember'
| 'canManageWebinarStream'
| 'canViewParticipants'
| 'canManageWhiteboard'
| 'canCloseNotOwnWhiteboard';
/**
* @deprecated for client use type JazzRoomUserPermissions from @salutejs/jazz-sdk-web
*/
type UserPermissions = Readonly<Record<UserPermissionKey, boolean>>;
type RoomMuteMediaType = 'audio' | 'video';
type JitsiXmppEvents = {
/**
* Indicates error while adding ice candidate.
*/
'xmpp.add_ice_candidate_failed': [];
// Designates an event indicating that the focus has asked us to mute our
// audio.
'xmpp.audio_muted_by_focus': [];
// Designates an event indicating that the focus has asked us to disable our
// camera.
'xmpp.video_muted_by_focus': [];
'xmpp.authentication_required': [];
'xmpp.bridge_down': [];
/**
* Triggered when 'session-accept' is received from the responder.
*/
'xmpp.callaccepted.jingle': [];
// Designates an event indicating that an offer (e.g. Jingle
// session-initiate) was received.
'xmpp.callincoming.jingle': [];
// Triggered when Jicofo kills our media session, this can happen while
// we're still in the MUC, when it decides to terminate the media session.
// For example when the session is idle for too long, because we're the only
// person in the conference room.
'xmpp.callended.jingle': [];
'xmpp.chat_error_received': [];
// The conference properties (as advertised by jicofo) have changed
'xmpp.conference_properties_changed': [];
/**
* This event is triggered when the ICE connects for the first time.
*/
'xmpp.connection.connected': [];
// Designates an event indicating that the connection to the XMPP server
// failed.
'xmpp.connection.failed': [];
// Designates an event indicating that the media (ICE) connection was
// interrupted. This should go to the RTC module.
'xmpp.connection.interrupted': [];
// Designates an event indicating that the media (ICE) connection was
// restored. This should go to the RTC module.
'xmpp.connection.restored': [];
// Designates an event indicating that the media (ICE) connection failed.
// This should go to the RTC module.
'xmpp.connection.ice.failed': [];
// Designates an event indicating that the call has been migrated to a different
// bridge and that the client needs to be restarted for a successful transition.
'xmpp.connection.restart': [];
/**
* Designates an event indicating connection status changes.
*/
'xmpp.connection.status.changed': [];
// Designates an event indicating that the display name of a participant
// has changed.
'xmpp.display_name_changed': [];
/**
* Chat room instance have been added to Strophe.emuc plugin.
*/
'xmpp.emuc_room_added': [];
/**
* Chat room instance have been removed from Strophe.emuc plugin.
*/
'xmpp.emuc_room_removed': [];
'xmpp.etherpad': [];
'xmpp.focus_disconnected': [];
'xmpp.focus_left': [];
'xmpp.graceful_shutdown': [];
/**
* Event fired when 'transport-replace' Jingle message has been received,
* before the new offer is set on the PeerConnection.
*/
'rtc.ice_restarting': [];
/**
* Event fired after the 'transport-replace' message has been processed
* and the new offer has been set successfully.
*/
'rtc.ice_restart_success': [];
/**
* Designates an event indicating that we were kicked from the XMPP MUC.
* @param {boolean} isSelfPresence - whether it is for local participant
* or another participant.
* @param {string} actorJid - the jid of the participant who was initator
* of the kick.
* @param {?string} participantJid - when it is not a kick for local participant,
* this is the jid of the participant which was kicked.
*/
'xmpp.kicked': [];
// Designates an event indicating that our role in the XMPP MUC has changed.
'xmpp.localrole_changed': [];
/**
* Event fired when the unique meeting id is set.
*/
'xmpp.meeting_id_set': [];
// Designates an event indicating that an XMPP message in the MUC was
// received.
'xmpp.message_received': [];
// Designates an event indicating that an invite XMPP message in the MUC was
// received.
'xmpp.invite_message_received': [
roomJid: string,
from: string,
txt: string,
invitePassword: string,
];
// Designates an event indicating that a private XMPP message in the MUC was
// received.
'xmpp.private_message_received': [];
// Designates an event indicating that a bot participant type had changed
'xmpp.muc_member_bot_type_changed': [];
// Designates an event indicating that the XMPP MUC was destroyed.
'xmpp.muc_destroyed': [];
// Designates an event indicating that we have joined the XMPP MUC.
'xmpp.muc_joined': [];
// Designates an event indicating that a participant joined the XMPP MUC.
'xmpp.muc_member_joined': [];
// Designates an event indicating that a participant left the XMPP MUC.
'xmpp.muc_member_left': [];
// Designates an event indicating that a participant joined the lobby XMPP MUC.
'xmpp.muc_lobby_member_joined': [];
// Designates an event indicating that a participant in the lobby XMPP MUC has been updated
'xmpp.muc_lobby_member_updated': [];
// Designates an event indicating that a participant left the XMPP MUC.
'xmpp.muc_lobby_member_left': [];
// Designates an event indicating that a participant was denied access to a conference from the lobby XMPP MUC.
'xmpp.muc_denied access': [];
// Designates an event indicating that local participant left the muc
'xmpp.muc_left': [];
// Designates an event indicating that the MUC role of a participant has
// changed.
'xmpp.muc_role_changed': [];
// Designates an event indicating that the MUC has been locked or unlocked.
'xmpp.muc_lock_changed': [];
// Designates an event indicating that the MUC members only config has changed.
'xmpp.muc_members_only_changed': [];
// Designates an event indicating that a participant in the XMPP MUC has
// advertised that they have audio muted (or unmuted).
'xmpp.audio_muted': [];
// Designates an event indicating that a participant in the XMPP MUC has
// advertised that they have video muted (or unmuted).
'xmpp.video_muted': [];
// Designates an event indicating that the video type (e.g. 'camera' or
// 'screen') for a participant has changed.
// Note: currently this event fires every time we receive presence from
// someone (regardless of whether or not the "video type" changed).
'xmpp.video_type': [];
/**
* Indicates that the features of the participant has been changed.
*/
'xmpp.participant_features_changed': [];
'xmpp.password_required': [];
/**
* Indicates that phone number changed.
*/
'conference.phoneNumberChanged': [];
'xmpp.presence_received': [];
'xmpp.presence_status': [];
'xmpp.prompt_for_login': [];
// xmpp is connected and obtained user media
'xmpp.ready_to_join': [];
/**
* Indicates that recording state changed.
*/
'xmpp.recorderStateChanged': [];
// Designates an event indicating that we received statistics from a
// participant in the MUC.
'xmpp.remote_stats': [];
/**
* Indicates that the offer / answer renegotiation has failed.
*/
'xmpp.renegotiation_failed': [];
'xmpp.room_reservation_error': [];
'xmpp.room_connect_error': [];
'xmpp.room_connect_error.not_allowed': [];
'xmpp.room_join_error': [];
'xmpp.room_connect_error.members_only': [];
/**
* Indicates that max users limit has been reached.
*/
'xmpp.room_max_users_error': [];
// Designates an event indicating that we sent an XMPP message to the MUC.
'xmpp.sending_chat_message': [];
// Designates an event indicating that we sent a private XMPP message to
// a specific user of the muc.
'xmpp.sending_private_chat_message': [];
// Event fired after receiving the confirmation about session accept.
'xmpp.session_accept': [];
// Event fired if we receive an error after sending the session accept.
'xmpp.session_accept_error': [];
/**
* Event fired when we do not get our 'session-accept' acknowledged by
* Jicofo. It most likely means that there is serious problem with our
* connection or XMPP server and we should reload the conference.
*
* We have seen that to happen in BOSH requests race condition when the BOSH
* request table containing the 'session-accept' was discarded by Prosody.
* Jicofo does send the RESULT immediately without any condition, so missing
* packets means that most likely it has never seen our IQ.
*/
'xmpp.session_accept_timeout': [];
/**
* Event fired when speaker stats update message is received.
*/
'xmpp.speaker_stats_received': [];
/**
* Event fired when conference creation timestamp is received.
*/
'xmpp.conference_timestamp_received': [];
/**
* Event fired when we receive a message for AV moderation approved for the local participant.
*/
'xmpp.av_moderation.approved': [];
/**
* Event fired when we receive a message for AV moderation.
*/
'xmpp.av_moderation.received': [];
/**
* Event fired when the moderation enable/disable changes.
*/
'xmpp.av_moderation.changed': [];
/**
* Event fired when we receive message that a new jid was approved.
*/
'xmpp.av_moderation.participant.approved': [];
// Designates an event indicating that we should join the conference with
// audio and/or video muted.
'xmpp.start_muted_from_focus': [];
// Designates an event indicating that the subject of the XMPP MUC has
// changed.
'xmpp.subject_changed': [];
// FIXME: how does it belong to XMPP ? - it's detected by the PeerConnection
// suspending detected
'xmpp.suspend_detected': [];
/**
* Notifies for transcription status changes. The event provides the
* following parameters to its listeners:
*
* @param {String} status - The new status.
*/
'xmpp.transcription_status_changed': [];
/**
* Event fired when 'transport-info' with new ICE candidates is received.
*/
'xmpp.transportinfo.jingle': [];
/**
* Indicates that video SIP GW state changed.
*
* @param {VideoSIPGWConstants} status - Any of the following statuses:
* STATUS_BUSY, STATUS_AVAILABLE or STATUS_UNDEFINED.
*/
'xmpp.videoSIPGWAvailabilityChanged': [];
/**
* Indicates that video SIP GW Session state changed.
* The statuses are any of the following statuses:
* STATE_ON, STATE_OFF, STATE_PENDING, STATE_RETRYING, STATE_FAILED.
* {@see VideoSIPGWConstants}
*
* @param {options} event - {address, oldState, newState, displayName}.
*/
'xmpp.videoSIPGWSessionStateChanged': [];
// Designates an event indicating that the local ICE connection state has
// changed.
'xmpp.ice_connection_state_changed': [];
/**
* Event which is emitted when the body in an XMPP message in the MUC
* contains JSON
*/
'xmmp.json_message_received': [from: string, data: unknown];
};
type JitsiXmppEventType$1 = keyof JitsiXmppEvents;
type JitsiRTCEventType$1 =
/**
* Indicates error while create answer call.
*/
| 'rtc.create_answer_failed'
/**
* Indicates error while create offer call.
*/
| 'rtc.create_offer_failed'
| 'rtc.data_channel_open'
| 'rtc.endpoint_conn_status_changed'
| 'rtc.dominant_speaker_changed'
| 'rtc.lastn_endpoint_changed'
/**
* Event emitted when the user granted/blocked a permission for the camera / mic.
* Used to keep track of the granted permissions on browsers which don't
* support the Permissions API.
*/
| 'rtc.permissions_changed'
| 'rtc.sender_video_constraints_changed'
/**
* Event emitted when {@link RTC.setLastN} method is called to update with
* the new value set.
* The first argument is the value passed to {@link RTC.setLastN}.
*/
| 'rtc.lastn_value_changed'
/**
* Event emitted when ssrc for a local track is extracted and stored
* in {@link TraceablePeerConnection}.
* @param {JitsiLocalTrack} track which ssrc was updated
* @param {string} ssrc that was stored
*/
| 'rtc.local_track_ssrc_updated'
/**
* The max enabled resolution of a local video track was changed.
*/
| 'rtc.local_track_max_enabled_resolution_changed'
| 'rtc.track_attached'
/**
* Event fired when we remote track is added to the conference.
* 1st event argument is the added <tt>JitsiRemoteTrack</tt> instance.
**/
| 'rtc.remote_track_added'
// FIXME get rid of this event in favour of NO_DATA_FROM_SOURCE event
// (currently implemented for local tracks only)
| 'rtc.remote_track_mute'
/**
* Indicates that the remote track has been removed from the conference.
* 1st event argument is the removed {@link JitsiRemoteTrack} instance.
*/
| 'rtc.remote_track_removed'
// FIXME get rid of this event in favour of NO_DATA_FROM_SOURCE event
// (currently implemented for local tracks only)
| 'rtc.remote_track_unmute'
/**
* Indicates error while set local description.
*/
| 'rtc.set_local_description_failed'
/**
* Indicates error while set remote description.
*/
| 'rtc.set_remote_description_failed'
| 'rtc.audio_output_device_changed'
| 'rtc.device_list_changed'
/**
* Indicates that the list with available devices will change.
*/
| 'rtc.device_list_will_change'
| 'rtc.device_list_available'
/**
* Indicates that a message from another participant is received on
* data channel.
*/
| 'rtc.endpoint_message_received'
/**
* Indicates that the remote endpoint stats have been received on data channnel.
*/
| 'rtc.endpoint_stats_received'
/**
* Designates an event indicating that the local ICE username fragment of
* the jingle session has changed.
* The first argument of the vent is <tt>TraceablePeerConnection</tt> which
* is the source of the event.
* The second argument is the actual "ufrag" string.
*/
| 'rtc.local_ufrag_changed'
/**
* Designates an event indicating that the local ICE username fragment of
* the jingle session has changed.
* The first argument of the vent is <tt>TraceablePeerConnection</tt> which
* is the source of the event.
* The second argument is the actual "ufrag" string.
*/
| 'rtc.remote_ufrag_changed'
/**
* Custom server messages
*/
| `rtc.datachannel.${string}`;
type JitsiRTCEventType = JitsiRTCEventType$1;
type JitsiXmppEventType = JitsiXmppEventType$1;
type JitsiOutputType = 'video' | 'audio';
type JitsiVideoType = 'camera' | 'desktop';
// Not typed yet
// eslint-disable-next-line @typescript-eslint/no-explicit-any
type UntypedCallback = (...data: any[]) => void;
type PayloadObject = object;
interface JitsiTrack {
containers: HTMLMediaElement[];
disposed: boolean;
track: MediaStreamTrack;
stream: MediaStream;
videoType?: JitsiVideoType;
ssrc?: number;
// For local tracks
maxEnabledResolution?: number;
isAudioTrack(): boolean;
isWebRTCTrackMuted(): boolean;
isVideoTrack(): boolean;
isLocal(): boolean;
isLocalAudioTrack(): boolean;
isActive(): boolean;
isMuted(): boolean;
getType(): JitsiOutputType;
getOriginalStream(): MediaStream | null;
getStreamId(): string | null;
getTrack(): MediaStreamTrack;
getTrackLabel(): string;
getTrackId(): string | null;
getUsageLabel(): JitsiVideoType | 'mic' | 'default';
getId(): string | null;
getParticipantId(): string | null;
getSourceName(): string;
attach(element: HTMLVideoElement | HTMLAudioElement): void;
detach(element: HTMLVideoElement | HTMLAudioElement): void;
dispose(): Promise<void>;
// audioLevel: value between 0 and 1
setAudioLevel(audioLevel: number, tpc: TraceablePeerConnection): void;
getMSID(): `${string} ${string}` | null;
setAudioOutput(audioOutputDeviceId: string): Promise<void>;
addEventListener(event: string, callback: UntypedCallback): void;
removeEventListener(event: string, callback: UntypedCallback): void;
}
interface JitsiRemoteTrack extends JitsiTrack {
isP2P: boolean;
setMute(value: boolean): void;
getSSRC(): number; // synchronization source identifier
_getStatus(): `readyState: ${MediaStreamTrackState}, muted: ${boolean}, enabled: ${boolean}`;
toString(): `RemoteTrack[userID: ${string}, type: ${JitsiOutputType}, ssrc: ${number}, p2p: ${boolean}, status: ${ReturnType<
JitsiRemoteTrack['_getStatus']
>}]`;
}
type JitsiLocalTrackEffect = Readonly<{
isEnabled: (track: JitsiLocalTrack) => boolean;
isMuted?: () => boolean;
setMuted?: (muted: boolean) => void;
startEffect: (stream: MediaStream) => MediaStream | null;
stopEffect: () => void;
}>;
interface JitsiLocalTrack extends JitsiTrack {
_realDeviceId: string;
deviceId: string;
isEnded(): boolean;
isReceivingData(): boolean;
getCameraFacingMode(): 'environment' | 'user' | undefined;
getDeviceId(): string;
setEffect(effect: JitsiLocalTrackEffect | undefined): Promise<void>;
setConference(conference: JitsiConference | null): void;
mute(): Promise<void>;
unmute(): Promise<void>;
stopStream(): void;
toString(): `LocalTrack[${number},${JitsiOutputType}]`;
_originalStream: MediaStream | null;
rtcId: number;
}
type TPCGroupInfo = {
/** the SSRC groups semantics */
semantics: string;
/** group's SSRCs in order where the first one is group's primary SSRC,
* the second one is secondary (RTX) and so on... */
ssrcs: Array<number>;
};
type TPCSSRCInfo = {
/** an array which holds all track's SSRCs */
ssrcs: Array<number>;
/** an array stores all track's SSRC groups */
groups: Array<TPCGroupInfo>;
};
type TraceablePeerConnection = {
peerconnection?: RTCPeerConnection;
localSSRCs: Map<string, TPCSSRCInfo>;
getLocalSSRC(localTrack: JitsiTrack): number | undefined;
isSimulcastOn(): boolean;
getActiveSimulcastStreams(): number;
getTargetVideoBitrates(): Record<string, number>;
getConfiguredVideoCodec(): string;
configureSenderVideoEncodings(): void;
};
interface JitsiConnectionOptions {
billingId?: string;
hosts: {
domain: string;
muc?: string;
bridge?: string;
focus?: string;
};
bosh?: string;
websocket?: string;
clientNode?: string;
serviceUrl?: string;
confID?: string;
siteID?: string;
startSilent?: boolean;
applicationName?: string;
resolution?: number;
constraints?: {
video: {
aspectRatio: number;
height: {
ideal: number;
max: number;
min: number;
};
width: {
ideal: number;
max: number;
min: number;
};
};
};
enableWebsocketResume?: boolean;
enableNoAudioDetection?: boolean;
enableNoisyMicDetection?: boolean;
enableTalkWhileMuted?: boolean;
enableUnifiedOnChrome?: boolean;
enableLayerSuspension?: boolean;
createVADProcessor?: () => Promise<VADProcessor>;
channelLastN?: number;
disableSimulcast?: boolean;
audioQuality?: {
stereo?: boolean;
opusMaxAverageBitrate?: number; // 6000 - 510000
};
videoQuality?: {
preferredCodec?: string;
enforcePreferredCodec?: boolean;
disabledCodec?: string;
maxBitratesVideo?: {
low: number;
standard: number;
high: number;
};
desktopBitrate?: number;
configureVP9?: boolean; // custom flag for jazz. see patch 28_vp9-encodings.
multiplierVP9?: number; // custom flag for jazz. see patch 28_vp9-encodings.
};
p2p?: {
enabled?: boolean;
disabledCodec?: string;
preferredCodec?: string;
};
enableForcedReload?: boolean;
enableIceRestart?: boolean;
desktopSharingFrameRate?: {
min: number;
max: number;
};
/** Use TURN/UDP servers for the jitsi-videobridge connection */
useTurnUdp?: boolean;
useNewBandwidthAllocationStrategy?: boolean;
websocketKeepAlive?: number;
}
interface VADProcessor {
getSampleLength(): number;
getRequiredPCMFrequency(): number;
calculateAudioFrameVAD(pcmFrame: Float32Array): number;
}
interface JitsiConferenceOptions extends Omit<JitsiConnectionOptions, 'p2p'> {
openBridgeChannel?: string;
startSilent?: boolean;
p2p?: {
enabled?: boolean;
};
}
interface JitsiUser {
getId(): string;
getJid(): string;
getDisplayName(): string | undefined;
getRole(): string;
isAudioMuted(): boolean;
isVideoMuted(): boolean;
getStatus(): string;
getConnectionStatus(): string;
hasAnyVideoTrackWebRTCMuted(): boolean;
isHidden(): boolean;
isReplacing(): boolean;
isReplaced(): boolean;
getBotType(): string | undefined;
getTracks(): Array<JitsiTrack>;
}
interface JitsiCommand {
value?: string;
attributes?: Record<string, string | undefined>;
children?: JitsiCommand[];
tagName?: string;
}
interface DownloadUploadStats {
download: number;
upload: number;
}
interface JitsiBridgeStats {
bitrate?: DownloadUploadStats & {
audio?: DownloadUploadStats;
video?: DownloadUploadStats;
};
connectionQuality?: number;
packetLoss?: {
total: number;
download: number;
upload: number;
};
}
interface JitsiConnectionQuality {
_remoteStats: Record<string, JitsiBridgeStats>;
getStats(): JitsiBridgeStats;
}
interface JitsiStatistics {
addConnectionStatsListener(callback: () => void): void;
removeConnectionStatsListener(callback: () => void): void;
addMediaNotFlowingListener(callback: (track: JitsiRemoteTrack) => void): void;
removeMediaNotFlowingListener(
callback: (track: JitsiRemoteTrack) => void,
): void;
}
type JitsiListenable<EventName> = {
addListener(eventName: EventName, listener: UntypedCallback): () => void;
removeListener(eventName: EventName, listener: UntypedCallback);
// Aliases
addEventListener: JitsiListenable<EventName>['addListener'];
removeEventListener: JitsiListenable<EventName>['removeListener'];
on: JitsiListenable<EventName>['addListener'];
off: JitsiListenable<EventName>['removeListener'];
};
type StropheConnectionHandlerRef = unknown;
type JitsiXmppConnection = {
getJid(): string;
pingDomain: string | undefined | null;
ping: {
ping(
jid: string,
success: () => unknown,
error: () => unknown,
timeout: number,
): void;
};
_stropheConn: {
_doDisconnect(condition: string): void;
_proto: {
_abortAllRequests(): void;
};
addHandler(
handler: (presence: Node) => void,
ns: string | null,
name: string,
type: string | null,
id: string | null,
from?: string,
options?: { matchBare?: boolean },
): StropheConnectionHandlerRef;
deleteHandler(handlerRef: StropheConnectionHandlerRef): void;
};
disconnect(reason?: string): void;
flush(): void;
getXmppLog(): Array<[number, string, string]>;
connection: {
emuc: {
addEventListener(event: string, callback: UntypedCallback): () => void;
removeEventListener(event: string, callback: UntypedCallback): void;
rooms: Record<string, any>;
};
};
};
type JitsiXmppListenable = JitsiListenable<JitsiXmppEventType>;
type JitsiXmpp = JitsiXmppListenable & {
roomjid: string;
myroomjid: string;
connection: JitsiXmppConnection;
members: Record<string, unknown>;
/** @deprecated It doesn't work */
ping(timeout: number): Promise<boolean>;
/** Flush presence state */
sendPresence(): void;
kick(jid: string, reason?: string): void;
lobby?: {
lobbyRoom?: Omit<JitsiXmpp, 'lobby'>;
};
};
type LobbyRoom = {
isSupported: () => boolean;
enable: () => Promise<unknown>;
disable: () => void;
setLobbyRoomJid: (jid: string) => void;
join: (displayName?: string, email?: string) => Promise<unknown>;
denyAccess: (id: string) => void;
approveAccess: (id: string) => void;
};
type ChatRoom = JitsiXmpp & {
getLobby(): LobbyRoom | undefined;
lobby: LobbyRoom | undefined;
};
type JitsiPeerConnections = Map<
number,
{
peerconnection: RTCPeerConnection;
}
>;
type BridgeChannel = {
isOpen: () => boolean;
_retryWebSocketConnection: ({ code: number, reason: string }) => void;
};
type JitsiMediaType = 'audio' | 'presenter' | 'video';
type JitsiRTC = JitsiListenable<JitsiRTCEventType> & {
peerConnections: JitsiPeerConnections;
_channel?: BridgeChannel | null;
sendChannelMessage<Payload extends object = object>(
to: string | undefined,
payload: Payload,
): void;
getLocalTracks(mediaType?: JitsiMediaType): Array<JitsiLocalTrack>;
getRemoteTracks(mediaType?: JitsiMediaType): Array<JitsiRemoteTrack>;
};
interface JitsiConference {
lastDominantSpeaker: string | null;
options: { name: string };
connectionQuality: JitsiConnectionQuality;
participants: Record<string, JitsiUser>;
statistics: JitsiStatistics;
room: ChatRoom | undefined;
rtc: JitsiRTC;
connection: JitsiConnection;
xmpp: JitsiXmppConnection;
on(event: string, callback: UntypedCallback): void;
off(event: string, callback: UntypedCallback): void;
addEventListener(event: string, callback: UntypedCallback): void;
removeEventListener(event: string, callback: UntypedCallback): void;
enableLobby(): Promise<unknown>;
disableLobby(): void;
isLobbySupported(): boolean;
myLobbyUserId(): string;
joinLobby(name: string, email?: string): void;
lobbyDenyAccess(id: string): void;
lobbyApproveAccess(id: string): void;
join(
password?: string,
participantName?: string,
joinedPayload?: unknown, // custom parameter for jazz.
): void;
leave(): Promise<void>;
addTrack(track: JitsiTrack): Promise<void>;
removeTrack(track: JitsiTrack): Promise<void>;
replaceTrack(
oldTrack: JitsiTrack | null,
newTrack: JitsiTrack | null,
): Promise<void>;
getLocalTracks(
mediaType?: 'video' | 'audio' | 'presenter',
): Array<JitsiLocalTrack>;
getLocalAudioTrack(): JitsiLocalTrack | null;
getLocalVideoTrack(): JitsiLocalTrack | null;
getPhoneNumber(): string;
getPhonePin(): string;
myUserId(): string;
getParticipantById(participantId: string): JitsiUser | undefined;
selectParticipant(participantId: string): void;
getRole(): 'moderator' | 'none';
isModerator(): boolean;
isHidden(): boolean | undefined | null;
lock(password: string): Promise<void>; // moderator only
unlock(): Promise<void>; // moderator only
setStartMutedPolicy(policy: { video: boolean; audio: boolean }): void; // moderator only
getStartMutedPolicy(): { video: boolean; audio: boolean };
setReceiverVideoConstraint(resolution: number): void;
setSenderVideoConstraint(resolution: number | undefined): void;
setSubject(subject: string): void; // moderator only
setDisplayName(name: string): void;
sendMessage(text: string, to?: string): void;
sendJsonMessage(data: Object, from?: string, to?: string): Promise<void>;
sendEndpointMessage(to: string, payload: PayloadObject): void;
broadcastEndpointMessage(payload: PayloadObject): void;
setLastN(count: number): void;
/**
Отправляет команды всем, включая себя, иногда команды могут приходить повторно, с теми же
данными
*/
sendCommand(name: string, values: JitsiCommand): void;
removeCommand(name: string): void;
sendCommandOnce(name: string, values: JitsiCommand): void;
addCommandListener(
name: string,
handler: (values: JitsiCommand, participantId: string) => void,
): void;
removeCommandListener(
name: string,
handler: (values: JitsiCommand, participantId: string) => void,
): void;
setDesktopSharingFrameRate(maxFps: number): void;
getActivePeerConnection(): TraceablePeerConnection | undefined | null;
getParticipants(): Array<JitsiUser>;
muteParticipant(participantId: string, mediaType: JitsiMediaType): void;
kickParticipant(participantId: string, reason?: string): void;
_setupNewTrack(track: JitsiLocalTrack): void;
_onTrackAttach(track: JitsiLocalTrack, container: HTMLElement): void;
_removeLocalTrackFromPc(track: JitsiLocalTrack): Promise<void>;
_addLocalTrackToPc(track: JitsiLocalTrack): Promise<void>;
_setTrackMuteStatus(
mediaType: string,
track: JitsiLocalTrack,
isMuted: boolean,
): void;
_sendBridgeVideoTypeMessage(track: JitsiLocalTrack): void;
}
interface JitsiConnectionConnectOptions {
id: string;
password: string;
}
type JitsiConnection = {
new (
appId: string,
token: string | undefined | null,
options: JitsiConnectionOptions,
): JitsiConnection;
addEventListener(event: string, callback: UntypedCallback): void;
removeEventListener(event: string, callback: UntypedCallback): void;
connect(options?: JitsiConnectionConnectOptions): void;
initJitsiConference(
name: string,
options: JitsiConferenceOptions,
): JitsiConference;
disconnect(): Promise<void>;
getLogs(): any;
addFeature(feature: string, submit?: boolean): void;
xmpp: JitsiXmppConnection;
};
type RequestId = string;
type EventOk<T = string, P = unknown> = {
event: T;
requestId: RequestId;
roomId: string;
groupId: string | undefined;
payload: P;
};
type EventError<
Code = string,
Params = unknown,
Error extends string = 'error',
> = {
event: Error;
requestId: RequestId;
roomId: string;
groupId: string | undefined;
payload: PayloadError<Code, Params>;
};
type PayloadError<Code, Params> = {
code: Code;
message?: string;
params?: Params;
};
type ConnectionInterruptedReason =
| 'unknown'
| 'iceConnection'
| 'xmppConnection'
| 'jvbConnection';
type AuthStatus = 'anonymous' | 'authorised';
type AuthMethod = StringEnum<'token'>;
type DisplayCaptureMode = 'highQuality' | 'maxFPS';
/**
* Provider of a state value.
*/
type Query<T> = Query$1<T>;
/**
* Function which unsubscribes from something.
*/
type Unsubscriber = () => void;
/**
* Subscribes a listener on a value of the query and its changes.
* @example
* ```ts
import {
handleQuery,
} from '@salutejs/jazz-sdk-web';
...
const unsubscribe = handleQuery(room.participants, (participants) => {
console.log(participants);
});
unsubscribe()
```
*/
declare function handleQuery<T>(
query: Query<T> | Atom<T>,
observer: (value: T) => unknown,
): Unsubscriber;
/**
* Subscribes a listener on changes of the query only.
*
* @example
* ```ts
import {
handleQueryChanges,
} from '@salutejs/jazz-sdk-web';
...
const unsubscribe = handleQueryChanges(room.participants, (participants) => {
console.log(participants);
});
unsubscribe()
```
*/
declare function handleQueryChanges<T>(
query: Query<T> | Atom<T>,
listener: (value: T) => unknown,
): Unsubscriber;
/**
* Subscribes a listener on an event bus by type.
*
* @example
* ```ts
import {
handleEvent,
} from '@salutejs/jazz-sdk-web';
...
const unsubscribe = handleEvent(
client.event$,
'addRoom',
async ({ payload }) => {
console.log(payload.room);
},
);
unsubscribe();
```
*/
declare function handleEvent<
Event extends EventLike,
Type extends Event['type'],
TypedEvent extends Event & {
type: Type;
},
>(
eventBus: Observable<Event> | Signal<Event>,
type: Type,
listener: (event: TypedEvent) => unknown,
isOnce?: boolean,
): Unsubscriber;
/**
* Subscribes a listener on an event bus.
*
* @example
* ```ts
import {
handleEvents,
} from '@salutejs/jazz-sdk-web';
...
const unsubscribe = handleEvents(client.event$, (event) => {
if (event.type === 'addRoom') {
console.log(payload.room);
}
});
unsubscribe()
```
*/
declare function handleEvents<Event extends EventLike>(
eventBus: Observable<Event> | Signal<Event>,
listener: (event: Event) => unknown,
isOnce?: boolean,
): Unsubscriber;
type MediaPermission = 'granted' | 'denied' | 'prompt';
type UserMediaType = 'audio' | 'video';
type DisplayMediaType = 'displayScreen';
type MediaType = UserMediaType | DisplayMediaType;
type UserMediaPermissionState = Readonly<
Record<UserMediaType, MediaPermission>
>;
type DisplayMediaPermissionState = Readonly<
Record<DisplayMediaType, MediaPermission>
>;
type GroupedDevices = {
['audioInput']: LocalAudioInputDevice[];
['audioOutput']: LocalAudioOutputDevice[];
['videoInput']: LocalVideoInputDevice[];
};
type LocalMediaDeviceKind = 'audioInput' | 'audioOutput' | 'videoInput';
type LocalMediaDeviceId = string;
type BaseMediaDeviceInfo = {
deviceId: LocalMediaDeviceId;
groupId?: string;
label: string | '';
};
type LocalAudioInputDevice = Readonly<
{
kind: 'audioInput';
} & BaseMediaDeviceInfo
>;
type LocalAudioOutputDevice = Readonly<
{
kind: 'audioOutput';
} & BaseMediaDeviceInfo
>;
type LocalVideoInputDevice = Readonly<
{
kind: 'videoInput';
} & BaseMediaDeviceInfo
>;
type LocalMediaDevice =
| LocalAudioInputDevice
| LocalAudioOutputDevice
| LocalVideoInputDevice;
type MediaPermissionErrorType = 'browser' | 'OS' | 'unknown';
type MediaPermissionErrorKind = 'audio' | 'video';
/**
* type Query is deprecated, the name of the future reactive data is Atom
*/
type QueryAtom<T> = Atom<T> & Query$1<T>;
declare class JazzRoomError<
T extends JazzRoomErrorReason = JazzRoomErrorReason,
> extends Error {
readonly reason: T;
constructor(message: string, reason: T);
}
declare class AuthorizationRequiredError extends Error {
constructor();
}
declare class RoomConnectedError extends Error {
constructor();
}
declare class PermissionDeniedError extends Error {
constructor(permission: string);
}
declare const LOCAL_MEDIA_DEVICE_KIND: {
readonly AUDIO_INPUT: 'audioInput';
readonly AUDIO_OUTPUT: 'audioOutput';
readonly VIDEO_INPUT: 'videoInput';
};
declare const MEDIA_PERMISSION: {
readonly GRANTED: 'granted';
readonly DENIED: 'denied';
readonly PROMPT: 'prompt';
};
declare const DISPLAY_MEDIA_TYPE: {
readonly SCREEN: 'displayScreen';
};
declare const USER_MEDIA_TYPE: {
readonly AUDIO: 'audio';
readonly VIDEO: 'video';
};
type LocalTrackEffect = JitsiLocalTrackEffect;
type JazzVideoResolution =
| '2160'
| '4k'
| '1080'
| 'fullhd'
| '720'
| 'hd'
| '540'
| 'qhd'
| '480'
| 'vga'
| '360'
| '240'
| '180';
type JazzRoomEventLocalParticipantId = Readonly<{
type: 'localParticipantId';
payload: {
participantId: JazzRoomParticipantId;
};
}>;
type JazzRoomEventParticipants = Readonly<{
type: 'participants';
payload: {
participants: JazzRoomParticipant[];
};
}>;
type JazzRoomEventParticipantUpdate = Readonly<{
type: 'participantUpdate';
payload: {
participant: {
id: JazzRoomParticipantId;
} & Partial<Omit<JazzRoomParticipant, 'id'>>;
};
}>;
type JazzRoomEventParticipantLeft = Readonly<{
type: 'participantLeft';
payload: {
participant: JazzRoomParticipant;
};
}>;
type JazzRoomEventParticipantJoined = Readonly<{
type: 'participantJoined';
payload: {
participant: JazzRoomParticipant;
};
}>;
type JazzRoomParticipantRole = StringEnum<'owner' | 'member' | 'moderator'>;
type JazzRoomParticipantId = string;
type JazzRoomParticipantCommon = {
id: JazzRoomParticipantId;
name: string;
isGuest: boolean;
role: JazzRoomParticipantRole;
joinedDate: number;
email?: string;
};
type JazzRoomParticipantBotType = string;
type JazzRoomParticipantBotDetails = {
type: JazzRoomParticipantBotType;
};
type JazzRoomParticipantBot = JazzRoomParticipantCommon & {
bot: JazzRoomParticipantBotDetails;
};
type JazzRoomParticipantUser = JazzRoomParticipantCommon & {
bot?: undefined;
};
type JazzRoomParticipant = JazzRoomParticipantBot | JazzRoomParticipantUser;
type JazzRoomStatus = JazzRoomStatusMap[keyof JazzRoomStatusMap];
type JazzRoomStatusMap = {
readonly CONNECTED: 'connected';
readonly CONNECTING: 'connecting';
readonly DISCONNECTING: 'disconnecting';
readonly DISCONNECTED: 'disconnected';
readonly ERROR: 'error';
};
type JazzRoomConnectionStatus =
JazzRoomConnectionStatusMap[keyof JazzRoomConnectionStatusMap];
type JazzRoomConnectionStatusMap = {
readonly CONNECTED: 'connected';
readonly CONNECTING: 'connecting';
readonly DISCONNECTED: 'disconnected';
readonly FAILED: 'failed';
};
type JazzRoomReconnectingReason =
| ConnectionInterruptedReason
| 'errorConferenceRestarted'
| 'suspendDetected'
| 'network';
type JazzRoomAudioSource = 'user' | 'display';
type JazzRoomVideoSource = 'user' | 'display';
/** @deprecated please use width and height */
type JazzRoomQuality = 'high' | 'medium' | 'low';
type JazzRoomVideoQuality = Readonly<{
/** @deprecated please use width and height */
quality?: JazzRoomQuality;
height: number;
width: number;
}>;
type JazzRoomMediaSourceState = Readonly<{
isMuted: boolean;
stream?: MediaStream;
}>;
type JazzRoomAudioSourceState = Readonly<
Record<JazzRoomAudioSource, JazzRoomMediaSourceState | undefined>
>;
type JazzRoomVideoSourceState = Readonly<
Record<JazzRoomVideoSource, JazzRoomMediaSourceState | undefined>
>;
type JazzRoomVideoRequest = Readonly<
{
source: JazzRoomVideoSource;
} & JazzRoomVideoQuality
>;
type JazzRoomSettings = {
title: string;
isGuestEnabled: boolean;
};
type JazzRoomSettingsUpdates = {
title: string;
guestEnabled: boolean;
};
type JazzRoomSettingsUpdate = Partial<JazzRoomSettingsUpdates>;
type JazzRoomSettingsState = {
[key in keyof JazzRoomSettings]: JazzRoomSettings[key] | undefined;
};
type JazzRoomSettingsQueries = {
[key in keyof JazzRoomSettingsState]: QueryAtom<JazzRoomSettingsState[key]>;
};
type JazzRoomUserPermissionRequest = {
permissionKey: JazzRoomUserPermissionKey;
created: Timestamp;
canRequestAgain: boolean;
};
type JazzRoomUserPermissionKey = keyof JazzRoomUserPermissions;
type JazzRoomUserPermissions = UserPermissions;
type JazzRoomPartialUserPermissions = Partial<JazzRoomUserPermissions>;
type NotAllowedError = {
type: 'notAllowed';
};
type AccessByPermissionError = {
type: 'accessByPermission';
};
type ExceededMaxSdkMeetingsError = {
type: 'exceededMaxSdkMeetings';
};
type NetworkError = {
type: 'network';
};
type OpenConnectionError = {
type: 'openConnection';
};
type RoomNotFoundError = {
type: 'roomNotFound';
};
type RoomNotSupportedByClientError = {
type: 'roomNotSupportedByClientError';
};
type UnauthorizedError = {
type: 'unauthorized';
};
type ForbiddenError = {
type: 'forbidden';
};
type RoomCapacityExceededError = {
type: 'roomCapacityExceeded';
payload: {
roomCapacity?: number;
};
};
type UnknownError = {
type: 'unknown';
};
type JazzRoomErrorReason =
| NotAllowedError
| AccessByPermissionError
| ExceededMaxSdkMeetingsError
| NetworkError
| OpenConnectionError
| RoomNotFoundError
| RoomNotSupportedByClientError
| UnauthorizedError
| ForbiddenError
| RoomCapacityExceededError
| UnknownError;
type JazzRoomKickedReason = StringEnum<
| 'callEnded'
| 'kicked'
| 'exceededMaxConferenceCapacity'
| 'exceededMaxConferenceViewersCapacity'
| 'exceededMaxConferenceDuration'
| 'guestsNotAllowed'
>;
type JazzRoomKickedPayload = {
reason: JazzRoomKickedReason;
};
type JazzRoomEventKicked = {
type: 'kicked';
payload: JazzRoomKickedPayload;
};
type JazzRoomLeaveReason = 'localEnd' | 'callEnd';
type JazzRoomEventLeave = {
type: 'leave';
payload: {
reason: JazzRoomLeaveReason;
};
};
type JazzRoomEventAddTrack = Readonly<{
type: 'addTrack';
payload: {
stream: MediaStream;
mediaType: MediaType;
participantId: JazzRoomParticipantId;
isMuted: boolean;
isLocal: boolean;
};
}>;
type JazzRoomEventRemoveTrack = Readonly<{
type: 'removeTrack';
payload: {
stream: MediaStream;
mediaType: MediaType;
participantId: JazzRoomParticipantId;
isMuted: boolean;
isLocal: boolean;
};
}>;
type JazzRoomEventTrackMuteChanged = Readonly<{
type: 'trackMuteChanged';
payload: {
isMuted: boolean;
stream: MediaStream;
mediaType: MediaType;
participantId: JazzRoomParticipantId;
changedByParticipantId: string;
isLocal: boolean;
};
}>;
type JazzRoomEventTrackMuteChangeRejected = Readonly<{
type: 'trackMuteChangeRejected';
payload: {
stream: MediaStream;
mediaType: MediaType;
};
}>;
type JazzRoomEventTrackAddRejected = Readonly<{
type: 'trackAddRejected';
payload: {
stream: MediaStream;
mediaType: MediaType;
};
}>;
type JazzRoomEventTrackUpdated = Readonly<{
type: 'trackUpdated';
payload: {
stream: MediaStream;
mediaType: MediaType;
participantId: JazzRoomParticipantId;
isMuted: boolean;
isLocal: boolean;
};
}>;
type JazzRoomEventRemoteTrackInfo = Readonly<{
type: 'remoteTrackInfo';
payload: {
participantId: JazzRoomParticipantId;
mediaType: MediaType;
isMuted: boolean;
};
}>;
type JazzRoomEventSettingsChanged = Readonly<{
type: 'settingsChanged';
payload: Partial<{
title: string;
isGuestEnabled: boolean;
}>;
}>;
type JazzRoomParamsUpdate = Readonly<{
conferenceId: JazzRoomConferenceId;
conferencePassword: string;
roomId: JazzRoomId;
roomPassword: string;
roomType: JazzRoomType;
nodeUrl: string;
nodeToken: string;
domainUrl: string | undefined;
sessionSecret: string;
}>;
type JazzRoomEventParamsChanged = Readonly<{
type: 'paramsChanged';
payload: JazzRoomParamsUpdate;
}>;
type JazzRoomEventLocalParticipantChanged = Readonly<{
type: 'localParticipantChanged';
payload: {
participant: JazzRoomParticipant;
};
}>;
type JazzRoomEventDominantSpeakerChanged = Readonly<{
type: 'dominantSpeakerChanged';
payload: {
id: JazzRoomParticipantId;
prevId: JazzRoomParticipantId | undefined;
};
}>;
type JazzRoomEventDestroy = Readonly<{
type: 'destroy';
}>;
type JazzRoomEventAccessByPermission = Readonly<{
type: 'accessByPermission';
}>;
type JazzRoomEventStatusChanged = Readonly<{
type: 'statusChanged';
payload:
| {
status: JazzRoomStatusMap['CONNECTING'];
}
| {
status: JazzRoomStatusMap['CONNECTED'];
}
| {
status: JazzRoomStatusMap['DISCONNECTING'];
}
| {
status: JazzRoomStatusMap['DISCONNECTED'];
}
| {
status: JazzRoomStatusMap['ERROR'];
error: JazzRoomErrorReason;
};
}>;
type JazzRoomEventConnecting = Readonly<{
type: 'connecting';
}>;
type JazzRoomEventConnected = Readonly<{
type: 'connected';
payload: {
localParticipantId: JazzRoomParticipantId;
roomId: JazzRoomId;
meetingId: JazzMeetingId;
};
}>;
type JazzRoomEventDisconnecting = Readonly<{
type: 'disconnecting';
}>;
type JazzRoomEventDisconnected = Readonly<{
type: 'disconnected';
}>;
type JazzRoomEventError = Readonly<{
type: 'error';
payload: {
error: JazzRoomErrorReason;
};
}>;
type JazzRoomEventConnectionChanged = Readonly<{
type: 'connectionChanged';
payload:
| {
status: JazzRoomConnectionStatusMap['FAILED'];
reason: string;
}
| {
status: JazzRoomConnectionStatusMap['CONNECTING'];
}
| {
status: JazzRoomConnectionStatusMap['CONNECTED'];
}
| {
status: JazzRoomConnectionStatusMap['DISCONNECTED'];
};
}>;
type JazzRoomEventConnectionFailed = Readonly<{
type: 'connectionFailed';
payload: {
reason: string;
};
}>;
type JazzRoomEventConnectionConnecting = Readonly<{
type: 'connectionConnecting';
}>;
type JazzRoomEventConnectionOpen = Readonly<{
type: 'connectionOpen';
}>;
type JazzRoomEventConnectionDisconnected = Readonly<{
type: 'connectionDisconnected';
}>;
type JazzRoomEventReconnecting = Readonly<{
type: 'reconnecting';
payload: {
reason: JazzRoomReconnectingReason;
};
}>;
type JazzRoomEventConnectionInterrupted = Readonly<{
type: 'connectionInterrupted';
payload: {
reason: ConnectionInterruptedReason;
};
}>;
type JazzRoomEventPermissionGranted = Readonly<{
type: 'permissionGranted';
payload: {
permission: JazzRoomUserPermissionKey;
};
}>;
type JazzRoomEventPermissionDenied = Readonly<{
type: 'permissionDenied';
payload: {
permission: JazzRoomUserPermissionKey;
};
}>;
type JazzRoomEventRolePermissionsChanged = Readonly<{
type: 'rolePermissionsChanged';
payload: {
userRole: JazzRoomParticipantRole;
permissions: JazzRoomPartialUserPermissions;
prevPermissions: JazzRoomPartialUserPermissions;
};
}>;
type JazzRoomEventPermissionRequested = Readonly<{
type: 'permissionRequested';
payload: {
participantId: JazzRoomParticipantId;
permission: JazzRoomUserPermissionKey;
};
}>;
type JazzRoomEvent =
| JazzRoomEventAddTrack
| JazzRoomEventRemoveTrack
| JazzRoomEventTrackMuteChanged
| JazzRoomEventTrackMuteChangeRejected
| JazzRoomEventTrackAddRejected
| JazzRoomEventTrackUpdated
| JazzRoomEventRemoteTrackInfo
| JazzRoomEventSettingsChanged
| JazzRoomEventLocalParticipantId
| JazzRoomEventLocalParticipantChanged
| JazzRoomEventParticipants
| JazzRoomEventParticipantUpdate
| JazzRoomEventParticipantLe