You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

SettingsMenu.js 11KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316
  1. /* global APP, $, JitsiMeetJS, interfaceConfig, AJS */
  2. import UIUtil from "../../util/UIUtil";
  3. import UIEvents from "../../../../service/UI/UIEvents";
  4. import languages from "../../../../service/translation/languages";
  5. import Settings from '../../../settings/Settings';
  6. /**
  7. * Generate html select options for available languages.
  8. *
  9. * @param {string[]} items available languages
  10. * @param {string} [currentLang] current language
  11. * @returns {string}
  12. */
  13. function generateLanguagesOptions(items, currentLang) {
  14. return items.map(function (lang) {
  15. let attrs = {
  16. value: lang,
  17. 'data-i18n': `languages:${lang}`
  18. };
  19. if (lang === currentLang) {
  20. attrs.selected = 'selected';
  21. }
  22. let attrsStr = UIUtil.attrsToString(attrs);
  23. return `<option ${attrsStr}></option>`;
  24. }).join('');
  25. }
  26. /**
  27. * Generate html select options for available physical devices.
  28. *
  29. * @param {{ deviceId, label }[]} items available devices
  30. * @param {string} [selectedId] id of selected device
  31. * @param {boolean} permissionGranted if permission to use selected device type
  32. * is granted
  33. * @returns {string}
  34. */
  35. function generateDevicesOptions(items, selectedId, permissionGranted) {
  36. if (!permissionGranted && items.length) {
  37. return '<option data-i18n="settings.noPermission"></option>';
  38. }
  39. var options = items.map(function (item) {
  40. let attrs = {
  41. value: item.deviceId
  42. };
  43. if (item.deviceId === selectedId) {
  44. attrs.selected = 'selected';
  45. }
  46. let attrsStr = UIUtil.attrsToString(attrs);
  47. return `<option ${attrsStr}>${item.label}</option>`;
  48. });
  49. if (!items.length) {
  50. options.unshift('<option data-i18n="settings.noDevice"></option>');
  51. }
  52. return options.join('');
  53. }
  54. /**
  55. * Replace html select element to select2 custom dropdown
  56. *
  57. * @param {jQueryElement} $el native select element
  58. * @param {function} onSelectedCb fired if item is selected
  59. */
  60. function initSelect2($el, onSelectedCb) {
  61. $el.auiSelect2({
  62. minimumResultsForSearch: Infinity,
  63. dropdownCssClass: 'dropdown-dark',
  64. containerCssClass: 'input-container-dark',
  65. });
  66. if (typeof onSelectedCb === 'function'){
  67. $el.change(onSelectedCb);
  68. }
  69. }
  70. export default {
  71. init (emitter) {
  72. //LANGUAGES BOX
  73. if (UIUtil.isSettingEnabled('language')) {
  74. const wrapperId = 'languagesSelectWrapper';
  75. const selectId = 'languagesSelect';
  76. const selectEl = AJS.$(`#${selectId}`);
  77. let selectInput;
  78. selectEl.html(generateLanguagesOptions(
  79. languages.getLanguages(),
  80. APP.translation.getCurrentLanguage()
  81. ));
  82. initSelect2(selectEl, () => {
  83. const val = selectEl.val();
  84. selectInput[0].dataset.i18n = `languages:${val}`;
  85. APP.translation.translateElement(selectInput);
  86. emitter.emit(UIEvents.LANG_CHANGED, val);
  87. });
  88. //find new selectInput element
  89. selectInput = $(`#s2id_${selectId} .select2-chosen`);
  90. //first select fix for languages options
  91. selectInput[0].dataset.i18n =
  92. `languages:${APP.translation.getCurrentLanguage()}`;
  93. APP.translation.translateElement(selectEl);
  94. UIUtil.showElement(wrapperId);
  95. }
  96. // DEVICES LIST
  97. if (UIUtil.isSettingEnabled('devices')) {
  98. const wrapperId = 'deviceOptionsWrapper';
  99. JitsiMeetJS.mediaDevices.isDeviceListAvailable()
  100. .then((isDeviceListAvailable) => {
  101. if (isDeviceListAvailable &&
  102. JitsiMeetJS.mediaDevices.isDeviceChangeAvailable()) {
  103. this._initializeDeviceSelectionSettings(emitter);
  104. }
  105. });
  106. // Only show the subtitle if this isn't the only setting section.
  107. if (interfaceConfig.SETTINGS_SECTIONS.length > 1)
  108. UIUtil.showElement("deviceOptionsTitle");
  109. UIUtil.showElement(wrapperId);
  110. }
  111. // MODERATOR
  112. if (UIUtil.isSettingEnabled('moderator')) {
  113. const wrapperId = 'moderatorOptionsWrapper';
  114. // START MUTED
  115. $("#startMutedOptions").change(function () {
  116. let startAudioMuted = $("#startAudioMuted").is(":checked");
  117. let startVideoMuted = $("#startVideoMuted").is(":checked");
  118. emitter.emit(
  119. UIEvents.START_MUTED_CHANGED,
  120. startAudioMuted,
  121. startVideoMuted
  122. );
  123. });
  124. // FOLLOW ME
  125. let followMeToggle = document.getElementById('followMeCheckBox');
  126. followMeToggle.addEventListener('change', function() {
  127. let isFollowMeEnabled = followMeToggle.checked;
  128. emitter.emit(
  129. UIEvents.FOLLOW_ME_ENABLED,
  130. isFollowMeEnabled
  131. );
  132. });
  133. UIUtil.showElement(wrapperId);
  134. }
  135. },
  136. _initializeDeviceSelectionSettings(emitter) {
  137. this.changeDevicesList([]);
  138. $('#selectCamera').change(function () {
  139. let cameraDeviceId = $(this).val();
  140. if (cameraDeviceId !== Settings.getCameraDeviceId()) {
  141. emitter.emit(UIEvents.VIDEO_DEVICE_CHANGED, cameraDeviceId);
  142. }
  143. });
  144. $('#selectMic').change(function () {
  145. let micDeviceId = $(this).val();
  146. if (micDeviceId !== Settings.getMicDeviceId()) {
  147. emitter.emit(UIEvents.AUDIO_DEVICE_CHANGED, micDeviceId);
  148. }
  149. });
  150. $('#selectAudioOutput').change(function () {
  151. let audioOutputDeviceId = $(this).val();
  152. if (audioOutputDeviceId !== Settings.getAudioOutputDeviceId()) {
  153. emitter.emit(
  154. UIEvents.AUDIO_OUTPUT_DEVICE_CHANGED, audioOutputDeviceId);
  155. }
  156. });
  157. },
  158. /**
  159. * If start audio muted/start video muted options should be visible or not.
  160. * @param {boolean} show
  161. */
  162. showStartMutedOptions (show) {
  163. if (show && UIUtil.isSettingEnabled('moderator')) {
  164. // Only show the subtitle if this isn't the only setting section.
  165. if (!$("#moderatorOptionsTitle").is(":visible")
  166. && interfaceConfig.SETTINGS_SECTIONS.length > 1)
  167. UIUtil.showElement("moderatorOptionsTitle");
  168. UIUtil.showElement("startMutedOptions");
  169. } else {
  170. // Only show the subtitle if this isn't the only setting section.
  171. if ($("#moderatorOptionsTitle").is(":visible"))
  172. UIUtil.hideElement("moderatorOptionsTitle");
  173. UIUtil.hideElement("startMutedOptions");
  174. }
  175. },
  176. updateStartMutedBox (startAudioMuted, startVideoMuted) {
  177. $("#startAudioMuted").attr("checked", startAudioMuted);
  178. $("#startVideoMuted").attr("checked", startVideoMuted);
  179. },
  180. /**
  181. * Shows/hides the follow me options in the settings dialog.
  182. *
  183. * @param {boolean} show {true} to show those options, {false} to hide them
  184. */
  185. showFollowMeOptions (show) {
  186. if (show && UIUtil.isSettingEnabled('moderator')) {
  187. UIUtil.showElement("followMeOptions");
  188. } else {
  189. UIUtil.hideElement("followMeOptions");
  190. }
  191. },
  192. /**
  193. * Check if settings menu is visible or not.
  194. * @returns {boolean}
  195. */
  196. isVisible () {
  197. return UIUtil.isVisible(document.getElementById("settings_container"));
  198. },
  199. /**
  200. * Sets microphone's <select> element to select microphone ID from settings.
  201. */
  202. setSelectedMicFromSettings () {
  203. $('#selectMic').val(Settings.getMicDeviceId());
  204. },
  205. /**
  206. * Sets camera's <select> element to select camera ID from settings.
  207. */
  208. setSelectedCameraFromSettings () {
  209. $('#selectCamera').val(Settings.getCameraDeviceId());
  210. },
  211. /**
  212. * Sets audio outputs's <select> element to select audio output ID from
  213. * settings.
  214. */
  215. setSelectedAudioOutputFromSettings () {
  216. $('#selectAudioOutput').val(Settings.getAudioOutputDeviceId());
  217. },
  218. /**
  219. * Change available cameras/microphones or hide selects completely if
  220. * no devices available.
  221. * @param {{ deviceId, label, kind }[]} devices list of available devices
  222. */
  223. changeDevicesList (devices) {
  224. let $selectCamera= AJS.$('#selectCamera'),
  225. $selectMic = AJS.$('#selectMic'),
  226. $selectAudioOutput = AJS.$('#selectAudioOutput'),
  227. $selectAudioOutputParent = $selectAudioOutput.parent();
  228. let audio = devices.filter(device => device.kind === 'audioinput'),
  229. video = devices.filter(device => device.kind === 'videoinput'),
  230. audioOutput = devices
  231. .filter(device => device.kind === 'audiooutput'),
  232. selectedAudioDevice = audio.find(
  233. d => d.deviceId === Settings.getMicDeviceId()) || audio[0],
  234. selectedVideoDevice = video.find(
  235. d => d.deviceId === Settings.getCameraDeviceId()) || video[0],
  236. selectedAudioOutputDevice = audioOutput.find(
  237. d => d.deviceId === Settings.getAudioOutputDeviceId()),
  238. videoPermissionGranted =
  239. JitsiMeetJS.mediaDevices.isDevicePermissionGranted('video'),
  240. audioPermissionGranted =
  241. JitsiMeetJS.mediaDevices.isDevicePermissionGranted('audio');
  242. $selectCamera
  243. .html(generateDevicesOptions(
  244. video,
  245. selectedVideoDevice ? selectedVideoDevice.deviceId : '',
  246. videoPermissionGranted))
  247. .prop('disabled', !video.length || !videoPermissionGranted);
  248. initSelect2($selectCamera);
  249. $selectMic
  250. .html(generateDevicesOptions(
  251. audio,
  252. selectedAudioDevice ? selectedAudioDevice.deviceId : '',
  253. audioPermissionGranted))
  254. .prop('disabled', !audio.length || !audioPermissionGranted);
  255. initSelect2($selectMic);
  256. if (JitsiMeetJS.mediaDevices.isDeviceChangeAvailable('output')) {
  257. $selectAudioOutput
  258. .html(generateDevicesOptions(
  259. audioOutput,
  260. selectedAudioOutputDevice
  261. ? selectedAudioOutputDevice.deviceId
  262. : 'default',
  263. videoPermissionGranted || audioPermissionGranted))
  264. .prop('disabled', !audioOutput.length ||
  265. (!videoPermissionGranted && !audioPermissionGranted));
  266. initSelect2($selectAudioOutput);
  267. $selectAudioOutputParent.show();
  268. } else {
  269. $selectAudioOutputParent.hide();
  270. }
  271. APP.translation.translateElement($('#settings_container option'));
  272. }
  273. };