import React, { MutableRefObject, useCallback, useRef } from 'react'; import { useMedia } from 'react-use'; import { VariableSizeList } from 'react-window'; import { selectSessionStore, selectUnreadHMSMessagesCount } from '@100mslive/hms-video-store'; import { match } from 'ts-pattern'; import { selectHMSMessagesCount, useHMSActions, useHMSStore, useHMSVanillaStore } from '@100mslive/react-sdk'; import { ChevronDownIcon } from '@100mslive/react-icons'; import { Button } from '../../../Button'; import { Box, Flex } from '../../../Layout'; import { config as cssConfig } from '../../../Theme'; // @ts-ignore: No implicit Any import { EmojiReaction } from '../EmojiReaction'; import { MoreSettings } from '../MoreSettings/MoreSettings'; import { RaiseHand } from '../RaiseHand'; import { ChatBody } from './ChatBody'; import { ChatFooter } from './ChatFooter'; import { ChatBlocked, ChatPaused } from './ChatStates'; import { PinnedMessage } from './PinnedMessage'; import { useRoomLayoutConferencingScreen } from '../../provider/roomLayoutProvider/hooks/useRoomLayoutScreen'; import { useSidepaneResetOnLayoutUpdate } from '../AppData/useSidepaneResetOnLayoutUpdate'; import { useIsPeerBlacklisted } from '../hooks/useChatBlacklist'; import { useLandscapeHLSStream, useMobileHLSStream } from '../../common/hooks'; import { SESSION_STORE_KEY, SIDE_PANE_OPTIONS } from '../../common/constants'; export const Chat = () => { const { elements, screenType } = useRoomLayoutConferencingScreen(); const listRef = useRef(null); const hmsActions = useHMSActions(); const vanillaStore = useHMSVanillaStore(); const { enabled: isChatEnabled = true } = useHMSStore(selectSessionStore(SESSION_STORE_KEY.CHAT_STATE)) || {}; const isMobile = useMedia(cssConfig.media.md); const isMobileHLSStream = useMobileHLSStream(); const isLandscapeStream = useLandscapeHLSStream(); useSidepaneResetOnLayoutUpdate('chat', SIDE_PANE_OPTIONS.CHAT); const isLocalPeerBlacklisted = useIsPeerBlacklisted({ local: true }); const scrollToBottom = useCallback( (unreadCount = 0) => { if (listRef.current && listRef.current.scrollToItem && unreadCount > 0) { const messagesCount = vanillaStore.getState(selectHMSMessagesCount); listRef.current?.scrollToItem(messagesCount, 'end'); requestAnimationFrame(() => { listRef.current?.scrollToItem(messagesCount, 'end'); }); hmsActions.setMessageRead(true); } }, [hmsActions, vanillaStore], ); const streaming = isMobileHLSStream || isLandscapeStream; return ( {isMobile && elements?.chat?.is_overlay && !streaming ? null : } {streaming && (!isChatEnabled || isLocalPeerBlacklisted) && ( <> )} {isMobile && elements?.chat?.is_overlay && !streaming ? : null} {isChatEnabled ? ( ) : null} {streaming && ( ({ bottom: '$19', right: '$10' }), ) .with( { isLandscapeStream: true, isChatEnabled: false, }, () => ({ bottom: '$20', right: '$10' }), ) .with( { isMobileHLSStream: true, isChatEnabled: false, }, () => ({ bottom: '$19', right: '$8' }), ) .with( { isMobileHLSStream: true, isChatEnabled: true, isLocalPeerBlacklisted: false, }, () => ({ bottom: '$17', right: '$8' }), ) .with( { isLandscapeStream: false, isChatEnabled: true, isLocalPeerBlacklisted: true, }, () => ({ bottom: '$18', right: '$8' }), ) .with( { isMobileHLSStream: true, isLocalPeerBlacklisted: true, }, () => ({ bottom: '$20', right: '$8' }), ) .otherwise(() => ({})), }} > )} ); }; const NewMessageIndicator = ({ scrollToBottom, listRef, }: { scrollToBottom: (count: number) => void; listRef: MutableRefObject; }) => { const unreadCount = useHMSStore(selectUnreadHMSMessagesCount); if (!unreadCount || !listRef.current) { return null; } // @ts-ignore const outerElement = listRef.current._outerRef; if ( outerElement && outerElement.clientHeight + outerElement.scrollTop + outerElement.offsetTop >= outerElement.scrollHeight ) { return null; } return ( ); };