jiti-meet/modules/API/API.js

553 lines
15 KiB
JavaScript
Raw Normal View History

// @flow
import * as JitsiMeetConferenceEvents from '../../ConferenceEvents';
import {
Restructures the analytics events (#2333) * ref: Restructures the pinned/unpinned events. * ref: Refactors the "audio only disabled" event. * ref: Refactors the "stream switch delay" event. * ref: Refactors the "select participant failed" event. * ref: Refactors the "initially muted" events. * ref: Refactors the screen sharing started/stopped events. * ref: Restructures the "device list changed" events. * ref: Restructures the "shared video" events. * ref: Restructures the "start muted" events. * ref: Restructures the "start audio only" event. * ref: Restructures the "sync track state" event. * ref: Restructures the "callkit" events. * ref: Restructures the "replace track". * ref: Restructures keyboard shortcuts events. * ref: Restructures most of the toolbar events. * ref: Refactors the API events. * ref: Restructures the video quality, profile button and invite dialog events. * ref: Refactors the "device changed" events. * ref: Refactors the page reload event. * ref: Removes an unused function. * ref: Removes a method which is needlessly exposed under a different name. * ref: Refactors the events from the remote video menu. * ref: Refactors the events from the profile pane. * ref: Restructures the recording-related events. Removes events fired when recording with something other than jibri (which isn't currently supported anyway). * ref: Cleans up AnalyticsEvents.js. * ref: Removes an unused function and adds documentation. * feat: Adds events for all API calls. * fix: Addresses feedback. * fix: Brings back mistakenly removed code. * fix: Simplifies code and fixes a bug in toggleFilmstrip when the 'visible' parameter is defined. * feat: Removes the resolution change application log. * ref: Uses consistent naming for events' attributes. Uses "_" as a separator instead of camel case or ".". * ref: Don't add the user agent and conference name as permanent properties. The library does this on its own now. * ref: Adapts the GA handler to changes in lib-jitsi-meet. * ref: Removes unused fields from the analytics handler initializaiton. * ref: Renames the google analytics file and add docs. * fix: Fixes the push-to-talk events and logs. * npm: Updates lib-jitsi-meet to 515374c8d383cb17df8ed76427e6f0fb5ea6ff1e. * fix: Fixes a recently introduced bug in the google analytics handler. * ref: Uses "value" instead of "delay" since this is friendlier to GA.
2018-01-03 21:24:07 +00:00
createApiEvent,
sendAnalytics
} from '../../react/features/analytics';
import { parseJWTFromURLParams } from '../../react/features/base/jwt';
import { invite } from '../../react/features/invite';
import { getJitsiMeetTransport } from '../transport';
2016-11-11 15:00:54 +00:00
import { API_ID } from './constants';
2016-06-13 21:11:44 +00:00
const logger = require('jitsi-meet-logger').getLogger(__filename);
declare var APP: Object;
2015-01-09 13:39:32 +00:00
/**
* List of the available commands.
*/
2016-06-13 21:11:44 +00:00
let commands = {};
/**
2017-04-11 19:30:00 +00:00
* The state of screen sharing(started/stopped) before the screen sharing is
* enabled and initialized.
* NOTE: This flag help us to cache the state and use it if toggle-share-screen
* was received before the initialization.
2016-06-13 21:11:44 +00:00
*/
2017-04-11 19:30:00 +00:00
let initialScreenSharingState = false;
2016-06-13 21:11:44 +00:00
/**
* The transport instance used for communication with external apps.
*
* @type {Transport}
2016-06-13 21:11:44 +00:00
*/
const transport = getJitsiMeetTransport();
2017-08-04 08:15:11 +00:00
/**
* The current audio availability.
*
* @type {boolean}
*/
let audioAvailable = true;
/**
* The current video availability.
*
* @type {boolean}
*/
let videoAvailable = true;
/**
* Initializes supported commands.
*
* @returns {void}
*/
function initCommands() {
commands = {
Restructures the analytics events (#2333) * ref: Restructures the pinned/unpinned events. * ref: Refactors the "audio only disabled" event. * ref: Refactors the "stream switch delay" event. * ref: Refactors the "select participant failed" event. * ref: Refactors the "initially muted" events. * ref: Refactors the screen sharing started/stopped events. * ref: Restructures the "device list changed" events. * ref: Restructures the "shared video" events. * ref: Restructures the "start muted" events. * ref: Restructures the "start audio only" event. * ref: Restructures the "sync track state" event. * ref: Restructures the "callkit" events. * ref: Restructures the "replace track". * ref: Restructures keyboard shortcuts events. * ref: Restructures most of the toolbar events. * ref: Refactors the API events. * ref: Restructures the video quality, profile button and invite dialog events. * ref: Refactors the "device changed" events. * ref: Refactors the page reload event. * ref: Removes an unused function. * ref: Removes a method which is needlessly exposed under a different name. * ref: Refactors the events from the remote video menu. * ref: Refactors the events from the profile pane. * ref: Restructures the recording-related events. Removes events fired when recording with something other than jibri (which isn't currently supported anyway). * ref: Cleans up AnalyticsEvents.js. * ref: Removes an unused function and adds documentation. * feat: Adds events for all API calls. * fix: Addresses feedback. * fix: Brings back mistakenly removed code. * fix: Simplifies code and fixes a bug in toggleFilmstrip when the 'visible' parameter is defined. * feat: Removes the resolution change application log. * ref: Uses consistent naming for events' attributes. Uses "_" as a separator instead of camel case or ".". * ref: Don't add the user agent and conference name as permanent properties. The library does this on its own now. * ref: Adapts the GA handler to changes in lib-jitsi-meet. * ref: Removes unused fields from the analytics handler initializaiton. * ref: Renames the google analytics file and add docs. * fix: Fixes the push-to-talk events and logs. * npm: Updates lib-jitsi-meet to 515374c8d383cb17df8ed76427e6f0fb5ea6ff1e. * fix: Fixes a recently introduced bug in the google analytics handler. * ref: Uses "value" instead of "delay" since this is friendlier to GA.
2018-01-03 21:24:07 +00:00
'display-name': displayName => {
sendAnalytics(createApiEvent('display.name.changed'));
APP.conference.changeLocalDisplayName(displayName);
},
'submit-feedback': feedback => {
sendAnalytics(createApiEvent('submit.feedback'));
APP.conference.submitFeedback(feedback.score, feedback.message);
},
'toggle-audio': () => {
Restructures the analytics events (#2333) * ref: Restructures the pinned/unpinned events. * ref: Refactors the "audio only disabled" event. * ref: Refactors the "stream switch delay" event. * ref: Refactors the "select participant failed" event. * ref: Refactors the "initially muted" events. * ref: Refactors the screen sharing started/stopped events. * ref: Restructures the "device list changed" events. * ref: Restructures the "shared video" events. * ref: Restructures the "start muted" events. * ref: Restructures the "start audio only" event. * ref: Restructures the "sync track state" event. * ref: Restructures the "callkit" events. * ref: Restructures the "replace track". * ref: Restructures keyboard shortcuts events. * ref: Restructures most of the toolbar events. * ref: Refactors the API events. * ref: Restructures the video quality, profile button and invite dialog events. * ref: Refactors the "device changed" events. * ref: Refactors the page reload event. * ref: Removes an unused function. * ref: Removes a method which is needlessly exposed under a different name. * ref: Refactors the events from the remote video menu. * ref: Refactors the events from the profile pane. * ref: Restructures the recording-related events. Removes events fired when recording with something other than jibri (which isn't currently supported anyway). * ref: Cleans up AnalyticsEvents.js. * ref: Removes an unused function and adds documentation. * feat: Adds events for all API calls. * fix: Addresses feedback. * fix: Brings back mistakenly removed code. * fix: Simplifies code and fixes a bug in toggleFilmstrip when the 'visible' parameter is defined. * feat: Removes the resolution change application log. * ref: Uses consistent naming for events' attributes. Uses "_" as a separator instead of camel case or ".". * ref: Don't add the user agent and conference name as permanent properties. The library does this on its own now. * ref: Adapts the GA handler to changes in lib-jitsi-meet. * ref: Removes unused fields from the analytics handler initializaiton. * ref: Renames the google analytics file and add docs. * fix: Fixes the push-to-talk events and logs. * npm: Updates lib-jitsi-meet to 515374c8d383cb17df8ed76427e6f0fb5ea6ff1e. * fix: Fixes a recently introduced bug in the google analytics handler. * ref: Uses "value" instead of "delay" since this is friendlier to GA.
2018-01-03 21:24:07 +00:00
sendAnalytics(createApiEvent('toggle-audio'));
logger.log('Audio toggle: API command received');
APP.conference.toggleAudioMuted(false /* no UI */);
},
'toggle-video': () => {
Restructures the analytics events (#2333) * ref: Restructures the pinned/unpinned events. * ref: Refactors the "audio only disabled" event. * ref: Refactors the "stream switch delay" event. * ref: Refactors the "select participant failed" event. * ref: Refactors the "initially muted" events. * ref: Refactors the screen sharing started/stopped events. * ref: Restructures the "device list changed" events. * ref: Restructures the "shared video" events. * ref: Restructures the "start muted" events. * ref: Restructures the "start audio only" event. * ref: Restructures the "sync track state" event. * ref: Restructures the "callkit" events. * ref: Restructures the "replace track". * ref: Restructures keyboard shortcuts events. * ref: Restructures most of the toolbar events. * ref: Refactors the API events. * ref: Restructures the video quality, profile button and invite dialog events. * ref: Refactors the "device changed" events. * ref: Refactors the page reload event. * ref: Removes an unused function. * ref: Removes a method which is needlessly exposed under a different name. * ref: Refactors the events from the remote video menu. * ref: Refactors the events from the profile pane. * ref: Restructures the recording-related events. Removes events fired when recording with something other than jibri (which isn't currently supported anyway). * ref: Cleans up AnalyticsEvents.js. * ref: Removes an unused function and adds documentation. * feat: Adds events for all API calls. * fix: Addresses feedback. * fix: Brings back mistakenly removed code. * fix: Simplifies code and fixes a bug in toggleFilmstrip when the 'visible' parameter is defined. * feat: Removes the resolution change application log. * ref: Uses consistent naming for events' attributes. Uses "_" as a separator instead of camel case or ".". * ref: Don't add the user agent and conference name as permanent properties. The library does this on its own now. * ref: Adapts the GA handler to changes in lib-jitsi-meet. * ref: Removes unused fields from the analytics handler initializaiton. * ref: Renames the google analytics file and add docs. * fix: Fixes the push-to-talk events and logs. * npm: Updates lib-jitsi-meet to 515374c8d383cb17df8ed76427e6f0fb5ea6ff1e. * fix: Fixes a recently introduced bug in the google analytics handler. * ref: Uses "value" instead of "delay" since this is friendlier to GA.
2018-01-03 21:24:07 +00:00
sendAnalytics(createApiEvent('toggle-video'));
logger.log('Video toggle: API command received');
APP.conference.toggleVideoMuted(false /* no UI */);
},
Restructures the analytics events (#2333) * ref: Restructures the pinned/unpinned events. * ref: Refactors the "audio only disabled" event. * ref: Refactors the "stream switch delay" event. * ref: Refactors the "select participant failed" event. * ref: Refactors the "initially muted" events. * ref: Refactors the screen sharing started/stopped events. * ref: Restructures the "device list changed" events. * ref: Restructures the "shared video" events. * ref: Restructures the "start muted" events. * ref: Restructures the "start audio only" event. * ref: Restructures the "sync track state" event. * ref: Restructures the "callkit" events. * ref: Restructures the "replace track". * ref: Restructures keyboard shortcuts events. * ref: Restructures most of the toolbar events. * ref: Refactors the API events. * ref: Restructures the video quality, profile button and invite dialog events. * ref: Refactors the "device changed" events. * ref: Refactors the page reload event. * ref: Removes an unused function. * ref: Removes a method which is needlessly exposed under a different name. * ref: Refactors the events from the remote video menu. * ref: Refactors the events from the profile pane. * ref: Restructures the recording-related events. Removes events fired when recording with something other than jibri (which isn't currently supported anyway). * ref: Cleans up AnalyticsEvents.js. * ref: Removes an unused function and adds documentation. * feat: Adds events for all API calls. * fix: Addresses feedback. * fix: Brings back mistakenly removed code. * fix: Simplifies code and fixes a bug in toggleFilmstrip when the 'visible' parameter is defined. * feat: Removes the resolution change application log. * ref: Uses consistent naming for events' attributes. Uses "_" as a separator instead of camel case or ".". * ref: Don't add the user agent and conference name as permanent properties. The library does this on its own now. * ref: Adapts the GA handler to changes in lib-jitsi-meet. * ref: Removes unused fields from the analytics handler initializaiton. * ref: Renames the google analytics file and add docs. * fix: Fixes the push-to-talk events and logs. * npm: Updates lib-jitsi-meet to 515374c8d383cb17df8ed76427e6f0fb5ea6ff1e. * fix: Fixes a recently introduced bug in the google analytics handler. * ref: Uses "value" instead of "delay" since this is friendlier to GA.
2018-01-03 21:24:07 +00:00
'toggle-film-strip': () => {
sendAnalytics(createApiEvent('film.strip.toggled'));
APP.UI.toggleFilmstrip();
},
'toggle-chat': () => {
sendAnalytics(createApiEvent('chat.toggled'));
APP.UI.toggleChat();
},
'toggle-share-screen': () => {
sendAnalytics(createApiEvent('screen.sharing.toggled'));
toggleScreenSharing();
},
'video-hangup': () => {
sendAnalytics(createApiEvent('video.hangup'));
APP.conference.hangup(true);
},
'email': email => {
sendAnalytics(createApiEvent('email.changed'));
APP.conference.changeLocalEmail(email);
},
'avatar-url': avatarUrl => {
sendAnalytics(createApiEvent('avatar.url.changed'));
APP.conference.changeLocalAvatarUrl(avatarUrl);
}
};
transport.on('event', ({ data, name }) => {
if (name && commands[name]) {
commands[name](...data);
return true;
}
return false;
});
transport.on('request', (request, callback) => {
const { name } = request;
2017-08-04 08:15:11 +00:00
switch (name) {
2018-10-02 13:03:23 +00:00
case 'invite': {
const { invitees } = request;
if (!Array.isArray(invitees) || invitees.length === 0) {
callback({
error: new Error('Unexpected format of invitees')
});
break;
}
2018-06-26 22:56:22 +00:00
// The store should be already available because API.init is called
// on appWillMount action.
APP.store.dispatch(
invite(invitees, true))
.then(failedInvitees => {
let error;
let result;
if (failedInvitees.length) {
error = new Error('One or more invites failed!');
} else {
result = true;
}
callback({
error,
result
});
});
break;
2018-10-02 13:03:23 +00:00
}
2017-08-04 08:15:11 +00:00
case 'is-audio-muted':
callback(APP.conference.isLocalAudioMuted());
2017-08-04 08:15:11 +00:00
break;
case 'is-video-muted':
callback(APP.conference.isLocalVideoMuted());
2017-08-04 08:15:11 +00:00
break;
case 'is-audio-available':
callback(audioAvailable);
break;
case 'is-video-available':
callback(videoAvailable);
break;
default:
return false;
}
return true;
});
}
2015-01-09 13:39:32 +00:00
2017-04-11 19:30:00 +00:00
/**
* Listens for desktop/screen sharing enabled events and toggles the screen
* sharing if needed.
*
* @param {boolean} enabled - Current screen sharing enabled status.
* @returns {void}
*/
function onDesktopSharingEnabledChanged(enabled = false) {
if (enabled && initialScreenSharingState) {
toggleScreenSharing();
}
}
2016-01-14 15:05:54 +00:00
/**
* Check whether the API should be enabled or not.
*
2016-01-14 15:05:54 +00:00
* @returns {boolean}
*/
function shouldBeEnabled() {
return (
typeof API_ID === 'number'
// XXX Enable the API when a JSON Web Token (JWT) is specified in
// the location/URL because then it is very likely that the Jitsi
// Meet (Web) app is being used by an external/wrapping (Web) app
// and, consequently, the latter will need to communicate with the
// former. (The described logic is merely a heuristic though.)
|| parseJWTFromURLParams());
}
2016-01-14 15:05:54 +00:00
/**
2017-04-11 19:30:00 +00:00
* Executes on toggle-share-screen command.
*
* @returns {void}
2016-01-14 15:05:54 +00:00
*/
2017-04-11 19:30:00 +00:00
function toggleScreenSharing() {
if (APP.conference.isDesktopSharingEnabled) {
// eslint-disable-next-line no-empty-function
APP.conference.toggleScreenSharing().catch(() => {});
2017-04-11 19:30:00 +00:00
} else {
initialScreenSharingState = !initialScreenSharingState;
2016-01-14 15:05:54 +00:00
}
}
/**
2017-04-11 19:30:00 +00:00
* Implements API class that communicates with external API class and provides
* interface to access Jitsi Meet features by external applications that embed
* Jitsi Meet.
*/
class API {
_enabled: boolean;
2015-01-09 13:39:32 +00:00
/**
2017-04-11 19:30:00 +00:00
* Initializes the API. Setups message event listeners that will receive
* information from external applications that embed Jitsi Meet. It also
* sends a message to the external application that API is initialized.
*
* @param {Object} options - Optional parameters.
* @returns {void}
2015-01-09 13:39:32 +00:00
*/
init() {
if (!shouldBeEnabled()) {
2016-01-14 15:05:54 +00:00
return;
}
2016-06-13 21:11:44 +00:00
/**
* Current status (enabled/disabled) of API.
*
* @private
* @type {boolean}
*/
this._enabled = true;
APP.conference.addListener(
JitsiMeetConferenceEvents.DESKTOP_SHARING_ENABLED_CHANGED,
onDesktopSharingEnabledChanged);
initCommands();
}
/**
* Notify external application (if API is enabled) that the large video
* visibility changed.
*
* @param {boolean} isHidden - True if the large video is hidden and false
* otherwise.
* @returns {void}
*/
notifyLargeVideoVisibilityChanged(isHidden: boolean) {
this._sendEvent({
name: 'large-video-visibility-changed',
isVisible: !isHidden
});
}
/**
* Sends event to the external application.
*
* @param {Object} event - The event to be sent.
* @returns {void}
*/
_sendEvent(event: Object = {}) {
if (this._enabled) {
transport.sendEvent(event);
}
}
2016-01-14 15:05:54 +00:00
/**
* Notify external application (if API is enabled) that message was sent.
*
* @param {string} message - Message body.
* @returns {void}
2016-01-14 15:05:54 +00:00
*/
notifySendingChatMessage(message: string) {
this._sendEvent({
name: 'outgoing-message',
message
});
}
2016-06-13 21:11:44 +00:00
2015-01-09 13:39:32 +00:00
/**
2017-04-11 19:30:00 +00:00
* Notify external application (if API is enabled) that message was
* received.
*
* @param {Object} options - Object with the message properties.
* @returns {void}
2015-01-09 13:39:32 +00:00
*/
notifyReceivedChatMessage(
{ body, id, nick, ts }: {
body: *, id: string, nick: string, ts: *
} = {}) {
2016-01-14 15:05:54 +00:00
if (APP.conference.isLocalId(id)) {
return;
}
this._sendEvent({
name: 'incoming-message',
from: id,
message: body,
nick,
stamp: ts
});
}
2015-01-09 13:39:32 +00:00
/**
2017-04-11 19:30:00 +00:00
* Notify external application (if API is enabled) that user joined the
* conference.
*
* @param {string} id - User id.
* @param {Object} props - The display name of the user.
* @returns {void}
2015-01-09 13:39:32 +00:00
*/
notifyUserJoined(id: string, props: Object) {
this._sendEvent({
name: 'participant-joined',
id,
...props
});
}
2016-01-14 15:05:54 +00:00
/**
2017-04-11 19:30:00 +00:00
* Notify external application (if API is enabled) that user left the
* conference.
*
* @param {string} id - User id.
* @returns {void}
2016-01-14 15:05:54 +00:00
*/
notifyUserLeft(id: string) {
this._sendEvent({
name: 'participant-left',
id
});
}
2016-01-14 15:05:54 +00:00
/**
* Notify external application (if API is enabled) that user changed their
* avatar.
*
* @param {string} id - User id.
* @param {string} avatarURL - The new avatar URL of the participant.
* @returns {void}
*/
notifyAvatarChanged(id: string, avatarURL: string) {
this._sendEvent({
name: 'avatar-changed',
avatarURL,
id
});
}
2016-01-14 15:05:54 +00:00
/**
2017-04-11 19:30:00 +00:00
* Notify external application (if API is enabled) that user changed their
* nickname.
*
* @param {string} id - User id.
* @param {string} displayname - User nickname.
* @param {string} formattedDisplayName - The display name shown in Jitsi
* meet's UI for the user.
* @returns {void}
2016-01-14 15:05:54 +00:00
*/
notifyDisplayNameChanged(
id: string,
{ displayName, formattedDisplayName }: Object) {
this._sendEvent({
name: 'display-name-change',
displayname: displayName,
formattedDisplayName,
id
});
}
2018-06-18 09:19:07 +00:00
/**
* Notify external application (if API is enabled) that user changed their
* email.
*
* @param {string} id - User id.
* @param {string} email - The new email of the participant.
* @returns {void}
*/
notifyEmailChanged(
id: string,
{ email }: Object) {
this._sendEvent({
name: 'email-change',
email,
id
});
}
/**
2017-04-11 19:30:00 +00:00
* Notify external application (if API is enabled) that the conference has
* been joined.
*
* @param {string} roomName - The room name.
* @param {string} id - The id of the local user.
* @param {Object} props - The display name and avatar URL of the local
* user.
* @returns {void}
*/
notifyConferenceJoined(roomName: string, id: string, props: Object) {
this._sendEvent({
name: 'video-conference-joined',
roomName,
id,
...props
});
}
/**
2017-04-11 19:30:00 +00:00
* Notify external application (if API is enabled) that user changed their
* nickname.
*
* @param {string} roomName - User id.
* @returns {void}
*/
notifyConferenceLeft(roomName: string) {
this._sendEvent({
name: 'video-conference-left',
roomName
});
}
2015-01-09 13:39:32 +00:00
/**
2017-04-11 19:30:00 +00:00
* Notify external application (if API is enabled) that we are ready to be
* closed.
*
* @returns {void}
*/
notifyReadyToClose() {
this._sendEvent({ name: 'video-ready-to-close' });
}
2017-08-04 08:15:11 +00:00
/**
* Notify external application (if API is enabled) for audio muted status
* changed.
*
* @param {boolean} muted - The new muted status.
* @returns {void}
*/
notifyAudioMutedStatusChanged(muted: boolean) {
2017-08-04 08:15:11 +00:00
this._sendEvent({
name: 'audio-mute-status-changed',
muted
});
}
/**
* Notify external application (if API is enabled) for video muted status
* changed.
*
* @param {boolean} muted - The new muted status.
* @returns {void}
*/
notifyVideoMutedStatusChanged(muted: boolean) {
2017-08-04 08:15:11 +00:00
this._sendEvent({
name: 'video-mute-status-changed',
muted
});
}
/**
* Notify external application (if API is enabled) for audio availability
* changed.
*
* @param {boolean} available - True if available and false otherwise.
* @returns {void}
*/
notifyAudioAvailabilityChanged(available: boolean) {
2017-08-04 08:15:11 +00:00
audioAvailable = available;
this._sendEvent({
name: 'audio-availability-changed',
available
});
}
/**
* Notify external application (if API is enabled) for video available
* status changed.
*
* @param {boolean} available - True if available and false otherwise.
* @returns {void}
*/
notifyVideoAvailabilityChanged(available: boolean) {
2017-08-04 08:15:11 +00:00
videoAvailable = available;
this._sendEvent({
name: 'video-availability-changed',
available
});
}
/**
* Notify external application (if API is enabled) that the on stage
* participant has changed.
*
* @param {string} id - User id of the new on stage participant.
* @returns {void}
*/
notifyOnStageParticipantChanged(id: string) {
this._sendEvent({
name: 'on-stage-participant-changed',
id
});
}
/**
* Notify external application (if API is enabled) that conference feedback
* has been submitted. Intended to be used in conjunction with the
* submit-feedback command to get notified if feedback was submitted.
*
* @returns {void}
*/
notifyFeedbackSubmitted() {
this._sendEvent({ name: 'feedback-submitted' });
}
2017-08-04 08:15:11 +00:00
/**
* Notify external application (if API is enabled) that the screen sharing
* has been turned on/off.
*
* @param {boolean} on - True if screen sharing is enabled.
* @returns {void}
*/
notifyScreenSharingStatusChanged(on: boolean) {
this._sendEvent({
name: 'screen-sharing-status-changed',
on
});
}
/**
* Disposes the allocated resources.
*
* @returns {void}
2015-01-09 13:39:32 +00:00
*/
dispose() {
if (this._enabled) {
this._enabled = false;
APP.conference.removeListener(
JitsiMeetConferenceEvents.DESKTOP_SHARING_ENABLED_CHANGED,
2017-04-11 19:30:00 +00:00
onDesktopSharingEnabledChanged);
}
2015-01-09 13:39:32 +00:00
}
}
export default new API();