UNPKG

@azure/communication-react

Version:

React library for building modern communication user experiences utilizing Azure Communication Services

117 lines 8.58 kB
// Copyright (c) Microsoft Corporation. // Licensed under the MIT License. import React, { useCallback, useMemo, useRef } from 'react'; import { VideoGallery, Announcer } from "../../../../../react-components/src"; import { _useContainerWidth, _useContainerHeight } from "../../../../../react-components/src"; import { usePropsFor } from '../hooks/usePropsFor'; import { AvatarPersona } from '../../common/AvatarPersona'; import { mergeStyles, Stack } from '@fluentui/react'; import { useHandlers } from '../hooks/useHandlers'; import { useSelector } from '../hooks/useSelector'; import { localVideoCameraCycleButtonSelector } from '../selectors/LocalVideoTileSelector'; import { LocalVideoCameraCycleButton } from "../../../../../react-components/src"; import { useParticipantChangedAnnouncement } from '../utils/MediaGalleryUtils'; import { useLocalSpotlightCallbacksWithPrompt, useRemoteSpotlightCallbacksWithPrompt } from '../utils/spotlightUtils'; import { getCapabilites, getIsRoomsCall, getReactionResources, getRole } from '../selectors/baseSelectors'; const VideoGalleryStyles = { root: { height: '100%', minHeight: '10rem', // space affordance to ensure media gallery is never collapsed minWidth: '6rem' } }; const localVideoViewOptions = { scalingMode: 'Crop', isMirrored: true }; const remoteVideoViewOptions = { scalingMode: 'Crop' }; /** * @private */ export const MediaGallery = (props) => { var _a, _b; const { pinnedParticipants = [], setPinnedParticipants, setIsPromptOpen, setPromptProps, hideSpotlightButtons, videoTilesOptions, captionsOptions, compositeContainerAspectRatio } = props; const videoGalleryProps = usePropsFor(VideoGallery); const cameraSwitcherCameras = useSelector(localVideoCameraCycleButtonSelector); const cameraSwitcherCallback = useHandlers(LocalVideoCameraCycleButton); const announcerString = useParticipantChangedAnnouncement(); const userRole = useSelector(getRole); const capabilities = useSelector(getCapabilites); const isRoomsCall = useSelector(getIsRoomsCall); const reactionResources = useSelector(getReactionResources); const containerRef = useRef(null); const containerWidth = _useContainerWidth(containerRef); const containerHeight = _useContainerHeight(containerRef); const layoutBasedOnTilePosition = getVideoGalleryLayoutBasedOnLocalOptions((_a = props.localVideoTileOptions) === null || _a === void 0 ? void 0 : _a.position); const cameraSwitcherProps = useMemo(() => { return Object.assign(Object.assign({}, cameraSwitcherCallback), cameraSwitcherCameras); }, [cameraSwitcherCallback, cameraSwitcherCameras]); const onRenderAvatar = useCallback((userId, options) => { return React.createElement(Stack, { className: mergeStyles({ position: 'absolute', height: '100%', width: '100%' }) }, React.createElement(Stack, { styles: { root: { margin: 'auto', maxHeight: '100%' } } }, (options === null || options === void 0 ? void 0 : options.coinSize) && React.createElement(AvatarPersona, Object.assign({ userId: userId }, options, { dataProvider: props.onFetchAvatarPersonaData })))); }, [props.onFetchAvatarPersonaData]); const remoteVideoTileMenuOptions = useMemo(() => { var _a; return ((_a = props.remoteVideoTileMenuOptions) === null || _a === void 0 ? void 0 : _a.isHidden) ? false : props.isMobile ? { kind: 'drawer', hostId: props.drawerMenuHostId } : { kind: 'contextual' }; }, [(_b = props.remoteVideoTileMenuOptions) === null || _b === void 0 ? void 0 : _b.isHidden, props.isMobile, props.drawerMenuHostId]); const overflowGalleryPosition = useMemo(() => { return containerWidth && containerHeight && containerWidth / containerHeight >= 16 / 9 ? 'verticalRight' : 'horizontalBottom'; }, [containerWidth, containerHeight]); const { onStartLocalSpotlight, onStopLocalSpotlight, onStartRemoteSpotlight, onStopRemoteSpotlight } = videoGalleryProps; const { onStartLocalSpotlightWithPrompt, onStopLocalSpotlightWithPrompt } = useLocalSpotlightCallbacksWithPrompt(onStartLocalSpotlight, onStopLocalSpotlight, setIsPromptOpen, setPromptProps); const { onStartRemoteSpotlightWithPrompt, onStopRemoteSpotlightWithPrompt } = useRemoteSpotlightCallbacksWithPrompt(onStartRemoteSpotlight, onStopRemoteSpotlight, setIsPromptOpen, setPromptProps); const galleryStyles = useMemo(() => { return Object.assign(Object.assign({}, VideoGalleryStyles), ((captionsOptions === null || captionsOptions === void 0 ? void 0 : captionsOptions.height) === 'full' ? { root: { postion: 'absolute' } } : {})); }, [captionsOptions === null || captionsOptions === void 0 ? void 0 : captionsOptions.height]); const onPinParticipant = useMemo(() => { return setPinnedParticipants ? (userId) => { if (!pinnedParticipants.includes(userId)) { setPinnedParticipants(pinnedParticipants.concat(userId)); } } : undefined; }, [setPinnedParticipants, pinnedParticipants]); const onUnpinParticipant = useMemo(() => { return setPinnedParticipants ? (userId) => { setPinnedParticipants(pinnedParticipants.filter(participantId => participantId !== userId)); } : undefined; }, [setPinnedParticipants, pinnedParticipants]); const VideoGalleryMemoized = useMemo(() => { var _a; const layoutBasedOnUserSelection = () => { return props.localVideoTileOptions ? layoutBasedOnTilePosition : props.userSetGalleryLayout; }; return React.createElement(VideoGallery, Object.assign({}, videoGalleryProps, { videoTilesOptions: videoTilesOptions, localVideoViewOptions: localVideoViewOptions, remoteVideoViewOptions: remoteVideoViewOptions, styles: galleryStyles, layout: layoutBasedOnUserSelection(), showCameraSwitcherInLocalPreview: props.isMobile, localVideoCameraCycleButtonProps: cameraSwitcherProps, onRenderAvatar: onRenderAvatar, remoteVideoTileMenu: remoteVideoTileMenuOptions, overflowGalleryPosition: overflowGalleryPosition, localVideoTileSize: props.localVideoTileOptions === false || userRole === 'Consumer' || isRoomsCall && userRole === 'Unknown' ? 'hidden' : props.isMobile && compositeContainerAspectRatio && compositeContainerAspectRatio < 1 ? '9:16' : '16:9', pinnedParticipants: pinnedParticipants, onPinParticipant: onPinParticipant, onUnpinParticipant: onUnpinParticipant, reactionResources: reactionResources, onStartLocalSpotlight: hideSpotlightButtons ? undefined : onStartLocalSpotlightWithPrompt, onStopLocalSpotlight: hideSpotlightButtons ? undefined : onStopLocalSpotlightWithPrompt, onStartRemoteSpotlight: hideSpotlightButtons ? undefined : onStartRemoteSpotlightWithPrompt, onStopRemoteSpotlight: hideSpotlightButtons ? undefined : onStopRemoteSpotlightWithPrompt, onMuteParticipant: ((_a = capabilities === null || capabilities === void 0 ? void 0 : capabilities.muteOthers) === null || _a === void 0 ? void 0 : _a.isPresent) || userRole === 'Unknown' ? videoGalleryProps.onMuteParticipant : undefined, localScreenShareView: props.localScreenShareView })); }, [videoGalleryProps, videoTilesOptions, galleryStyles, props.isMobile, props.localVideoTileOptions, props.userSetGalleryLayout, cameraSwitcherProps, onRenderAvatar, remoteVideoTileMenuOptions, overflowGalleryPosition, userRole, isRoomsCall, pinnedParticipants, onPinParticipant, onUnpinParticipant, reactionResources, hideSpotlightButtons, onStartLocalSpotlightWithPrompt, onStopLocalSpotlightWithPrompt, onStartRemoteSpotlightWithPrompt, onStopRemoteSpotlightWithPrompt, layoutBasedOnTilePosition, capabilities === null || capabilities === void 0 ? void 0 : capabilities.muteOthers, props.localScreenShareView, compositeContainerAspectRatio]); return React.createElement("div", { ref: containerRef, style: mediaGalleryContainerStyles }, React.createElement(Announcer, { announcementString: announcerString, ariaLive: 'polite' }), VideoGalleryMemoized); }; const mediaGalleryContainerStyles = { width: '100%', height: '100%' }; const getVideoGalleryLayoutBasedOnLocalOptions = (localTileOptions) => { return localTileOptions === 'grid' ? 'default' : 'floatingLocalVideo'; }; //# sourceMappingURL=MediaGallery.js.map