|
@@ -5,7 +5,7 @@ import React from 'react';
|
5
|
5
|
import { AbstractDialogTab } from '../../base/dialog';
|
6
|
6
|
import type { Props as AbstractDialogTabProps } from '../../base/dialog';
|
7
|
7
|
import { translate } from '../../base/i18n';
|
8
|
|
-import { createLocalTrack } from '../../base/lib-jitsi-meet';
|
|
8
|
+import JitsiMeetJS, { createLocalTrack } from '../../base/lib-jitsi-meet';
|
9
|
9
|
|
10
|
10
|
import AudioInputPreview from './AudioInputPreview';
|
11
|
11
|
import AudioOutputPreview from './AudioOutputPreview';
|
|
@@ -40,18 +40,6 @@ export type Props = {
|
40
|
40
|
*/
|
41
|
41
|
disableDeviceChange: boolean,
|
42
|
42
|
|
43
|
|
- /**
|
44
|
|
- * Function that checks whether or not a new audio input source can be
|
45
|
|
- * selected.
|
46
|
|
- */
|
47
|
|
- hasAudioPermission: Function,
|
48
|
|
-
|
49
|
|
- /**
|
50
|
|
- * Function that checks whether or not a new video input sources can be
|
51
|
|
- * selected.
|
52
|
|
- */
|
53
|
|
- hasVideoPermission: Function,
|
54
|
|
-
|
55
|
43
|
/**
|
56
|
44
|
* If true, the audio meter will not display. Necessary for browsers or
|
57
|
45
|
* configurations that do not support local stats to prevent a
|
|
@@ -98,6 +86,16 @@ export type Props = {
|
98
|
86
|
*/
|
99
|
87
|
type State = {
|
100
|
88
|
|
|
89
|
+ /**
|
|
90
|
+ * Whether or not the audio permission was granted.
|
|
91
|
+ */
|
|
92
|
+ hasAudioPermission: boolean,
|
|
93
|
+
|
|
94
|
+ /**
|
|
95
|
+ * Whether or not the audio permission was granted.
|
|
96
|
+ */
|
|
97
|
+ hasVideoPermission: boolean,
|
|
98
|
+
|
101
|
99
|
/**
|
102
|
100
|
* The JitsiTrack to use for previewing audio input.
|
103
|
101
|
*/
|
|
@@ -130,6 +128,8 @@ class DeviceSelection extends AbstractDialogTab<Props, State> {
|
130
|
128
|
super(props);
|
131
|
129
|
|
132
|
130
|
this.state = {
|
|
131
|
+ hasAudioPermission: false,
|
|
132
|
+ hasVideoPermission: false,
|
133
|
133
|
previewAudioTrack: null,
|
134
|
134
|
previewVideoTrack: null,
|
135
|
135
|
previewVideoTrackError: null
|
|
@@ -150,6 +150,32 @@ class DeviceSelection extends AbstractDialogTab<Props, State> {
|
150
|
150
|
.then(() => this.props.mountCallback && this.props.mountCallback());
|
151
|
151
|
}
|
152
|
152
|
|
|
153
|
+ /**
|
|
154
|
+ * Checks if audio / video permissions were granted.
|
|
155
|
+ *
|
|
156
|
+ * @param {Object} prevProps - Previous props this component received.
|
|
157
|
+ * @param {Object} prevState - Previous state this component had.
|
|
158
|
+ * @returns {void}
|
|
159
|
+ */
|
|
160
|
+ componentDidUpdate(prevProps, prevState) {
|
|
161
|
+ const { previewAudioTrack, previewVideoTrack } = prevState;
|
|
162
|
+
|
|
163
|
+ if ((!previewAudioTrack && this.state.previewAudioTrack)
|
|
164
|
+ || (!previewVideoTrack && this.state.previewVideoTrack)) {
|
|
165
|
+ Promise.all([
|
|
166
|
+ JitsiMeetJS.mediaDevices.isDevicePermissionGranted('audio'),
|
|
167
|
+ JitsiMeetJS.mediaDevices.isDevicePermissionGranted('video')
|
|
168
|
+ ]).then(r => {
|
|
169
|
+ const [ hasAudioPermission, hasVideoPermission ] = r;
|
|
170
|
+
|
|
171
|
+ this.setState({
|
|
172
|
+ hasAudioPermission,
|
|
173
|
+ hasVideoPermission
|
|
174
|
+ });
|
|
175
|
+ });
|
|
176
|
+ }
|
|
177
|
+ }
|
|
178
|
+
|
153
|
179
|
/**
|
154
|
180
|
* Updates audio input and video input previews.
|
155
|
181
|
*
|
|
@@ -316,11 +342,12 @@ class DeviceSelection extends AbstractDialogTab<Props, State> {
|
316
|
342
|
*/
|
317
|
343
|
_renderSelectors() {
|
318
|
344
|
const { availableDevices } = this.props;
|
|
345
|
+ const { hasAudioPermission, hasVideoPermission } = this.state;
|
319
|
346
|
|
320
|
347
|
const configurations = [
|
321
|
348
|
{
|
322
|
349
|
devices: availableDevices.videoInput,
|
323
|
|
- hasPermission: this.props.hasVideoPermission(),
|
|
350
|
+ hasPermission: hasVideoPermission,
|
324
|
351
|
icon: 'icon-camera',
|
325
|
352
|
isDisabled: this.props.disableDeviceChange,
|
326
|
353
|
key: 'videoInput',
|
|
@@ -331,7 +358,7 @@ class DeviceSelection extends AbstractDialogTab<Props, State> {
|
331
|
358
|
},
|
332
|
359
|
{
|
333
|
360
|
devices: availableDevices.audioInput,
|
334
|
|
- hasPermission: this.props.hasAudioPermission(),
|
|
361
|
+ hasPermission: hasAudioPermission,
|
335
|
362
|
icon: 'icon-microphone',
|
336
|
363
|
isDisabled: this.props.disableAudioInputChange
|
337
|
364
|
|| this.props.disableDeviceChange,
|
|
@@ -346,8 +373,7 @@ class DeviceSelection extends AbstractDialogTab<Props, State> {
|
346
|
373
|
if (!this.props.hideAudioOutputSelect) {
|
347
|
374
|
configurations.push({
|
348
|
375
|
devices: availableDevices.audioOutput,
|
349
|
|
- hasPermission: this.props.hasAudioPermission()
|
350
|
|
- || this.props.hasVideoPermission(),
|
|
376
|
+ hasPermission: hasAudioPermission || hasVideoPermission,
|
351
|
377
|
icon: 'icon-speaker',
|
352
|
378
|
isDisabled: this.props.disableDeviceChange,
|
353
|
379
|
key: 'audioOutput',
|