2020-06-16 21:41:51 +08:00
|
|
|
import React, { Component } from 'react';
|
|
|
|
import PropTypes from 'prop-types';
|
|
|
|
import hark from 'hark';
|
2022-02-15 22:51:51 +08:00
|
|
|
import Icon from '/imports/ui/components/common/icon/component';
|
2021-10-28 01:07:09 +08:00
|
|
|
import Styled from './styles';
|
2021-04-29 20:55:01 +08:00
|
|
|
import { defineMessages, injectIntl } from 'react-intl';
|
|
|
|
import { notify } from '/imports/ui/services/notification';
|
2022-02-16 02:07:09 +08:00
|
|
|
import TooltipContainer from '/imports/ui/components/common/tooltip/container';
|
2020-06-16 21:41:51 +08:00
|
|
|
|
|
|
|
const propTypes = {
|
2021-04-01 03:09:08 +08:00
|
|
|
inputStream: PropTypes.objectOf(PropTypes.any).isRequired,
|
2021-01-31 01:04:07 +08:00
|
|
|
isPresenter: PropTypes.bool.isRequired,
|
|
|
|
isViewer: PropTypes.bool.isRequired,
|
|
|
|
muted: PropTypes.bool.isRequired,
|
2020-06-16 21:41:51 +08:00
|
|
|
};
|
|
|
|
|
2021-04-29 20:55:01 +08:00
|
|
|
const intlMessages = defineMessages({
|
|
|
|
disableMessage: {
|
|
|
|
id: 'app.muteWarning.disableMessage',
|
|
|
|
description: 'Message used when mute alerts has been disabled',
|
|
|
|
},
|
|
|
|
tooltip: {
|
|
|
|
id: 'app.muteWarning.tooltip',
|
|
|
|
description: 'Tooltip message',
|
|
|
|
},
|
|
|
|
warningLabel: {
|
|
|
|
id: 'app.muteWarning.label',
|
|
|
|
description: 'Warning when someone speaks while muted',
|
|
|
|
},
|
|
|
|
});
|
|
|
|
|
2020-06-16 21:41:51 +08:00
|
|
|
class MutedAlert extends Component {
|
|
|
|
constructor(props) {
|
|
|
|
super(props);
|
|
|
|
|
|
|
|
this.state = {
|
|
|
|
visible: false,
|
|
|
|
};
|
|
|
|
|
2021-01-31 01:04:07 +08:00
|
|
|
this.inputStream = null;
|
2020-06-16 21:41:51 +08:00
|
|
|
this.speechEvents = null;
|
|
|
|
this.timer = null;
|
|
|
|
|
2021-01-31 01:04:07 +08:00
|
|
|
this.cloneMediaStream = this.cloneMediaStream.bind(this);
|
2020-06-16 21:41:51 +08:00
|
|
|
this.resetTimer = this.resetTimer.bind(this);
|
2021-04-29 20:55:01 +08:00
|
|
|
this.closeAlert = this.closeAlert.bind(this);
|
2020-06-16 21:41:51 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
componentDidMount() {
|
2024-05-29 21:26:11 +08:00
|
|
|
const MUTE_ALERT_CONFIG = window.meetingClientSettings.public.app.mutedAlert;
|
|
|
|
|
2020-06-16 21:41:51 +08:00
|
|
|
this._isMounted = true;
|
2021-04-01 03:09:08 +08:00
|
|
|
|
|
|
|
if (!this.hasValidInputStream()) return;
|
|
|
|
|
2021-01-31 01:04:07 +08:00
|
|
|
this.cloneMediaStream();
|
|
|
|
if (this.inputStream) {
|
|
|
|
const { interval, threshold, duration } = MUTE_ALERT_CONFIG;
|
|
|
|
this.speechEvents = hark(this.inputStream, { interval, threshold });
|
|
|
|
this.speechEvents.on('speaking', () => {
|
|
|
|
this.resetTimer();
|
|
|
|
if (this._isMounted) this.setState({ visible: true });
|
|
|
|
});
|
|
|
|
this.speechEvents.on('stopped_speaking', () => {
|
|
|
|
if (this._isMounted) {
|
|
|
|
this.timer = setTimeout(() => this.setState(
|
|
|
|
{ visible: false },
|
|
|
|
), duration);
|
|
|
|
}
|
|
|
|
});
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
componentDidUpdate() {
|
|
|
|
this.cloneMediaStream();
|
2020-06-16 21:41:51 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
componentWillUnmount() {
|
|
|
|
this._isMounted = false;
|
|
|
|
if (this.speechEvents) this.speechEvents.stop();
|
2021-04-01 02:34:52 +08:00
|
|
|
if (this.inputStream) {
|
2021-04-16 21:45:40 +08:00
|
|
|
this.inputStream.getTracks().forEach((t) => t.stop());
|
2021-04-01 02:34:52 +08:00
|
|
|
}
|
2020-06-23 21:38:59 +08:00
|
|
|
this.resetTimer();
|
2020-06-16 21:41:51 +08:00
|
|
|
}
|
|
|
|
|
2021-01-31 01:04:07 +08:00
|
|
|
cloneMediaStream() {
|
2021-04-01 02:34:52 +08:00
|
|
|
if (this.inputStream) return;
|
2021-04-16 21:45:40 +08:00
|
|
|
const { inputStream } = this.props;
|
|
|
|
|
|
|
|
if (inputStream) {
|
|
|
|
this.inputStream = inputStream.clone();
|
|
|
|
this.enableInputStreamAudioTracks(this.inputStream);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-04-17 02:24:14 +08:00
|
|
|
/* eslint-disable no-param-reassign */
|
2021-04-16 21:45:40 +08:00
|
|
|
enableInputStreamAudioTracks() {
|
|
|
|
if (!this.inputStream) return;
|
|
|
|
this.inputStream.getAudioTracks().forEach((t) => { t.enabled = true; });
|
2021-01-31 01:04:07 +08:00
|
|
|
}
|
2021-04-17 02:24:14 +08:00
|
|
|
/* eslint-enable no-param-reassign */
|
2021-01-31 01:04:07 +08:00
|
|
|
|
2020-06-16 21:41:51 +08:00
|
|
|
resetTimer() {
|
|
|
|
if (this.timer) clearTimeout(this.timer);
|
|
|
|
this.timer = null;
|
|
|
|
}
|
|
|
|
|
2021-04-01 03:09:08 +08:00
|
|
|
hasValidInputStream() {
|
|
|
|
const { inputStream } = this.props;
|
|
|
|
|
|
|
|
if (inputStream
|
|
|
|
&& (typeof inputStream.getAudioTracks === 'function')
|
|
|
|
&& (inputStream.getAudioTracks().length > 0)
|
|
|
|
) return true;
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2021-04-29 20:55:01 +08:00
|
|
|
closeAlert() {
|
|
|
|
const { intl } = this.props;
|
|
|
|
|
|
|
|
this.setState({ visible: false });
|
|
|
|
this.speechEvents.stop();
|
|
|
|
|
|
|
|
notify(intl.formatMessage(intlMessages.disableMessage), 'info', 'mute');
|
|
|
|
}
|
|
|
|
|
2020-06-16 21:41:51 +08:00
|
|
|
render() {
|
2021-04-29 20:55:01 +08:00
|
|
|
const {
|
|
|
|
isViewer, isPresenter, muted, intl,
|
|
|
|
} = this.props;
|
2020-06-16 21:41:51 +08:00
|
|
|
const { visible } = this.state;
|
2020-06-23 21:38:59 +08:00
|
|
|
|
2021-01-31 01:04:07 +08:00
|
|
|
return visible && muted ? (
|
2021-04-29 20:55:01 +08:00
|
|
|
<TooltipContainer
|
|
|
|
title={intl.formatMessage(intlMessages.tooltip)}
|
|
|
|
position="top"
|
|
|
|
>
|
2021-10-28 01:07:09 +08:00
|
|
|
<Styled.MuteWarning
|
|
|
|
alignForMod={!isViewer || isPresenter}
|
|
|
|
alignForViewer={isViewer}
|
2021-04-29 20:55:01 +08:00
|
|
|
onClick={() => this.closeAlert()}
|
|
|
|
>
|
|
|
|
<span>
|
|
|
|
{intl.formatMessage(intlMessages.warningLabel, { 0: <Icon iconName="mute" /> })}
|
|
|
|
</span>
|
2021-10-28 01:07:09 +08:00
|
|
|
</Styled.MuteWarning>
|
2021-04-29 20:55:01 +08:00
|
|
|
</TooltipContainer>
|
2020-06-16 21:41:51 +08:00
|
|
|
) : null;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
MutedAlert.propTypes = propTypes;
|
|
|
|
|
2021-04-29 20:55:01 +08:00
|
|
|
export default injectIntl(MutedAlert);
|