@azure/communication-react 1.12.1-alpha-202401240013 → 1.12.1-alpha-202401250013

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (69) hide show
  1. package/dist/communication-react.d.ts +10 -5
  2. package/dist/dist-cjs/communication-react/index.js +330 -254
  3. package/dist/dist-cjs/communication-react/index.js.map +1 -1
  4. package/dist/dist-esm/acs-ui-common/src/telemetryVersion.js +1 -1
  5. package/dist/dist-esm/acs-ui-common/src/telemetryVersion.js.map +1 -1
  6. package/dist/dist-esm/communication-react/src/index.d.ts +1 -1
  7. package/dist/dist-esm/communication-react/src/index.js.map +1 -1
  8. package/dist/dist-esm/react-components/src/components/ChatMessage/ChatMessageComponentAsEditBox.js +2 -1
  9. package/dist/dist-esm/react-components/src/components/ChatMessage/ChatMessageComponentAsEditBox.js.map +1 -1
  10. package/dist/dist-esm/react-components/src/components/Dialpad/Dialpad.d.ts +9 -5
  11. package/dist/dist-esm/react-components/src/components/Dialpad/Dialpad.js +5 -9
  12. package/dist/dist-esm/react-components/src/components/Dialpad/Dialpad.js.map +1 -1
  13. package/dist/dist-esm/react-components/src/components/FileUploadCards.d.ts +32 -1
  14. package/dist/dist-esm/react-components/src/components/FileUploadCards.js.map +1 -1
  15. package/dist/dist-esm/react-components/src/components/InputBoxButton.d.ts +19 -0
  16. package/dist/dist-esm/react-components/src/components/InputBoxButton.js +32 -0
  17. package/dist/dist-esm/react-components/src/components/InputBoxButton.js.map +1 -0
  18. package/dist/dist-esm/react-components/src/components/InputBoxComponent.d.ts +0 -17
  19. package/dist/dist-esm/react-components/src/components/InputBoxComponent.js +3 -29
  20. package/dist/dist-esm/react-components/src/components/InputBoxComponent.js.map +1 -1
  21. package/dist/dist-esm/react-components/src/components/RTE/RTEInputBoxComponent.d.ts +19 -0
  22. package/dist/dist-esm/react-components/src/components/RTE/RTEInputBoxComponent.js +13 -0
  23. package/dist/dist-esm/react-components/src/components/RTE/RTEInputBoxComponent.js.map +1 -0
  24. package/dist/dist-esm/react-components/src/components/RTE/RTESendBox.d.ts +34 -1
  25. package/dist/dist-esm/react-components/src/components/RTE/RTESendBox.js +45 -3
  26. package/dist/dist-esm/react-components/src/components/RTE/RTESendBox.js.map +1 -1
  27. package/dist/dist-esm/react-components/src/components/RTE/RTESendBoxErrors.d.ts +15 -0
  28. package/dist/dist-esm/react-components/src/components/RTE/RTESendBoxErrors.js +18 -0
  29. package/dist/dist-esm/react-components/src/components/RTE/RTESendBoxErrors.js.map +1 -0
  30. package/dist/dist-esm/react-components/src/components/RTE/RichTextEditor.d.ts +18 -0
  31. package/dist/dist-esm/react-components/src/components/RTE/RichTextEditor.js +40 -0
  32. package/dist/dist-esm/react-components/src/components/RTE/RichTextEditor.js.map +1 -0
  33. package/dist/dist-esm/react-components/src/components/SendBox.d.ts +1 -32
  34. package/dist/dist-esm/react-components/src/components/SendBox.js +33 -30
  35. package/dist/dist-esm/react-components/src/components/SendBox.js.map +1 -1
  36. package/dist/dist-esm/react-components/src/components/TextFieldWithMention/TextFieldWithMention.d.ts +0 -17
  37. package/dist/dist-esm/react-components/src/components/TextFieldWithMention/TextFieldWithMention.js +1 -28
  38. package/dist/dist-esm/react-components/src/components/TextFieldWithMention/TextFieldWithMention.js.map +1 -1
  39. package/dist/dist-esm/react-components/src/components/index.d.ts +2 -1
  40. package/dist/dist-esm/react-components/src/components/index.js.map +1 -1
  41. package/dist/dist-esm/react-components/src/components/styles/InputBoxButton.style.d.ts +13 -0
  42. package/dist/dist-esm/react-components/src/components/styles/InputBoxButton.style.js +30 -0
  43. package/dist/dist-esm/react-components/src/components/styles/InputBoxButton.style.js.map +1 -0
  44. package/dist/dist-esm/react-components/src/components/styles/InputBoxComponent.style.d.ts +0 -16
  45. package/dist/dist-esm/react-components/src/components/styles/InputBoxComponent.style.js +0 -32
  46. package/dist/dist-esm/react-components/src/components/styles/InputBoxComponent.style.js.map +1 -1
  47. package/dist/dist-esm/react-components/src/components/styles/RichTextEditor.styles.d.ts +5 -0
  48. package/dist/dist-esm/react-components/src/components/styles/RichTextEditor.styles.js +16 -0
  49. package/dist/dist-esm/react-components/src/components/styles/RichTextEditor.styles.js.map +1 -0
  50. package/dist/dist-esm/react-components/src/components/styles/SendBox.styles.d.ts +8 -2
  51. package/dist/dist-esm/react-components/src/components/styles/SendBox.styles.js +13 -7
  52. package/dist/dist-esm/react-components/src/components/styles/SendBox.styles.js.map +1 -1
  53. package/dist/dist-esm/react-components/src/components/utils/SendBoxUtils.d.ts +10 -0
  54. package/dist/dist-esm/react-components/src/components/utils/SendBoxUtils.js +18 -0
  55. package/dist/dist-esm/react-components/src/components/utils/SendBoxUtils.js.map +1 -0
  56. package/dist/dist-esm/react-composites/src/composites/CallComposite/pages/CallPage.js +30 -3
  57. package/dist/dist-esm/react-composites/src/composites/CallComposite/pages/CallPage.js.map +1 -1
  58. package/dist/dist-esm/react-composites/src/composites/CallComposite/pages/DtmfDialpadPage.js +11 -4
  59. package/dist/dist-esm/react-composites/src/composites/CallComposite/pages/DtmfDialpadPage.js.map +1 -1
  60. package/dist/dist-esm/react-composites/src/composites/CallComposite/selectors/baseSelectors.d.ts +5 -0
  61. package/dist/dist-esm/react-composites/src/composites/CallComposite/selectors/baseSelectors.js +4 -0
  62. package/dist/dist-esm/react-composites/src/composites/CallComposite/selectors/baseSelectors.js.map +1 -1
  63. package/dist/dist-esm/react-composites/src/composites/CallComposite/utils/MediaGalleryUtils.d.ts +7 -0
  64. package/dist/dist-esm/react-composites/src/composites/CallComposite/utils/MediaGalleryUtils.js +13 -0
  65. package/dist/dist-esm/react-composites/src/composites/CallComposite/utils/MediaGalleryUtils.js.map +1 -1
  66. package/dist/dist-esm/react-composites/src/composites/common/ControlBar/DesktopMoreButton.js +11 -16
  67. package/dist/dist-esm/react-composites/src/composites/common/ControlBar/DesktopMoreButton.js.map +1 -1
  68. package/dist/tsdoc-metadata.json +1 -1
  69. package/package.json +5 -1
@@ -14,6 +14,9 @@ var textareaCaretTs = require('textarea-caret-ts');
14
14
  var reactComponents = require('@fluentui/react-components');
15
15
  var useDebounce = require('use-debounce');
16
16
  var reactFileTypeIcons = require('@fluentui/react-file-type-icons');
17
+ require('roosterjs-editor-plugins');
18
+ require('roosterjs-editor-core');
19
+ require('roosterjs-react');
17
20
  var uuid = require('uuid');
18
21
  var reactChat = require('@fluentui-contrib/react-chat');
19
22
  var react$1 = require('@griffel/react');
@@ -170,7 +173,7 @@ function getDefaultExportFromCjs (x) {
170
173
  // Copyright (c) Microsoft Corporation.
171
174
  // Licensed under the MIT License.
172
175
  // GENERATED FILE. DO NOT EDIT MANUALLY.
173
- var telemetryVersion = '1.12.1-alpha-202401240013';
176
+ var telemetryVersion = '1.12.1-alpha-202401250013';
174
177
 
175
178
 
176
179
  var telemetryVersion$1 = /*@__PURE__*/getDefaultExportFromCjs(telemetryVersion);
@@ -6029,11 +6032,17 @@ const sendButtonStyle = react.mergeStyles({
6029
6032
  /**
6030
6033
  * @private
6031
6034
  */
6032
- const sendIconStyle = react.mergeStyles({
6033
- width: '1.25rem',
6034
- height: '1.25rem',
6035
- margin: 'auto'
6036
- });
6035
+ const sendIconStyle = (props) => {
6036
+ const { theme, hasText,
6037
+ /* @conditional-compile-remove(file-sharing) */ hasFile, hasErrorMessage, customSendIconStyle } = props;
6038
+ const hasNoContent = !hasText && /* @conditional-compile-remove(file-sharing) */ !hasFile;
6039
+ return react.mergeStyles({
6040
+ width: '1.25rem',
6041
+ height: '1.25rem',
6042
+ margin: 'auto',
6043
+ color: hasErrorMessage || hasNoContent ? theme.palette.neutralTertiary : theme.palette.themePrimary
6044
+ }, customSendIconStyle);
6045
+ };
6037
6046
  /**
6038
6047
  * @private
6039
6048
  */
@@ -6066,7 +6075,7 @@ const borderAndBoxShadowStyle = (props) => {
6066
6075
  const borderColorActive = hasErrorMessage ? theme.semanticColors.errorText : theme.palette.themePrimary;
6067
6076
  const borderThickness = disabled ? 0 : defaultSendBoxInactiveBorderThicknessREM;
6068
6077
  const borderActiveThickness = disabled ? 0 : defaultSendBoxActiveBorderThicknessREM;
6069
- return {
6078
+ return react.mergeStyles({
6070
6079
  borderRadius: theme.effects.roundedCorner4,
6071
6080
  border: `${borderThickness}rem solid ${borderColor}`,
6072
6081
  // The border thickness of the sendbox wrapper changes on hover, to prevent the border thickness change causing the
@@ -6076,7 +6085,7 @@ const borderAndBoxShadowStyle = (props) => {
6076
6085
  border: `${borderActiveThickness}rem solid ${borderColorActive}`,
6077
6086
  margin: `${defaultSendBoxActiveBorderThicknessREM - borderActiveThickness}rem`
6078
6087
  }
6079
- };
6088
+ });
6080
6089
  };
6081
6090
 
6082
6091
  // Copyright (c) Microsoft Corporation.
@@ -6544,57 +6553,6 @@ const textFieldStyle = {
6544
6553
  borderRadius: '0.25rem'
6545
6554
  }
6546
6555
  };
6547
- /**
6548
- * @private
6549
- */
6550
- const inputButtonStyle = react.mergeStyles({
6551
- color: 'grey',
6552
- margin: 'auto',
6553
- width: '1.0625rem',
6554
- height: '1.0625rem',
6555
- backgroundColor: 'transparent',
6556
- '&:hover': {
6557
- backgroundColor: 'transparent'
6558
- }
6559
- });
6560
- /**
6561
- * @private
6562
- */
6563
- const inputButtonTooltipStyle = react.mergeStyles({
6564
- // The toolTip host container show be a flex box, so that alignItems: 'center' works for inside buttons
6565
- display: 'flex'
6566
- });
6567
- /**
6568
- * @private
6569
- */
6570
- const iconWrapperStyle$1 = react.mergeStyles({
6571
- pointerEvents: 'none'
6572
- });
6573
-
6574
- // Copyright (c) Microsoft Corporation.
6575
- // Licensed under the MIT License.
6576
- /**
6577
- * @private
6578
- */
6579
- const isDarkThemed = (theme) => {
6580
- const themeBlackBrightness = getPerceptualBrightnessOfHexColor(theme.palette.black);
6581
- const themeWhiteBrightness = getPerceptualBrightnessOfHexColor(theme.palette.white);
6582
- if (Number.isNaN(themeBlackBrightness) || Number.isNaN(themeWhiteBrightness)) {
6583
- return false;
6584
- }
6585
- return themeBlackBrightness > themeWhiteBrightness;
6586
- };
6587
- const getPerceptualBrightnessOfHexColor = (hexColor) => {
6588
- // return NaN if hexColor is not a hex code
6589
- if (!/^#[0-9A-Fa-f]{6}$/i.test(hexColor)) {
6590
- return NaN;
6591
- }
6592
- const r = parseInt(hexColor.substring(1, 3), 16);
6593
- const g = parseInt(hexColor.substring(3, 5), 16);
6594
- const b = parseInt(hexColor.substring(5, 7), 16);
6595
- // arithmetic mean μ of the red, green, and blue color coordinates. Source: https://en.wikipedia.org/wiki/Brightness
6596
- return (r + g + b) / 3;
6597
- };
6598
6556
 
6599
6557
  // Copyright (c) Microsoft Corporation.
6600
6558
  // Licensed under the MIT License.
@@ -8317,14 +8275,71 @@ const InputBoxComponent = (props) => {
8317
8275
  return (React.createElement(react.Stack, { className: mergedRootStyle },
8318
8276
  React.createElement("div", { className: mergedTextContainerStyle }, renderTextField())));
8319
8277
  };
8278
+
8279
+ // Copyright (c) Microsoft Corporation.
8280
+ // Licensed under the MIT License.
8281
+ /**
8282
+ * @private
8283
+ */
8284
+ const isDarkThemed = (theme) => {
8285
+ const themeBlackBrightness = getPerceptualBrightnessOfHexColor(theme.palette.black);
8286
+ const themeWhiteBrightness = getPerceptualBrightnessOfHexColor(theme.palette.white);
8287
+ if (Number.isNaN(themeBlackBrightness) || Number.isNaN(themeWhiteBrightness)) {
8288
+ return false;
8289
+ }
8290
+ return themeBlackBrightness > themeWhiteBrightness;
8291
+ };
8292
+ const getPerceptualBrightnessOfHexColor = (hexColor) => {
8293
+ // return NaN if hexColor is not a hex code
8294
+ if (!/^#[0-9A-Fa-f]{6}$/i.test(hexColor)) {
8295
+ return NaN;
8296
+ }
8297
+ const r = parseInt(hexColor.substring(1, 3), 16);
8298
+ const g = parseInt(hexColor.substring(3, 5), 16);
8299
+ const b = parseInt(hexColor.substring(5, 7), 16);
8300
+ // arithmetic mean μ of the red, green, and blue color coordinates. Source: https://en.wikipedia.org/wiki/Brightness
8301
+ return (r + g + b) / 3;
8302
+ };
8303
+
8304
+ // Copyright (c) Microsoft Corporation.
8305
+ // Licensed under the MIT License.
8306
+ /**
8307
+ * @private
8308
+ */
8309
+ const inputBoxButtonStyle = react.mergeStyles({
8310
+ color: 'grey',
8311
+ margin: 'auto',
8312
+ width: '1.0625rem',
8313
+ height: '1.0625rem',
8314
+ backgroundColor: 'transparent',
8315
+ '&:hover': {
8316
+ backgroundColor: 'transparent'
8317
+ }
8318
+ });
8319
+ /**
8320
+ * @private
8321
+ */
8322
+ const inputBoxButtonTooltipStyle = react.mergeStyles({
8323
+ // The toolTip host container show be a flex box, so that alignItems: 'center' works for inside buttons
8324
+ display: 'flex'
8325
+ });
8326
+ /**
8327
+ * @private
8328
+ */
8329
+ const iconWrapperStyle$1 = react.mergeStyles({
8330
+ pointerEvents: 'none'
8331
+ });
8332
+
8333
+ // Copyright (c) Microsoft Corporation.
8334
+ // Licensed under the MIT License.
8320
8335
  /**
8321
8336
  * @private
8322
8337
  */
8323
8338
  const InputBoxButton = (props) => {
8324
8339
  const { onRenderIcon, onClick, ariaLabel, className, id, tooltipContent } = props;
8325
8340
  const [isHover, setIsHover] = React.useState(false);
8326
- const mergedButtonStyle = react.mergeStyles(inputButtonStyle, className);
8327
- const theme = useTheme();
8341
+ const mergedButtonStyle = react.mergeStyles(inputBoxButtonStyle, className);
8342
+ const theme = react.useTheme();
8328
8343
  const calloutStyle = { root: { padding: 0 }, calloutMain: { padding: '0.5rem' } };
8329
8344
  // Place callout with no gap between it and the button.
8330
8345
  const calloutProps = {
@@ -8332,7 +8347,7 @@ const InputBoxButton = (props) => {
8332
8347
  styles: calloutStyle,
8333
8348
  backgroundColor: isDarkThemed(theme) ? theme.palette.neutralLighter : ''
8334
8349
  };
8335
- return (React.createElement(react.TooltipHost, { hostClassName: inputButtonTooltipStyle, content: tooltipContent, calloutProps: Object.assign({}, calloutProps) },
8350
+ return (React.createElement(react.TooltipHost, { hostClassName: inputBoxButtonTooltipStyle, content: tooltipContent, calloutProps: Object.assign({}, calloutProps) },
8336
8351
  React.createElement(react.IconButton, { className: mergedButtonStyle, ariaLabel: ariaLabel, onClick: onClick, id: id, onMouseEnter: () => {
8337
8352
  setIsHover(true);
8338
8353
  }, onMouseLeave: () => {
@@ -8568,8 +8583,26 @@ const _FileUploadCards = (props) => {
8568
8583
 
8569
8584
  // Copyright (c) Microsoft Corporation.
8570
8585
  // Licensed under the MIT License.
8571
- const EMPTY_MESSAGE_REGEX = /^\s*$/;
8586
+ /* @conditional-compile-remove(file-sharing) */
8587
+ /**
8588
+ * @private
8589
+ */
8590
+ const hasIncompleteFileUploads = (activeFileUploads) => {
8591
+ return !!((activeFileUploads === null || activeFileUploads === void 0 ? void 0 : activeFileUploads.length) &&
8592
+ !activeFileUploads.filter((fileUpload) => !fileUpload.error).every((fileUpload) => fileUpload.uploadComplete));
8593
+ };
8594
+ /* @conditional-compile-remove(file-sharing) */
8595
+ /**
8596
+ * @private
8597
+ */
8598
+ const hasCompletedFileUploads = (activeFileUploads) => {
8599
+ return !!(activeFileUploads === null || activeFileUploads === void 0 ? void 0 : activeFileUploads.find((file) => !file.error));
8600
+ };
8601
+
8602
+ // Copyright (c) Microsoft Corporation.
8603
+ // Licensed under the MIT License.
8572
8604
  const MAXIMUM_LENGTH_OF_MESSAGE$1 = 8000;
8605
+ const EMPTY_MESSAGE_REGEX = /^\s*$/;
8573
8606
  /**
8574
8607
  * Component for typing and sending messages.
8575
8608
  *
@@ -8581,15 +8614,17 @@ const MAXIMUM_LENGTH_OF_MESSAGE$1 = 8000;
8581
8614
  const SendBox = (props) => {
8582
8615
  const { disabled, systemMessage, supportNewline, onSendMessage, onTyping, onRenderIcon, onRenderSystemMessage, styles, autoFocus,
8583
8616
  /* @conditional-compile-remove(mention) */
8584
- mentionLookupOptions } = props;
8617
+ mentionLookupOptions,
8618
+ /* @conditional-compile-remove(file-sharing) */
8619
+ activeFileUploads } = props;
8585
8620
  const theme = useTheme();
8586
8621
  const localeStrings = useLocale$1().strings.sendBox;
8587
8622
  const strings = Object.assign(Object.assign({}, localeStrings), props.strings);
8588
8623
  const ids = useIdentifiers();
8589
- const activeFileUploads = activeFileUploadsTrampoline(props);
8590
8624
  const [textValue, setTextValue] = React.useState('');
8591
8625
  const [textValueOverflow, setTextValueOverflow] = React.useState(false);
8592
8626
  const sendTextFieldRef = React.useRef(null);
8627
+ /* @conditional-compile-remove(file-sharing) */
8593
8628
  const [fileUploadsPendingError, setFileUploadsPendingError] = React.useState(undefined);
8594
8629
  const sendMessageOnClick = () => {
8595
8630
  var _a;
@@ -8598,16 +8633,18 @@ const SendBox = (props) => {
8598
8633
  return;
8599
8634
  }
8600
8635
  // Don't send message until all files have been uploaded successfully
8636
+ /* @conditional-compile-remove(file-sharing) */
8601
8637
  setFileUploadsPendingError(undefined);
8602
- if (hasIncompleteFileUploads(props)) {
8603
- /* @conditional-compile-remove(file-sharing) */
8638
+ /* @conditional-compile-remove(file-sharing) */
8639
+ if (hasIncompleteFileUploads(activeFileUploads)) {
8604
8640
  setFileUploadsPendingError({ message: strings.fileUploadsPendingError, timestamp: Date.now() });
8605
8641
  return;
8606
8642
  }
8607
8643
  const message = textValue;
8608
8644
  // we don't want to send empty messages including spaces, newlines, tabs
8609
8645
  // Message can be empty if there is a valid file upload
8610
- if (!EMPTY_MESSAGE_REGEX.test(message) || hasFile(props)) {
8646
+ if (!EMPTY_MESSAGE_REGEX.test(message) ||
8647
+ /* @conditional-compile-remove(file-sharing) */ hasCompletedFileUploads(activeFileUploads)) {
8611
8648
  onSendMessage && onSendMessage(sanitizeText(message));
8612
8649
  setTextValue('');
8613
8650
  }
@@ -8629,18 +8666,28 @@ const SendBox = (props) => {
8629
8666
  const errorMessage = systemMessage !== null && systemMessage !== void 0 ? systemMessage : textTooLongMessage;
8630
8667
  const mergedSendButtonStyle = React.useMemo(() => react.mergeStyles(sendButtonStyle, styles === null || styles === void 0 ? void 0 : styles.sendMessageIconContainer), [styles === null || styles === void 0 ? void 0 : styles.sendMessageIconContainer]);
8631
8668
  const mergedStyles = React.useMemo(() => react.concatStyleSets(styles), [styles]);
8632
- const hasText = !!textValue;
8633
- const hasTextOrFile = hasText || hasFile(props);
8634
- const mergedSendIconStyle = React.useMemo(() => react.mergeStyles(sendIconStyle, {
8635
- color: !!errorMessage || !hasTextOrFile ? theme.palette.neutralTertiary : theme.palette.themePrimary
8636
- }, styles === null || styles === void 0 ? void 0 : styles.sendMessageIcon), [errorMessage, hasTextOrFile, theme, styles === null || styles === void 0 ? void 0 : styles.sendMessageIcon]);
8669
+ const mergedSendIconStyle = React.useMemo(() => sendIconStyle({
8670
+ theme,
8671
+ hasText: !!textValue,
8672
+ /* @conditional-compile-remove(file-sharing) */ hasFile: hasCompletedFileUploads(activeFileUploads),
8673
+ hasErrorMessage: !!errorMessage,
8674
+ customSendIconStyle: styles === null || styles === void 0 ? void 0 : styles.sendMessageIcon
8675
+ }), [
8676
+ theme,
8677
+ textValue,
8678
+ /* @conditional-compile-remove(file-sharing) */ activeFileUploads,
8679
+ errorMessage,
8680
+ styles === null || styles === void 0 ? void 0 : styles.sendMessageIcon
8681
+ ]);
8637
8682
  const onRenderSendIcon = React.useCallback((isHover) => onRenderIcon ? (onRenderIcon(isHover)) : (React.createElement(react.Icon, { iconName: isHover && textValue ? 'SendBoxSendHovered' : 'SendBoxSend', className: mergedSendIconStyle })), [mergedSendIconStyle, onRenderIcon, textValue]);
8638
8683
  // Ensure that errors are cleared when there are no files in sendBox
8684
+ /* @conditional-compile-remove(file-sharing) */
8639
8685
  React.useEffect(() => {
8640
8686
  if (!(activeFileUploads === null || activeFileUploads === void 0 ? void 0 : activeFileUploads.filter((upload) => !upload.error).length)) {
8641
8687
  setFileUploadsPendingError(undefined);
8642
8688
  }
8643
8689
  }, [activeFileUploads]);
8690
+ /* @conditional-compile-remove(file-sharing) */
8644
8691
  const sendBoxErrorsProps = React.useMemo(() => {
8645
8692
  var _a;
8646
8693
  return {
@@ -8662,13 +8709,13 @@ const SendBox = (props) => {
8662
8709
  } })));
8663
8710
  }, [activeFileUploads, props, localeStrings]);
8664
8711
  return (React.createElement(react.Stack, { className: react.mergeStyles(sendBoxWrapperStyles, { overflow: 'visible' } // This is needed for the mention popup to be visible
8665
- ) },
8712
+ ) }, /* @conditional-compile-remove(file-sharing) */
8666
8713
  React.createElement(SendBoxErrors, Object.assign({}, sendBoxErrorsProps)),
8667
- React.createElement(react.Stack, { className: react.mergeStyles(borderAndBoxShadowStyle({
8714
+ React.createElement(react.Stack, { className: borderAndBoxShadowStyle({
8668
8715
  theme,
8669
8716
  hasErrorMessage: !!errorMessage,
8670
8717
  disabled: !!disabled
8671
- })) },
8718
+ }) },
8672
8719
  React.createElement(InputBoxComponent, { autoFocus: autoFocus, "data-ui-id": ids.sendboxTextField, disabled: disabled, errorMessage: onRenderSystemMessage ? onRenderSystemMessage(errorMessage) : errorMessage, textFieldRef: sendTextFieldRef, id: "sendbox", placeholderText: strings.placeholderText, textValue: textValue, onChange: (_, newValue) => setText(newValue), onKeyDown: (ev) => {
8673
8720
  const keyWasSendingMessage = ev.key === 'Enter' && (ev.shiftKey === false || !supportNewline);
8674
8721
  if (!keyWasSendingMessage) {
@@ -8691,15 +8738,6 @@ const SendBox = (props) => {
8691
8738
  /**
8692
8739
  * @private
8693
8740
  */
8694
- const hasIncompleteFileUploads = (props) => {
8695
- const activeFileUploads = activeFileUploadsTrampoline(props);
8696
- return !!((activeFileUploads === null || activeFileUploads === void 0 ? void 0 : activeFileUploads.length) &&
8697
- !activeFileUploads.filter((fileUpload) => !fileUpload.error).every((fileUpload) => fileUpload.uploadComplete));
8698
- };
8699
- const hasFile = (props) => {
8700
- const activeFileUploads = activeFileUploadsTrampoline(props);
8701
- return !!(activeFileUploads === null || activeFileUploads === void 0 ? void 0 : activeFileUploads.find((file) => !file.error));
8702
- };
8703
8741
  const sanitizeText = (message) => {
8704
8742
  if (EMPTY_MESSAGE_REGEX.test(message)) {
8705
8743
  return '';
@@ -8708,10 +8746,6 @@ const sanitizeText = (message) => {
8708
8746
  return message;
8709
8747
  }
8710
8748
  };
8711
- const activeFileUploadsTrampoline = (props) => {
8712
- /* @conditional-compile-remove(file-sharing) */
8713
- return props.activeFileUploads;
8714
- };
8715
8749
 
8716
8750
  // Copyright (c) Microsoft Corporation.
8717
8751
  // Licensed under the MIT License.
@@ -8959,6 +8993,21 @@ const ImageGallery = (props) => {
8959
8993
  renderBodyWithLightDismiss()));
8960
8994
  };
8961
8995
 
8996
+ // Copyright (c) Microsoft Corporation.
8997
+ // Licensed under the MIT License.
8998
+ /**
8999
+ * @private
9000
+ */
9001
+ react.mergeStyles({
9002
+ border: 'none',
9003
+ overflow: 'auto',
9004
+ padding: '10px',
9005
+ outline: 'none',
9006
+ bottom: '0',
9007
+ minHeight: '2.25rem',
9008
+ maxHeight: '8.25rem'
9009
+ });
9010
+
8962
9011
  // Copyright (c) Microsoft Corporation.
8963
9012
  // Licensed under the MIT License.
8964
9013
  /** @private */
@@ -18403,7 +18452,7 @@ const DialpadButton = (props) => {
18403
18452
  const DialpadContainer = (props) => {
18404
18453
  var _a, _b;
18405
18454
  const theme = react.useTheme();
18406
- const { onSendDtmfTone, onClickDialpadButton, textFieldValue, onChange, showDeleteButton = true, isMobile = false, disableDtmfPlayback, enableInputEditing } = props;
18455
+ const { onSendDtmfTone, onClickDialpadButton, textFieldValue, onChange, showDeleteButton = true, isMobile = false, disableDtmfPlayback, dialpadMode = 'dialer' } = props;
18407
18456
  const dtmfToneAudioContext = React.useRef(new AudioContext());
18408
18457
  const [plainTextValue, setPlainTextValue] = React.useState(textFieldValue !== null && textFieldValue !== void 0 ? textFieldValue : '');
18409
18458
  const plainTextValuePreviousRenderValue = React.useRef(plainTextValue);
@@ -18450,20 +18499,16 @@ const DialpadContainer = (props) => {
18450
18499
  setText(modifiedInput);
18451
18500
  };
18452
18501
  return (React.createElement(react.Stack, { className: react.mergeStyles(containerStyles$3(theme), (_a = props.styles) === null || _a === void 0 ? void 0 : _a.root), "data-test-id": "dialpadContainer", "data-ui-id": "dialpadContainer", horizontalAlign: 'center' },
18453
- React.createElement(react.TextField, { styles: react.concatStyleSets(textFieldStyles(theme), (_b = props.styles) === null || _b === void 0 ? void 0 : _b.textField), value: textFieldValue ? textFieldValue : enableInputEditing ? formatPhoneNumber(plainTextValue) : plainTextValue,
18502
+ dialpadMode === 'dialer' && (React.createElement(react.TextField, { styles: react.concatStyleSets(textFieldStyles(theme), (_b = props.styles) === null || _b === void 0 ? void 0 : _b.textField), value: textFieldValue ? textFieldValue : formatPhoneNumber(plainTextValue),
18454
18503
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
18455
18504
  onChange: (e) => {
18456
- if (enableInputEditing) {
18457
- setText(e.target.value);
18458
- }
18505
+ setText(e.target.value);
18459
18506
  }, onClick: (e) => {
18460
- if (!enableInputEditing) {
18461
- e.preventDefault();
18462
- }
18507
+ e.preventDefault();
18463
18508
  }, placeholder: props.strings.placeholderText, "data-test-id": "dialpad-input", onRenderSuffix: () => {
18464
18509
  var _a;
18465
18510
  return (React.createElement(React.Fragment, null, showDeleteButton && plainTextValue.length !== 0 && (React.createElement(react.IconButton, { ariaLabel: props.strings.deleteButtonAriaLabel, onClick: deleteNumbers, styles: react.concatStyleSets(iconButtonStyles(theme), (_a = props.styles) === null || _a === void 0 ? void 0 : _a.deleteIcon), iconProps: { iconName: 'DialpadBackspace' } }))));
18466
- } }),
18511
+ } })),
18467
18512
  React.createElement(react.FocusZone, null, dialPadButtonsDefault.map((rows, rowIndex) => {
18468
18513
  return (React.createElement(react.Stack, { horizontal: true, key: `row_${rowIndex}`, horizontalAlign: "stretch", tokens: { childrenGap: '1rem' } }, rows.map((button, columnIndex) => (React.createElement(DialpadButton, { key: `button_${columnIndex}`,
18469
18514
  /* row index = 0
@@ -25714,6 +25759,10 @@ const getLatestCapabilitiesChangedInfo = (state) => {
25714
25759
  var _a, _b;
25715
25760
  return (_b = (_a = state.call) === null || _a === void 0 ? void 0 : _a.capabilitiesFeature) === null || _b === void 0 ? void 0 : _b.latestCapabilitiesChangeInfo;
25716
25761
  };
25762
+ /**
25763
+ * @private
25764
+ */
25765
+ const getTargetCallees = (state) => state.targetCallees;
25717
25766
 
25718
25767
  // Copyright (c) Microsoft Corporation.
25719
25768
  // Licensed under the MIT License.
@@ -26472,6 +26521,151 @@ const useCallWithChatCompositeStrings = () => {
26472
26521
  return locale.strings.callWithChat;
26473
26522
  };
26474
26523
 
26524
+ // Copyright (c) Microsoft Corporation.
26525
+ // Licensed under the MIT License.
26526
+ /**
26527
+ * @private
26528
+ */
26529
+ const mediaGallerySelector = reselect__namespace.createSelector([getLocalVideoStreams], (localVideoStreams) => {
26530
+ var _a, _b;
26531
+ return {
26532
+ isVideoStreamOn: !!((_b = (_a = localVideoStreams === null || localVideoStreams === void 0 ? void 0 : localVideoStreams.find((stream) => stream.mediaStreamType === 'Video')) === null || _a === void 0 ? void 0 : _a.view) === null || _b === void 0 ? void 0 : _b.target)
26533
+ };
26534
+ });
26535
+ /**
26536
+ * Custom selector for this hook to retrieve all the participants that are currently
26537
+ * connected to the call.
26538
+ */
26539
+ const getRemoteParticipantsConnectedSelector = reselect__namespace.createSelector([getRemoteParticipants], (remoteParticipants) => {
26540
+ const participants = Object.values(remoteParticipants !== null && remoteParticipants !== void 0 ? remoteParticipants : {});
26541
+ return participants.filter((p) => p.state === 'Connected');
26542
+ });
26543
+
26544
+ // Copyright (c) Microsoft Corporation.
26545
+ // Licensed under the MIT License.
26546
+ /**
26547
+ * sets the announcement string whenever a Participant comes or goes from a call to be
26548
+ * used by the system narrator.
26549
+ *
26550
+ * @returns string to be used by the narrator and Announcer component
26551
+ *
26552
+ * @internal
26553
+ */
26554
+ const useParticipantChangedAnnouncement = () => {
26555
+ const locale = useLocale().strings.call;
26556
+ const strings = React.useMemo(() => {
26557
+ return {
26558
+ participantJoinedNoticeString: locale.participantJoinedNoticeString,
26559
+ twoParticipantJoinedNoticeString: locale.twoParticipantJoinedNoticeString,
26560
+ threeParticipantJoinedNoticeString: locale.threeParticipantJoinedNoticeString,
26561
+ participantLeftNoticeString: locale.participantLeftNoticeString,
26562
+ twoParticipantLeftNoticeString: locale.twoParticipantLeftNoticeString,
26563
+ threeParticipantLeftNoticeString: locale.threeParticipantLeftNoticeString,
26564
+ unnamedParticipantString: locale.unnamedParticipantString,
26565
+ manyParticipantsJoined: locale.manyParticipantsJoined,
26566
+ manyParticipantsLeft: locale.manyParticipantsLeft,
26567
+ manyUnnamedParticipantsJoined: locale.manyUnnamedParticipantsJoined,
26568
+ manyUnnamedParticipantsLeft: locale.manyUnnamedParticipantsLeft
26569
+ };
26570
+ }, [locale]);
26571
+ const [announcerString, setAnnouncerString] = React.useState('');
26572
+ const currentParticipants = useSelector$1(getRemoteParticipantsConnectedSelector);
26573
+ /**
26574
+ * We want to use a useRef here since we want to not fire this hook based on the previous participants
26575
+ * this allows this value to be used in the hook without being in the dependency array.
26576
+ *
26577
+ * Note: By definition if this hook is used in another component it is not pure anymore.
26578
+ */
26579
+ const previousParticipants = React.useRef(currentParticipants);
26580
+ const resetAnnoucement = (string) => {
26581
+ setAnnouncerString(string);
26582
+ };
26583
+ React.useMemo(() => {
26584
+ const currentIds = currentParticipants.map((p) => toFlatCommunicationIdentifier(p.identifier));
26585
+ const previousIds = previousParticipants.current.map((p) => toFlatCommunicationIdentifier(p.identifier));
26586
+ const whoJoined = currentParticipants.filter((p) => !previousIds.includes(toFlatCommunicationIdentifier(p.identifier)));
26587
+ const whoLeft = previousParticipants.current.filter((p) => !currentIds.includes(toFlatCommunicationIdentifier(p.identifier)));
26588
+ if (whoJoined.length > 0) {
26589
+ resetAnnoucement(createAnnouncementString('joined', whoJoined, strings));
26590
+ }
26591
+ if (whoLeft.length > 0) {
26592
+ resetAnnoucement(createAnnouncementString('left', whoLeft, strings));
26593
+ }
26594
+ // Update cached value at the end.
26595
+ previousParticipants.current = currentParticipants;
26596
+ }, [currentParticipants, strings]);
26597
+ return announcerString;
26598
+ };
26599
+ /**
26600
+ * Generates the announcement string for when a participant joins or leaves a call.
26601
+ */
26602
+ const createAnnouncementString = (direction, participants, strings) => {
26603
+ var _a, _b, _c;
26604
+ /**
26605
+ * If there are no participants return empty string.
26606
+ */
26607
+ if (participants.length === 0) {
26608
+ return '';
26609
+ }
26610
+ /**
26611
+ * Filter participants into two arrays to put all the unnamed participants at the back of the
26612
+ * names being announced.
26613
+ */
26614
+ const unnamedParticipants = participants.filter((p) => !p.displayName);
26615
+ const namedParicipants = participants.filter((p) => p.displayName);
26616
+ const sortedParticipants = namedParicipants.concat(unnamedParticipants);
26617
+ /**
26618
+ * if there are only unnamed participants present in the array announce a special unnamed participants
26619
+ * only string.
26620
+ */
26621
+ if (sortedParticipants.filter((p) => p.displayName).length === 0 && sortedParticipants.length > 1) {
26622
+ return _formatString(direction === 'joined' ? strings.manyUnnamedParticipantsJoined : strings.manyUnnamedParticipantsLeft, {
26623
+ numOfParticipants: (sortedParticipants.length - 1).toString()
26624
+ });
26625
+ }
26626
+ const participantNames = sortedParticipants.map((p) => { var _a; return (_a = p.displayName) !== null && _a !== void 0 ? _a : strings.unnamedParticipantString; });
26627
+ switch (sortedParticipants.length) {
26628
+ case 1:
26629
+ return _formatString(direction === 'joined' ? strings.participantJoinedNoticeString : strings.participantLeftNoticeString, { displayName: participantNames[0] });
26630
+ case 2:
26631
+ return _formatString(direction === 'joined' ? strings.twoParticipantJoinedNoticeString : strings.twoParticipantLeftNoticeString, {
26632
+ displayName1: participantNames[0],
26633
+ displayName2: participantNames[1]
26634
+ });
26635
+ case 3:
26636
+ return _formatString(direction === 'joined' ? strings.threeParticipantJoinedNoticeString : strings.threeParticipantLeftNoticeString, {
26637
+ displayName1: participantNames[0],
26638
+ displayName2: participantNames[1],
26639
+ displayName3: participantNames[2]
26640
+ });
26641
+ }
26642
+ /**
26643
+ * If we have more than 3 participants joining we need to do something more to announce them
26644
+ * appropriately.
26645
+ *
26646
+ * We don't want to announce every name when more than 3 participants join at once so
26647
+ * we parse out the first 3 names we have and announce those with the number of others.
26648
+ */
26649
+ const numberOfExtraParticipants = sortedParticipants.length - 3;
26650
+ return _formatString(direction === 'joined' ? strings.manyParticipantsJoined : strings.manyParticipantsLeft, {
26651
+ displayName1: (_a = sortedParticipants[0].displayName) !== null && _a !== void 0 ? _a : strings.unnamedParticipantString,
26652
+ displayName2: (_b = sortedParticipants[1].displayName) !== null && _b !== void 0 ? _b : strings.unnamedParticipantString,
26653
+ displayName3: (_c = sortedParticipants[2].displayName) !== null && _c !== void 0 ? _c : strings.unnamedParticipantString,
26654
+ numOfParticipants: numberOfExtraParticipants.toString()
26655
+ });
26656
+ };
26657
+ /* @conditional-compile-remove(dtmf-dialer) */
26658
+ /**
26659
+ * determines if the media gallery should be replaced by the dtmf dialer
26660
+ * @param callees Target callees to determine if the dtmf dialer should be shown
26661
+ * @returns whether the dialer should be the gallery content or not
26662
+ */
26663
+ const showDtmfDialer = (callees) => {
26664
+ return !!((callees === null || callees === void 0 ? void 0 : callees.filter((callee) => {
26665
+ return communicationCommon.isPhoneNumberIdentifier(callee) || communicationCommon.isMicrosoftTeamsAppIdentifier(callee);
26666
+ })) && callees.length > 0);
26667
+ };
26668
+
26475
26669
  // Copyright (c) Microsoft Corporation.
26476
26670
  // Licensed under the MIT License.
26477
26671
  var __awaiter$f = (window && window.__awaiter) || function (thisArg, _arguments, P, generator) {
@@ -26510,6 +26704,10 @@ const DesktopMoreButton = (props) => {
26510
26704
  /* @conditional-compile-remove(gallery-layouts) */
26511
26705
  const [previousLayout, setPreviousLayout] = React.useState((_a = props.userSetGalleryLayout) !== null && _a !== void 0 ? _a : 'floatingLocalVideo');
26512
26706
  /* @conditional-compile-remove(dtmf-dialer) */
26707
+ const callees = useSelector$1(getTargetCallees);
26708
+ /* @conditional-compile-remove(dtmf-dialer) */
26709
+ const allowDtmfDialer = showDtmfDialer(callees);
26710
+ /* @conditional-compile-remove(dtmf-dialer) */
26513
26711
  const [dtmfDialerChecked, setDtmfDialerChecked] = React.useState((_b = props.dtmfDialerPresent) !== null && _b !== void 0 ? _b : false);
26514
26712
  /* @conditional-compile-remove(PSTN-calls) */ /* @conditional-compile-remove(one-to-n-calling) */ /* @conditional-compile-remove(close-captions) */
26515
26713
  const moreButtonStrings = React.useMemo(() => ({
@@ -26624,24 +26822,9 @@ const DesktopMoreButton = (props) => {
26624
26822
  /**
26625
26823
  * Only render the dtmf dialer if the dialpad for PSTN calls is not present
26626
26824
  */
26627
- if (props.onSetDialpadPage && !props.onClickShowDialpad) {
26825
+ if (props.onSetDialpadPage && allowDtmfDialer) {
26628
26826
  moreButtonContextualMenuItems.push(dtmfDialerScreenOption);
26629
26827
  }
26630
- /*@conditional-compile-remove(PSTN-calls) */
26631
- if (props.onClickShowDialpad) {
26632
- moreButtonContextualMenuItems.push({
26633
- key: 'showDialpadKey',
26634
- text: localeStrings.strings.callWithChat.openDtmfDialpadLabel,
26635
- onClick: () => {
26636
- props.onClickShowDialpad && props.onClickShowDialpad();
26637
- },
26638
- iconProps: { iconName: 'Dialpad', styles: { root: { lineHeight: 0 } } },
26639
- itemProps: {
26640
- styles: buttonFlyoutIncreasedSizeStyles
26641
- },
26642
- disabled: props.disableButtonsForHoldScreen
26643
- });
26644
- }
26645
26828
  /* @conditional-compile-remove(gallery-layouts) */
26646
26829
  if (props.onUserSetOverflowGalleryPositionChange) {
26647
26830
  const galleryOptions = {
@@ -29385,140 +29568,6 @@ const localVideoCameraCycleButtonSelector = reselect.createSelector([getDeviceMa
29385
29568
  };
29386
29569
  });
29387
29570
 
29388
- // Copyright (c) Microsoft Corporation.
29389
- // Licensed under the MIT License.
29390
- /**
29391
- * @private
29392
- */
29393
- const mediaGallerySelector = reselect__namespace.createSelector([getLocalVideoStreams], (localVideoStreams) => {
29394
- var _a, _b;
29395
- return {
29396
- isVideoStreamOn: !!((_b = (_a = localVideoStreams === null || localVideoStreams === void 0 ? void 0 : localVideoStreams.find((stream) => stream.mediaStreamType === 'Video')) === null || _a === void 0 ? void 0 : _a.view) === null || _b === void 0 ? void 0 : _b.target)
29397
- };
29398
- });
29399
- /**
29400
- * Custom selector for this hook to retrieve all the participants that are currently
29401
- * connected to the call.
29402
- */
29403
- const getRemoteParticipantsConnectedSelector = reselect__namespace.createSelector([getRemoteParticipants], (remoteParticipants) => {
29404
- const participants = Object.values(remoteParticipants !== null && remoteParticipants !== void 0 ? remoteParticipants : {});
29405
- return participants.filter((p) => p.state === 'Connected');
29406
- });
29407
-
29408
- // Copyright (c) Microsoft Corporation.
29409
- // Licensed under the MIT License.
29410
- /**
29411
- * sets the announcement string whenever a Participant comes or goes from a call to be
29412
- * used by the system narrator.
29413
- *
29414
- * @returns string to be used by the narrator and Announcer component
29415
- *
29416
- * @internal
29417
- */
29418
- const useParticipantChangedAnnouncement = () => {
29419
- const locale = useLocale().strings.call;
29420
- const strings = React.useMemo(() => {
29421
- return {
29422
- participantJoinedNoticeString: locale.participantJoinedNoticeString,
29423
- twoParticipantJoinedNoticeString: locale.twoParticipantJoinedNoticeString,
29424
- threeParticipantJoinedNoticeString: locale.threeParticipantJoinedNoticeString,
29425
- participantLeftNoticeString: locale.participantLeftNoticeString,
29426
- twoParticipantLeftNoticeString: locale.twoParticipantLeftNoticeString,
29427
- threeParticipantLeftNoticeString: locale.threeParticipantLeftNoticeString,
29428
- unnamedParticipantString: locale.unnamedParticipantString,
29429
- manyParticipantsJoined: locale.manyParticipantsJoined,
29430
- manyParticipantsLeft: locale.manyParticipantsLeft,
29431
- manyUnnamedParticipantsJoined: locale.manyUnnamedParticipantsJoined,
29432
- manyUnnamedParticipantsLeft: locale.manyUnnamedParticipantsLeft
29433
- };
29434
- }, [locale]);
29435
- const [announcerString, setAnnouncerString] = React.useState('');
29436
- const currentParticipants = useSelector$1(getRemoteParticipantsConnectedSelector);
29437
- /**
29438
- * We want to use a useRef here since we want to not fire this hook based on the previous participants
29439
- * this allows this value to be used in the hook without being in the dependency array.
29440
- *
29441
- * Note: By definition if this hook is used in another component it is not pure anymore.
29442
- */
29443
- const previousParticipants = React.useRef(currentParticipants);
29444
- const resetAnnoucement = (string) => {
29445
- setAnnouncerString(string);
29446
- };
29447
- React.useMemo(() => {
29448
- const currentIds = currentParticipants.map((p) => toFlatCommunicationIdentifier(p.identifier));
29449
- const previousIds = previousParticipants.current.map((p) => toFlatCommunicationIdentifier(p.identifier));
29450
- const whoJoined = currentParticipants.filter((p) => !previousIds.includes(toFlatCommunicationIdentifier(p.identifier)));
29451
- const whoLeft = previousParticipants.current.filter((p) => !currentIds.includes(toFlatCommunicationIdentifier(p.identifier)));
29452
- if (whoJoined.length > 0) {
29453
- resetAnnoucement(createAnnouncementString('joined', whoJoined, strings));
29454
- }
29455
- if (whoLeft.length > 0) {
29456
- resetAnnoucement(createAnnouncementString('left', whoLeft, strings));
29457
- }
29458
- // Update cached value at the end.
29459
- previousParticipants.current = currentParticipants;
29460
- }, [currentParticipants, strings]);
29461
- return announcerString;
29462
- };
29463
- /**
29464
- * Generates the announcement string for when a participant joins or leaves a call.
29465
- */
29466
- const createAnnouncementString = (direction, participants, strings) => {
29467
- var _a, _b, _c;
29468
- /**
29469
- * If there are no participants return empty string.
29470
- */
29471
- if (participants.length === 0) {
29472
- return '';
29473
- }
29474
- /**
29475
- * Filter participants into two arrays to put all the unnamed participants at the back of the
29476
- * names being announced.
29477
- */
29478
- const unnamedParticipants = participants.filter((p) => !p.displayName);
29479
- const namedParicipants = participants.filter((p) => p.displayName);
29480
- const sortedParticipants = namedParicipants.concat(unnamedParticipants);
29481
- /**
29482
- * if there are only unnamed participants present in the array announce a special unnamed participants
29483
- * only string.
29484
- */
29485
- if (sortedParticipants.filter((p) => p.displayName).length === 0 && sortedParticipants.length > 1) {
29486
- return _formatString(direction === 'joined' ? strings.manyUnnamedParticipantsJoined : strings.manyUnnamedParticipantsLeft, {
29487
- numOfParticipants: (sortedParticipants.length - 1).toString()
29488
- });
29489
- }
29490
- const participantNames = sortedParticipants.map((p) => { var _a; return (_a = p.displayName) !== null && _a !== void 0 ? _a : strings.unnamedParticipantString; });
29491
- switch (sortedParticipants.length) {
29492
- case 1:
29493
- return _formatString(direction === 'joined' ? strings.participantJoinedNoticeString : strings.participantLeftNoticeString, { displayName: participantNames[0] });
29494
- case 2:
29495
- return _formatString(direction === 'joined' ? strings.twoParticipantJoinedNoticeString : strings.twoParticipantLeftNoticeString, {
29496
- displayName1: participantNames[0],
29497
- displayName2: participantNames[1]
29498
- });
29499
- case 3:
29500
- return _formatString(direction === 'joined' ? strings.threeParticipantJoinedNoticeString : strings.threeParticipantLeftNoticeString, {
29501
- displayName1: participantNames[0],
29502
- displayName2: participantNames[1],
29503
- displayName3: participantNames[2]
29504
- });
29505
- }
29506
- /**
29507
- * If we have more than 3 participants joining we need to do something more to announce them
29508
- * appropriately.
29509
- *
29510
- * We don't want to announce every name when more than 3 participants join at once so
29511
- * we parse out the first 3 names we have and announce those with the number of others.
29512
- */
29513
- const numberOfExtraParticipants = sortedParticipants.length - 3;
29514
- return _formatString(direction === 'joined' ? strings.manyParticipantsJoined : strings.manyParticipantsLeft, {
29515
- displayName1: (_a = sortedParticipants[0].displayName) !== null && _a !== void 0 ? _a : strings.unnamedParticipantString,
29516
- displayName2: (_b = sortedParticipants[1].displayName) !== null && _b !== void 0 ? _b : strings.unnamedParticipantString,
29517
- displayName3: (_c = sortedParticipants[2].displayName) !== null && _c !== void 0 ? _c : strings.unnamedParticipantString,
29518
- numOfParticipants: numberOfExtraParticipants.toString()
29519
- });
29520
- };
29521
-
29522
29571
  // Copyright (c) Microsoft Corporation.
29523
29572
  // Licensed under the MIT License.
29524
29573
  const VideoGalleryStyles = {
@@ -29878,16 +29927,22 @@ const DtmfDialpadPageContent = (props) => {
29878
29927
  const remoteParticipants = (_b = adapterState.call) === null || _b === void 0 ? void 0 : _b.remoteParticipants;
29879
29928
  let calleeName;
29880
29929
  if (remoteParticipants) {
29881
- calleeName = Object.values(remoteParticipants).find((p) => p.identifier === calleeId);
29930
+ const remoteParticipantValues = Object.values(remoteParticipants);
29931
+ if (calleeId && communicationCommon.isPhoneNumberIdentifier(calleeId)) {
29932
+ calleeName = calleeId.phoneNumber;
29933
+ }
29934
+ else {
29935
+ calleeName = remoteParticipantValues.find((p) => p.identifier === calleeId);
29936
+ }
29882
29937
  }
29883
29938
  return (React.createElement(react.Stack, { style: { height: '100%', width: '100%', background: theme.palette.white } },
29884
- React.createElement(react.Stack, { style: { margin: 'auto' } },
29939
+ React.createElement(react.Stack, { verticalAlign: 'center', style: { margin: 'auto' } },
29885
29940
  React.createElement(DtmfDialerContentTimer, null),
29886
- React.createElement(react.Text, null, calleeName !== 'Unnamed participant' ? calleeName : ''),
29941
+ React.createElement(react.Text, { style: { margin: 'auto' } }, calleeName !== 'Unnamed participant' ? calleeName : ''),
29887
29942
  React.createElement(Dialpad, { onSendDtmfTone: (tone) => __awaiter$b(void 0, void 0, void 0, function* () {
29888
29943
  /* @conditional-compile-remove(dtmf-dialer) */
29889
29944
  yield adapter.sendDtmfTone(tone);
29890
- }), enableInputEditing: false }))));
29945
+ }), dialpadMode: 'dtmf' }))));
29891
29946
  };
29892
29947
  const DtmfDialerContentTimer = () => {
29893
29948
  const [time, setTime] = React.useState(0);
@@ -29936,7 +29991,26 @@ const CallPage = (props) => {
29936
29991
  const mutedNotificationProps = useSelector$1(mutedNotificationSelector);
29937
29992
  const networkReconnectTileProps = useSelector$1(networkReconnectTileSelector);
29938
29993
  /* @conditional-compile-remove(dtmf-dialer) */
29939
- const [dtmfDialerPresent, setDtmfDialerPresent] = React.useState(false);
29994
+ const remoteParticipantsConnected = useSelector$1(getRemoteParticipantsConnectedSelector);
29995
+ /* @conditional-compile-remove(dtmf-dialer) */
29996
+ const callees = useSelector$1(getTargetCallees);
29997
+ /* @conditional-compile-remove(dtmf-dialer) */
29998
+ const renderDtmfDialerFromStart = showDtmfDialer(callees);
29999
+ /* @conditional-compile-remove(dtmf-dialer) */
30000
+ const [dtmfDialerPresent, setDtmfDialerPresent] = React.useState(renderDtmfDialerFromStart);
30001
+ /* @conditional-compile-remove(dtmf-dialer) */
30002
+ const dialerShouldAutoDismiss = React.useRef(renderDtmfDialerFromStart);
30003
+ /* @conditional-compile-remove(dtmf-dialer) */
30004
+ /**
30005
+ * This useEffect is about clearing the dtmf dialer should there be a new participant that joins the call.
30006
+ * This will only happen the first time should the dialer be present when the call starts.
30007
+ */
30008
+ React.useEffect(() => {
30009
+ if (remoteParticipantsConnected.length > 1 && dtmfDialerPresent && dialerShouldAutoDismiss.current) {
30010
+ setDtmfDialerPresent(false);
30011
+ dialerShouldAutoDismiss.current = false;
30012
+ }
30013
+ }, [dtmfDialerPresent, remoteParticipantsConnected, setDtmfDialerPresent]);
29940
30014
  const strings = useLocale().strings.call;
29941
30015
  // Reduce the controls shown when mobile view is enabled.
29942
30016
  const callControlOptions = mobileView ? reduceCallControlsForMobile(options === null || options === void 0 ? void 0 : options.callControls) : options === null || options === void 0 ? void 0 : options.callControls;
@@ -29977,7 +30051,9 @@ const CallPage = (props) => {
29977
30051
  /* @conditional-compile-remove(capabilities) */
29978
30052
  capabilitiesChangedNotificationBarProps: props.capabilitiesChangedNotificationBarProps,
29979
30053
  /* @conditional-compile-remove(dtmf-dialer) */
29980
- onSetDialpadPage: () => setDtmfDialerPresent(!dtmfDialerPresent) }));
30054
+ onSetDialpadPage: () => setDtmfDialerPresent(!dtmfDialerPresent),
30055
+ /* @conditional-compile-remove(dtmf-dialer) */
30056
+ dtmfDialerPresent: dtmfDialerPresent }));
29981
30057
  };
29982
30058
  /**
29983
30059
  * @private