UNPKG

@azure/communication-react

Version:

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

304 lines • 19.2 kB
// Copyright (c) Microsoft Corporation. // Licensed under the MIT License. var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } return new (P || (P = Promise))(function (resolve, reject) { function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } step((generator = generator.apply(thisArg, _arguments || [])).next()); }); }; import { memoizeFunction, Stack, useTheme } from '@fluentui/react'; import { ControlBar, DevicesButton } from "../../../../../react-components/src"; import { HoldButton } from "../../../../../react-components/src"; import React, { useMemo, useCallback, useState, useEffect } from 'react'; import { Camera } from './buttons/Camera'; import { Devices } from './buttons/Devices'; import { EndCall } from './buttons/EndCall'; import { Microphone } from './buttons/Microphone'; import { Participants } from './buttons/Participants'; import { ScreenShare } from './buttons/ScreenShare'; import { People } from './buttons/People'; import { useLocale } from '../../localization'; import { MoreButton } from '../../common/MoreButton'; import { usePropsFor } from '../hooks/usePropsFor'; import { buttonFlyoutIncreasedSizeStyles } from '../styles/Buttons.styles'; import { useAdapter } from '../adapter/CallAdapterProvider'; import { isDisabled } from '../utils'; import { callControlsContainerStyles } from '../styles/CallPage.styles'; import { RaiseHand } from './buttons/RaiseHand'; import { RaiseHandButton } from "../../../../../react-components/src"; import { _generateDefaultDeviceMenuProps } from "../../../../../react-components/src"; import { CUSTOM_BUTTON_OPTIONS, generateCustomCallControlBarButton, generateCustomCallDesktopOverflowButtons, onFetchCustomButtonPropsTrampoline } from '../../common/ControlBar/CustomButton'; import { Reaction } from './buttons/Reaction'; import { useSelector } from '../hooks/useSelector'; import { capabilitySelector } from '../../CallComposite/selectors/capabilitySelector'; import { callStatusSelector } from '../../CallComposite/selectors/callStatusSelector'; import { _isSafari } from '../../CallComposite/utils'; import { getIsRoomsCall, getReactionResources, getRole, getDeepNoiseSuppresionEffectsDependency, getDeepNoiseSuppresionIsOnByDefault, getHideDeepNoiseSupressionButton, getEnvironmentInfo } from '../selectors/baseSelectors'; // Enforce a background color on control bar to ensure it matches the composite background color. const controlBarStyles = memoizeFunction((background) => ({ root: { background: background } })); const inferCallControlOptions = (mobileView, callControlOptions) => { if (callControlOptions === false) { return {}; } const options = callControlOptions === true || callControlOptions === undefined ? {} : callControlOptions; if (mobileView) { // Set options to always not show screen share button for mobile options.screenShareButton = false; } return options; }; /** * @private */ export const CallControls = (props) => { var _a; const options = useMemo(() => inferCallControlOptions(!!props.isMobile, props.options), [props.isMobile, props.options]); const localeStrings = useLocale(); const [isDeepNoiseSuppressionOn, setDeepNoiseSuppressionOn] = useState(false); const adapter = useAdapter(); const startDeepNoiseSuppression = useCallback(() => __awaiter(void 0, void 0, void 0, function* () { yield adapter.startNoiseSuppressionEffect(); }), [adapter]); const deepNoiseSuppresionEffectsDependency = useSelector(getDeepNoiseSuppresionEffectsDependency); const deepNoiseSuppressionOnByDefault = useSelector(getDeepNoiseSuppresionIsOnByDefault); useEffect(() => { if (deepNoiseSuppresionEffectsDependency && deepNoiseSuppressionOnByDefault) { startDeepNoiseSuppression(); setDeepNoiseSuppressionOn(true); } }, [deepNoiseSuppresionEffectsDependency, deepNoiseSuppressionOnByDefault, startDeepNoiseSuppression]); const environmentInfo = useSelector(getEnvironmentInfo); const isSafari = _isSafari(environmentInfo); const hideDeepNoiseSuppressionButton = useSelector(getHideDeepNoiseSupressionButton); const showNoiseSuppressionButton = !!(deepNoiseSuppresionEffectsDependency && !hideDeepNoiseSuppressionButton && !isSafari); const onClickNoiseSuppression = useCallback(() => __awaiter(void 0, void 0, void 0, function* () { if (isDeepNoiseSuppressionOn) { yield adapter.stopNoiseSuppressionEffect(); setDeepNoiseSuppressionOn(false); } else { yield adapter.startNoiseSuppressionEffect(); setDeepNoiseSuppressionOn(true); } }), [adapter, isDeepNoiseSuppressionOn]); const peopleButtonStrings = useMemo(() => ({ label: localeStrings.strings.call.peopleButtonLabel, tooltipOffContent: localeStrings.strings.call.peopleButtonTooltipOpen, tooltipOnContent: localeStrings.strings.call.peopleButtonTooltipClose }), [localeStrings]); const moreButtonStrings = useMemo(() => ({ label: localeStrings.strings.call.moreButtonCallingLabel, tooltipOffContent: localeStrings.strings.callWithChat.moreDrawerButtonTooltip }), [localeStrings]); const holdButtonProps = usePropsFor(HoldButton); const raiseHandButtonProps = usePropsFor(RaiseHandButton); const capabilitiesSelector = useSelector(capabilitySelector); const callState = useSelector(callStatusSelector); const isReactionAllowed = callState.callStatus !== 'Connected' || !(capabilitiesSelector === null || capabilitiesSelector === void 0 ? void 0 : capabilitiesSelector.capabilities) || capabilitiesSelector.capabilities.useReactions.isPresent; const devicesButtonProps = usePropsFor(DevicesButton); let numberOfButtons = 0; const screenShareButtonIsEnabled = isEnabled(options === null || options === void 0 ? void 0 : options.screenShareButton); if (screenShareButtonIsEnabled) { numberOfButtons++; } const microphoneButtonIsEnabled = isEnabled(options === null || options === void 0 ? void 0 : options.microphoneButton); if (microphoneButtonIsEnabled) { numberOfButtons++; } const cameraButtonIsEnabled = isEnabled(options === null || options === void 0 ? void 0 : options.cameraButton); if (cameraButtonIsEnabled) { numberOfButtons++; } if (isEnabled(options === null || options === void 0 ? void 0 : options.endCallButton)) { numberOfButtons++; } const showParticipantsButtonInControlBar = isEnabled(options === null || options === void 0 ? void 0 : options.participantsButton) && !props.isMobile; if (showParticipantsButtonInControlBar) { numberOfButtons++; } const showReactionButtonInControlBar = isEnabled(options === null || options === void 0 ? void 0 : options.reactionButton) && isReactionAllowed && !props.isMobile; if (showReactionButtonInControlBar) { numberOfButtons++; } const isRoomsCall = useSelector(getIsRoomsCall); const moreButtonContextualMenuItems = () => { const items = []; if (props.isMobile && props.onPeopleButtonClicked && isEnabled(options === null || options === void 0 ? void 0 : options.participantsButton)) { items.push({ key: 'peopleButtonKey', text: localeStrings.component.strings.participantsButton.label, onClick: () => { if (props.onPeopleButtonClicked) { props.onPeopleButtonClicked(); } }, iconProps: { iconName: 'ControlButtonParticipantsContextualMenuItem', styles: { root: { lineHeight: 0 } } }, itemProps: { styles: buttonFlyoutIncreasedSizeStyles }, disabled: isDisabled(options === null || options === void 0 ? void 0 : options.participantsButton), ['data-ui-id']: 'call-composite-more-menu-people-button' }); } if (!isRoomsCall) { items.push({ key: 'holdButtonKey', text: localeStrings.component.strings.holdButton.tooltipOffContent, onClick: () => { holdButtonProps.onToggleHold(); }, iconProps: { iconName: 'HoldCallContextualMenuItem', styles: { root: { lineHeight: 0 } } }, itemProps: { styles: buttonFlyoutIncreasedSizeStyles }, disabled: isDisabled(options === null || options === void 0 ? void 0 : options.holdButton), ['data-ui-id']: 'hold-button' }); } return items; }; const customDrawerButtons = useMemo(() => generateCustomCallDesktopOverflowButtons(onFetchCustomButtonPropsTrampoline(typeof options === 'object' ? options : undefined), typeof options === 'object' ? options.displayType : undefined), [options]); const moreButtonMenuItems = moreButtonContextualMenuItems(); let showMoreButton = isEnabled(options === null || options === void 0 ? void 0 : options.moreButton) && moreButtonMenuItems.length > 0; if (showMoreButton) { numberOfButtons++; } const customButtons = useMemo(() => generateCustomCallControlBarButton(onFetchCustomButtonPropsTrampoline(options), options === null || options === void 0 ? void 0 : options.displayType), [options]); numberOfButtons += React.Children.count(customButtons['primary']) + React.Children.count(customButtons['secondary']); let showDevicesButtonInControlBar = isEnabled(options === null || options === void 0 ? void 0 : options.devicesButton); if (showDevicesButtonInControlBar && (props.isMobile ? numberOfButtons < 5 : true)) { numberOfButtons++; } else { showDevicesButtonInControlBar = false; showMoreButton = isEnabled(options === null || options === void 0 ? void 0 : options.moreButton); } const reactionResources = useSelector(getReactionResources); const raiseHandButtonIsEnabled = isEnabled(options === null || options === void 0 ? void 0 : options.raiseHandButton); let showRaiseHandButtonInControlBar = raiseHandButtonIsEnabled; const role = useSelector(getRole); const hideRaiseHandButtonInRoomsCall = isRoomsCall && role && ['Consumer', 'Unknown'].includes(role); if (showRaiseHandButtonInControlBar && (props.isMobile ? numberOfButtons < 5 : true)) { numberOfButtons++; } else { // If more button is not present but enabled then replace previous button (devices button) with more button if (!showMoreButton && isEnabled(options === null || options === void 0 ? void 0 : options.moreButton)) { showMoreButton = true; showDevicesButtonInControlBar = false; } showRaiseHandButtonInControlBar = false; } if (!showDevicesButtonInControlBar) { const devicesButtonMenu = _generateDefaultDeviceMenuProps(devicesButtonProps, localeStrings.component.strings.devicesButton); moreButtonMenuItems.push({ key: 'devicesButtonKey', text: localeStrings.component.strings.devicesButton.label, iconProps: { iconName: 'ControlButtonOptions', styles: { root: { lineHeight: 0 } } }, subMenuProps: devicesButtonMenu, ['data-ui-id']: 'call-composite-more-menu-devices-button' }); } if (!showRaiseHandButtonInControlBar && !hideRaiseHandButtonInRoomsCall) { moreButtonMenuItems.push({ key: 'raiseHandButtonKey', text: raiseHandButtonProps.checked ? localeStrings.component.strings.raiseHandButton.onLabel : localeStrings.component.strings.raiseHandButton.offLabel, onClick: () => { if (raiseHandButtonProps.onToggleRaiseHand) { raiseHandButtonProps.onToggleRaiseHand(); } }, iconProps: { iconName: 'RaiseHandContextualMenuItem', styles: { root: { lineHeight: 0 } } }, itemProps: { styles: buttonFlyoutIncreasedSizeStyles }, disabled: isDisabled(options === null || options === void 0 ? void 0 : options.raiseHandButton), ['data-ui-id']: 'call-composite-more-menu-raise-hand-button' }); } // Custom Buttons in More Button Menu should always be the last items pushed into the moreButtonMenuItems array if (customDrawerButtons['primary']) { customDrawerButtons['primary'].slice(props.isMobile ? CUSTOM_BUTTON_OPTIONS.MAX_PRIMARY_MOBILE_CUSTOM_BUTTONS : CUSTOM_BUTTON_OPTIONS.MAX_PRIMARY_DESKTOP_CUSTOM_BUTTONS).forEach(element => { moreButtonMenuItems.push(Object.assign({ itemProps: { styles: buttonFlyoutIncreasedSizeStyles } }, element)); }); } if (customDrawerButtons['secondary']) { customDrawerButtons['secondary'].forEach(element => { moreButtonMenuItems.push(Object.assign({ itemProps: { styles: buttonFlyoutIncreasedSizeStyles } }, element)); }); } if (customDrawerButtons['overflow']) { customDrawerButtons['overflow'].forEach(element => { moreButtonMenuItems.push(Object.assign({ itemProps: { styles: buttonFlyoutIncreasedSizeStyles } }, element)); }); } const theme = useTheme(); // when props.options is false then we want to hide the whole control bar. if (props.options === false) { return React.createElement(React.Fragment, null); } return React.createElement(Stack, { horizontalAlign: "center", className: callControlsContainerStyles }, React.createElement(Stack.Item, null, React.createElement(ControlBar, { layout: props.displayVertical ? 'vertical' : 'horizontal', styles: controlBarStyles(theme.semanticColors.bodyBackground) }, microphoneButtonIsEnabled && React.createElement(Microphone, { displayType: options === null || options === void 0 ? void 0 : options.displayType, disabled: isDisabled(options === null || options === void 0 ? void 0 : options.microphoneButton), onClickNoiseSuppression: onClickNoiseSuppression, isDeepNoiseSuppressionOn: isDeepNoiseSuppressionOn, showNoiseSuppressionButton: showNoiseSuppressionButton }), cameraButtonIsEnabled && React.createElement(Camera, { displayType: options === null || options === void 0 ? void 0 : options.displayType, disabled: isDisabled(options === null || options === void 0 ? void 0 : options.cameraButton) }), showReactionButtonInControlBar && reactionResources && React.createElement(Reaction, { displayType: options === null || options === void 0 ? void 0 : options.displayType, reactionResource: reactionResources }), showRaiseHandButtonInControlBar && !hideRaiseHandButtonInRoomsCall && React.createElement(RaiseHand, { displayType: options === null || options === void 0 ? void 0 : options.displayType }), screenShareButtonIsEnabled && React.createElement(ScreenShare, { option: options === null || options === void 0 ? void 0 : options.screenShareButton, displayType: options === null || options === void 0 ? void 0 : options.displayType, disabled: isDisabled(options === null || options === void 0 ? void 0 : options.screenShareButton) }), showParticipantsButtonInControlBar && React.createElement(Participants, { option: options === null || options === void 0 ? void 0 : options.participantsButton, callInvitationURL: props.callInvitationURL, onFetchParticipantMenuItems: props.onFetchParticipantMenuItems, displayType: options === null || options === void 0 ? void 0 : options.displayType, increaseFlyoutItemSize: props.increaseFlyoutItemSize, isMobile: props.isMobile, disabled: isDisabled(options === null || options === void 0 ? void 0 : options.participantsButton) }) && React.createElement(People, { checked: props.peopleButtonChecked, ariaLabel: peopleButtonStrings === null || peopleButtonStrings === void 0 ? void 0 : peopleButtonStrings.label, showLabel: (options === null || options === void 0 ? void 0 : options.displayType) !== 'compact', onClick: props.onPeopleButtonClicked, "data-ui-id": "call-composite-people-button", strings: peopleButtonStrings, disabled: isDisabled(options === null || options === void 0 ? void 0 : options.participantsButton), disableTooltip: props.isMobile }), showDevicesButtonInControlBar && React.createElement(Devices, { displayType: options === null || options === void 0 ? void 0 : options.displayType, increaseFlyoutItemSize: props.increaseFlyoutItemSize, disabled: isDisabled(options === null || options === void 0 ? void 0 : options.devicesButton) }), (_a = customButtons['primary']) === null || _a === void 0 ? void 0 : _a.slice(0, props.isMobile ? CUSTOM_BUTTON_OPTIONS.MAX_PRIMARY_MOBILE_CUSTOM_BUTTONS : CUSTOM_BUTTON_OPTIONS.MAX_PRIMARY_DESKTOP_CUSTOM_BUTTONS).map((CustomButton, i) => { return React.createElement(CustomButton, { key: `primary-custom-button-${i}`, // styles={commonButtonStyles} showLabel: (options === null || options === void 0 ? void 0 : options.displayType) !== 'compact', disableTooltip: props.isMobile }); }), showMoreButton && React.createElement(MoreButton, { disableTooltip: props.isMobile, "data-ui-id": "common-call-composite-more-button", strings: moreButtonStrings, menuIconProps: { hidden: true }, menuProps: { items: moreButtonMenuItems }, showLabel: (options === null || options === void 0 ? void 0 : options.displayType) !== 'compact' }), isEnabled(options === null || options === void 0 ? void 0 : options.endCallButton) && React.createElement(EndCall, { displayType: options === null || options === void 0 ? void 0 : options.displayType })))); }; const isEnabled = (option) => option !== false; //# sourceMappingURL=CallControls.js.map