import { VideoTileState } from 'amazon-chime-sdk-js' ; import classNames from 'classnames/bind' ; import React , { useCallback , useContext , useEffect , useState } from 'react' ; import { FormattedMessage } from 'react-intl' ; import ChimeSdkWrapper from '../chime/ChimeSdkWrapper' ; import getChimeContext from '../context/getChimeContext' ; import ViewMode from '../enums/ViewMode' ; import Size from '../enums/Size' ; import useRaisedHandAttendees from '../hooks/useRaisedHandAttendees' ; import RemoteVideo from './RemoteVideo' ; import styles from './RemoteVideoGroup.css' ; import useRoster from '../hooks/useRoster' ; const cx = classNames . bind ( styles ) ; const MAX_REMOTE_VIDEOS = 16 ; type Props = { viewMode : ViewMode ; isContentShareEnabled : boolean ; } ; export default function RemoteVideoGroup ( props ) { const { viewMode , isContentShareEnabled } = props ; const chime = useContext ( getChimeContext ( ) ) ; const [ visibleIndices , setVisibleIndices ] = useState < { [ index ] : { boundAttendeeId : string ; } ; } > ( { } ) ; const raisedHandAttendees = useRaisedHandAttendees ( ) ; const roster = useRoster ( ) ; const videoElements = [ ] ; const tiles = { } ; const acquireVideoIndex = ( tileId ) : number => { for ( let index = 0 ; index < MAX_REMOTE_VIDEOS ; index += 1 ) { if ( tiles [ index ] === tileId ) { return index ; } } for ( let index = 0 ; index < MAX_REMOTE_VIDEOS ; index += 1 ) { if ( ! ( index in tiles ) ) { tiles [ index ] = tileId ; return index ; } } throw new Error ( 'no tiles are available' ) ; } ; const releaseVideoIndex = ( tileId ) : number => { for ( let index = 0 ; index < MAX_REMOTE_VIDEOS ; index += 1 ) { if ( tiles [ index ] === tileId ) { delete tiles [ index ] ; return index ; } } return - 1 ; } ; const numberOfVisibleIndices = Object . keys ( visibleIndices ) . reduce < number > ( ( result , key ) => result + ( visibleIndices [ key ] ? 1 : 0 ) , 0 ) ; useEffect ( ( ) => { chime ?. audioVideo ?. addObserver ( { videoTileDidUpdate : ( tileState ) : void => { if ( ! tileState . boundAttendeeId || tileState . localTile || tileState . isContent || ! tileState . tileId ) { return ; } const index = acquireVideoIndex ( tileState . tileId ) ; chime ?. audioVideo ?. bindVideoElement ( tileState . tileId , videoElements [ index ] ) ; setVisibleIndices ( previousVisibleIndices => ( { ... previousVisibleIndices , [ index ] : { boundAttendeeId : tileState . boundAttendeeId } } ) ) ; } , videoTileWasRemoved : ( tileId ) : void => { const index = releaseVideoIndex ( tileId ) ; setVisibleIndices ( previousVisibleIndices => ( { ... previousVisibleIndices , [ index ] : null } ) ) ; } } ) ; } , [ ] ) ; const getSize = ( ) : Size => { if ( numberOfVisibleIndices >= 10 ) { return Size . Small ; } if ( numberOfVisibleIndices >= 5 ) { return Size . Medium ; } return Size . Large ; } ; return ( < div className = { cx ( 'remoteVideoGroup' , `remoteVideoGroup-${ numberOfVisibleIndices } `, {
            roomMode: viewMode === ViewMode.Room,
            screenShareMode: viewMode === ViewMode.ScreenShare,
            isContentShareEnabled
        })}>
      {numberOfVisibleIndices === 0 && (<div className={cx('instruction')}>
          <FormattedMessage id="RemoteVideoGroup.noVideo"/>
        </div>)}
      {Array.from(Array(MAX_REMOTE_VIDEOS).keys()).map((key, index) => {
            const visibleIndex = visibleIndices[index];
            const attendeeId = visibleIndex ? visibleIndex.boundAttendeeId : null;
            const raisedHand = raisedHandAttendees
                ? raisedHandAttendees.has(attendeeId)
                : false;
            const activeSpeaker = visibleIndex
                ? roster[visibleIndex.boundAttendeeId]?.active
                : false;
            return (<RemoteVideo key={key} viewMode={viewMode} enabled={!!visibleIndex} videoElementRef={useCallback((element) => {
                    if (element) {
                        videoElements[index] = element;
                    }
                }, [])} size={getSize()} attendeeId={attendeeId} raisedHand={raisedHand} activeSpeaker={activeSpeaker} isContentShareEnabled={isContentShareEnabled}/>);
        })}
    </div>);
}
