feat(mobile): Adds visitors count.

This commit is contained in:
damencho 2023-02-14 09:24:38 -06:00 committed by Дамян Минков
parent abe2fa4dd4
commit 3c69645169
8 changed files with 141 additions and 57 deletions

View File

@ -8,12 +8,14 @@ import { JitsiRecordingConstants } from '../../../base/lib-jitsi-meet';
import { RecordingLabel } from '../../../recording';
import { openHighlightDialog } from '../../../recording/actions.native';
import HighlightButton from '../../../recording/components/Recording/native/HighlightButton';
import VisitorsCountLabel from '../../../visitors/components/native/VisitorsCountLabel';
import RaisedHandsCountLabel from './RaisedHandsCountLabel';
import {
LABEL_ID_RAISED_HANDS_COUNT,
LABEL_ID_RECORDING,
LABEL_ID_STREAMING,
LABEL_ID_VISITORS_COUNT,
LabelHitSlop
} from './constants';
@ -51,6 +53,11 @@ const AlwaysOnLabels = ({ createOnPress }: Props) => {
onPress = { createOnPress(LABEL_ID_RAISED_HANDS_COUNT) } >
<RaisedHandsCountLabel />
</TouchableOpacity>
<TouchableOpacity
hitSlop = { LabelHitSlop }
onPress = { createOnPress(LABEL_ID_VISITORS_COUNT) } >
<VisitorsCountLabel />
</TouchableOpacity>
</>);
};

View File

@ -26,6 +26,7 @@ export const LABEL_ID_STREAMING = 'streaming';
export const LABEL_ID_TRANSCRIBING = 'transcribing';
export const LABEL_ID_INSECURE_ROOM_NAME = 'insecure-room-name';
export const LABEL_ID_RAISED_HANDS_COUNT = 'raised-hands-count';
export const LABEL_ID_VISITORS_COUNT = 'visitors-count';
/**
* The {@code ExpandedLabel} components to be rendered for the individual

View File

@ -2,7 +2,7 @@
import React, { PureComponent } from 'react';
import { WithTranslation } from 'react-i18next';
import { FlatList } from 'react-native';
import { FlatList, Text } from 'react-native';
import { IReduxState } from '../../../app/types';
import { translate } from '../../../base/i18n/functions';
@ -68,6 +68,11 @@ type Props = WithTranslation & {
*/
_sortedRemoteParticipants: Map<string, string>;
/**
* The current visitors count if any.
*/
_visitorsCount: number;
/**
* List of breakout rooms that were created.
*/
@ -189,6 +194,7 @@ class MeetingParticipantList extends PureComponent<Props> {
_participantsCount,
_showInviteButton,
_sortedRemoteParticipants,
_visitorsCount,
breakoutRooms,
isLocalModerator,
lobbyParticipants,
@ -217,48 +223,54 @@ class MeetingParticipantList extends PureComponent<Props> {
const finalContainerStyle
= _participantsCount > 6 && containerStyle;
const { color, shareDialogVisible } = _inviteOthersControl;
const _visitorsLabelText = _visitorsCount > 0
? t('participantsPane.headings.visitors', { count: _visitorsCount })
: undefined;
return (
<CollapsibleList
containerStyle = { finalContainerStyle }
title = { title } >
{
_showInviteButton
&& <Button
accessibilityLabel = 'participantsPane.actions.invite'
disabled = { shareDialogVisible }
// eslint-disable-next-line react/jsx-no-bind
icon = { () => (
<Icon
color = { color }
size = { 20 }
src = { IconAddUser } />
) }
labelKey = 'participantsPane.actions.invite'
onClick = { this._onInvite }
style = { styles.inviteButton }
type = { BUTTON_TYPES.PRIMARY } />
<>
{ _visitorsCount > 0 && <Text style = { styles.visitorsLabel }>{ _visitorsLabelText }</Text>
}
<Input
clearable = { true }
// @ts-ignore
customStyles = {{
container: styles.inputContainer,
input: styles.centerInput }}
onChange = { this._onSearchStringChange }
placeholder = { t('participantsPane.search') }
value = { this.props.searchString } />
<FlatList
bounces = { false }
data = { [ _localParticipant?.id, ..._sortedRemoteParticipants ] }
horizontal = { false }
keyExtractor = { this._keyExtractor }
renderItem = { this._renderParticipant }
scrollEnabled = { true }
showsHorizontalScrollIndicator = { false }
windowSize = { 2 } />
</CollapsibleList>
);
<CollapsibleList
containerStyle = { finalContainerStyle }
title = { title } >
{
_showInviteButton
&& <Button
accessibilityLabel = 'participantsPane.actions.invite'
disabled = { shareDialogVisible }
// eslint-disable-next-line react/jsx-no-bind
icon = { () => (
<Icon
color = { color }
size = { 20 }
src = { IconAddUser } />
) }
labelKey = 'participantsPane.actions.invite'
onClick = { this._onInvite }
style = { styles.inviteButton }
type = { BUTTON_TYPES.PRIMARY } />
}
<Input
clearable = { true }
// @ts-ignore
customStyles = {{
container: styles.inputContainer,
input: styles.centerInput }}
onChange = { this._onSearchStringChange }
placeholder = { t('participantsPane.search') }
value = { this.props.searchString } />
<FlatList
bounces = { false }
data = { [ _localParticipant?.id, ..._sortedRemoteParticipants ] }
horizontal = { false }
keyExtractor = { this._keyExtractor }
renderItem = { this._renderParticipant }
scrollEnabled = { true }
showsHorizontalScrollIndicator = { false }
windowSize = { 2 } />
</CollapsibleList>
</>);
}
}
@ -287,7 +299,8 @@ function _mapStateToProps(state: IReduxState): Object {
_showInviteButton,
_sortedRemoteParticipants: remoteParticipants,
_localParticipant: getLocalParticipant(state),
_shareDialogVisible: shareDialogVisible
_shareDialogVisible: shareDialogVisible,
_visitorsCount: state['features/visitors'].count || 0
};
}

View File

@ -288,5 +288,11 @@ export default {
centerInput: {
paddingRight: BaseTheme.spacing[3],
textAlign: 'center'
},
visitorsLabel: {
...BaseTheme.typography.heading6,
color: BaseTheme.palette.warning02,
marginLeft: BaseTheme.spacing[3]
}
};

View File

@ -48,6 +48,11 @@ type Props = {
*/
_visible: boolean,
/**
* Whether we are in visitors mode.
*/
_visitorsModeEnabled: boolean,
/**
* The width of the screen.
*/
@ -61,7 +66,7 @@ type Props = {
* @returns {React$Element}.
*/
function Toolbox(props: Props) {
const { _endConferenceSupported, _reactionsEnabled, _styles, _visible, _width } = props;
const { _endConferenceSupported, _reactionsEnabled, _styles, _visible, _visitorsModeEnabled, _width } = props;
if (!_visible) {
return null;
@ -87,20 +92,22 @@ function Toolbox(props: Props) {
edges = { [ bottomEdge && 'bottom' ].filter(Boolean) }
pointerEvents = 'box-none'
style = { styles.toolbox }>
<AudioMuteButton
{!_visitorsModeEnabled && <AudioMuteButton
styles = { buttonStylesBorderless }
toggledStyles = { toggledButtonStyles } />
<VideoMuteButton
}
{!_visitorsModeEnabled && <VideoMuteButton
styles = { buttonStylesBorderless }
toggledStyles = { toggledButtonStyles } />
{
additionalButtons.has('chat')
}
{!_visitorsModeEnabled && additionalButtons.has('chat')
&& <ChatButton
styles = { buttonStylesBorderless }
toggledStyles = { backgroundToggledStyle } />
}
{additionalButtons.has('screensharing') && <ScreenSharingButton styles = { buttonStylesBorderless } />}
{ additionalButtons.has('raisehand') && (_reactionsEnabled
{!_visitorsModeEnabled && additionalButtons.has('screensharing')
&& <ScreenSharingButton styles = { buttonStylesBorderless } />}
{ !_visitorsModeEnabled && additionalButtons.has('raisehand') && (_reactionsEnabled
? <ReactionsMenuButton
styles = { buttonStylesBorderless }
toggledStyles = { backgroundToggledStyle } />
@ -108,9 +115,10 @@ function Toolbox(props: Props) {
styles = { buttonStylesBorderless }
toggledStyles = { backgroundToggledStyle } />)}
{additionalButtons.has('tileview') && <TileViewButton styles = { buttonStylesBorderless } />}
<OverflowMenuButton
{!_visitorsModeEnabled && <OverflowMenuButton
styles = { buttonStylesBorderless }
toggledStyles = { toggledButtonStyles } />
}
{ _endConferenceSupported
? <HangupMenuButton
styles = { hangupMenuButtonStyles }
@ -140,6 +148,7 @@ function _mapStateToProps(state: Object): Object {
_endConferenceSupported: Boolean(endConferenceSupported),
_styles: ColorSchemeRegistry.get(state, 'Toolbox'),
_visible: isToolboxVisible(state),
_visitorsModeEnabled: state['features/visitors'].enabled,
_width: state['features/base/responsive-ui'].clientWidth,
_reactionsEnabled: isReactionsEnabled(state)
};

View File

@ -0,0 +1,43 @@
import React from 'react';
import { useSelector } from 'react-redux';
import { IReduxState } from '../../../app/types';
import { IconUsers } from '../../../base/icons/svg';
// eslint-disable-next-line lines-around-comment
// @ts-ignore
import Label from '../../../base/label/components/native/Label';
import BaseTheme from '../../../base/ui/components/BaseTheme.native';
import { getVisitorsShortText } from '../../functions';
const styles = {
raisedHandsCountLabel: {
alignItems: 'center',
backgroundColor: BaseTheme.palette.warning02,
borderRadius: BaseTheme.shape.borderRadius,
flexDirection: 'row',
marginLeft: BaseTheme.spacing[0],
marginBottom: BaseTheme.spacing[0]
},
raisedHandsCountLabelText: {
color: BaseTheme.palette.uiBackground,
paddingLeft: BaseTheme.spacing[2]
}
};
const VisitorsCountLabel = () => {
const visitorsMode = useSelector((state: IReduxState) => state['features/visitors'].enabled);
const visitorsCount = useSelector((state: IReduxState) =>
state['features/visitors'].count || 0);
return visitorsMode && (
<Label
icon = { IconUsers }
iconColor = { BaseTheme.palette.uiBackground }
style = { styles.raisedHandsCountLabel }
text = { `${getVisitorsShortText(visitorsCount)}` }
textStyle = { styles.raisedHandsCountLabelText } />
);
};
export default VisitorsCountLabel;

View File

@ -9,6 +9,7 @@ import Label from '../../../base/label/components/web/Label';
// eslint-disable-next-line lines-around-comment
// @ts-ignore
import { Tooltip } from '../../../base/tooltip';
import { getVisitorsShortText } from '../../functions';
const useStyles = makeStyles()(theme => {
return {
@ -26,13 +27,6 @@ const VisitorsCountLabel = () => {
state['features/visitors'].count || 0);
const { t } = useTranslation();
let visitorsCountLabel = String(visitorsCount);
// over 100 we show numbers lik 0.2 K or 9.5 K.
if (visitorsCount > 100) {
visitorsCountLabel = `${Math.round(visitorsCount / 100) / 10} K`;
}
return visitorsMode && (<Tooltip
content = { t('visitorsLabel', { count: visitorsCount }) }
position = { 'bottom' }>
@ -41,7 +35,7 @@ const VisitorsCountLabel = () => {
icon = { IconUsers }
iconColor = { theme.palette.icon04 }
id = 'visitorsCountLabel'
text = { `${visitorsCountLabel}` } />
text = { `${getVisitorsShortText(visitorsCount)}` } />
</Tooltip>);
};

View File

@ -0,0 +1,11 @@
/**
* A short string to represent the number of visitors.
* Over 100 we show numbers like 0.2 K or 9.5 K.
*
* @param {number} visitorsCount - The number of visitors to shorten.
*
* @returns {string} Short string representing the number of visitors.
*/
export function getVisitorsShortText(visitorsCount: number) {
return visitorsCount > 100 ? `${Math.round(visitorsCount / 100) / 10} K` : String(visitorsCount);
}