diff --git a/react/features/participants-pane/components/web/ParticipantsPane.tsx b/react/features/participants-pane/components/web/ParticipantsPane.tsx index 3aaaea1b8..f1d63069d 100644 --- a/react/features/participants-pane/components/web/ParticipantsPane.tsx +++ b/react/features/participants-pane/components/web/ParticipantsPane.tsx @@ -1,16 +1,15 @@ /* eslint-disable lines-around-comment */ import { Theme } from '@mui/material'; -import { withStyles } from '@mui/styles'; -import React, { Component } from 'react'; -import { WithTranslation } from 'react-i18next'; +import React, { useCallback, useEffect, useState } from 'react'; +import { useTranslation } from 'react-i18next'; +import { useDispatch, useSelector } from 'react-redux'; +import { makeStyles } from 'tss-react/mui'; import { IState } from '../../../app/types'; import participantsPaneTheme from '../../../base/components/themes/participantsPaneTheme.json'; import { openDialog } from '../../../base/dialog/actions'; -import { translate } from '../../../base/i18n/functions'; import { IconClose, IconHorizontalPoints } from '../../../base/icons/svg'; import { isLocalParticipantModerator } from '../../../base/participants/functions'; -import { connect } from '../../../base/redux/functions'; import Button from '../../../base/ui/components/web/Button'; import ClickableIcon from '../../../base/ui/components/web/ClickableIcon'; import { BUTTON_TYPES } from '../../../base/ui/constants'; @@ -32,74 +31,8 @@ import { FooterContextMenu } from './FooterContextMenu'; import LobbyParticipants from './LobbyParticipants'; import MeetingParticipants from './MeetingParticipants'; -/** - * The type of the React {@code Component} props of {@link ParticipantsPane}. - */ -interface Props extends WithTranslation { - /** - * Whether there is backend support for Breakout Rooms. - */ - _isBreakoutRoomsSupported: Boolean; - - /** - * Whether to display the context menu as a drawer. - */ - _overflowDrawer: boolean; - - /** - * Is the participants pane open. - */ - _paneOpen: boolean; - - /** - * Should the add breakout room button be displayed? - */ - _showAddRoomButton: boolean; - - /** - * Whether to show the footer menu. - */ - _showFooter: boolean; - - /** - * Whether to show the more actions button. - */ - _showMoreActionsButton: boolean; - - /** - * Whether to show the mute all button. - */ - _showMuteAllButton: boolean; - - /** - * An object containing the CSS classes. - */ - classes: any; - - /** - * The Redux dispatch function. - */ - dispatch: Function; -} - -/** - * The type of the React {@code Component} state of {@link ParticipantsPane}. - */ -type State = { - - /** - * Indicates if the footer context menu is open. - */ - contextOpen: boolean; - - /** - * Participants search string. - */ - searchString: string; -}; - -const styles = (theme: Theme) => { +const useStyles = makeStyles()((theme: Theme) => { return { container: { boxSizing: 'border-box' as const, @@ -159,217 +92,104 @@ const styles = (theme: Theme) => { position: 'relative' as const } }; +}); + +const ParticipantsPane = () => { + const { classes } = useStyles(); + const paneOpen = useSelector(getParticipantsPaneOpen); + const isBreakoutRoomsSupported = useSelector((state: IState) => state['features/base/conference']) + .conference?.getBreakoutRooms()?.isSupported(); + const showAddRoomButton = useSelector(isAddBreakoutRoomButtonVisible); + const showFooter = useSelector(isLocalParticipantModerator); + const showMuteAllButton = useSelector(isMuteAllVisible); + const showMoreActionsButton = useSelector(isMoreActionsVisible); + const dispatch = useDispatch(); + const { t } = useTranslation(); + + const [ contextOpen, setContextOpen ] = useState(false); + const [ searchString, setSearchString ] = useState(''); + + const onWindowClickListener = useCallback((e: any) => { + if (contextOpen && !findAncestorByClass(e.target, classes.footerMoreContainer)) { + setContextOpen(false); + } + }, [ contextOpen ]); + + useEffect(() => { + window.addEventListener('click', onWindowClickListener); + + return () => { + window.removeEventListener('click', onWindowClickListener); + }; + }, []); + + const onClosePane = useCallback(() => { + dispatch(close()); + }, []); + + const onDrawerClose = useCallback(() => { + setContextOpen(false); + }, []); + + const onMuteAll = useCallback(() => { + dispatch(openDialog(MuteEveryoneDialog)); + }, []); + + const onToggleContext = useCallback(() => { + setContextOpen(open => !open); + }, []); + + if (!paneOpen) { + return null; + } + + return ( +