2019-11-02 03:29:33 +08:00
|
|
|
import React, { PureComponent } from 'react';
|
|
|
|
import cx from 'classnames';
|
|
|
|
import _ from 'lodash';
|
2019-11-15 23:54:07 +08:00
|
|
|
import { defineMessages, injectIntl } from 'react-intl';
|
2019-11-23 06:25:05 +08:00
|
|
|
import Button from '/imports/ui/components/button/component';
|
2019-11-02 03:29:33 +08:00
|
|
|
import { styles } from './styles';
|
|
|
|
|
2019-11-15 23:54:07 +08:00
|
|
|
const intlMessages = defineMessages({
|
|
|
|
wasTalking: {
|
|
|
|
id: 'app.talkingIndicator.wasTalking',
|
|
|
|
description: 'aria label for user who is not talking but still visible',
|
|
|
|
},
|
|
|
|
isTalking: {
|
|
|
|
id: 'app.talkingIndicator.isTalking',
|
|
|
|
description: 'aria label for user currently talking',
|
|
|
|
},
|
|
|
|
ariaMuteDesc: {
|
|
|
|
id: 'app.talkingIndicator.ariaMuteDesc',
|
|
|
|
description: 'aria description for muting a user',
|
|
|
|
},
|
2019-12-04 02:49:09 +08:00
|
|
|
muteLabel: {
|
|
|
|
id: 'app.actionsBar.muteLabel',
|
|
|
|
description: 'indicator mute label for moderators',
|
|
|
|
},
|
2019-11-15 23:54:07 +08:00
|
|
|
});
|
|
|
|
|
2019-11-02 03:29:33 +08:00
|
|
|
class TalkingIndicator extends PureComponent {
|
2019-11-15 23:54:07 +08:00
|
|
|
handleMuteUser(id) {
|
2020-11-20 03:12:05 +08:00
|
|
|
const { muteUser, amIModerator, isBreakoutRoom } = this.props;
|
|
|
|
// only allow moderator muting anyone in non-breakout
|
|
|
|
if (!amIModerator || isBreakoutRoom) return;
|
2019-11-15 23:54:07 +08:00
|
|
|
muteUser(id);
|
|
|
|
}
|
|
|
|
|
2019-11-02 03:29:33 +08:00
|
|
|
render() {
|
2019-12-04 02:49:09 +08:00
|
|
|
const {
|
|
|
|
intl, talkers, openPanel, amIModerator,
|
|
|
|
} = this.props;
|
2019-11-02 03:29:33 +08:00
|
|
|
if (!talkers) return null;
|
|
|
|
|
2019-11-27 00:44:58 +08:00
|
|
|
const talkingUserElements = Object.keys(talkers).map((id) => {
|
2019-11-02 03:29:33 +08:00
|
|
|
const {
|
|
|
|
talking,
|
|
|
|
color,
|
2019-11-14 01:56:26 +08:00
|
|
|
voiceUserId,
|
|
|
|
muted,
|
2019-11-27 00:44:58 +08:00
|
|
|
callerName,
|
|
|
|
} = talkers[`${id}`];
|
2019-11-02 03:29:33 +08:00
|
|
|
|
|
|
|
const style = {
|
|
|
|
[styles.talker]: true,
|
|
|
|
[styles.spoke]: !talking,
|
2019-11-14 01:56:26 +08:00
|
|
|
[styles.muted]: muted,
|
2019-11-26 03:24:12 +08:00
|
|
|
[styles.mobileHide]: openPanel !== '',
|
2019-12-04 02:49:09 +08:00
|
|
|
[styles.isViewer]: !amIModerator,
|
2019-11-02 03:29:33 +08:00
|
|
|
};
|
|
|
|
|
2019-11-23 06:25:05 +08:00
|
|
|
const ariaLabel = intl.formatMessage(talking
|
|
|
|
? intlMessages.isTalking : intlMessages.wasTalking, {
|
2019-11-27 00:44:58 +08:00
|
|
|
0: callerName,
|
2019-11-15 23:54:07 +08:00
|
|
|
});
|
|
|
|
|
2019-11-23 06:25:05 +08:00
|
|
|
let icon = talking ? 'unmute' : 'blank';
|
|
|
|
icon = muted ? 'mute' : icon;
|
|
|
|
|
2019-11-02 03:29:33 +08:00
|
|
|
return (
|
2019-11-23 06:25:05 +08:00
|
|
|
<Button
|
2019-11-27 00:44:58 +08:00
|
|
|
key={_.uniqueId(`${callerName}-`)}
|
2019-11-02 03:29:33 +08:00
|
|
|
className={cx(style)}
|
2019-11-23 06:25:05 +08:00
|
|
|
onClick={() => this.handleMuteUser(voiceUserId)}
|
2019-11-27 00:44:58 +08:00
|
|
|
label={callerName}
|
2019-12-04 02:49:09 +08:00
|
|
|
tooltipLabel={!muted && amIModerator
|
|
|
|
? `${intl.formatMessage(intlMessages.muteLabel)} ${callerName}`
|
|
|
|
: null
|
|
|
|
}
|
2020-03-04 22:50:56 +08:00
|
|
|
data-test={talking ? 'isTalking' : 'wasTalking'}
|
2019-11-15 23:54:07 +08:00
|
|
|
aria-label={ariaLabel}
|
|
|
|
aria-describedby={talking ? 'description' : null}
|
2019-11-23 06:25:05 +08:00
|
|
|
color="primary"
|
|
|
|
icon={icon}
|
|
|
|
size="sm"
|
2019-11-02 03:29:33 +08:00
|
|
|
style={{
|
|
|
|
backgroundColor: color,
|
2019-11-23 06:25:05 +08:00
|
|
|
border: `solid 2px ${color}`,
|
2019-11-02 03:29:33 +08:00
|
|
|
}}
|
|
|
|
>
|
2019-11-23 06:25:05 +08:00
|
|
|
{talking ? (
|
|
|
|
<div id="description" className={styles.hidden}>
|
|
|
|
{`${intl.formatMessage(intlMessages.ariaMuteDesc)}`}
|
|
|
|
</div>
|
|
|
|
) : null
|
|
|
|
}
|
|
|
|
</Button>
|
2019-11-02 03:29:33 +08:00
|
|
|
);
|
|
|
|
});
|
|
|
|
|
|
|
|
return (
|
|
|
|
<div className={styles.isTalkingWrapper}>
|
|
|
|
<div className={styles.speaking}>
|
|
|
|
{talkingUserElements}
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-11-15 23:54:07 +08:00
|
|
|
export default injectIntl(TalkingIndicator);
|