UNPKG

@azure/communication-react

Version:

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

117 lines • 11.1 kB
// Copyright (c) Microsoft Corporation. // Licensed under the MIT License. import { DiagnosticQuality } from '@azure/communication-calling'; import { useId } from '@fluentui/react-hooks'; import { _isInCall } from "../../../../../calling-component-bindings/src"; import { _useContainerHeight, _useContainerWidth, ErrorBar } from "../../../../../react-components/src"; import { VideoTile } from "../../../../../react-components/src"; import React, { useMemo, useRef } from 'react'; import { useCallback } from 'react'; import { useState } from 'react'; import { AvatarPersona } from '../../common/AvatarPersona'; import { useLocale } from '../../localization'; import { CallArrangement } from '../components/CallArrangement'; import { MediaGallery } from '../components/MediaGallery'; import { NetworkReconnectTile } from '../components/NetworkReconnectTile'; import { useHandlers } from '../hooks/useHandlers'; import { usePropsFor } from '../hooks/usePropsFor'; import { useSelector } from '../hooks/useSelector'; import { callStatusSelector } from '../selectors/callStatusSelector'; import { complianceBannerSelector } from '../selectors/complianceBannerSelector'; import { mediaGallerySelector } from '../selectors/mediaGallerySelector'; import { getRemoteParticipantsConnectedSelector } from '../selectors/mediaGallerySelector'; import { mutedNotificationSelector } from '../selectors/mutedNotificationSelector'; import { networkReconnectTileSelector } from '../selectors/networkReconnectTileSelector'; import { reduceCallControlsForMobile } from '../utils'; import { DtmfDialpadPage } from './DtmfDialpadPage'; import { showDtmfDialer } from '../utils/MediaGalleryUtils'; import { getTargetCallees } from '../selectors/baseSelectors'; import { Prompt } from '../components/Prompt'; import { toFlatCommunicationIdentifier } from "../../../../../acs-ui-common/src"; import { mergeStyles, Stack } from '@fluentui/react'; import { isPhoneNumberIdentifier } from '@azure/communication-common'; /** * @private */ export const CallPage = (props) => { var _a, _b; const { callInvitationURL, onFetchAvatarPersonaData, onFetchParticipantMenuItems, options, mobileView, galleryLayout = 'floatingLocalVideo', onUserSetGalleryLayoutChange, userSetOverflowGalleryPosition = 'Responsive', onSetUserSetOverflowGalleryPosition, onCloseChatPane, pinnedParticipants = [], setPinnedParticipants, compositeAudioContext, disableAutoShowDtmfDialer = { dialerBehavior: 'autoShow' }, latestNotifications, onDismissNotification } = props; // To use useProps to get these states, we need to create another file wrapping Call, // It seems unnecessary in this case, so we get the updated states using this approach. const { callStatus } = useSelector(callStatusSelector); const mediaGalleryProps = useSelector(mediaGallerySelector); const mediaGalleryHandlers = useHandlers(MediaGallery); const complianceBannerProps = useSelector(complianceBannerSelector); const errorBarProps = usePropsFor(ErrorBar); const mutedNotificationProps = useSelector(mutedNotificationSelector); const networkReconnectTileProps = useSelector(networkReconnectTileSelector); const remoteParticipantsConnected = useSelector(getRemoteParticipantsConnectedSelector); const callees = useSelector(getTargetCallees); const renderDtmfDialerFromStart = showDtmfDialer(callees, remoteParticipantsConnected, disableAutoShowDtmfDialer); const [dtmfDialerPresent, setDtmfDialerPresent] = useState(renderDtmfDialerFromStart); const isPstnCall = callees === null || callees === void 0 ? void 0 : callees.some(callee => isPhoneNumberIdentifier(callee)); const isCTECall = useSelector(state => state.userId.kind === 'microsoftTeamsUser'); const containerRef = useRef(null); const containerWidth = _useContainerWidth(containerRef); const containerHeight = _useContainerHeight(containerRef); const containerAspectRatio = containerWidth && containerHeight ? containerWidth / containerHeight : 0; const strings = useLocale().strings.call; const pinnedParticipantsChecked = useMemo(() => pinnedParticipants.filter(pinnedParticipant => remoteParticipantsConnected.find(remoteParticipant => toFlatCommunicationIdentifier(remoteParticipant.identifier) === pinnedParticipant)), [pinnedParticipants, remoteParticipantsConnected]); // Reduce the controls shown when mobile view is enabled. const callControlOptions = mobileView ? reduceCallControlsForMobile(options === null || options === void 0 ? void 0 : options.callControls) : options === null || options === void 0 ? void 0 : options.callControls; const drawerMenuHostId = useId('drawerMenuHost'); const [isPromptOpen, setIsPromptOpen] = useState(false); const [promptProps, setPromptProps] = useState(); const page = useSelector(state => state.page); const userId = useSelector(state => state.userId); const displayName = useSelector(state => state.displayName); 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]); let galleryContentWhenNotInCall = React.createElement(React.Fragment, null); if (!_isInCall(callStatus) && page === 'returningFromBreakoutRoom') { galleryContentWhenNotInCall = React.createElement(VideoTile, { userId: toFlatCommunicationIdentifier(userId), displayName: displayName, initialsName: displayName, onRenderPlaceholder: onRenderAvatar }); } const onRenderGalleryContentTrampoline = () => { var _a, _b; if (dtmfDialerPresent) { return React.createElement(DtmfDialpadPage, { mobileView: props.mobileView, modalLayerHostId: props.modalLayerHostId, options: props.options, updateSidePaneRenderer: props.updateSidePaneRenderer, mobileChatTabHeader: props.mobileChatTabHeader, latestErrors: props.latestErrors, onDismissError: props.onDismissError, capabilitiesChangedNotificationBarProps: props.capabilitiesChangedNotificationBarProps, onSetDialpadPage: () => setDtmfDialerPresent(!dtmfDialerPresent), dtmfDialerPresent: dtmfDialerPresent, compositeAudioContext: compositeAudioContext }); } else { return React.createElement(MediaGallery, Object.assign({ isMobile: mobileView }, mediaGalleryProps, mediaGalleryHandlers, { onFetchAvatarPersonaData: onFetchAvatarPersonaData, remoteVideoTileMenuOptions: options === null || options === void 0 ? void 0 : options.remoteVideoTileMenuOptions, drawerMenuHostId: drawerMenuHostId, localVideoTileOptions: options === null || options === void 0 ? void 0 : options.localVideoTile, userSetOverflowGalleryPosition: userSetOverflowGalleryPosition, userSetGalleryLayout: galleryLayout, pinnedParticipants: pinnedParticipantsChecked, setPinnedParticipants: setPinnedParticipants, setIsPromptOpen: setIsPromptOpen, setPromptProps: setPromptProps, hideSpotlightButtons: (_a = options === null || options === void 0 ? void 0 : options.spotlight) === null || _a === void 0 ? void 0 : _a.hideSpotlightButtons, videoTilesOptions: options === null || options === void 0 ? void 0 : options.videoTilesOptions, captionsOptions: options === null || options === void 0 ? void 0 : options.captionsBanner, localScreenShareView: (_b = options === null || options === void 0 ? void 0 : options.galleryOptions) === null || _b === void 0 ? void 0 : _b.localScreenShareView, compositeContainerAspectRatio: containerAspectRatio })); } }; return React.createElement("div", { ref: containerRef, style: { height: '100%', width: '100%' } }, React.createElement(CallArrangement, { id: drawerMenuHostId, complianceBannerProps: Object.assign(Object.assign({}, complianceBannerProps), { strings }), errorBarProps: (options === null || options === void 0 ? void 0 : options.errorBar) !== false && errorBarProps, showErrorNotifications: (_a = options === null || options === void 0 ? void 0 : options.errorBar) !== null && _a !== void 0 ? _a : true, mutedNotificationProps: mutedNotificationProps, callControlProps: { callInvitationURL: callInvitationURL, onFetchParticipantMenuItems: onFetchParticipantMenuItems, options: callControlOptions, increaseFlyoutItemSize: mobileView }, onFetchAvatarPersonaData: onFetchAvatarPersonaData, mobileView: mobileView, modalLayerHostId: props.modalLayerHostId, onRenderGalleryContent: () => _isInCall(callStatus) ? isNetworkHealthy(networkReconnectTileProps.networkReconnectValue) ? onRenderGalleryContentTrampoline() : React.createElement(NetworkReconnectTile, Object.assign({}, networkReconnectTileProps, { isMobile: mobileView })) : galleryContentWhenNotInCall, updateSidePaneRenderer: props.updateSidePaneRenderer, mobileChatTabHeader: props.mobileChatTabHeader, onCloseChatPane: onCloseChatPane, dataUiId: 'call-page', latestErrors: props.latestErrors, latestNotifications: latestNotifications, onDismissError: props.onDismissError, onDismissNotification: onDismissNotification, onUserSetOverflowGalleryPositionChange: onSetUserSetOverflowGalleryPosition, onUserSetGalleryLayoutChange: onUserSetGalleryLayoutChange, userSetGalleryLayout: galleryLayout, capabilitiesChangedNotificationBarProps: props.capabilitiesChangedNotificationBarProps, onSetDialpadPage: () => setDtmfDialerPresent(!dtmfDialerPresent), dtmfDialerPresent: dtmfDialerPresent, setIsPromptOpen: setIsPromptOpen, setPromptProps: setPromptProps, hideSpotlightButtons: (_b = options === null || options === void 0 ? void 0 : options.spotlight) === null || _b === void 0 ? void 0 : _b.hideSpotlightButtons, pinnedParticipants: pinnedParticipantsChecked, setPinnedParticipants: setPinnedParticipants, captionsOptions: options === null || options === void 0 ? void 0 : options.captionsBanner, dtmfDialerOptions: disableAutoShowDtmfDialer, notificationOptions: props.notificationOptions, isRTTSupportedCall: !isPstnCall && !isCTECall }), React.createElement(Prompt, Object.assign({ isOpen: isPromptOpen, onDismiss: () => setIsPromptOpen(false) }, promptProps))); }; /** * @private */ export const isNetworkHealthy = (value) => { // We know that the value is actually of type DiagnosticQuality for this diagnostic. // We ignore any boolen values, considering the network to still be healthy. // Thus, only DiagnosticQuality.Poor or .Bad indicate network problems. return value === true || value === false || value === undefined || value === DiagnosticQuality.Good; }; //# sourceMappingURL=CallPage.js.map