fix(settings): Always show mic audio levels
This commit is contained in:
parent
4b1743bb2f
commit
99e7d636b7
|
@ -4,7 +4,8 @@ import React, { Component } from 'react';
|
||||||
|
|
||||||
import { translate } from '../../../../base/i18n';
|
import { translate } from '../../../../base/i18n';
|
||||||
import { IconMicrophoneEmpty, IconVolumeEmpty } from '../../../../base/icons';
|
import { IconMicrophoneEmpty, IconVolumeEmpty } from '../../../../base/icons';
|
||||||
import { createLocalAudioTrack } from '../../../functions';
|
import { equals } from '../../../../base/redux';
|
||||||
|
import { createLocalAudioTracks } from '../../../functions';
|
||||||
|
|
||||||
import AudioSettingsHeader from './AudioSettingsHeader';
|
import AudioSettingsHeader from './AudioSettingsHeader';
|
||||||
import MicrophoneEntry from './MicrophoneEntry';
|
import MicrophoneEntry from './MicrophoneEntry';
|
||||||
|
@ -53,10 +54,10 @@ export type Props = {
|
||||||
type State = {
|
type State = {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An object containing the jitsiTrack and the error (if the case)
|
* An list of objects, each containing the microphone label, audio track, device id
|
||||||
* for the microphone that is in use.
|
* and track error if the case.
|
||||||
*/
|
*/
|
||||||
currentMicData: Object
|
audioTracks: Object[]
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -81,10 +82,14 @@ class AudioSettingsContent extends Component<Props, State> {
|
||||||
this._onSpeakerEntryClick = this._onSpeakerEntryClick.bind(this);
|
this._onSpeakerEntryClick = this._onSpeakerEntryClick.bind(this);
|
||||||
|
|
||||||
this.state = {
|
this.state = {
|
||||||
currentMicData: {
|
audioTracks: props.microphoneDevices.map(({ deviceId, label }) => {
|
||||||
error: false,
|
return {
|
||||||
jitsiTrack: null
|
deviceId,
|
||||||
}
|
hasError: false,
|
||||||
|
jitsiTrack: null,
|
||||||
|
label
|
||||||
|
};
|
||||||
|
})
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -115,20 +120,13 @@ class AudioSettingsContent extends Component<Props, State> {
|
||||||
/**
|
/**
|
||||||
* Renders a single microphone entry.
|
* Renders a single microphone entry.
|
||||||
*
|
*
|
||||||
* @param {Object} data - An object with the deviceId and label of the microphone.
|
* @param {Object} data - An object with the deviceId, jitsiTrack & label of the microphone.
|
||||||
* @param {number} index - The index of the element, used for creating a key.
|
* @param {number} index - The index of the element, used for creating a key.
|
||||||
* @returns {React$Node}
|
* @returns {React$Node}
|
||||||
*/
|
*/
|
||||||
_renderMicrophoneEntry(data, index) {
|
_renderMicrophoneEntry(data, index) {
|
||||||
const { deviceId, label } = data;
|
const { deviceId, label, jitsiTrack, hasError } = data;
|
||||||
const key = `me-${index}`;
|
|
||||||
const isSelected = deviceId === this.props.currentMicDeviceId;
|
const isSelected = deviceId === this.props.currentMicDeviceId;
|
||||||
let jitsiTrack = null;
|
|
||||||
let hasError = false;
|
|
||||||
|
|
||||||
if (isSelected) {
|
|
||||||
({ jitsiTrack, hasError } = this.state.currentMicData);
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<MicrophoneEntry
|
<MicrophoneEntry
|
||||||
|
@ -136,7 +134,7 @@ class AudioSettingsContent extends Component<Props, State> {
|
||||||
hasError = { hasError }
|
hasError = { hasError }
|
||||||
isSelected = { isSelected }
|
isSelected = { isSelected }
|
||||||
jitsiTrack = { jitsiTrack }
|
jitsiTrack = { jitsiTrack }
|
||||||
key = { key }
|
key = { `me-${index}` }
|
||||||
onClick = { this._onMicrophoneEntryClick }>
|
onClick = { this._onMicrophoneEntryClick }>
|
||||||
{label}
|
{label}
|
||||||
</MicrophoneEntry>
|
</MicrophoneEntry>
|
||||||
|
@ -166,50 +164,36 @@ class AudioSettingsContent extends Component<Props, State> {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Disposes the audio track for a given micData object.
|
* Creates and updates the audio tracks.
|
||||||
*
|
|
||||||
* @param {Object} micData - The object holding the track.
|
|
||||||
* @returns {Promise<void>}
|
|
||||||
*/
|
|
||||||
_disposeTrack(micData) {
|
|
||||||
const { jitsiTrack } = micData;
|
|
||||||
|
|
||||||
return jitsiTrack ? jitsiTrack.dispose() : Promise.resolve();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Updates the current microphone data.
|
|
||||||
* Disposes previously created track and creates a new one.
|
|
||||||
*
|
*
|
||||||
* @returns {void}
|
* @returns {void}
|
||||||
*/
|
*/
|
||||||
async _updateCurrentMicData() {
|
async _setTracks() {
|
||||||
await this._disposeTrack(this.state.currentMicData);
|
this._disposeTracks(this.state.audioTracks);
|
||||||
|
|
||||||
const currentMicData = await createLocalAudioTrack(
|
const audioTracks = await createLocalAudioTracks(
|
||||||
this.props.currentMicDeviceId,
|
this.props.microphoneDevices
|
||||||
);
|
);
|
||||||
|
|
||||||
// In case the component gets unmounted before the track is created
|
|
||||||
// avoid a leak by not setting the state
|
|
||||||
if (this._componentWasUnmounted) {
|
if (this._componentWasUnmounted) {
|
||||||
this._disposeTrack(currentMicData);
|
this._disposeTracks(audioTracks);
|
||||||
} else {
|
} else {
|
||||||
this.setState({
|
this.setState({
|
||||||
currentMicData
|
audioTracks
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Implements React's {@link Component#componentDidUpdate}.
|
* Disposes the audio tracks.
|
||||||
*
|
*
|
||||||
* @inheritdoc
|
* @param {Object} audioTracks - The object holding the audio tracks.
|
||||||
|
* @returns {void}
|
||||||
*/
|
*/
|
||||||
componentDidUpdate(prevProps) {
|
_disposeTracks(audioTracks) {
|
||||||
if (prevProps.currentMicDeviceId !== this.props.currentMicDeviceId) {
|
audioTracks.forEach(({ jitsiTrack }) => {
|
||||||
this._updateCurrentMicData();
|
jitsiTrack && jitsiTrack.dispose();
|
||||||
}
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -218,7 +202,7 @@ class AudioSettingsContent extends Component<Props, State> {
|
||||||
* @inheritdoc
|
* @inheritdoc
|
||||||
*/
|
*/
|
||||||
componentDidMount() {
|
componentDidMount() {
|
||||||
this._updateCurrentMicData();
|
this._setTracks();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -228,16 +212,28 @@ class AudioSettingsContent extends Component<Props, State> {
|
||||||
*/
|
*/
|
||||||
componentWillUnmount() {
|
componentWillUnmount() {
|
||||||
this._componentWasUnmounted = true;
|
this._componentWasUnmounted = true;
|
||||||
this._disposeTrack(this.state.currentMicData);
|
this._disposeTracks(this.state.audioTracks);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Implements React's {@link Component#componentDidUpdate}.
|
||||||
|
*
|
||||||
|
* @inheritdoc
|
||||||
|
*/
|
||||||
|
componentDidUpdate(prevProps) {
|
||||||
|
if (!equals(this.props.microphoneDevices, prevProps.microphoneDevices)) {
|
||||||
|
this._setTracks();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Implements React's {@link Component#render}.
|
* Implements React's {@link Component#render}.
|
||||||
*
|
*
|
||||||
* @inheritdoc
|
* @inheritdoc
|
||||||
*/
|
*/
|
||||||
render() {
|
render() {
|
||||||
const { microphoneDevices, outputDevices, t } = this.props;
|
const { outputDevices, t } = this.props;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
|
@ -245,7 +241,7 @@ class AudioSettingsContent extends Component<Props, State> {
|
||||||
<AudioSettingsHeader
|
<AudioSettingsHeader
|
||||||
IconComponent = { IconMicrophoneEmpty }
|
IconComponent = { IconMicrophoneEmpty }
|
||||||
text = { t('settings.microphones') } />
|
text = { t('settings.microphones') } />
|
||||||
{microphoneDevices.map((data, i) =>
|
{this.state.audioTracks.map((data, i) =>
|
||||||
this._renderMicrophoneEntry(data, i),
|
this._renderMicrophoneEntry(data, i),
|
||||||
)}
|
)}
|
||||||
<AudioSettingsHeader
|
<AudioSettingsHeader
|
||||||
|
|
|
@ -176,27 +176,36 @@ export function createLocalVideoTracks(ids: string[]) {
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns a promise which resolves with an object containing the corresponding
|
* Returns a promise which resolves with a list of objects containing
|
||||||
* the audio jitsiTrack/error.
|
* the audio track and the corresponding audio device information.
|
||||||
*
|
*
|
||||||
* @param {string} deviceId - The deviceId for the current microphone.
|
* @param {Object[]} devices - A list of microphone devices.
|
||||||
*
|
* @returns {Promise<{
|
||||||
* @returns {Promise<Object>}
|
* deviceId: string,
|
||||||
|
* hasError: boolean,
|
||||||
|
* jitsiTrack: Object,
|
||||||
|
* label: string
|
||||||
|
* }[]>}
|
||||||
*/
|
*/
|
||||||
export function createLocalAudioTrack(deviceId: string) {
|
export function createLocalAudioTracks(devices: Object[]) {
|
||||||
return createLocalTrack('audio', deviceId)
|
return Promise.all(
|
||||||
.then(jitsiTrack => {
|
devices.map(async ({ deviceId, label }) => {
|
||||||
return {
|
let jitsiTrack = null;
|
||||||
hasError: false,
|
let hasError = false;
|
||||||
jitsiTrack
|
|
||||||
};
|
try {
|
||||||
})
|
jitsiTrack = await createLocalTrack('audio', deviceId);
|
||||||
.catch(() => {
|
} catch (err) {
|
||||||
return {
|
hasError = true;
|
||||||
hasError: true,
|
}
|
||||||
jitsiTrack: null
|
|
||||||
};
|
return {
|
||||||
});
|
deviceId,
|
||||||
|
hasError,
|
||||||
|
jitsiTrack,
|
||||||
|
label
|
||||||
|
};
|
||||||
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
Loading…
Reference in New Issue