diff --git a/react/features/device-selection/components/DeviceSelection.js b/react/features/device-selection/components/DeviceSelection.js index 1f9358203..2344896d4 100644 --- a/react/features/device-selection/components/DeviceSelection.js +++ b/react/features/device-selection/components/DeviceSelection.js @@ -5,7 +5,7 @@ import React from 'react'; import { AbstractDialogTab } from '../../base/dialog'; import type { Props as AbstractDialogTabProps } from '../../base/dialog'; import { translate } from '../../base/i18n'; -import { createLocalTrack } from '../../base/lib-jitsi-meet'; +import JitsiMeetJS, { createLocalTrack } from '../../base/lib-jitsi-meet'; import AudioInputPreview from './AudioInputPreview'; import AudioOutputPreview from './AudioOutputPreview'; @@ -40,18 +40,6 @@ export type Props = { */ disableDeviceChange: boolean, - /** - * Function that checks whether or not a new audio input source can be - * selected. - */ - hasAudioPermission: Function, - - /** - * Function that checks whether or not a new video input sources can be - * selected. - */ - hasVideoPermission: Function, - /** * If true, the audio meter will not display. Necessary for browsers or * configurations that do not support local stats to prevent a @@ -98,6 +86,16 @@ export type Props = { */ type State = { + /** + * Whether or not the audio permission was granted. + */ + hasAudioPermission: boolean, + + /** + * Whether or not the audio permission was granted. + */ + hasVideoPermission: boolean, + /** * The JitsiTrack to use for previewing audio input. */ @@ -130,6 +128,8 @@ class DeviceSelection extends AbstractDialogTab { super(props); this.state = { + hasAudioPermission: false, + hasVideoPermission: false, previewAudioTrack: null, previewVideoTrack: null, previewVideoTrackError: null @@ -150,6 +150,32 @@ class DeviceSelection extends AbstractDialogTab { .then(() => this.props.mountCallback && this.props.mountCallback()); } + /** + * Checks if audio / video permissions were granted. + * + * @param {Object} prevProps - Previous props this component received. + * @param {Object} prevState - Previous state this component had. + * @returns {void} + */ + componentDidUpdate(prevProps, prevState) { + const { previewAudioTrack, previewVideoTrack } = prevState; + + if ((!previewAudioTrack && this.state.previewAudioTrack) + || (!previewVideoTrack && this.state.previewVideoTrack)) { + Promise.all([ + JitsiMeetJS.mediaDevices.isDevicePermissionGranted('audio'), + JitsiMeetJS.mediaDevices.isDevicePermissionGranted('video') + ]).then(r => { + const [ hasAudioPermission, hasVideoPermission ] = r; + + this.setState({ + hasAudioPermission, + hasVideoPermission + }); + }); + } + } + /** * Updates audio input and video input previews. * @@ -316,11 +342,12 @@ class DeviceSelection extends AbstractDialogTab { */ _renderSelectors() { const { availableDevices } = this.props; + const { hasAudioPermission, hasVideoPermission } = this.state; const configurations = [ { devices: availableDevices.videoInput, - hasPermission: this.props.hasVideoPermission(), + hasPermission: hasVideoPermission, icon: 'icon-camera', isDisabled: this.props.disableDeviceChange, key: 'videoInput', @@ -331,7 +358,7 @@ class DeviceSelection extends AbstractDialogTab { }, { devices: availableDevices.audioInput, - hasPermission: this.props.hasAudioPermission(), + hasPermission: hasAudioPermission, icon: 'icon-microphone', isDisabled: this.props.disableAudioInputChange || this.props.disableDeviceChange, @@ -346,8 +373,7 @@ class DeviceSelection extends AbstractDialogTab { if (!this.props.hideAudioOutputSelect) { configurations.push({ devices: availableDevices.audioOutput, - hasPermission: this.props.hasAudioPermission() - || this.props.hasVideoPermission(), + hasPermission: hasAudioPermission || hasVideoPermission, icon: 'icon-speaker', isDisabled: this.props.disableDeviceChange, key: 'audioOutput', diff --git a/react/features/device-selection/functions.js b/react/features/device-selection/functions.js index bfe075484..0c2ce25e7 100644 --- a/react/features/device-selection/functions.js +++ b/react/features/device-selection/functions.js @@ -20,10 +20,6 @@ export function getDeviceSelectionDialogProps(stateful: Object | Function) { !JitsiMeetJS.isMultipleAudioInputSupported(), disableDeviceChange: !JitsiMeetJS.mediaDevices.isDeviceChangeAvailable(), - hasAudioPermission: JitsiMeetJS.mediaDevices - .isDevicePermissionGranted.bind(null, 'audio'), - hasVideoPermission: JitsiMeetJS.mediaDevices - .isDevicePermissionGranted.bind(null, 'video'), hideAudioInputPreview: !JitsiMeetJS.isCollectingLocalStats(), hideAudioOutputSelect: !JitsiMeetJS.mediaDevices diff --git a/react/features/settings/DeviceSelectionPopup.js b/react/features/settings/DeviceSelectionPopup.js index 35fa7f900..29f61b084 100644 --- a/react/features/settings/DeviceSelectionPopup.js +++ b/react/features/settings/DeviceSelectionPopup.js @@ -64,10 +64,6 @@ export default class DeviceSelectionPopup { disableAudioInputChange: true, disableBlanketClickDismiss: true, disableDeviceChange: true, - hasAudioPermission: JitsiMeetJS.mediaDevices - .isDevicePermissionGranted.bind(null, 'audio'), - hasVideoPermission: JitsiMeetJS.mediaDevices - .isDevicePermissionGranted.bind(null, 'video'), hideAudioInputPreview: !JitsiMeetJS.isCollectingLocalStats(), hideAudioOutputSelect: true