UNPKG

@salutejs/jazz-sdk-web

Version:

Jazz SDK for web applications

1,919 lines (1,649 loc) 95.8 kB
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