communication-react-19
Version:
React library for building modern communication user experiences utilizing Azure Communication Services (React 19 compatible fork)
132 lines • 7.94 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 React, { useCallback, useState, useMemo } from 'react';
import { useLocale } from '../localization';
import { ControlBarButton } from './ControlBarButton';
import { _HighContrastAwareIcon } from './HighContrastAwareIcon';
import { ContextualMenuItemType } from '@fluentui/react';
import { generateDefaultDeviceMenuProps } from './DevicesButton';
import { Announcer } from './Announcer';
const defaultLocalVideoViewOptions = {
scalingMode: 'Crop',
isMirrored: true
};
/**
* A button to turn camera on / off.
*
* Can be used with {@link ControlBar}.
*
* @public
*/
export const CameraButton = (props) => {
var _a, _b, _c, _d, _e, _f, _g, _h;
const { localVideoViewOptions, onToggleCamera, onSelectCamera } = props;
const [waitForCamera, setWaitForCamera] = useState(false);
const localeStrings = useLocale().strings.cameraButton;
const strings = Object.assign(Object.assign({}, localeStrings), props.strings);
const [announcerString, setAnnouncerString] = useState(undefined);
const [announcerPresent, setAnnouncerPresent] = useState(false);
const disabled = props.disabled || waitForCamera;
const onRenderCameraOnIcon = () => (React.createElement(_HighContrastAwareIcon, { disabled: disabled, iconName: "ControlButtonCameraOn" }));
const onRenderCameraOffIcon = () => (React.createElement(_HighContrastAwareIcon, { disabled: disabled, iconName: "ControlButtonCameraOff" }));
if (waitForCamera && strings.tooltipVideoLoadingContent) {
strings.tooltipDisabledContent = strings.tooltipVideoLoadingContent;
}
const cameraOn = props.checked;
const cameraTurningOn = waitForCamera && !cameraOn;
// Ensure Aria-label by default reflects the loading state of the camera
const ariaLabel = ((_a = props.ariaLabel) !== null && _a !== void 0 ? _a : cameraTurningOn) ? strings.tooltipVideoLoadingContent : undefined;
const splitButtonAriaString = cameraTurningOn
? strings.tooltipVideoLoadingContent
: cameraOn
? strings.onSplitButtonAriaLabel
: strings.offSplitButtonAriaLabel;
const toggleAnnouncerString = useCallback((isCameraOn) => {
setAnnouncerString(!isCameraOn ? strings.cameraActionTurnedOffAnnouncement : strings.cameraActionTurnedOnAnnouncement);
}, [strings.cameraActionTurnedOffAnnouncement, strings.cameraActionTurnedOnAnnouncement]);
const onVideoIsLoadingAnnouncementCallback = useCallback(() => {
if (!cameraOn) {
setAnnouncerString(strings.tooltipVideoLoadingContent);
}
}, [setAnnouncerString, cameraOn, strings.tooltipVideoLoadingContent]);
const onToggleClick = useCallback(() => __awaiter(void 0, void 0, void 0, function* () {
// Throttle click on camera, need to await onToggleCamera then allow another click
if (onToggleCamera) {
setWaitForCamera(true);
try {
yield onToggleCamera(localVideoViewOptions !== null && localVideoViewOptions !== void 0 ? localVideoViewOptions : defaultLocalVideoViewOptions);
// allows for the setting of narrator strings triggering the announcer when camera is turned on or off.
toggleAnnouncerString(!cameraOn);
}
finally {
setWaitForCamera(false);
}
}
}), [cameraOn, localVideoViewOptions, onToggleCamera, toggleAnnouncerString]);
const onToggleClickCallback = useCallback(() => {
onVideoIsLoadingAnnouncementCallback();
onToggleClick();
}, [onVideoIsLoadingAnnouncementCallback, onToggleClick]);
const onChangeCameraClick = useCallback((device) => __awaiter(void 0, void 0, void 0, function* () {
// Throttle changing camera to prevent too many callbacks
if (onSelectCamera) {
setWaitForCamera(true);
try {
yield onSelectCamera(device);
}
finally {
setWaitForCamera(false);
}
}
}), [onSelectCamera]);
const splitButtonMenuItems = [];
if (props.onClickVideoEffects) {
splitButtonMenuItems.push({
key: 'effects',
'data-ui-id': 'camera-split-button-video-effects',
text: strings.videoEffectsMenuItemTitle,
iconProps: { iconName: 'ControlButtonVideoEffectsOption', styles: { root: { lineHeight: 0 } } },
onClick: () => {
if (props.onClickVideoEffects) {
props.onClickVideoEffects(true);
}
}
});
}
splitButtonMenuItems.push({
key: 'cameraPrimaryAction',
text: props.checked ? strings.onSplitButtonPrimaryActionCamera : strings.offSplitButtonPrimaryActionCamera,
onClick: () => {
onToggleClick();
},
iconProps: {
iconName: props.checked ? 'SplitButtonPrimaryActionCameraOn' : 'SplitButtonPrimaryActionCameraOff',
styles: { root: { lineHeight: 0 } }
}
});
const splitButtonPrimaryAction = {
key: 'primaryAction',
title: 'toggle camera',
itemType: ContextualMenuItemType.Section,
sectionProps: {
topDivider: true,
items: splitButtonMenuItems
}
};
const splitButtonMenuProps = useMemo(() => (Object.assign(Object.assign({}, props.splitButtonMenuProps), { className: 'camera-split-button' })), [props.splitButtonMenuProps]);
return (React.createElement(React.Fragment, null,
announcerPresent && React.createElement(Announcer, { announcementString: announcerString, ariaLive: 'polite' }),
React.createElement(ControlBarButton, Object.assign({}, props, { disabled: disabled, onClick: onToggleCamera ? onToggleClickCallback : props.onClick, onRenderOnIcon: (_b = props.onRenderOnIcon) !== null && _b !== void 0 ? _b : onRenderCameraOnIcon, onRenderOffIcon: (_c = props.onRenderOffIcon) !== null && _c !== void 0 ? _c : onRenderCameraOffIcon, strings: strings, labelKey: (_d = props.labelKey) !== null && _d !== void 0 ? _d : 'cameraButtonLabel', menuProps: (_e = props.menuProps) !== null && _e !== void 0 ? _e : (props.enableDeviceSelectionMenu
? generateDefaultDeviceMenuProps(Object.assign(Object.assign({}, props), { onSelectCamera: onChangeCameraClick, styles: (_f = props.styles) === null || _f === void 0 ? void 0 : _f.menuStyles }), strings, splitButtonPrimaryAction)
: undefined), menuIconProps: ((_g = props.menuIconProps) !== null && _g !== void 0 ? _g : !props.enableDeviceSelectionMenu) ? { hidden: true } : undefined, split: (_h = props.split) !== null && _h !== void 0 ? _h : props.enableDeviceSelectionMenu, "aria-description": strings.cameraButtonAriaDescription, "aria-roledescription": props.enableDeviceSelectionMenu ? strings.cameraButtonSplitRoleDescription : undefined, ariaLabel: ariaLabel, splitButtonAriaLabel: props.enableDeviceSelectionMenu ? splitButtonAriaString : undefined, splitButtonMenuProps: splitButtonMenuProps, onFocus: () => setAnnouncerPresent(true), onBlur: () => setAnnouncerPresent(false) }))));
};
//# sourceMappingURL=CameraButton.js.map