import React, { useEffect } from 'react'; import { useMeasure } from 'react-use'; import { FixedSizeList } from 'react-window'; import { HMSPeer, selectIsLargeRoom, useHMSStore, usePaginatedParticipants } from '@100mslive/react-sdk'; import { AddIcon, ChevronRightIcon, CrossIcon } from '@100mslive/react-icons'; import { Accordion } from '../../../Accordion'; import { Button } from '../../../Button'; import { HorizontalDivider } from '../../../Divider'; import { Flex } from '../../../Layout'; import { Text } from '../../../Text'; import { Participant } from './ParticipantList'; import { RoleOptions } from './RoleOptions'; import { useGroupOnStageActions } from '../hooks/useGroupOnStageActions'; // @ts-ignore: No implicit Any import { getFormattedCount } from '../../common/utils'; export const ROW_HEIGHT = 50; const ITER_TIMER = 5000; export interface ItemData { peerList: HMSPeer[]; isHandRaisedAccordion?: boolean; isConnected: boolean; } export function itemKey(index: number, data: ItemData) { return data.peerList[index]?.id; } export const VirtualizedParticipantItem = React.memo( ({ index, data, style }: { index: number; data: ItemData; style: React.CSSProperties }) => { return ( ); }, ); export const RoleAccordion = ({ peerList = [], roleName, isConnected, filter, isHandRaisedAccordion = false, offStageRoles, onActive, }: ItemData & { roleName: string; isHandRaisedAccordion?: boolean; filter?: { search?: string }; offStageRoles: string[]; onActive?: (role: string) => void; }) => { const [ref, { width }] = useMeasure(); const isLargeRoom = useHMSStore(selectIsLargeRoom); const { peers, total, loadPeers } = usePaginatedParticipants({ role: roleName, limit: 10 }); const isOffStageRole = roleName && offStageRoles.includes(roleName); let peersInAccordion = peerList; // for large rooms, peer list would be empty if (isOffStageRole && isLargeRoom) { peersInAccordion = peers; if (filter?.search) { peersInAccordion = peersInAccordion.filter(peer => peer.name.toLowerCase().includes(filter.search || '')); } } const { bringAllToStage, bring_to_stage_label, canBringToStage, lowerAllHands } = useGroupOnStageActions({ peers: peersInAccordion, }); useEffect(() => { if (!isOffStageRole || !isLargeRoom) { return; } loadPeers(); const interval = setInterval(() => { loadPeers(); }, ITER_TIMER); return () => clearInterval(interval); }, [isOffStageRole, isLargeRoom]); //eslint-disable-line if (peersInAccordion.length === 0 || (isHandRaisedAccordion && filter?.search)) { return null; } const height = ROW_HEIGHT * peersInAccordion.length; const hasNext = total > peersInAccordion.length && !filter?.search; return ( {roleName} {`(${getFormattedCount(isLargeRoom && isOffStageRole ? total : peerList.length)})`} { try { const aHandRaisedAt = JSON.parse(a.metadata || '{}').handRaisedAt; const bHandRaisedAt = JSON.parse(b.metadata || '{}').handRaisedAt; return aHandRaisedAt - bHandRaisedAt; } catch (err) { return 0; } }) : peersInAccordion, isConnected, isHandRaisedAccordion, }} itemKey={itemKey} itemCount={peersInAccordion.length} width={width} height={height} > {VirtualizedParticipantItem} {offStageRoles?.includes(roleName) && hasNext ? ( onActive?.(roleName)} > View All ) : null} {isHandRaisedAccordion && canBringToStage && ( <> )} ); };