feat(participants) Add count badge to toolbar button

Update title bar button: ParticipantsCountLabel -> SpeakerStatsLabel. Only show button when speaker stats is enabled
Add badge to the participants pane button to show participants count
This commit is contained in:
robertpin 2023-01-19 10:59:07 +02:00 committed by Saúl Ibarra Corretgé
parent 8e91851a2f
commit 6de306e46e
7 changed files with 98 additions and 122 deletions

View File

@ -88,7 +88,6 @@ export { default as IconSubtitles } from './subtitles.svg';
export { default as IconTileView } from './tile-view.svg';
export { default as IconTrash } from './trash.svg';
export { default as IconUserDeleted } from './user-deleted.svg';
export { default as IconUserGroups } from './user-groups.svg';
export { default as IconUsers } from './users.svg';
export { default as IconVideo } from './video.svg';
export { default as IconVideoOff } from './video-off.svg';

View File

@ -1,3 +0,0 @@
<svg width="16" height="16" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd" d="M5.33331 2C6.28101 2 7.09675 2.56499 7.46207 3.37651C7.00766 3.45023 6.58406 3.61583 6.21095 3.85361C6.04111 3.54356 5.71176 3.33333 5.33331 3.33333C4.78103 3.33333 4.33331 3.78105 4.33331 4.33333C4.33331 4.75895 4.59921 5.12246 4.97395 5.26682C4.77672 5.69245 4.66665 6.16671 4.66665 6.66667L4.66678 6.6967C3.12249 6.85332 2.66665 7.65415 2.66665 9.83333C2.66665 9.89666 2.66835 9.95222 2.67088 10H3.13441C2.977 10.3982 2.86114 10.8423 2.7841 11.3333H2.33331C1.66665 11.3333 1.33331 10.8333 1.33331 9.83333C1.33331 7.60559 1.88097 6.20498 3.39417 5.63152C3.14521 5.26038 2.99998 4.81382 2.99998 4.33333C2.99998 3.04467 4.04465 2 5.33331 2ZM9.78901 3.85361C9.4159 3.61583 8.9923 3.45023 8.53788 3.37651C8.90321 2.56499 9.71895 2 10.6666 2C11.9553 2 13 3.04467 13 4.33333C13 4.81382 12.8547 5.26038 12.6058 5.63152C14.119 6.20498 14.6666 7.60559 14.6666 9.83333C14.6666 10.8333 14.3333 11.3333 13.6666 11.3333H13.2159C13.1388 10.8423 13.023 10.3982 12.8656 10H13.3291C13.3316 9.95222 13.3333 9.89666 13.3333 9.83333C13.3333 7.65415 12.8775 6.85332 11.3332 6.6967L11.3333 6.66667C11.3333 6.1667 11.2232 5.69245 11.026 5.26682C11.4008 5.12246 11.6666 4.75895 11.6666 4.33333C11.6666 3.78105 11.2189 3.33333 10.6666 3.33333C10.2882 3.33333 9.95885 3.54356 9.78901 3.85361ZM4.49998 14.6667C3.7222 14.6667 3.33331 14.1111 3.33331 13C3.33331 10.4598 4.0062 8.8875 5.87888 8.28308C5.5366 7.83462 5.33331 7.27438 5.33331 6.66667C5.33331 5.19391 6.52722 4 7.99998 4C9.47274 4 10.6666 5.19391 10.6666 6.66667C10.6666 7.27438 10.4634 7.83462 10.1211 8.28308C11.9938 8.8875 12.6666 10.4598 12.6666 13C12.6666 14.1111 12.2778 14.6667 11.5 14.6667H4.49998ZM9.33331 6.66667C9.33331 7.40305 8.73636 8 7.99998 8C7.2636 8 6.66665 7.40305 6.66665 6.66667C6.66665 5.93029 7.2636 5.33333 7.99998 5.33333C8.73636 5.33333 9.33331 5.93029 9.33331 6.66667ZM11.3333 13C11.3333 13.1426 11.3252 13.2536 11.3152 13.3333H4.68477C4.67476 13.2536 4.66665 13.1426 4.66665 13C4.66665 10.1957 5.42021 9.33333 7.99998 9.33333C10.5797 9.33333 11.3333 10.1957 11.3333 13Z" />
</svg>

Before

Width:  |  Height:  |  Size: 2.1 KiB

View File

@ -17,8 +17,8 @@ import { getConferenceInfo } from '../functions';
import ConferenceInfoContainer from './ConferenceInfoContainer';
import InsecureRoomNameLabel from './InsecureRoomNameLabel';
import ParticipantsCount from './ParticipantsCount';
import RaisedHandsCountLabel from './RaisedHandsCountLabel';
import SpeakerStatsLabel from './SpeakerStatsLabel';
import SubjectText from './SubjectText';
import ToggleTopPanelLabel from './ToggleTopPanelLabel';
@ -52,7 +52,7 @@ const COMPONENTS = [
id: 'conference-timer'
},
{
Component: ParticipantsCount,
Component: SpeakerStatsLabel,
id: 'participants-count'
},
{

View File

@ -1,116 +0,0 @@
// @flow
import React, { PureComponent } from 'react';
import type { Dispatch } from 'redux';
import { openDialog } from '../../../base/dialog';
import { IconUserGroups } from '../../../base/icons';
import { Label } from '../../../base/label';
import { COLORS } from '../../../base/label/constants';
import { getParticipantCount } from '../../../base/participants';
import { connect } from '../../../base/redux';
import { SpeakerStats } from '../../../speaker-stats';
import { isSpeakerStatsDisabled } from '../../../speaker-stats/functions';
/**
* The type of the React {@code Component} props of {@link ParticipantsCount}.
*/
type Props = {
/**
* Number of the conference participants.
*/
count: number,
/**
* Conference data.
*/
conference: Object,
/**
* Invoked to open Speaker stats.
*/
dispatch: Dispatch<any>,
/**
* Weather or not the speaker stats is disabled.
*/
_isSpeakerStatsDisabled: Boolean,
};
/**
* ParticipantsCount react component.
* Displays the number of participants and opens Speaker stats on click.
*
* @class ParticipantsCount
*/
class ParticipantsCount extends PureComponent<Props> {
/**
* Initializes a new ParticipantsCount instance.
*
* @param {Object} props - The read-only properties with which the new
* instance is to be initialized.
*/
constructor(props: Props) {
super(props);
this._onClick = this._onClick.bind(this);
}
_onClick: () => void;
/**
* Callback invoked to display {@code SpeakerStats}.
*
* @private
* @returns {void}
*/
_onClick() {
const { dispatch, conference } = this.props;
dispatch(openDialog(SpeakerStats, { conference }));
}
/**
* Implements React's {@link PureComponent#render()}.
*
* @inheritdoc
* @returns {ReactElement}
*/
render() {
const { count } = this.props;
if (count <= 2) {
return null;
}
return (
<Label
color = { COLORS.white }
icon = { IconUserGroups }
iconColor = '#fff'
onClick = { !this.props._isSpeakerStatsDisabled && this._onClick }
text = { count } />
);
}
}
/**
* Maps (parts of) the Redux state to the associated props for the
* {@code ParticipantsCount} component.
*
* @param {Object} state - The Redux state.
* @private
* @returns {Props}
*/
function mapStateToProps(state) {
return {
conference: state['features/base/conference'].conference,
count: getParticipantCount(state),
_isSpeakerStatsDisabled: isSpeakerStatsDisabled(state)
};
}
export default connect(mapStateToProps)(ParticipantsCount);

View File

@ -0,0 +1,44 @@
import React from 'react';
import { useDispatch, useSelector } from 'react-redux';
import { IReduxState } from '../../../app/types';
import { openDialog } from '../../../base/dialog/actions';
import { IconConnection } from '../../../base/icons/svg';
import Label from '../../../base/label/components/web/Label';
import { COLORS } from '../../../base/label/constants';
import { getParticipantCount } from '../../../base/participants/functions';
import { SpeakerStats } from '../../../speaker-stats';
import { isSpeakerStatsDisabled } from '../../../speaker-stats/functions';
/**
* ParticipantsCount react component.
* Displays the number of participants and opens Speaker stats on click.
*
* @class ParticipantsCount
*/
function SpeakerStatsLabel() {
const conference = useSelector((state: IReduxState) => state['features/base/conference'].conference);
const count = useSelector(getParticipantCount);
const _isSpeakerStatsDisabled = useSelector(isSpeakerStatsDisabled);
const dispatch = useDispatch();
const onClick = () => {
dispatch(openDialog(SpeakerStats, { conference }));
};
if (count <= 2 || _isSpeakerStatsDisabled) {
return null;
}
return (
<Label
color = { COLORS.white }
icon = { IconConnection }
iconColor = '#fff'
// eslint-disable-next-line react/jsx-no-bind
onClick = { onClick }
text = { `${count}` } />
);
}
export default SpeakerStatsLabel;

View File

@ -0,0 +1,32 @@
import React from 'react';
import { useSelector } from 'react-redux';
import { makeStyles } from 'tss-react/mui';
import { getParticipantCount } from '../../../base/participants/functions';
import { withPixelLineHeight } from '../../../base/styles/functions.web';
const useStyles = makeStyles()(theme => {
return {
badge: {
backgroundColor: theme.palette.ui03,
borderRadius: '100%',
height: '16px',
width: '16px',
color: theme.palette.text01,
...withPixelLineHeight(theme.typography.labelBold),
pointerEvents: 'none',
position: 'absolute',
right: '-3px',
top: '-2px'
}
};
});
const ParticipantsCounter = () => {
const { classes } = useStyles();
const participantsCount = useSelector(getParticipantCount);
return <span className = { classes.badge }>{participantsCount}</span>;
};
export default ParticipantsCounter;

View File

@ -1,10 +1,13 @@
// @flow
import React from 'react';
import { translate } from '../../../base/i18n';
import { IconUsers } from '../../../base/icons';
import { connect } from '../../../base/redux';
import { AbstractButton, type AbstractButtonProps } from '../../../base/toolbox/components';
import ParticipantsCounter from './ParticipantsCounter';
/**
* The type of the React {@code Component} props of {@link ParticipantsPaneButton}.
*/
@ -35,6 +38,23 @@ class ParticipantsPaneButton extends AbstractButton<Props, *> {
_isToggled() {
return this.props._isOpen;
}
/**
* Overrides AbstractButton's {@link Component#render()}.
*
* @override
* @protected
* @returns {React$Node}
*/
render(): React$Node {
return (
<div
className = 'toolbar-button-with-badge'>
{super.render()}
<ParticipantsCounter />
</div>
);
}
}
/**