@azure/communication-react
Version:
React library for building modern communication user experiences utilizing Azure Communication Services
304 lines • 19.2 kB
JavaScript
// 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