import React, { useEffect, useState } from 'react'; import { useInView } from 'react-intersection-observer'; import { useMeasure } from 'react-use'; import { VariableSizeList } from 'react-window'; import { selectIsConnectedToRoom, useHMSStore, usePaginatedParticipants } from '@100mslive/react-sdk'; import { ChevronLeftIcon, CrossIcon } from '@100mslive/react-icons'; import { IconButton } from '../../../IconButton'; import { Box, Flex } from '../../../Layout'; import { Loading } from '../../../Loading'; import { Text } from '../../../Text'; import { Participant, ParticipantSearch } from './ParticipantList'; import { ItemData, itemKey, ROW_HEIGHT } from './RoleAccordion'; // @ts-ignore: No implicit Any import { useSidepaneReset } from '../AppData/useSidepane'; // @ts-ignore: No implicit Any import { getFormattedCount } from '../../common/utils'; const LoadMoreParticipants = ({ hasNext, loadMore, style, }: { hasNext: boolean; loadMore: () => Promise; style: React.CSSProperties; }) => { const { ref, inView } = useInView(); const [inProgress, setInProgress] = useState(false); useEffect(() => { if (hasNext && inView && !inProgress) { setInProgress(true); loadMore() .catch(console.error) .finally(() => setInProgress(false)); } }, [hasNext, loadMore, inView, inProgress]); return ( {inProgress ? : null} ); }; const VirtualizedParticipantItem = React.memo( ({ index, data, style, }: { index: number; data: ItemData & { hasNext: boolean; loadMorePeers: () => Promise }; style: React.CSSProperties; }) => { if (!data.peerList[index]) { return ; } return ( ); }, ); export const PaginatedParticipants = ({ roleName, onBack }: { roleName: string; onBack: () => void }) => { const { peers, total, hasNext, loadPeers, loadMorePeers } = usePaginatedParticipants({ role: roleName, limit: 20 }); const [search, setSearch] = useState(''); const filteredPeers = peers.filter(p => p.name?.toLowerCase().includes(search?.toLowerCase())); const isConnected = useHMSStore(selectIsConnectedToRoom); const [ref, { width }] = useMeasure(); const height = ROW_HEIGHT * (filteredPeers.length + 1); const resetSidePane = useSidepaneReset(); useEffect(() => { loadPeers(); // eslint-disable-next-line react-hooks/exhaustive-deps }, []); return ( Participants { e.stopPropagation(); resetSidePane(); }} data-testid="close_sidepane" > setSearch(search)} placeholder={`Search for ${roleName}`} /> {roleName}({getFormattedCount(peers.length)}/{getFormattedCount(total)}) (index === filteredPeers.length + 1 ? 16 : ROW_HEIGHT)} itemData={{ peerList: filteredPeers, hasNext: hasNext(), loadMorePeers, isConnected: isConnected === true }} itemKey={itemKey} itemCount={filteredPeers.length + 1} width={width} height={height} > {VirtualizedParticipantItem} ); };