import React, { useCallback, useMemo, useState } from 'react';
import { useMeasure } from 'react-use';
import {
selectAudioTrackByPeerID,
selectHasPeerHandRaised,
selectIsPeerAudioEnabled,
selectLocalPeerID,
selectPeerMetadata,
selectPeerNameByID,
selectVideoTrackByID,
selectVideoTrackByPeerID,
useHMSStore,
} from '@100mslive/react-sdk';
import { BrbTileIcon, HandIcon, MicOffIcon } from '@100mslive/react-icons';
import TileConnection from './Connection/TileConnection';
import TileMenu, { isSameTile } from './TileMenu/TileMenu';
import { AudioLevel } from '../../AudioLevel';
import { Avatar } from '../../Avatar';
import { VideoTileStats } from '../../Stats';
import { CSS } from '../../Theme';
import { Video } from '../../Video';
import { StyledVideoTile } from '../../VideoTile';
import { getVideoTileLabel } from './peerTileUtils';
// @ts-ignore: No implicit Any
import { useSetAppDataByKey, useUISettings } from './AppData/useUISettings';
// @ts-ignore: No implicit Any
import { calculateAvatarAndAttribBoxSize } from '../common/utils';
import { APP_DATA, UI_SETTINGS } from '../common/constants';
const PeerMetadata = ({ peerId, size }: { peerId: string; size?: 'medium' | 'small' }) => {
const metaData = useHMSStore(selectPeerMetadata(peerId));
const isBRB = metaData?.isBRBOn || false;
const isHandRaised = useHMSStore(selectHasPeerHandRaised(peerId));
return (
<>
{isHandRaised ? (
) : null}
{isBRB ? (
) : null}
>
);
};
const Tile = ({
peerId = '',
trackId = '',
width,
height,
objectFit = 'cover',
canMinimise = false,
isDragabble = false,
rootCSS = {},
containerCSS = {},
enableSpotlightingPeer = true,
hideParticipantNameOnTile = false,
roundedVideoTile = true,
hideAudioMuteOnTile = false,
hideMetadataOnTile = false,
}: {
peerId?: string;
trackId?: string;
width?: string | number;
height?: string | number;
objectFit?: string;
canMinimise?: boolean;
isDragabble?: boolean;
rootCSS?: CSS;
containerCSS?: CSS;
enableSpotlightingPeer?: boolean;
hideParticipantNameOnTile?: boolean;
roundedVideoTile?: boolean;
hideAudioMuteOnTile?: boolean;
hideMetadataOnTile?: boolean;
}) => {
const trackSelector = trackId ? selectVideoTrackByID(trackId) : selectVideoTrackByPeerID(peerId);
const track = useHMSStore(trackSelector);
const peerName = useHMSStore(selectPeerNameByID(peerId));
const audioTrack = useHMSStore(selectAudioTrackByPeerID(peerId));
const localPeerID = useHMSStore(selectLocalPeerID);
const isAudioOnly = useUISettings(UI_SETTINGS.isAudioOnly);
const mirrorLocalVideo = useUISettings(UI_SETTINGS.mirrorLocalVideo);
const showStatsOnTiles = useUISettings(UI_SETTINGS.showStatsOnTiles);
const isAudioMuted = !useHMSStore(selectIsPeerAudioEnabled(peerId));
const isVideoMuted = !track?.enabled;
const [isMouseHovered, setIsMouseHovered] = useState(false);
const isVideoDegraded = track?.degraded;
const isLocal = localPeerID === peerId;
const [pinnedTrackId] = useSetAppDataByKey(APP_DATA.pinnedTrackId);
const pinned = isSameTile({
trackId: pinnedTrackId,
videoTrackID: track?.id,
audioTrackID: audioTrack?.id,
});
const label = getVideoTileLabel({
peerName,
isLocal,
videoTrack: track,
audioTrack,
});
const onHoverHandler = useCallback((event: React.MouseEvent) => {
setIsMouseHovered(event.type === 'mouseenter');
}, []);
const [ref, { width: calculatedWidth, height: calculatedHeight }] = useMeasure();
const isTileBigEnoughToShowStats = calculatedHeight >= 180 && calculatedWidth >= 180;
const [avatarSize, attribBoxSize] = useMemo(
() => calculateAvatarAndAttribBoxSize(calculatedWidth, calculatedHeight),
[calculatedWidth, calculatedHeight],
);
return (
{peerName !== undefined ? (
{showStatsOnTiles && isTileBigEnoughToShowStats ? (
) : null}
{calculatedWidth > 0 && calculatedHeight > 0 ? (
<>
{isVideoMuted || (!isLocal && isAudioOnly) ? (
) : null}
{!hideAudioMuteOnTile && isAudioMuted ? (
) : null}
{!hideAudioMuteOnTile && !isAudioMuted ? (
) : null}
{!hideMetadataOnTile && }
>
) : null}
{isMouseHovered || (isDragabble && navigator.maxTouchPoints > 0) ? (
) : null}
) : null}
);
};
const VideoTile = React.memo(Tile);
export default VideoTile;