UNPKG

communication-react-19

Version:

React library for building modern communication user experiences utilizing Azure Communication Services (React 19 compatible fork)

99 lines 5.94 kB
// Copyright (c) Microsoft Corporation. // Licensed under the MIT License. import React, { useMemo, useRef, useState } from 'react'; import { isNarrowWidth } from '../utils/responsive'; import { isShortHeight } from '../utils/responsive'; import { OverflowGallery } from './OverflowGallery'; import { GridLayout } from '../GridLayout'; import { Stack } from '@fluentui/react'; import { renderTiles, useOrganizedParticipants } from './utils/videoGalleryLayoutUtils'; import { rootLayoutStyle } from './styles/DefaultLayout.styles'; import { videoGalleryLayoutGap } from './styles/Layout.styles'; import { VERTICAL_GALLERY_TILE_SIZE_REM } from './styles/VideoGalleryResponsiveVerticalGallery.styles'; const DEFAULT_CHILDREN_PER_PAGE = 5; const REM_TO_PIXEL = 16; const LARGE_GALLERY_PARTICIPANT_CAP = 48; /** * VideoGallery Layout for when user is in a large meeting and wants to see more participants * * Caps the number of tiles that a participant can see in the grid to 49, Video and Audio. * * @private */ export const LargeGalleryLayout = (props) => { const { remoteParticipants = [], localParticipant, dominantSpeakers, localVideoComponent, screenShareComponent, onRenderRemoteParticipant, styles, maxRemoteVideoStreams, parentWidth, parentHeight, pinnedParticipantUserIds = [], overflowGalleryPosition = 'horizontalBottom', spotlightedParticipantUserIds = [] } = props; const isNarrow = parentWidth ? isNarrowWidth(parentWidth) : false; const isShort = parentHeight ? isShortHeight(parentHeight) : false; const maxStreamsTrampoline = () => { return parentWidth && parentHeight ? calculateMaxTilesInLargeGrid(parentWidth, parentHeight) : maxRemoteVideoStreams; }; // This is for tracking the number of children in the first page of overflow gallery. // This number will be used for the maxOverflowGalleryDominantSpeakers when organizing the remote participants. // We need to add the local participant to the pinned participant count so we are placing the speakers correctly. const childrenPerPage = useRef(DEFAULT_CHILDREN_PER_PAGE); const { gridParticipants, overflowGalleryParticipants } = useOrganizedParticipants({ remoteParticipants, localParticipant, dominantSpeakers, maxGridParticipants: maxStreamsTrampoline(), isScreenShareActive: !!screenShareComponent, maxOverflowGalleryDominantSpeakers: screenShareComponent ? childrenPerPage.current - ((pinnedParticipantUserIds.length + 1) % childrenPerPage.current) : childrenPerPage.current, pinnedParticipantUserIds, /* @conditional-compile-remove(large-gallery) */ layout: 'largeGallery', spotlightedParticipantUserIds }); /** * instantiate indexes available to render with indexes available that would be on first page * * For some components which do not strictly follow the order of the array, we might * re-render the initial tiles -> dispose them -> create new tiles, we need to take care of * this case when those components are here */ const [indexesToRender, setIndexesToRender] = useState([]); let { gridTiles, overflowGalleryTiles } = renderTiles(gridParticipants, onRenderRemoteParticipant, maxRemoteVideoStreams, indexesToRender, overflowGalleryParticipants, dominantSpeakers); if (localVideoComponent) { if (screenShareComponent || spotlightedParticipantUserIds.length > 0) { overflowGalleryTiles = [localVideoComponent].concat(overflowGalleryTiles); } else { gridTiles = [localVideoComponent].concat(gridTiles); } } const overflowGallery = useMemo(() => { if (overflowGalleryTiles.length === 0) { return null; } return (React.createElement(OverflowGallery, { isNarrow: isNarrow, isShort: isShort, shouldFloatLocalVideo: false, overflowGalleryElements: overflowGalleryTiles, horizontalGalleryStyles: styles === null || styles === void 0 ? void 0 : styles.horizontalGallery, verticalGalleryStyles: styles === null || styles === void 0 ? void 0 : styles.verticalGallery, overflowGalleryPosition: overflowGalleryPosition, onFetchTilesToRender: setIndexesToRender, onChildrenPerPageChange: (n) => { childrenPerPage.current = n; }, parentWidth: parentWidth })); }, [ isNarrow, isShort, overflowGalleryTiles, styles === null || styles === void 0 ? void 0 : styles.horizontalGallery, overflowGalleryPosition, setIndexesToRender, styles === null || styles === void 0 ? void 0 : styles.verticalGallery, parentWidth ]); return (React.createElement(Stack, { horizontal: overflowGalleryPosition === 'verticalRight', styles: rootLayoutStyle, tokens: videoGalleryLayoutGap }, props.overflowGalleryPosition === 'horizontalTop' ? overflowGallery : React.createElement(React.Fragment, null), screenShareComponent ? (screenShareComponent) : (React.createElement(GridLayout, { key: "grid-layout", styles: styles === null || styles === void 0 ? void 0 : styles.gridLayout }, gridTiles)), overflowGalleryTrampoline(overflowGallery, props.overflowGalleryPosition))); }; const overflowGalleryTrampoline = (gallery, galleryPosition) => { return galleryPosition !== 'horizontalTop' ? gallery : React.createElement(React.Fragment, null); return gallery; }; const calculateMaxTilesInLargeGrid = (parentWidth, parentHeight) => { const xAxisTiles = Math.floor(parentWidth / (VERTICAL_GALLERY_TILE_SIZE_REM.width * REM_TO_PIXEL)); const yAxisTiles = Math.floor(parentHeight / (VERTICAL_GALLERY_TILE_SIZE_REM.minHeight * REM_TO_PIXEL)); return xAxisTiles * yAxisTiles < LARGE_GALLERY_PARTICIPANT_CAP ? xAxisTiles * yAxisTiles : LARGE_GALLERY_PARTICIPANT_CAP; }; //# sourceMappingURL=LargeGalleryLayout.js.map