您最多选择25个主题 主题必须以字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符

API.js 9.5KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380
  1. import * as JitsiMeetConferenceEvents from '../../ConferenceEvents';
  2. import { parseJWTFromURLParams } from '../../react/features/jwt';
  3. import { getJitsiMeetTransport } from '../transport';
  4. import { API_ID } from './constants';
  5. declare var APP: Object;
  6. /**
  7. * List of the available commands.
  8. */
  9. let commands = {};
  10. /**
  11. * The state of screen sharing(started/stopped) before the screen sharing is
  12. * enabled and initialized.
  13. * NOTE: This flag help us to cache the state and use it if toggle-share-screen
  14. * was received before the initialization.
  15. */
  16. let initialScreenSharingState = false;
  17. /**
  18. * The transport instance used for communication with external apps.
  19. *
  20. * @type {Transport}
  21. */
  22. const transport = getJitsiMeetTransport();
  23. /**
  24. * The current audio availability.
  25. *
  26. * @type {boolean}
  27. */
  28. let audioAvailable = true;
  29. /**
  30. * The current video availability.
  31. *
  32. * @type {boolean}
  33. */
  34. let videoAvailable = true;
  35. /**
  36. * Initializes supported commands.
  37. *
  38. * @returns {void}
  39. */
  40. function initCommands() {
  41. commands = {
  42. 'display-name':
  43. APP.conference.changeLocalDisplayName.bind(APP.conference),
  44. 'toggle-audio': () => {
  45. APP.conference.toggleAudioMuted(false /* no UI */);
  46. },
  47. 'toggle-video': () => {
  48. APP.conference.toggleVideoMuted(false /* no UI */);
  49. },
  50. 'toggle-film-strip': APP.UI.toggleFilmstrip,
  51. 'toggle-chat': APP.UI.toggleChat,
  52. 'toggle-contact-list': APP.UI.toggleContactList,
  53. 'toggle-share-screen': toggleScreenSharing,
  54. 'video-hangup': () => APP.conference.hangup(),
  55. 'email': APP.conference.changeLocalEmail,
  56. 'avatar-url': APP.conference.changeLocalAvatarUrl
  57. };
  58. transport.on('event', ({ data, name }) => {
  59. if (name && commands[name]) {
  60. commands[name](...data);
  61. return true;
  62. }
  63. return false;
  64. });
  65. transport.on('request', ({ name }, callback) => {
  66. switch (name) {
  67. case 'is-audio-muted':
  68. callback(APP.conference.isLocalAudioMuted());
  69. break;
  70. case 'is-video-muted':
  71. callback(APP.conference.isLocalVideoMuted());
  72. break;
  73. case 'is-audio-available':
  74. callback(audioAvailable);
  75. break;
  76. case 'is-video-available':
  77. callback(videoAvailable);
  78. break;
  79. default:
  80. return false;
  81. }
  82. return true;
  83. });
  84. }
  85. /**
  86. * Listens for desktop/screen sharing enabled events and toggles the screen
  87. * sharing if needed.
  88. *
  89. * @param {boolean} enabled - Current screen sharing enabled status.
  90. * @returns {void}
  91. */
  92. function onDesktopSharingEnabledChanged(enabled = false) {
  93. if (enabled && initialScreenSharingState) {
  94. toggleScreenSharing();
  95. }
  96. }
  97. /**
  98. * Check whether the API should be enabled or not.
  99. *
  100. * @returns {boolean}
  101. */
  102. function shouldBeEnabled() {
  103. return (
  104. typeof API_ID === 'number'
  105. // XXX Enable the API when a JSON Web Token (JWT) is specified in
  106. // the location/URL because then it is very likely that the Jitsi
  107. // Meet (Web) app is being used by an external/wrapping (Web) app
  108. // and, consequently, the latter will need to communicate with the
  109. // former. (The described logic is merely a heuristic though.)
  110. || parseJWTFromURLParams());
  111. }
  112. /**
  113. * Executes on toggle-share-screen command.
  114. *
  115. * @returns {void}
  116. */
  117. function toggleScreenSharing() {
  118. if (APP.conference.isDesktopSharingEnabled) {
  119. // eslint-disable-next-line no-empty-function
  120. APP.conference.toggleScreenSharing().catch(() => {});
  121. } else {
  122. initialScreenSharingState = !initialScreenSharingState;
  123. }
  124. }
  125. /**
  126. * Implements API class that communicates with external API class and provides
  127. * interface to access Jitsi Meet features by external applications that embed
  128. * Jitsi Meet.
  129. */
  130. class API {
  131. _enabled: boolean;
  132. /**
  133. * Initializes the API. Setups message event listeners that will receive
  134. * information from external applications that embed Jitsi Meet. It also
  135. * sends a message to the external application that API is initialized.
  136. *
  137. * @param {Object} options - Optional parameters.
  138. * @returns {void}
  139. */
  140. init() {
  141. if (!shouldBeEnabled()) {
  142. return;
  143. }
  144. /**
  145. * Current status (enabled/disabled) of API.
  146. *
  147. * @private
  148. * @type {boolean}
  149. */
  150. this._enabled = true;
  151. APP.conference.addListener(
  152. JitsiMeetConferenceEvents.DESKTOP_SHARING_ENABLED_CHANGED,
  153. onDesktopSharingEnabledChanged);
  154. initCommands();
  155. }
  156. /**
  157. * Sends event to the external application.
  158. *
  159. * @param {Object} event - The event to be sent.
  160. * @returns {void}
  161. */
  162. _sendEvent(event: Object = {}) {
  163. if (this._enabled) {
  164. transport.sendEvent(event);
  165. }
  166. }
  167. /**
  168. * Notify external application (if API is enabled) that message was sent.
  169. *
  170. * @param {string} message - Message body.
  171. * @returns {void}
  172. */
  173. notifySendingChatMessage(message: string) {
  174. this._sendEvent({
  175. name: 'outgoing-message',
  176. message
  177. });
  178. }
  179. /**
  180. * Notify external application (if API is enabled) that message was
  181. * received.
  182. *
  183. * @param {Object} options - Object with the message properties.
  184. * @returns {void}
  185. */
  186. notifyReceivedChatMessage({ body, id, nick, ts } = {}) {
  187. if (APP.conference.isLocalId(id)) {
  188. return;
  189. }
  190. this._sendEvent({
  191. name: 'incoming-message',
  192. from: id,
  193. message: body,
  194. nick,
  195. stamp: ts
  196. });
  197. }
  198. /**
  199. * Notify external application (if API is enabled) that user joined the
  200. * conference.
  201. *
  202. * @param {string} id - User id.
  203. * @returns {void}
  204. */
  205. notifyUserJoined(id: string) {
  206. this._sendEvent({
  207. name: 'participant-joined',
  208. id
  209. });
  210. }
  211. /**
  212. * Notify external application (if API is enabled) that user left the
  213. * conference.
  214. *
  215. * @param {string} id - User id.
  216. * @returns {void}
  217. */
  218. notifyUserLeft(id: string) {
  219. this._sendEvent({
  220. name: 'participant-left',
  221. id
  222. });
  223. }
  224. /**
  225. * Notify external application (if API is enabled) that user changed their
  226. * nickname.
  227. *
  228. * @param {string} id - User id.
  229. * @param {string} displayname - User nickname.
  230. * @returns {void}
  231. */
  232. notifyDisplayNameChanged(id: string, displayname: string) {
  233. this._sendEvent({
  234. name: 'display-name-change',
  235. displayname,
  236. id
  237. });
  238. }
  239. /**
  240. * Notify external application (if API is enabled) that the conference has
  241. * been joined.
  242. *
  243. * @param {string} roomName - The room name.
  244. * @returns {void}
  245. */
  246. notifyConferenceJoined(roomName: string) {
  247. this._sendEvent({
  248. name: 'video-conference-joined',
  249. roomName
  250. });
  251. }
  252. /**
  253. * Notify external application (if API is enabled) that user changed their
  254. * nickname.
  255. *
  256. * @param {string} roomName - User id.
  257. * @returns {void}
  258. */
  259. notifyConferenceLeft(roomName: string) {
  260. this._sendEvent({
  261. name: 'video-conference-left',
  262. roomName
  263. });
  264. }
  265. /**
  266. * Notify external application (if API is enabled) that we are ready to be
  267. * closed.
  268. *
  269. * @returns {void}
  270. */
  271. notifyReadyToClose() {
  272. this._sendEvent({ name: 'video-ready-to-close' });
  273. }
  274. /**
  275. * Notify external application (if API is enabled) for audio muted status
  276. * changed.
  277. *
  278. * @param {boolean} muted - The new muted status.
  279. * @returns {void}
  280. */
  281. notifyAudioMutedStatusChanged(muted: boolean) {
  282. this._sendEvent({
  283. name: 'audio-mute-status-changed',
  284. muted
  285. });
  286. }
  287. /**
  288. * Notify external application (if API is enabled) for video muted status
  289. * changed.
  290. *
  291. * @param {boolean} muted - The new muted status.
  292. * @returns {void}
  293. */
  294. notifyVideoMutedStatusChanged(muted: boolean) {
  295. this._sendEvent({
  296. name: 'video-mute-status-changed',
  297. muted
  298. });
  299. }
  300. /**
  301. * Notify external application (if API is enabled) for audio availability
  302. * changed.
  303. *
  304. * @param {boolean} available - True if available and false otherwise.
  305. * @returns {void}
  306. */
  307. notifyAudioAvailabilityChanged(available: boolean) {
  308. audioAvailable = available;
  309. this._sendEvent({
  310. name: 'audio-availability-changed',
  311. available
  312. });
  313. }
  314. /**
  315. * Notify external application (if API is enabled) for video available
  316. * status changed.
  317. *
  318. * @param {boolean} available - True if available and false otherwise.
  319. * @returns {void}
  320. */
  321. notifyVideoAvailabilityChanged(available: boolean) {
  322. videoAvailable = available;
  323. this._sendEvent({
  324. name: 'video-availability-changed',
  325. available
  326. });
  327. }
  328. /**
  329. * Disposes the allocated resources.
  330. *
  331. * @returns {void}
  332. */
  333. dispose() {
  334. if (this._enabled) {
  335. this._enabled = false;
  336. APP.conference.removeListener(
  337. JitsiMeetConferenceEvents.DESKTOP_SHARING_ENABLED_CHANGED,
  338. onDesktopSharingEnabledChanged);
  339. }
  340. }
  341. }
  342. export default new API();