fix(audio): review device selection in mobile endpoints

Mobile users have no way to change I/O devices after joining audio.
The removal of the audio options chevron in mobile browsers was supposed
to be replaced by something else - in this case, by the dedicated
leave/join audio button. That didn't happen, leave/join audio button
retained the old behavior.

Review device selection in mobile endpoints via two UI/UX changes:
  - Restore the device selection chevron/icon in mobile endpoints
  - Override the leave/join button action in mobile endpoints so that it
    opens the device selection contextual menu, which also includes the
    "Leave audio" option. This retains the old behavior (leaving audio)
    while also providing an way for users to change devices mid-call in
    mobile browsers.
This commit is contained in:
prlanzarin 2024-04-15 14:37:20 -03:00
parent be96230894
commit 141c553b17
2 changed files with 40 additions and 29 deletions

View File

@ -109,18 +109,14 @@ class AudioControls extends PureComponent {
inAudio,
} = this.props;
const { isMobile } = deviceInfo;
let { enableDynamicAudioDeviceSelection } = Meteor.settings.public.app;
if (typeof enableDynamicAudioDeviceSelection === 'undefined') {
enableDynamicAudioDeviceSelection = true;
}
const _enableDynamicDeviceSelection = enableDynamicAudioDeviceSelection && !isMobile;
if (inAudio) {
return this.renderButtonsAndStreamSelector(_enableDynamicDeviceSelection);
return this.renderButtonsAndStreamSelector(enableDynamicAudioDeviceSelection);
}
return this.renderJoinButton();

View File

@ -77,6 +77,7 @@ const propTypes = {
disable: PropTypes.bool.isRequired,
talking: PropTypes.bool,
notify: PropTypes.func.isRequired,
isMobile: PropTypes.bool.isRequired,
};
const defaultProps = {
@ -95,7 +96,7 @@ class InputStreamLiveSelector extends Component {
super(props);
this.updateDeviceList = this.updateDeviceList.bind(this);
this.renderDeviceList = this.renderDeviceList.bind(this);
this.renderListenOnlyButton = this.renderListenOnlyButton.bind(this);
this.renderAudioButton = this.renderAudioButton.bind(this);
this.renderMuteToggleButton = this.renderMuteToggleButton.bind(this);
this.renderButtonsWithSelectorDevice = this.renderButtonsWithSelectorDevice.bind(this);
this.renderButtonsWithoutSelectorDevice = this.renderButtonsWithoutSelectorDevice.bind(this);
@ -345,18 +346,23 @@ class InputStreamLiveSelector extends Component {
);
}
renderListenOnlyButton() {
renderAudioButton() {
const {
handleLeaveAudio,
intl,
shortcuts,
isListenOnly,
_enableDynamicDeviceSelection,
isMobile,
} = this.props;
const actAsSelectorTrigger = _enableDynamicDeviceSelection && isMobile;
return (
<Button
aria-label={intl.formatMessage(intlMessages.leaveAudio)}
label={intl.formatMessage(intlMessages.leaveAudio)}
label={actAsSelectorTrigger
? intl.formatMessage(intlMessages.changeAudioDevice)
: intl.formatMessage(intlMessages.leaveAudio)}
accessKey={shortcuts.leaveaudio}
data-test="leaveListenOnly"
hideLabel
@ -364,14 +370,36 @@ class InputStreamLiveSelector extends Component {
icon={isListenOnly ? 'listen' : 'volume_level_2'}
size="lg"
circle
onClick={(e) => {
e.stopPropagation();
handleLeaveAudio();
}}
onClick={actAsSelectorTrigger
? () => null
: (e) => {
e.stopPropagation();
handleLeaveAudio();
}}
/>
);
}
renderMenuTrigger() {
const { intl, isMobile, isListenOnly } = this.props;
return (
<>
{!isListenOnly && !isMobile
? this.renderMuteToggleButton()
: this.renderAudioButton()}
<Styled.AudioDropdown
data-test="audioDropdownMenu"
emoji="device_list_selector"
label={intl.formatMessage(intlMessages.changeAudioDevice)}
hideLabel
tabIndex={0}
rotate
/>
</>
);
}
renderButtonsWithSelectorDevice() {
const {
audioInputDevices,
@ -433,23 +461,10 @@ class InputStreamLiveSelector extends Component {
aria-hidden="true"
/>
) : null}
{(!isListenOnly && isMobile) && this.renderMuteToggleButton()}
<BBBMenu
customStyles={!isMobile ? customStyles : null}
trigger={(
<>
{isListenOnly
? this.renderListenOnlyButton()
: this.renderMuteToggleButton()}
<Styled.AudioDropdown
data-test="audioDropdownMenu"
emoji="device_list_selector"
label={intl.formatMessage(intlMessages.changeAudioDevice)}
hideLabel
tabIndex={0}
rotate
/>
</>
)}
trigger={this.renderMenuTrigger()}
actions={dropdownListComplete}
opts={{
id: 'audio-selector-dropdown-menu',
@ -469,11 +484,11 @@ class InputStreamLiveSelector extends Component {
renderButtonsWithoutSelectorDevice() {
const { isListenOnly } = this.props;
return isListenOnly
? this.renderListenOnlyButton()
? this.renderAudioButton()
: (
<>
{this.renderMuteToggleButton()}
{this.renderListenOnlyButton()}
{this.renderAudioButton()}
</>
);
}