Nelze vybrat více než 25 témat Téma musí začínat písmenem nebo číslem, může obsahovat pomlčky („-“) a může být dlouhé až 35 znaků.

DeviceSelectionPopup.js 8.0KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300
  1. import Logger from 'jitsi-meet-logger';
  2. import React from 'react';
  3. import ReactDOM from 'react-dom';
  4. import { I18nextProvider } from 'react-i18next';
  5. import {
  6. PostMessageTransportBackend,
  7. Transport
  8. } from '../../../modules/transport';
  9. import { parseURLParams } from '../base/config';
  10. import DeviceSelectionDialogBase from './components/DeviceSelectionDialogBase';
  11. declare var JitsiMeetJS: Object;
  12. const logger = Logger.getLogger(__filename);
  13. /**
  14. * Implements a class that renders the React components for the device selection
  15. * popup page and handles the communication between the components and Jitsi
  16. * Meet.
  17. */
  18. export default class DeviceSelectionPopup {
  19. /**
  20. * Initializes a new DeviceSelectionPopup instance.
  21. *
  22. * @param {Object} i18next - The i18next instance used for translation.
  23. */
  24. constructor(i18next) {
  25. this.close = this.close.bind(this);
  26. this._setVideoInputDevice = this._setVideoInputDevice.bind(this);
  27. this._setAudioInputDevice = this._setAudioInputDevice.bind(this);
  28. this._setAudioOutputDevice = this._setAudioOutputDevice.bind(this);
  29. this._i18next = i18next;
  30. const { scope } = parseURLParams(window.location);
  31. this._transport = new Transport({
  32. backend: new PostMessageTransportBackend({
  33. postisOptions: {
  34. scope,
  35. window: window.opener
  36. }
  37. })
  38. });
  39. this._transport.on('event', event => {
  40. if (event.name === 'deviceListChanged') {
  41. this._updateAvailableDevices();
  42. return true;
  43. }
  44. return false;
  45. });
  46. this._dialogProps = {
  47. availableDevices: {},
  48. currentAudioInputId: '',
  49. currentAudioOutputId: '',
  50. currentVideoInputId: '',
  51. disableAudioInputChange: true,
  52. disableDeviceChange: true,
  53. hasAudioPermission: JitsiMeetJS.mediaDevices
  54. .isDevicePermissionGranted('audio'),
  55. hasVideoPermission: JitsiMeetJS.mediaDevices
  56. .isDevicePermissionGranted('video'),
  57. hideAudioInputPreview: !JitsiMeetJS.isCollectingLocalStats(),
  58. hideAudioOutputSelect: true
  59. };
  60. this._initState();
  61. }
  62. /**
  63. * Sends event to Jitsi Meet to close the popup dialog.
  64. *
  65. * @returns {void}
  66. */
  67. close() {
  68. this._transport.sendEvent({
  69. type: 'devices-dialog',
  70. name: 'close'
  71. });
  72. }
  73. /**
  74. * Changes the properties of the react component and re-renders it.
  75. *
  76. * @param {Object} newProps - The new properties that will be assigned to
  77. * the current ones.
  78. * @returns {void}
  79. */
  80. _changeDialogProps(newProps) {
  81. this._dialogProps = {
  82. ...this._dialogProps,
  83. ...newProps
  84. };
  85. this._render();
  86. }
  87. /**
  88. * Returns Promise that resolves with result an list of available devices.
  89. *
  90. * @returns {Promise}
  91. */
  92. _getAvailableDevices() {
  93. return this._transport.sendRequest({
  94. type: 'devices',
  95. name: 'getAvailableDevices'
  96. }).catch(e => {
  97. logger.error(e);
  98. return {};
  99. });
  100. }
  101. /**
  102. * Returns Promise that resolves with current selected devices.
  103. *
  104. * @returns {Promise}
  105. */
  106. _getCurrentDevices() {
  107. return this._transport.sendRequest({
  108. type: 'devices',
  109. name: 'getCurrentDevices'
  110. }).catch(e => {
  111. logger.error(e);
  112. return {};
  113. });
  114. }
  115. /**
  116. * Initializes the state.
  117. *
  118. * @returns {void}
  119. */
  120. _initState() {
  121. return Promise.all([
  122. this._getAvailableDevices(),
  123. this._isDeviceListAvailable(),
  124. this._isDeviceChangeAvailable(),
  125. this._getCurrentDevices(),
  126. this._isMultipleAudioInputSupported()
  127. ]).then(([
  128. availableDevices,
  129. listAvailable,
  130. changeAvailable,
  131. currentDevices,
  132. multiAudioInputSupported
  133. ]) => {
  134. this._changeDialogProps({
  135. availableDevices,
  136. currentAudioInputId: currentDevices.audioInput,
  137. currentAudioOutputId: currentDevices.audioOutput,
  138. currentVideoInputId: currentDevices.videoInput,
  139. disableAudioInputChange: !multiAudioInputSupported,
  140. disableDeviceChange: !listAvailable || !changeAvailable,
  141. hideAudioOutputSelect: !changeAvailable
  142. });
  143. });
  144. }
  145. /**
  146. * Returns Promise that resolves with true if the device change is available
  147. * and with false if not.
  148. *
  149. * @returns {Promise}
  150. */
  151. _isDeviceChangeAvailable() {
  152. return this._transport.sendRequest({
  153. type: 'devices',
  154. name: 'isDeviceChangeAvailable'
  155. }).catch(e => {
  156. logger.error(e);
  157. return false;
  158. });
  159. }
  160. /**
  161. * Returns Promise that resolves with true if the device list is available
  162. * and with false if not.
  163. *
  164. * @returns {Promise}
  165. */
  166. _isDeviceListAvailable() {
  167. return this._transport.sendRequest({
  168. type: 'devices',
  169. name: 'isDeviceListAvailable'
  170. }).catch(e => {
  171. logger.error(e);
  172. return false;
  173. });
  174. }
  175. /**
  176. * Returns Promise that resolves with true if the device list is available
  177. * and with false if not.
  178. *
  179. * @returns {Promise}
  180. */
  181. _isMultipleAudioInputSupported() {
  182. return this._transport.sendRequest({
  183. type: 'devices',
  184. name: 'isMultipleAudioInputSupported'
  185. }).catch(e => {
  186. logger.error(e);
  187. return false;
  188. });
  189. }
  190. /**
  191. * Renders the React components for the popup page.
  192. *
  193. * @returns {void}
  194. */
  195. _render() {
  196. const props = {
  197. ...this._dialogProps,
  198. closeModal: this.close,
  199. disableBlanketClickDismiss: true,
  200. setAudioInputDevice: this._setAudioInputDevice,
  201. setAudioOutputDevice: this._setAudioOutputDevice,
  202. setVideoInputDevice: this._setVideoInputDevice
  203. };
  204. ReactDOM.render(
  205. <I18nextProvider
  206. i18n = { this._i18next }>
  207. <DeviceSelectionDialogBase { ...props } />
  208. </I18nextProvider>,
  209. document.getElementById('react'));
  210. }
  211. /**
  212. * Sets the audio input device to the one with the id that is passed.
  213. *
  214. * @param {string} id - The id of the new device.
  215. * @returns {Promise}
  216. */
  217. _setAudioInputDevice(id) {
  218. return this._setDevice({
  219. id,
  220. kind: 'audioinput'
  221. });
  222. }
  223. /**
  224. * Sets the audio output device to the one with the id that is passed.
  225. *
  226. * @param {string} id - The id of the new device.
  227. * @returns {Promise}
  228. */
  229. _setAudioOutputDevice(id) {
  230. return this._setDevice({
  231. id,
  232. kind: 'audiooutput'
  233. });
  234. }
  235. /**
  236. * Sets the currently used device to the one that is passed.
  237. *
  238. * @param {Object} device - The new device to be used.
  239. * @returns {Promise}
  240. */
  241. _setDevice(device) {
  242. return this._transport.sendRequest({
  243. type: 'devices',
  244. name: 'setDevice',
  245. device
  246. });
  247. }
  248. /**
  249. * Sets the video input device to the one with the id that is passed.
  250. *
  251. * @param {string} id - The id of the new device.
  252. * @returns {Promise}
  253. */
  254. _setVideoInputDevice(id) {
  255. return this._setDevice({
  256. id,
  257. kind: 'videoinput'
  258. });
  259. }
  260. /**
  261. * Updates the available devices.
  262. *
  263. * @returns {void}
  264. */
  265. _updateAvailableDevices() {
  266. this._getAvailableDevices().then(devices =>
  267. this._changeDialogProps({ availableDevices: devices })
  268. );
  269. }
  270. }