import React, { useEffect, useMemo, useState } from 'react'; import { GridVideoTileLayout } from '@100mslive/types-prebuilt/elements/video_tile_layout'; import { selectLocalPeerID, selectLocalPeerRoleName, selectPeers, selectPeerScreenSharing, selectWhiteboard, useHMSStore, useHMSVanillaStore, } from '@100mslive/react-sdk'; import { EqualProminence } from './EqualProminence'; import { RoleProminence } from './RoleProminence'; import { ScreenshareLayout } from './ScreenshareLayout'; import { WhiteboardLayout } from './WhiteboardLayout'; // @ts-ignore: No implicit Any import { usePinnedTrack, useSetAppDataByKey } from '../AppData/useUISettings'; import { VideoTileContext } from '../hooks/useVideoTileLayout'; import PeersSorter from '../../common/PeersSorter'; import { APP_DATA } from '../../common/constants'; export type TileCustomisationProps = { hide_participant_name_on_tile: boolean; rounded_video_tile: boolean; hide_audio_mute_on_tile: boolean; video_object_fit: 'contain' | 'cover'; edge_to_edge: boolean; hide_metadata_on_tile: boolean; }; export type GridLayoutProps = GridVideoTileLayout & TileCustomisationProps; export const GridLayout = ({ enable_local_tile_inset: isInsetEnabled = false, prominent_roles: prominentRoles = [], enable_spotlighting_peer = false, hide_participant_name_on_tile = false, rounded_video_tile = true, hide_audio_mute_on_tile = false, video_object_fit = 'contain', edge_to_edge = false, hide_metadata_on_tile = false, }: GridLayoutProps) => { const peerSharing = useHMSStore(selectPeerScreenSharing); const whiteboard = useHMSStore(selectWhiteboard); const pinnedTrack = usePinnedTrack(); const peers = useHMSStore(selectPeers); const localPeerRole = useHMSStore(selectLocalPeerRoleName); const localPeerID = useHMSStore(selectLocalPeerID); const [activeScreensharePeerId] = useSetAppDataByKey(APP_DATA.activeScreensharePeerId); const isRoleProminence = (prominentRoles.length && peers.some( peer => peer.roleName && prominentRoles.includes(peer.roleName) && (peer.videoTrack || peer.audioTrack), )) || pinnedTrack; const updatedPeers = useMemo(() => { // remove screenshare/whiteboard peer from active speaker sorting if (activeScreensharePeerId || whiteboard?.open) { return peers.filter(peer => peer.id !== activeScreensharePeerId || peer.customerUserId !== whiteboard?.owner); } if (isInsetEnabled) { const isLocalPeerPinned = localPeerID === pinnedTrack?.peerId; // if localPeer role is prominent role, it shows up in the center or local peer is pinned, so allow it in active speaker sorting if ((localPeerRole && prominentRoles.includes(localPeerRole)) || isLocalPeerPinned) { return peers; } else { return peers.filter(peer => !peer.isLocal); } } return peers; }, [ isInsetEnabled, whiteboard, activeScreensharePeerId, localPeerRole, localPeerID, prominentRoles, peers, pinnedTrack, ]); const vanillaStore = useHMSVanillaStore(); const [sortedPeers, setSortedPeers] = useState(updatedPeers); const peersSorter = useMemo(() => new PeersSorter(vanillaStore), [vanillaStore]); const [pageSize, setPageSize] = useState(0); const [mainPage, setMainPage] = useState(0); const tileLayout = { enableSpotlightingPeer: enable_spotlighting_peer, hideParticipantNameOnTile: hide_participant_name_on_tile, roundedVideoTile: rounded_video_tile, hideAudioMuteOnTile: hide_audio_mute_on_tile, hideMetadataOnTile: hide_metadata_on_tile, objectFit: video_object_fit, }; useEffect(() => { if (mainPage !== 0) { return; } peersSorter.setPeersAndTilesPerPage({ peers: updatedPeers, tilesPerPage: pageSize, }); peersSorter.onUpdate(setSortedPeers); }, [mainPage, peersSorter, updatedPeers, pageSize]); if (peerSharing) { return ( ); } else if (whiteboard?.open) { return ( ); } else if (isRoleProminence) { return ( ); } return ( ); };