2019-06-03 22:28:05 +08:00
|
|
|
import React, { PureComponent } from 'react';
|
2017-09-26 04:28:36 +08:00
|
|
|
import PropTypes from 'prop-types';
|
2018-06-19 23:38:09 +08:00
|
|
|
import cx from 'classnames';
|
2020-05-26 04:00:13 +08:00
|
|
|
import { defineMessages, injectIntl } from 'react-intl';
|
2021-04-01 01:13:36 +08:00
|
|
|
import deviceInfo from '/imports/utils/deviceInfo';
|
2017-09-20 01:47:57 +08:00
|
|
|
import Button from '/imports/ui/components/button/component';
|
2018-11-01 23:03:16 +08:00
|
|
|
import getFromUserSettings from '/imports/ui/services/users-settings';
|
2018-11-01 02:51:56 +08:00
|
|
|
import withShortcutHelper from '/imports/ui/components/shortcut-help/service';
|
2020-07-28 03:49:26 +08:00
|
|
|
import InputStreamLiveSelectorContainer from './input-stream-live-selector/container';
|
2020-06-16 21:41:51 +08:00
|
|
|
import MutedAlert from '/imports/ui/components/muted-alert/component';
|
2018-01-08 14:17:18 +08:00
|
|
|
import { styles } from './styles';
|
2017-09-20 01:47:57 +08:00
|
|
|
|
2017-12-11 21:47:50 +08:00
|
|
|
const intlMessages = defineMessages({
|
|
|
|
joinAudio: {
|
|
|
|
id: 'app.audio.joinAudio',
|
|
|
|
description: 'Join audio button label',
|
|
|
|
},
|
2021-03-19 02:12:01 +08:00
|
|
|
leaveAudio: {
|
|
|
|
id: 'app.audio.leaveAudio',
|
|
|
|
description: 'Leave audio button label',
|
|
|
|
},
|
2017-12-11 21:47:50 +08:00
|
|
|
muteAudio: {
|
|
|
|
id: 'app.actionsBar.muteLabel',
|
|
|
|
description: 'Mute audio button label',
|
|
|
|
},
|
|
|
|
unmuteAudio: {
|
|
|
|
id: 'app.actionsBar.unmuteLabel',
|
|
|
|
description: 'Unmute audio button label',
|
|
|
|
},
|
|
|
|
});
|
2017-09-20 01:47:57 +08:00
|
|
|
|
2017-09-26 04:28:36 +08:00
|
|
|
const propTypes = {
|
fix: breakout autojoin audio with wrong behavior
When joining/returning breakouts, audio would always connect
with full audio. This can lead to a performance problem, once
all listenonly users would join full audio, increasing the
number of streams in FreeSWITCH.
We now have a consistent behavior, which is:
1 - The choice made by the user in the main room is predominant:
if mic is active in main room, user will automatically
join mic in breakout room. When returning from breakout
room, user will also join with mic again.
2 - Changes made in breakout room won't have effect when
returning to the main room. This means if user, for example,
change from listenonly to mic in breakout room, the returning
will consider the option choosen previously (listenonly) and
listenonly will be active again in the main room.
3 - If user didn't join audio in the main room, the audio modal
will be prompted when joining the breakout room (this is
a special case of (1))
The following is some technicall information:
InputStreamLiveSelector (component.jsx) now calls
'handleLeaveAudio' function, which is the default
function when user leaves audio (also used when
dynamic devices are inactive).
We now store information about user's choice (mic or listenonly)
using local storage, instead of the previous cookie method (this
was triggering some warnings in browser's console).
Also did a small refactoring to match eslint rules.
Fixes #11662.
2021-04-21 01:38:11 +08:00
|
|
|
shortcuts: PropTypes.objectOf(PropTypes.string).isRequired,
|
2018-11-14 01:14:30 +08:00
|
|
|
processToggleMuteFromOutside: PropTypes.func.isRequired,
|
2017-09-26 04:28:36 +08:00
|
|
|
handleToggleMuteMicrophone: PropTypes.func.isRequired,
|
|
|
|
handleJoinAudio: PropTypes.func.isRequired,
|
|
|
|
handleLeaveAudio: PropTypes.func.isRequired,
|
2017-10-23 20:41:09 +08:00
|
|
|
disable: PropTypes.bool.isRequired,
|
2019-03-22 06:16:56 +08:00
|
|
|
muted: PropTypes.bool.isRequired,
|
|
|
|
showMute: PropTypes.bool.isRequired,
|
|
|
|
inAudio: PropTypes.bool.isRequired,
|
|
|
|
listenOnly: PropTypes.bool.isRequired,
|
2021-03-19 02:12:01 +08:00
|
|
|
intl: PropTypes.shape({
|
|
|
|
formatMessage: PropTypes.func.isRequired,
|
|
|
|
}).isRequired,
|
2019-03-22 06:16:56 +08:00
|
|
|
talking: PropTypes.bool.isRequired,
|
2017-09-26 04:28:36 +08:00
|
|
|
};
|
2017-09-20 01:47:57 +08:00
|
|
|
|
2019-06-03 22:28:05 +08:00
|
|
|
class AudioControls extends PureComponent {
|
2020-07-28 03:49:26 +08:00
|
|
|
constructor(props) {
|
|
|
|
super(props);
|
2021-03-19 02:12:01 +08:00
|
|
|
this.renderLeaveButtonWithoutLiveStreamSelector = this
|
|
|
|
.renderLeaveButtonWithoutLiveStreamSelector.bind(this);
|
|
|
|
|
|
|
|
this.renderJoinLeaveButton = this.renderJoinLeaveButton.bind(this);
|
2020-07-28 03:49:26 +08:00
|
|
|
}
|
|
|
|
|
2018-11-01 23:03:16 +08:00
|
|
|
componentDidMount() {
|
2018-11-14 01:14:30 +08:00
|
|
|
const { processToggleMuteFromOutside } = this.props;
|
2019-03-20 01:11:48 +08:00
|
|
|
if (Meteor.settings.public.allowOutsideCommands.toggleSelfVoice
|
2019-07-22 22:28:13 +08:00
|
|
|
|| getFromUserSettings('bbb_outside_toggle_self_voice', false)) {
|
2018-11-14 01:14:30 +08:00
|
|
|
window.addEventListener('message', processToggleMuteFromOutside);
|
2018-11-01 23:03:16 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-03-19 02:12:01 +08:00
|
|
|
renderJoinButton() {
|
|
|
|
const {
|
|
|
|
handleJoinAudio,
|
|
|
|
disable,
|
|
|
|
intl,
|
|
|
|
shortcuts,
|
|
|
|
} = this.props;
|
|
|
|
|
|
|
|
return (
|
|
|
|
<Button
|
2021-04-30 01:17:04 +08:00
|
|
|
className={styles.btn}
|
2021-03-19 02:12:01 +08:00
|
|
|
onClick={handleJoinAudio}
|
|
|
|
disabled={disable}
|
|
|
|
hideLabel
|
|
|
|
aria-label={intl.formatMessage(intlMessages.joinAudio)}
|
|
|
|
label={intl.formatMessage(intlMessages.joinAudio)}
|
2021-08-26 03:27:50 +08:00
|
|
|
data-test="joinAudio"
|
2021-03-19 02:12:01 +08:00
|
|
|
color="default"
|
|
|
|
ghost
|
|
|
|
icon="audio_off"
|
|
|
|
size="lg"
|
|
|
|
circle
|
|
|
|
accessKey={shortcuts.joinaudio}
|
|
|
|
/>
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
fix: breakout autojoin audio with wrong behavior
When joining/returning breakouts, audio would always connect
with full audio. This can lead to a performance problem, once
all listenonly users would join full audio, increasing the
number of streams in FreeSWITCH.
We now have a consistent behavior, which is:
1 - The choice made by the user in the main room is predominant:
if mic is active in main room, user will automatically
join mic in breakout room. When returning from breakout
room, user will also join with mic again.
2 - Changes made in breakout room won't have effect when
returning to the main room. This means if user, for example,
change from listenonly to mic in breakout room, the returning
will consider the option choosen previously (listenonly) and
listenonly will be active again in the main room.
3 - If user didn't join audio in the main room, the audio modal
will be prompted when joining the breakout room (this is
a special case of (1))
The following is some technicall information:
InputStreamLiveSelector (component.jsx) now calls
'handleLeaveAudio' function, which is the default
function when user leaves audio (also used when
dynamic devices are inactive).
We now store information about user's choice (mic or listenonly)
using local storage, instead of the previous cookie method (this
was triggering some warnings in browser's console).
Also did a small refactoring to match eslint rules.
Fixes #11662.
2021-04-21 01:38:11 +08:00
|
|
|
static renderLeaveButtonWithLiveStreamSelector(props) {
|
|
|
|
const { handleLeaveAudio } = props;
|
|
|
|
return (
|
|
|
|
<InputStreamLiveSelectorContainer {...{ handleLeaveAudio }} />
|
|
|
|
);
|
2020-07-28 03:49:26 +08:00
|
|
|
}
|
|
|
|
|
2021-03-19 02:12:01 +08:00
|
|
|
renderLeaveButtonWithoutLiveStreamSelector() {
|
|
|
|
const {
|
|
|
|
handleJoinAudio,
|
|
|
|
handleLeaveAudio,
|
|
|
|
disable,
|
|
|
|
inAudio,
|
|
|
|
listenOnly,
|
|
|
|
intl,
|
|
|
|
shortcuts,
|
|
|
|
} = this.props;
|
|
|
|
|
|
|
|
let joinIcon = 'audio_off';
|
|
|
|
if (inAudio) {
|
|
|
|
if (listenOnly) {
|
|
|
|
joinIcon = 'listen';
|
|
|
|
} else {
|
|
|
|
joinIcon = 'audio_on';
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return (
|
|
|
|
<Button
|
|
|
|
className={cx(inAudio || styles.btn)}
|
|
|
|
onClick={inAudio ? handleLeaveAudio : handleJoinAudio}
|
|
|
|
disabled={disable}
|
|
|
|
data-test={inAudio ? 'leaveAudio' : 'joinAudio'}
|
|
|
|
hideLabel
|
|
|
|
aria-label={inAudio ? intl.formatMessage(intlMessages.leaveAudio)
|
|
|
|
: intl.formatMessage(intlMessages.joinAudio)}
|
|
|
|
label={inAudio ? intl.formatMessage(intlMessages.leaveAudio)
|
|
|
|
: intl.formatMessage(intlMessages.joinAudio)}
|
|
|
|
color={inAudio ? 'primary' : 'default'}
|
|
|
|
ghost={!inAudio}
|
|
|
|
icon={joinIcon}
|
|
|
|
size="lg"
|
|
|
|
circle
|
|
|
|
accessKey={inAudio ? shortcuts.leaveaudio : shortcuts.joinaudio}
|
|
|
|
/>
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
renderJoinLeaveButton() {
|
|
|
|
const {
|
|
|
|
inAudio,
|
|
|
|
} = this.props;
|
|
|
|
|
2021-04-01 01:13:36 +08:00
|
|
|
const { isMobile } = deviceInfo;
|
|
|
|
|
2021-03-19 02:12:01 +08:00
|
|
|
let { enableDynamicAudioDeviceSelection } = Meteor.settings.public.app;
|
|
|
|
|
|
|
|
if (typeof enableDynamicAudioDeviceSelection === 'undefined') {
|
|
|
|
enableDynamicAudioDeviceSelection = true;
|
|
|
|
}
|
|
|
|
|
2021-03-20 01:05:08 +08:00
|
|
|
const _enableDynamicDeviceSelection = enableDynamicAudioDeviceSelection
|
|
|
|
&& !isMobile;
|
|
|
|
|
2021-03-19 02:12:01 +08:00
|
|
|
if (inAudio) {
|
2021-03-20 01:05:08 +08:00
|
|
|
if (_enableDynamicDeviceSelection) {
|
fix: breakout autojoin audio with wrong behavior
When joining/returning breakouts, audio would always connect
with full audio. This can lead to a performance problem, once
all listenonly users would join full audio, increasing the
number of streams in FreeSWITCH.
We now have a consistent behavior, which is:
1 - The choice made by the user in the main room is predominant:
if mic is active in main room, user will automatically
join mic in breakout room. When returning from breakout
room, user will also join with mic again.
2 - Changes made in breakout room won't have effect when
returning to the main room. This means if user, for example,
change from listenonly to mic in breakout room, the returning
will consider the option choosen previously (listenonly) and
listenonly will be active again in the main room.
3 - If user didn't join audio in the main room, the audio modal
will be prompted when joining the breakout room (this is
a special case of (1))
The following is some technicall information:
InputStreamLiveSelector (component.jsx) now calls
'handleLeaveAudio' function, which is the default
function when user leaves audio (also used when
dynamic devices are inactive).
We now store information about user's choice (mic or listenonly)
using local storage, instead of the previous cookie method (this
was triggering some warnings in browser's console).
Also did a small refactoring to match eslint rules.
Fixes #11662.
2021-04-21 01:38:11 +08:00
|
|
|
return AudioControls.renderLeaveButtonWithLiveStreamSelector(this
|
|
|
|
.props);
|
2021-03-19 02:12:01 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
return this.renderLeaveButtonWithoutLiveStreamSelector();
|
|
|
|
}
|
|
|
|
|
|
|
|
return this.renderJoinButton();
|
|
|
|
}
|
|
|
|
|
2018-11-01 23:03:16 +08:00
|
|
|
render() {
|
|
|
|
const {
|
|
|
|
handleToggleMuteMicrophone,
|
2019-03-22 06:16:56 +08:00
|
|
|
showMute,
|
|
|
|
muted,
|
2018-11-01 23:03:16 +08:00
|
|
|
disable,
|
2019-03-22 06:16:56 +08:00
|
|
|
talking,
|
2018-11-01 23:03:16 +08:00
|
|
|
intl,
|
2018-11-09 03:34:57 +08:00
|
|
|
shortcuts,
|
2019-08-22 20:05:06 +08:00
|
|
|
isVoiceUser,
|
2021-04-01 03:09:08 +08:00
|
|
|
listenOnly,
|
2020-06-16 23:03:45 +08:00
|
|
|
inputStream,
|
2020-06-23 21:38:59 +08:00
|
|
|
isViewer,
|
|
|
|
isPresenter,
|
2018-11-01 23:03:16 +08:00
|
|
|
} = this.props;
|
|
|
|
|
2020-06-16 21:41:51 +08:00
|
|
|
const label = muted ? intl.formatMessage(intlMessages.unmuteAudio)
|
|
|
|
: intl.formatMessage(intlMessages.muteAudio);
|
|
|
|
|
|
|
|
const toggleMuteBtn = (
|
|
|
|
<Button
|
|
|
|
className={cx(styles.muteToggle, !talking || styles.glow, !muted || styles.btn)}
|
|
|
|
onClick={handleToggleMuteMicrophone}
|
|
|
|
disabled={disable}
|
|
|
|
hideLabel
|
|
|
|
label={label}
|
|
|
|
aria-label={label}
|
|
|
|
color={!muted ? 'primary' : 'default'}
|
|
|
|
ghost={muted}
|
|
|
|
icon={muted ? 'mute' : 'unmute'}
|
|
|
|
size="lg"
|
|
|
|
circle
|
|
|
|
accessKey={shortcuts.togglemute}
|
|
|
|
/>
|
|
|
|
);
|
|
|
|
|
2020-10-27 05:07:15 +08:00
|
|
|
const MUTE_ALERT_CONFIG = Meteor.settings.public.app.mutedAlert;
|
|
|
|
const { enabled: muteAlertEnabled } = MUTE_ALERT_CONFIG;
|
2021-01-31 01:04:07 +08:00
|
|
|
|
2018-11-01 23:03:16 +08:00
|
|
|
return (
|
|
|
|
<span className={styles.container}>
|
2021-07-06 22:59:42 +08:00
|
|
|
{isVoiceUser && inputStream && muteAlertEnabled && !listenOnly && muted && showMute ? (
|
2021-01-31 01:04:07 +08:00
|
|
|
<MutedAlert {...{
|
|
|
|
muted, inputStream, isViewer, isPresenter,
|
|
|
|
}}
|
|
|
|
/>
|
|
|
|
) : null}
|
2020-06-16 21:41:51 +08:00
|
|
|
{showMute && isVoiceUser ? toggleMuteBtn : null}
|
2020-07-28 03:49:26 +08:00
|
|
|
{
|
2021-03-19 02:12:01 +08:00
|
|
|
this.renderJoinLeaveButton()
|
2020-07-28 03:49:26 +08:00
|
|
|
}
|
2020-06-16 21:41:51 +08:00
|
|
|
</span>
|
|
|
|
);
|
2018-11-01 23:03:16 +08:00
|
|
|
}
|
|
|
|
}
|
2017-09-26 04:28:36 +08:00
|
|
|
|
|
|
|
AudioControls.propTypes = propTypes;
|
|
|
|
|
2021-03-19 02:12:01 +08:00
|
|
|
export default withShortcutHelper(injectIntl(AudioControls), ['joinAudio',
|
|
|
|
'leaveAudio', 'toggleMute']);
|