@azure/communication-react 1.19.0-alpha-202408010015 → 1.19.0-alpha-202408020014

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 (76) hide show
  1. package/dist/communication-react.d.ts +33 -33
  2. package/dist/dist-cjs/communication-react/{ChatMessageComponentAsRichTextEditBox-B0zbyF6Z.js → ChatMessageComponentAsRichTextEditBox-DM13Kp5W.js} +52 -33
  3. package/dist/dist-cjs/communication-react/ChatMessageComponentAsRichTextEditBox-DM13Kp5W.js.map +1 -0
  4. package/dist/dist-cjs/communication-react/{RichTextSendBoxWrapper-BVOysnsq.js → RichTextSendBoxWrapper-8FsFMpKF.js} +3 -3
  5. package/dist/dist-cjs/communication-react/{RichTextSendBoxWrapper-BVOysnsq.js.map → RichTextSendBoxWrapper-8FsFMpKF.js.map} +1 -1
  6. package/dist/dist-cjs/communication-react/{index-YIP5Cyt3.js → index-D84PSTZV.js} +496 -193
  7. package/dist/dist-cjs/communication-react/index-D84PSTZV.js.map +1 -0
  8. package/dist/dist-cjs/communication-react/index.js +2 -2
  9. package/dist/dist-esm/acs-ui-common/src/constants.d.ts +5 -0
  10. package/dist/dist-esm/acs-ui-common/src/constants.js +6 -0
  11. package/dist/dist-esm/acs-ui-common/src/constants.js.map +1 -1
  12. package/dist/dist-esm/acs-ui-common/src/index.d.ts +1 -0
  13. package/dist/dist-esm/acs-ui-common/src/index.js +2 -0
  14. package/dist/dist-esm/acs-ui-common/src/index.js.map +1 -1
  15. package/dist/dist-esm/acs-ui-common/src/telemetryVersion.js +1 -1
  16. package/dist/dist-esm/acs-ui-common/src/telemetryVersion.js.map +1 -1
  17. package/dist/dist-esm/chat-component-bindings/src/handlers/createHandlers.js +6 -1
  18. package/dist/dist-esm/chat-component-bindings/src/handlers/createHandlers.js.map +1 -1
  19. package/dist/dist-esm/communication-react/src/index.d.ts +1 -1
  20. package/dist/dist-esm/communication-react/src/index.js.map +1 -1
  21. package/dist/dist-esm/react-components/src/components/ChatMessage/ChatMessageComponentWrapper.d.ts +3 -3
  22. package/dist/dist-esm/react-components/src/components/ChatMessage/ChatMessageComponentWrapper.js.map +1 -1
  23. package/dist/dist-esm/react-components/src/components/ChatMessage/MyMessageComponents/ChatMessageComponentAsEditBoxPicker.d.ts +3 -3
  24. package/dist/dist-esm/react-components/src/components/ChatMessage/MyMessageComponents/ChatMessageComponentAsEditBoxPicker.js.map +1 -1
  25. package/dist/dist-esm/react-components/src/components/ChatMessage/MyMessageComponents/ChatMessageComponentAsRichTextEditBox.d.ts +3 -3
  26. package/dist/dist-esm/react-components/src/components/ChatMessage/MyMessageComponents/ChatMessageComponentAsRichTextEditBox.js +53 -32
  27. package/dist/dist-esm/react-components/src/components/ChatMessage/MyMessageComponents/ChatMessageComponentAsRichTextEditBox.js.map +1 -1
  28. package/dist/dist-esm/react-components/src/components/ChatMessage/MyMessageComponents/ChatMyMessageComponent.d.ts +3 -3
  29. package/dist/dist-esm/react-components/src/components/ChatMessage/MyMessageComponents/ChatMyMessageComponent.js +2 -2
  30. package/dist/dist-esm/react-components/src/components/ChatMessage/MyMessageComponents/ChatMyMessageComponent.js.map +1 -1
  31. package/dist/dist-esm/react-components/src/components/ChatMessage/MyMessageComponents/FluentChatMyMessageComponent.js +6 -6
  32. package/dist/dist-esm/react-components/src/components/ChatMessage/MyMessageComponents/FluentChatMyMessageComponent.js.map +1 -1
  33. package/dist/dist-esm/react-components/src/components/MessageThread.d.ts +18 -6
  34. package/dist/dist-esm/react-components/src/components/MessageThread.js +3 -3
  35. package/dist/dist-esm/react-components/src/components/MessageThread.js.map +1 -1
  36. package/dist/dist-esm/react-components/src/components/RichTextEditor/Plugins/CopyPastePlugin.d.ts +2 -2
  37. package/dist/dist-esm/react-components/src/components/RichTextEditor/Plugins/CopyPastePlugin.js +18 -34
  38. package/dist/dist-esm/react-components/src/components/RichTextEditor/Plugins/CopyPastePlugin.js.map +1 -1
  39. package/dist/dist-esm/react-components/src/components/RichTextEditor/Plugins/UndoRedoPlugin.d.ts +14 -0
  40. package/dist/dist-esm/react-components/src/components/RichTextEditor/Plugins/UndoRedoPlugin.js +56 -0
  41. package/dist/dist-esm/react-components/src/components/RichTextEditor/Plugins/UndoRedoPlugin.js.map +1 -0
  42. package/dist/dist-esm/react-components/src/components/RichTextEditor/Plugins/UpdateContentPlugin.d.ts +1 -1
  43. package/dist/dist-esm/react-components/src/components/RichTextEditor/Plugins/UpdateContentPlugin.js +10 -16
  44. package/dist/dist-esm/react-components/src/components/RichTextEditor/Plugins/UpdateContentPlugin.js.map +1 -1
  45. package/dist/dist-esm/react-components/src/components/RichTextEditor/RichTextEditor.d.ts +2 -2
  46. package/dist/dist-esm/react-components/src/components/RichTextEditor/RichTextEditor.js +85 -8
  47. package/dist/dist-esm/react-components/src/components/RichTextEditor/RichTextEditor.js.map +1 -1
  48. package/dist/dist-esm/react-components/src/components/RichTextEditor/RichTextInputBoxComponent.d.ts +2 -2
  49. package/dist/dist-esm/react-components/src/components/RichTextEditor/RichTextInputBoxComponent.js.map +1 -1
  50. package/dist/dist-esm/react-components/src/components/RichTextEditor/RichTextSendBox.d.ts +16 -27
  51. package/dist/dist-esm/react-components/src/components/RichTextEditor/RichTextSendBox.js +33 -35
  52. package/dist/dist-esm/react-components/src/components/RichTextEditor/RichTextSendBox.js.map +1 -1
  53. package/dist/dist-esm/react-components/src/components/index.d.ts +1 -1
  54. package/dist/dist-esm/react-components/src/components/index.js.map +1 -1
  55. package/dist/dist-esm/react-components/src/components/utils/RichTextEditorUtils.d.ts +34 -0
  56. package/dist/dist-esm/react-components/src/components/utils/RichTextEditorUtils.js +121 -0
  57. package/dist/dist-esm/react-components/src/components/utils/RichTextEditorUtils.js.map +1 -1
  58. package/dist/dist-esm/react-components/src/components/utils/SendBoxUtils.d.ts +15 -13
  59. package/dist/dist-esm/react-components/src/components/utils/SendBoxUtils.js +42 -32
  60. package/dist/dist-esm/react-components/src/components/utils/SendBoxUtils.js.map +1 -1
  61. package/dist/dist-esm/react-composites/src/composites/CallComposite/utils/TrackCapabilityChangedNotifications.js +19 -6
  62. package/dist/dist-esm/react-composites/src/composites/CallComposite/utils/TrackCapabilityChangedNotifications.js.map +1 -1
  63. package/dist/dist-esm/react-composites/src/composites/ChatComposite/ChatScreen.js +21 -12
  64. package/dist/dist-esm/react-composites/src/composites/ChatComposite/ChatScreen.js.map +1 -1
  65. package/dist/dist-esm/react-composites/src/composites/ChatComposite/ImageUpload/ImageUploadUtils.d.ts +5 -5
  66. package/dist/dist-esm/react-composites/src/composites/ChatComposite/ImageUpload/ImageUploadUtils.js +61 -31
  67. package/dist/dist-esm/react-composites/src/composites/ChatComposite/ImageUpload/ImageUploadUtils.js.map +1 -1
  68. package/dist/dist-esm/react-composites/src/composites/common/SendBoxPicker.d.ts +32 -2
  69. package/dist/dist-esm/react-composites/src/composites/common/SendBoxPicker.js +3 -3
  70. package/dist/dist-esm/react-composites/src/composites/common/SendBoxPicker.js.map +1 -1
  71. package/dist/dist-esm/react-composites/src/composites/common/constants.d.ts +5 -0
  72. package/dist/dist-esm/react-composites/src/composites/common/constants.js +6 -0
  73. package/dist/dist-esm/react-composites/src/composites/common/constants.js.map +1 -1
  74. package/package.json +1 -1
  75. package/dist/dist-cjs/communication-react/ChatMessageComponentAsRichTextEditBox-B0zbyF6Z.js.map +0 -1
  76. package/dist/dist-cjs/communication-react/index-YIP5Cyt3.js.map +0 -1
@@ -16,12 +16,12 @@ var textareaCaretTs = require('textarea-caret-ts');
16
16
  var useDebounce = require('use-debounce');
17
17
  var reactFileTypeIcons = require('@fluentui/react-file-type-icons');
18
18
  var react$1 = require('@griffel/react');
19
+ var uuid = require('uuid');
19
20
  var roosterjsContentModelCore = require('roosterjs-content-model-core');
20
21
  var roosterjsContentModelDom = require('roosterjs-content-model-dom');
21
22
  var roosterjsContentModelPlugins = require('roosterjs-content-model-plugins');
22
23
  var roosterjsContentModelApi = require('roosterjs-content-model-api');
23
24
  var reactChat = require('@fluentui-contrib/react-chat');
24
- var uuid = require('uuid');
25
25
  var parse = require('html-react-parser');
26
26
  var Linkify = require('react-linkify');
27
27
  var DOMPurify = require('dompurify');
@@ -189,7 +189,7 @@ function getDefaultExportFromCjs (x) {
189
189
  // Copyright (c) Microsoft Corporation.
190
190
  // Licensed under the MIT License.
191
191
  // GENERATED FILE. DO NOT EDIT MANUALLY.
192
- var telemetryVersion = '1.19.0-alpha-202408010015';
192
+ var telemetryVersion = '1.19.0-alpha-202408020014';
193
193
 
194
194
 
195
195
  var telemetryVersion$1 = /*@__PURE__*/getDefaultExportFromCjs(telemetryVersion);
@@ -400,6 +400,19 @@ const removeImageTags = (event) => {
400
400
  });
401
401
  };
402
402
 
403
+ // Copyright (c) Microsoft Corporation.
404
+ // Licensed under the MIT License.
405
+ /**
406
+ * Default max listeners for use with {@link EventEmitter.setMaxListeners} function
407
+ * @internal
408
+ */
409
+ /* @conditional-compile-remove(rich-text-editor-image-upload) */
410
+ /**
411
+ * The key for the rich text editor inline image file name attribute
412
+ * @internal
413
+ */
414
+ const _IMAGE_ATTRIBUTE_INLINE_IMAGE_FILE_NAME_KEY = 'data-image-file-name';
415
+
403
416
  // Copyright (c) Microsoft Corporation.
404
417
  // Licensed under the MIT License.
405
418
  /**
@@ -1817,7 +1830,12 @@ const createDefaultChatHandlers = memoizeOne((chatClient, chatThreadClient) => {
1817
1830
  /* @conditional-compile-remove(rich-text-editor-image-upload) */
1818
1831
  onDeleteImage: function (imageId) {
1819
1832
  return __awaiter$T(this, void 0, void 0, function* () {
1820
- yield chatThreadClient.deleteImage(imageId);
1833
+ try {
1834
+ yield chatThreadClient.deleteImage(imageId);
1835
+ }
1836
+ catch (e) {
1837
+ console.log(`Error deleting image message: ${e}`);
1838
+ }
1821
1839
  return;
1822
1840
  });
1823
1841
  },
@@ -5634,33 +5652,41 @@ const isAttachmentUploadCompleted = (attachmentsWithProgress) => {
5634
5652
  return !!(attachmentsWithProgress === null || attachmentsWithProgress === void 0 ? void 0 : attachmentsWithProgress.find((attachment) => !attachment.error));
5635
5653
  };
5636
5654
  /* @conditional-compile-remove(rich-text-editor-image-upload) */
5655
+ /**
5656
+ * Check if the content has inline image.
5657
+ * @internal
5658
+ */
5659
+ const hasInlineImageContent = (content) => {
5660
+ const document = new DOMParser().parseFromString(content, 'text/html');
5661
+ return !!document.querySelector('img');
5662
+ };
5663
+ /* @conditional-compile-remove(rich-text-editor-image-upload) */
5637
5664
  /**
5638
5665
  * @internal
5666
+ *
5667
+ * @param message - The message content to update.
5668
+ * @param initialInlineImages - The initial inline images that comes with the message before editing.
5669
+ *
5670
+ * @returns The updated message content.
5639
5671
  */
5640
- // Before sending the image, we need to add the image id we get back after uploading the images to the message content.
5641
- const addUploadedImagesToMessage = (message, inlineImages) => __awaiter$Q(void 0, void 0, void 0, function* () {
5672
+ const updateStylesOfInlineImages = (message, initialInlineImages) => __awaiter$Q(void 0, void 0, void 0, function* () {
5642
5673
  if (message === '') {
5643
5674
  return message;
5644
5675
  }
5676
+ const initialInlineImagesIds = initialInlineImages.map((initialInlineImage) => initialInlineImage.id);
5645
5677
  const document = new DOMParser().parseFromString(message !== null && message !== void 0 ? message : '', 'text/html');
5646
5678
  const imagesPromise = Array.from(document.querySelectorAll('img')).map((img) => {
5647
5679
  return new Promise((resolve, rejects) => {
5648
- const uploadInlineImage = inlineImages.find((inlineImage) => !inlineImage.error && (inlineImage.url === img.src || inlineImage.id === img.id));
5649
- // The message might content images that comes with the message before editing, those images are not in the uploadInlineImages array.
5650
- // This function should only modify the message content for images in the uploadInlineImages array.
5651
- if (!uploadInlineImage) {
5680
+ // The message might content images that comes with the message before editing.
5681
+ // This function should only modify the message content for images that are newly added.
5682
+ if (initialInlineImagesIds.includes(img.id)) {
5652
5683
  resolve();
5653
5684
  return;
5654
5685
  }
5655
5686
  const imageElement = new Image();
5656
5687
  imageElement.src = img.src;
5657
5688
  imageElement.onload = () => {
5658
- var _a;
5659
5689
  // imageElement is a copy of original img element, so changes need to be made to the original img element
5660
- img.id = (_a = uploadInlineImage === null || uploadInlineImage === void 0 ? void 0 : uploadInlineImage.id) !== null && _a !== void 0 ? _a : '';
5661
- if (uploadInlineImage === null || uploadInlineImage === void 0 ? void 0 : uploadInlineImage.url) {
5662
- img.src = uploadInlineImage.url;
5663
- }
5664
5690
  img.width = imageElement.width;
5665
5691
  img.height = imageElement.height;
5666
5692
  img.style.aspectRatio = `${imageElement.width} / ${imageElement.height}`;
@@ -5716,21 +5742,6 @@ hasCompletedAttachmentUploads, hasError, disabled }) => {
5716
5742
  hasError ||
5717
5743
  disabled);
5718
5744
  };
5719
- /* @conditional-compile-remove(rich-text-editor-image-upload) */
5720
- /**
5721
- * @internal
5722
- */
5723
- const cancelInlineImageUpload$1 = (props) => {
5724
- const { imageSrcArray, inlineImages, messageId, editBoxOnCancelInlineImageUpload, sendBoxOnCancelInlineImageUpload } = props;
5725
- if (imageSrcArray && inlineImages && (inlineImages === null || inlineImages === void 0 ? void 0 : inlineImages.length) > 0) {
5726
- inlineImages === null || inlineImages === void 0 ? void 0 : inlineImages.map((inlineImage) => {
5727
- if (inlineImage.url && !(imageSrcArray === null || imageSrcArray === void 0 ? void 0 : imageSrcArray.includes(inlineImage.url))) {
5728
- sendBoxOnCancelInlineImageUpload && sendBoxOnCancelInlineImageUpload(inlineImage.id);
5729
- editBoxOnCancelInlineImageUpload && editBoxOnCancelInlineImageUpload(inlineImage.id, messageId || '');
5730
- }
5731
- });
5732
- }
5733
- };
5734
5745
  /* @conditional-compile-remove(file-sharing-acs) */
5735
5746
  /**
5736
5747
  * @internal
@@ -5748,15 +5759,13 @@ const toAttachmentMetadata = (attachmentsWithProgress) => {
5748
5759
  };
5749
5760
  });
5750
5761
  };
5751
- /* @conditional-compile-remove(rich-text-editor-image-upload) */
5752
5762
  /**
5753
5763
  * @internal
5754
5764
  */
5755
- const insertImagesToContentString = (content, inlineImages, onCompleted) => __awaiter$Q(void 0, void 0, void 0, function* () {
5756
- if (!inlineImages || inlineImages.length <= 0) {
5757
- onCompleted === null || onCompleted === void 0 ? void 0 : onCompleted(content);
5758
- }
5759
- const newContent = yield addUploadedImagesToMessage(content, inlineImages !== null && inlineImages !== void 0 ? inlineImages : []);
5765
+ const modifyInlineImagesInContentString = (content, initialInlineImages, onCompleted) => __awaiter$Q(void 0, void 0, void 0, function* () {
5766
+ let newContent = content;
5767
+ /* @conditional-compile-remove(rich-text-editor-image-upload) */
5768
+ newContent = yield updateStylesOfInlineImages(content, initialInlineImages);
5760
5769
  onCompleted === null || onCompleted === void 0 ? void 0 : onCompleted(newContent);
5761
5770
  });
5762
5771
  /* @conditional-compile-remove(rich-text-editor-image-upload) */
@@ -5785,6 +5794,25 @@ const removeBrokenImageContentAndClearImageSizeStyles = (content) => {
5785
5794
  });
5786
5795
  return document.body.innerHTML;
5787
5796
  };
5797
+ /* @conditional-compile-remove(rich-text-editor-image-upload) */
5798
+ /**
5799
+ * @internal
5800
+ */
5801
+ const getContentWithUpdatedInlineImagesInfo = (content, inlineImageWithProgress) => {
5802
+ if (!inlineImageWithProgress || inlineImageWithProgress.length <= 0) {
5803
+ return content;
5804
+ }
5805
+ const document = new DOMParser().parseFromString(content, 'text/html');
5806
+ document.querySelectorAll('img').forEach((img) => {
5807
+ const imageId = img.id;
5808
+ const inlineImage = inlineImageWithProgress.find((image) => !image.error && image.progress === 1 && image.id === imageId);
5809
+ if (inlineImage) {
5810
+ img.id = inlineImage.id;
5811
+ img.src = inlineImage.url || img.src;
5812
+ }
5813
+ });
5814
+ return document.body.innerHTML;
5815
+ };
5788
5816
 
5789
5817
  // Copyright (c) Microsoft Corporation.
5790
5818
  // Licensed under the MIT License.
@@ -6850,6 +6878,7 @@ var PluginEventType;
6850
6878
  PluginEventType["EditorReady"] = "editorReady";
6851
6879
  PluginEventType["BeforeDispose"] = "beforeDispose";
6852
6880
  PluginEventType["ContentChanged"] = "contentChanged";
6881
+ PluginEventType["BeforeSetContent"] = "beforeSetContent";
6853
6882
  PluginEventType["Input"] = "input";
6854
6883
  PluginEventType["KeyDown"] = "keyDown";
6855
6884
  PluginEventType["BeforePaste"] = "beforePaste";
@@ -6890,7 +6919,128 @@ const dataSetApplier = (format, element, context) => {
6890
6919
  context.defaultFormatAppliers.dataset(format, element, context);
6891
6920
  }
6892
6921
  };
6922
+ /* @conditional-compile-remove(rich-text-editor-image-upload) */
6923
+ /**
6924
+ * @internal
6925
+ */
6926
+ const getPreviousInlineImages = (content) => {
6927
+ if (!content) {
6928
+ return [];
6929
+ }
6930
+ const previousInlineImages = [];
6931
+ const document = new DOMParser().parseFromString(content !== null && content !== void 0 ? content : '', 'text/html');
6932
+ document.querySelectorAll('img').forEach((img) => {
6933
+ const imageAttributes = getInlineImageAttributes(img);
6934
+ previousInlineImages.push(imageAttributes);
6935
+ });
6936
+ return previousInlineImages;
6937
+ };
6938
+ /* @conditional-compile-remove(rich-text-editor-image-upload) */
6939
+ /**
6940
+ * @internal
6941
+ */
6942
+ const getRemovedInlineImages = (content, previousInlineImages) => {
6943
+ const document = new DOMParser().parseFromString(content !== null && content !== void 0 ? content : '', 'text/html');
6944
+ const currentContentIds = Array.from(document.querySelectorAll('img')).map((img) => img.id);
6945
+ previousInlineImages = previousInlineImages === null || previousInlineImages === void 0 ? void 0 : previousInlineImages.filter((img) => !(currentContentIds === null || currentContentIds === void 0 ? void 0 : currentContentIds.includes(img.id)));
6946
+ const removedInlineImages = [...previousInlineImages];
6947
+ return removedInlineImages;
6948
+ };
6949
+ /* @conditional-compile-remove(rich-text-editor-image-upload) */
6950
+ /**
6951
+ * @internal
6952
+ */
6953
+ const getInsertedInlineImages = (content, previousInlineImages) => {
6954
+ const document = new DOMParser().parseFromString(content !== null && content !== void 0 ? content : '', 'text/html');
6955
+ const currentContentInlineImages = Array.from(document.querySelectorAll('img'));
6956
+ const previousContentIds = Array.from(previousInlineImages).map((img) => img.id);
6957
+ // if check is updated, also update getRemovedInlineImages
6958
+ const insertedInlineImages = currentContentInlineImages.filter((img) => !previousContentIds.includes(img.id));
6959
+ return insertedInlineImages;
6960
+ };
6961
+ /* @conditional-compile-remove(rich-text-editor-image-upload) */
6962
+ /**
6963
+ * @internal
6964
+ */
6965
+ const getInlineImageAttributes = (image) => {
6966
+ const imageAttributes = {};
6967
+ image.getAttributeNames().forEach((attrName) => {
6968
+ const attrValue = image.getAttribute(attrName);
6969
+ if (attrValue) {
6970
+ imageAttributes[attrName] = attrValue;
6971
+ }
6972
+ });
6973
+ return imageAttributes;
6974
+ };
6975
+ /* @conditional-compile-remove(rich-text-editor) */
6976
+ /**
6977
+ * @internal
6978
+ */
6979
+ /**
6980
+ * Update the scroll position of the editor to ensure the content is visible.
6981
+ */
6982
+ const scrollToBottomRichTextEditor = () => {
6983
+ // Get the current selection in the document
6984
+ const selection = document.getSelection();
6985
+ // Check if a selection exists and it has at least one range
6986
+ if (!selection || selection.rangeCount <= 0) {
6987
+ // If no selection or range, exit the function
6988
+ return;
6989
+ }
6990
+ // Get the first range of the selection
6991
+ // A user can normally only select one range at a time, so the rangeCount will usually be 1
6992
+ const range = selection.getRangeAt(0);
6993
+ // If the common ancestor container of the range is the document itself,
6994
+ // it might mean that the editable element is getting removed from the DOM
6995
+ // In such cases, especially in Safari, trying to modify the range might throw a HierarchyRequest error
6996
+ if (range.commonAncestorContainer === document) {
6997
+ return;
6998
+ }
6999
+ // Create a temporary span element to use as an anchor for scrolling
7000
+ // We can't use the anchor node directly because if it's a Text node, calling scrollIntoView() on it will throw an error
7001
+ const tempElement = document.createElement('span');
7002
+ // Collapse the range to its end point
7003
+ // This means the start and end points of the range will be the same, and it will not contain any content
7004
+ range.collapse(false);
7005
+ // Insert the temporary element at the cursor's position at the end of the range
7006
+ range.insertNode(tempElement);
7007
+ // Scroll the temporary element into view
7008
+ // the element will be aligned at the center of the scroll container, otherwise, text and images may be positioned incorrectly
7009
+ tempElement.scrollIntoView({
7010
+ block: 'center'
7011
+ });
7012
+ tempElement.remove();
7013
+ };
7014
+ /* @conditional-compile-remove(rich-text-editor-image-upload) */
7015
+ /**
7016
+ * Revoke the blob urls in the removedInlineImages and remove them from the currentLocalBlobMap
7017
+ * @internal
7018
+ */
7019
+ const removeLocalBlobs = (currentLocalBlobMap, removedInlineImages) => {
7020
+ removedInlineImages.forEach((image) => {
7021
+ removeSingleLocalBlob(currentLocalBlobMap, image.id);
7022
+ });
7023
+ };
7024
+ /* @conditional-compile-remove(rich-text-editor-image-upload) */
7025
+ /**
7026
+ * Revoke all the blob urls in the currentLocalBlobMap and clean up the currentLocalBlobMap
7027
+ * @internal
7028
+ */
7029
+ const cleanAllLocalBlobs = (currentLocalBlobMap) => {
7030
+ Object.keys(currentLocalBlobMap).forEach((imageId) => {
7031
+ removeSingleLocalBlob(currentLocalBlobMap, imageId);
7032
+ });
7033
+ };
7034
+ /* @conditional-compile-remove(rich-text-editor-image-upload) */
7035
+ const removeSingleLocalBlob = (currentLocalBlobMap, imageId) => {
7036
+ const blobUrl = currentLocalBlobMap[imageId];
7037
+ if (blobUrl) {
7038
+ URL.revokeObjectURL(blobUrl);
7039
+ delete currentLocalBlobMap[imageId];
7040
+ }
7041
+ };
6893
7042
 
7043
+ /* @conditional-compile-remove(rich-text-editor) */
6894
7044
  /**
6895
7045
  * CopyPastePlugin is a plugin for handling copy and paste events in the editor.
6896
7046
  */
@@ -6945,16 +7095,24 @@ const handleInlineImage = (event, onInsertInlineImage) => {
6945
7095
  if (event.eventType === PluginEventType.BeforePaste && event.pasteType === 'normal' && onInsertInlineImage) {
6946
7096
  event.fragment.querySelectorAll('img').forEach((image) => {
6947
7097
  const clipboardImage = event.clipboardData.image;
6948
- const fileName = (clipboardImage === null || clipboardImage === void 0 ? void 0 : clipboardImage.name) || (clipboardImage === null || clipboardImage === void 0 ? void 0 : clipboardImage.type.replace('/', '.')) || 'image.png';
7098
+ const fileName = (clipboardImage === null || clipboardImage === void 0 ? void 0 : clipboardImage.name) ||
7099
+ (clipboardImage === null || clipboardImage === void 0 ? void 0 : clipboardImage.type.replace('/', '.')) ||
7100
+ image.getAttribute(_IMAGE_ATTRIBUTE_INLINE_IMAGE_FILE_NAME_KEY) ||
7101
+ '';
6949
7102
  // If the image src is an external url, call the onInsertInlineImage callback with the url.
6950
7103
  let imageUrl = image.src;
6951
7104
  if (image.src.startsWith('data:image/')) {
6952
7105
  const blobImage = _base64ToBlob(image.src);
6953
7106
  imageUrl = URL.createObjectURL(blobImage);
6954
7107
  }
6955
- onInsertInlineImage(imageUrl, fileName);
6956
7108
  image.src = imageUrl;
6957
7109
  image.alt = image.alt || 'image';
7110
+ // Assign a unique id to the image element so Contosos can identify the image element.
7111
+ // We also use it internally such as in getRemovedInlineImages to compare images in the content with previous images
7112
+ image.id = uuid.v1();
7113
+ image.dataset.imageFileName = fileName;
7114
+ const imageAttributes = getInlineImageAttributes(image);
7115
+ onInsertInlineImage(imageAttributes);
6958
7116
  });
6959
7117
  }
6960
7118
  };
@@ -6964,36 +7122,8 @@ const handleInlineImage = (event, onInsertInlineImage) => {
6964
7122
  */
6965
7123
  const scrollToBottomAfterContentPaste = (event) => {
6966
7124
  if (event.eventType === PluginEventType.ContentChanged && event.source === ContentChangedEventSource.Paste) {
6967
- // Get the current selection in the document
6968
- const selection = document.getSelection();
6969
- // Check if a selection exists and it has at least one range
6970
- if (!selection || selection.rangeCount <= 0) {
6971
- // If no selection or range, exit the function
6972
- return;
6973
- }
6974
- // Get the first range of the selection
6975
- // A user can normally only select one range at a time, so the rangeCount will usually be 1
6976
- const range = selection.getRangeAt(0);
6977
- // If the common ancestor container of the range is the document itself,
6978
- // it might mean that the editable element is getting removed from the DOM
6979
- // In such cases, especially in Safari, trying to modify the range might throw a HierarchyRequest error
6980
- if (range.commonAncestorContainer === document) {
6981
- return;
6982
- }
6983
- // Create a temporary span element to use as an anchor for scrolling
6984
- // We can't use the anchor node directly because if it's a Text node, calling scrollIntoView() on it will throw an error
6985
- const tempElement = document.createElement('span');
6986
- // Collapse the range to its end point
6987
- // This means the start and end points of the range will be the same, and it will not contain any content
6988
- range.collapse(false);
6989
- // Insert the temporary element at the cursor's position at the end of the range
6990
- range.insertNode(tempElement);
6991
- // Scroll the temporary element into view
6992
- // the element will be aligned at the center of the scroll container, otherwise, text and images may be positioned incorrectly
6993
- tempElement.scrollIntoView({
6994
- block: 'center'
6995
- });
6996
- tempElement.remove();
7125
+ /* @conditional-compile-remove(rich-text-editor) */
7126
+ scrollToBottomRichTextEditor();
6997
7127
  }
6998
7128
  };
6999
7129
 
@@ -7074,11 +7204,9 @@ class UpdateContentPlugin {
7074
7204
  }
7075
7205
  }
7076
7206
  onPluginEvent(event) {
7077
- var _a;
7078
7207
  if (this.onUpdate === null) {
7079
7208
  return;
7080
7209
  }
7081
- let imageSrcArray;
7082
7210
  switch (event.eventType) {
7083
7211
  case PluginEventType.EditorReady:
7084
7212
  this.onUpdate(UpdateEvent.Init);
@@ -7087,21 +7215,16 @@ class UpdateContentPlugin {
7087
7215
  this.onUpdate(UpdateEvent.Dispose);
7088
7216
  break;
7089
7217
  case PluginEventType.ContentChanged:
7090
- if (event.source.toLowerCase() === 'cut' ||
7091
- (event.source.toLowerCase() === 'keyboard' && (event.data === Keys.BACKSPACE || event.data === Keys.DELETE))) {
7092
- imageSrcArray = [];
7093
- (_a = event.contentModel) === null || _a === void 0 ? void 0 : _a.blocks.map((block) => {
7094
- if (block.blockType === 'Paragraph') {
7095
- const segments = block.segments;
7096
- segments.map((segment) => {
7097
- if (segment.segmentType === 'Image') {
7098
- imageSrcArray === null || imageSrcArray === void 0 ? void 0 : imageSrcArray.push(segment.src);
7099
- }
7100
- });
7101
- }
7102
- });
7218
+ if (event.source === roosterjsContentModelDom.ChangeSource.Cut ||
7219
+ // We need to add the paste source here for an edge case:
7220
+ // when user select an image that's already in the editor, then paste in an image to replace the selected one,
7221
+ // we will only get a paste event.
7222
+ // In this case, we need to update the removedInlineImage array to include the replaced image.
7223
+ event.source === roosterjsContentModelDom.ChangeSource.Paste ||
7224
+ (event.source === roosterjsContentModelDom.ChangeSource.Keyboard && (event.data === Keys.BACKSPACE || event.data === Keys.DELETE))) {
7225
+ this.onUpdate(UpdateEvent.ContentChanged, true);
7103
7226
  }
7104
- this.onUpdate(UpdateEvent.ContentChanged, imageSrcArray);
7227
+ this.onUpdate(UpdateEvent.ContentChanged);
7105
7228
  break;
7106
7229
  case PluginEventType.Input:
7107
7230
  this.onUpdate(UpdateEvent.UserInput);
@@ -7750,6 +7873,57 @@ class PlaceholderPlugin extends roosterjsContentModelPlugins.WatermarkPlugin {
7750
7873
  }
7751
7874
  }
7752
7875
 
7876
+ /* @conditional-compile-remove(rich-text-editor-image-upload) */
7877
+ /**
7878
+ * UndoRedoPlugin is a plugin for additional handling undo and redo events in the editor.
7879
+ */
7880
+ class UndoRedoPlugin {
7881
+ constructor() {
7882
+ /* @conditional-compile-remove(rich-text-editor-image-upload) */
7883
+ this.editor = null;
7884
+ this.onUpdateContent = null;
7885
+ }
7886
+ getName() {
7887
+ return 'CustomUndoRedoPlugin';
7888
+ }
7889
+ initialize(editor) {
7890
+ /* @conditional-compile-remove(rich-text-editor-image-upload) */
7891
+ this.editor = editor;
7892
+ }
7893
+ dispose() { }
7894
+ onPluginEvent(event) {
7895
+ // handle when new images are added to the editor because of undo/redo
7896
+ /* @conditional-compile-remove(rich-text-editor-image-upload) */
7897
+ if (this.editor && event.eventType === PluginEventType.BeforeSetContent && this.onInsertInlineImage) {
7898
+ handleBeforeSetEvent(event, this.editor, this.onInsertInlineImage);
7899
+ }
7900
+ // handle deleted images and updated content
7901
+ /* @conditional-compile-remove(rich-text-editor-image-upload) */
7902
+ if (this.onUpdateContent &&
7903
+ event.eventType === PluginEventType.ContentChanged &&
7904
+ event.source === roosterjsContentModelDom.ChangeSource.SetContent) {
7905
+ this.onUpdateContent();
7906
+ }
7907
+ /* @conditional-compile-remove(rich-text-editor-image-upload) */
7908
+ if (this.editor &&
7909
+ !this.editor.isDisposed() &&
7910
+ event.eventType === PluginEventType.ContentChanged &&
7911
+ event.source === roosterjsContentModelDom.ChangeSource.SetContent) {
7912
+ // scroll the editor to the correct position after undo/redo actions
7913
+ scrollToBottomRichTextEditor();
7914
+ }
7915
+ }
7916
+ }
7917
+ /* @conditional-compile-remove(rich-text-editor-image-upload) */
7918
+ const handleBeforeSetEvent = (event, editor, onInsertInlineImage) => {
7919
+ const currentImagesList = editor.getDocument().querySelectorAll('img');
7920
+ const insertedImages = getInsertedInlineImages(event.newContent, currentImagesList);
7921
+ insertedImages.forEach((image) => {
7922
+ const imageAttributes = getInlineImageAttributes(image);
7923
+ onInsertInlineImage(imageAttributes);
7924
+ });
7925
+ };
7926
+
7753
7927
  // Copyright (c) Microsoft Corporation.
7754
7928
  // Licensed under the MIT License.
7755
7929
  /**
@@ -7768,6 +7942,20 @@ const RichTextEditor = React.forwardRef((props, ref) => {
7768
7942
  const theme = useTheme();
7769
7943
  const [contextMenuProps, setContextMenuProps] = React.useState(null);
7770
7944
  const previousThemeDirection = React.useRef(themeDirection(theme));
7945
+ /* @conditional-compile-remove(rich-text-editor-image-upload) */
7946
+ // This will be set when the editor is initialized and when the content is updated.
7947
+ const [previousInlineImages, setPreviousInlineImages] = React.useState([]);
7948
+ /* @conditional-compile-remove(rich-text-editor-image-upload) */
7949
+ const [inlineImageLocalBlobs, setInlineImageLocalBlobs] = React.useState({});
7950
+ /* @conditional-compile-remove(rich-text-editor-image-upload) */
7951
+ React.useEffect(() => {
7952
+ return () => {
7953
+ // Cleanup Local Blob URLs when the component is unmounted
7954
+ cleanAllLocalBlobs(inlineImageLocalBlobs);
7955
+ };
7956
+ // This effect should only run once when the component is unmounted, so we don't need to add any dependencies
7957
+ // eslint-disable-next-line react-hooks/exhaustive-deps
7958
+ }, []);
7771
7959
  React.useImperativeHandle(ref, () => {
7772
7960
  return {
7773
7961
  focus() {
@@ -7776,6 +7964,10 @@ const RichTextEditor = React.forwardRef((props, ref) => {
7776
7964
  }
7777
7965
  },
7778
7966
  setEmptyContent() {
7967
+ /* @conditional-compile-remove(rich-text-editor-image-upload) */
7968
+ setPreviousInlineImages([]);
7969
+ /* @conditional-compile-remove(rich-text-editor-image-upload) */
7970
+ cleanAllLocalBlobs(inlineImageLocalBlobs);
7779
7971
  if (editor.current) {
7780
7972
  // remove all content from the editor and update the model
7781
7973
  // ContentChanged event will be sent by RoosterJS automatically
@@ -7799,7 +7991,7 @@ const RichTextEditor = React.forwardRef((props, ref) => {
7799
7991
  }
7800
7992
  }
7801
7993
  };
7802
- }, [onContentModelUpdate]);
7994
+ }, [/* @conditional-compile-remove(rich-text-editor-image-upload) */ inlineImageLocalBlobs, onContentModelUpdate]);
7803
7995
  const toolbarPlugin = React.useMemo(() => {
7804
7996
  return new RichTextToolbarPlugin();
7805
7997
  }, []);
@@ -7826,9 +8018,27 @@ const RichTextEditor = React.forwardRef((props, ref) => {
7826
8018
  const copyPastePlugin = React.useMemo(() => {
7827
8019
  return new CopyPastePlugin();
7828
8020
  }, []);
8021
+ const onChangeContent = React.useCallback((/* @conditional-compile-remove(rich-text-editor-image-upload) */ shouldUpdateInlineImages) => {
8022
+ if (editor.current === null) {
8023
+ return;
8024
+ }
8025
+ const content = roosterjsContentModelCore.exportContent(editor.current);
8026
+ /* @conditional-compile-remove(rich-text-editor-image-upload) */
8027
+ let removedInlineImages = [];
8028
+ /* @conditional-compile-remove(rich-text-editor-image-upload) */
8029
+ if (shouldUpdateInlineImages) {
8030
+ /* @conditional-compile-remove(rich-text-editor-image-upload) */
8031
+ removedInlineImages = getRemovedInlineImages(content, previousInlineImages);
8032
+ }
8033
+ onChange &&
8034
+ onChange(content, /* @conditional-compile-remove(rich-text-editor-image-upload) */ removedInlineImages);
8035
+ /* @conditional-compile-remove(rich-text-editor-image-upload) */
8036
+ setPreviousInlineImages(getPreviousInlineImages(content));
8037
+ }, [onChange, /* @conditional-compile-remove(rich-text-editor-image-upload) */ previousInlineImages]);
7829
8038
  React.useEffect(() => {
7830
8039
  // don't set callback in plugin constructor to update callback without plugin recreation
7831
- updatePlugin.onUpdate = (event, imageSrcArray) => {
8040
+ updatePlugin.onUpdate = (event,
8041
+ /* @conditional-compile-remove(rich-text-editor-image-upload) */ shouldRemoveInlineImages) => {
7832
8042
  if (editor.current === null) {
7833
8043
  return;
7834
8044
  }
@@ -7836,14 +8046,46 @@ const RichTextEditor = React.forwardRef((props, ref) => {
7836
8046
  onContentModelUpdate && onContentModelUpdate(editor.current.getContentModelCopy('disconnected'));
7837
8047
  }
7838
8048
  else {
7839
- onChange && onChange(roosterjsContentModelCore.exportContent(editor.current), imageSrcArray);
8049
+ const content = roosterjsContentModelCore.exportContent(editor.current);
8050
+ /* @conditional-compile-remove(rich-text-editor-image-upload) */
8051
+ let removedInlineImages = [];
8052
+ /* @conditional-compile-remove(rich-text-editor-image-upload) */
8053
+ if (shouldRemoveInlineImages) {
8054
+ removedInlineImages = getRemovedInlineImages(content, previousInlineImages);
8055
+ if (removedInlineImages.length > 0) {
8056
+ removeLocalBlobs(inlineImageLocalBlobs, removedInlineImages);
8057
+ }
8058
+ }
8059
+ onChange &&
8060
+ onChange(content, /* @conditional-compile-remove(rich-text-editor-image-upload) */ removedInlineImages);
8061
+ /* @conditional-compile-remove(rich-text-editor-image-upload) */
8062
+ setPreviousInlineImages(getPreviousInlineImages(content));
7840
8063
  }
7841
8064
  };
7842
- }, [onChange, onContentModelUpdate, updatePlugin]);
8065
+ }, [
8066
+ onChange,
8067
+ onContentModelUpdate,
8068
+ updatePlugin,
8069
+ /* @conditional-compile-remove(rich-text-editor-image-upload) */ previousInlineImages,
8070
+ /* @conditional-compile-remove(rich-text-editor-image-upload) */ inlineImageLocalBlobs
8071
+ ]);
8072
+ const undoRedoPlugin = React.useMemo(() => {
8073
+ return new UndoRedoPlugin();
8074
+ }, []);
7843
8075
  /* @conditional-compile-remove(rich-text-editor-image-upload) */
7844
8076
  React.useEffect(() => {
7845
- copyPastePlugin.onInsertInlineImage = onInsertInlineImage;
7846
- }, [copyPastePlugin, onInsertInlineImage]);
8077
+ copyPastePlugin.onInsertInlineImage = (imageAttributes) => {
8078
+ const { id, src } = imageAttributes;
8079
+ setInlineImageLocalBlobs(Object.assign(Object.assign({}, inlineImageLocalBlobs), { [id]: src }));
8080
+ onInsertInlineImage && onInsertInlineImage(imageAttributes);
8081
+ };
8082
+ undoRedoPlugin.onInsertInlineImage = onInsertInlineImage;
8083
+ }, [copyPastePlugin, inlineImageLocalBlobs, onInsertInlineImage, undoRedoPlugin]);
8084
+ React.useEffect(() => {
8085
+ undoRedoPlugin.onUpdateContent = () => {
8086
+ onChangeContent(/* @conditional-compile-remove(rich-text-editor-image-upload) */ true);
8087
+ };
8088
+ }, [onChangeContent, undoRedoPlugin]);
7847
8089
  const keyboardInputPlugin = React.useMemo(() => {
7848
8090
  return new KeyboardInputPlugin();
7849
8091
  }, []);
@@ -7895,7 +8137,8 @@ const RichTextEditor = React.forwardRef((props, ref) => {
7895
8137
  shortcutPlugin,
7896
8138
  // contextPlugin and tableEditMenuProvider allow to show insert/delete menu for the table
7897
8139
  contextMenuPlugin,
7898
- tableContextMenuPlugin
8140
+ tableContextMenuPlugin,
8141
+ undoRedoPlugin
7899
8142
  ];
7900
8143
  }, [
7901
8144
  onContextMenuRender,
@@ -7905,7 +8148,8 @@ const RichTextEditor = React.forwardRef((props, ref) => {
7905
8148
  updatePlugin,
7906
8149
  copyPastePlugin,
7907
8150
  toolbarPlugin,
7908
- tableContextMenuPlugin
8151
+ tableContextMenuPlugin,
8152
+ undoRedoPlugin
7909
8153
  ]);
7910
8154
  const announcerStringGetter = React.useCallback((key) => {
7911
8155
  var _a, _b;
@@ -7920,6 +8164,10 @@ const RichTextEditor = React.forwardRef((props, ref) => {
7920
8164
  }, [strings.richTextNewBulletedListItemAnnouncement, strings.richTextNewNumberedListItemAnnouncement]);
7921
8165
  React.useEffect(() => {
7922
8166
  var _a;
8167
+ /* @conditional-compile-remove(rich-text-editor-image-upload) */
8168
+ const prevInlineImage = getPreviousInlineImages(initialContent);
8169
+ /* @conditional-compile-remove(rich-text-editor-image-upload) */
8170
+ setPreviousInlineImages(prevInlineImage);
7923
8171
  const initialModel = createEditorInitialModel(initialContent, contentModel);
7924
8172
  if (editorDiv.current) {
7925
8173
  editor.current = new roosterjsContentModelCore.Editor(editorDiv.current, {
@@ -8228,9 +8476,9 @@ const RichTextSendBox = (props) => {
8228
8476
  /* @conditional-compile-remove(rich-text-editor-image-upload) */
8229
8477
  onInsertInlineImage,
8230
8478
  /* @conditional-compile-remove(rich-text-editor-image-upload) */
8231
- inlineImages,
8479
+ inlineImagesWithProgress,
8232
8480
  /* @conditional-compile-remove(rich-text-editor-image-upload) */
8233
- onCancelInlineImageUpload } = props;
8481
+ onRemoveInlineImage } = props;
8234
8482
  const theme = useTheme();
8235
8483
  const locale = useLocale$1();
8236
8484
  const localeStrings = React.useMemo(() => {
@@ -8256,29 +8504,34 @@ const RichTextSendBox = (props) => {
8256
8504
  setContentValue(newValue);
8257
8505
  }, []);
8258
8506
  const onChangeHandler = React.useCallback((newValue,
8259
- /* @conditional-compile-remove(rich-text-editor-image-upload) */ imageSrcArray) => {
8507
+ /* @conditional-compile-remove(rich-text-editor-image-upload) */ removedInlineImages) => {
8260
8508
  /* @conditional-compile-remove(rich-text-editor-image-upload) */
8261
- cancelInlineImageUpload$1({
8262
- imageSrcArray,
8263
- inlineImages,
8264
- messageId: undefined,
8265
- editBoxOnCancelInlineImageUpload: undefined,
8266
- sendBoxOnCancelInlineImageUpload: onCancelInlineImageUpload
8267
- });
8509
+ removedInlineImages === null || removedInlineImages === void 0 ? void 0 : removedInlineImages.forEach((removedInlineImage) => onRemoveInlineImage && onRemoveInlineImage(removedInlineImage));
8268
8510
  setContent(newValue);
8269
- }, [
8270
- setContent,
8271
- /* @conditional-compile-remove(rich-text-editor-image-upload) */ onCancelInlineImageUpload,
8272
- /* @conditional-compile-remove(rich-text-editor-image-upload) */ inlineImages
8273
- ]);
8511
+ }, [setContent, /* @conditional-compile-remove(rich-text-editor-image-upload) */ onRemoveInlineImage]);
8274
8512
  const hasContent = React.useMemo(() => {
8275
8513
  var _a;
8276
8514
  // get plain text content from the editor to check if the message is empty
8277
8515
  // as the content may contain tags even when the content is empty
8278
8516
  const plainTextContent = (_a = editorComponentRef.current) === null || _a === void 0 ? void 0 : _a.getPlainContent();
8279
- return sanitizeText(contentValue !== null && contentValue !== void 0 ? contentValue : '').length > 0 && sanitizeText(plainTextContent !== null && plainTextContent !== void 0 ? plainTextContent : '').length > 0;
8517
+ const hasPlainText = sanitizeText(contentValue !== null && contentValue !== void 0 ? contentValue : '').length > 0 && sanitizeText(plainTextContent !== null && plainTextContent !== void 0 ? plainTextContent : '').length > 0;
8518
+ /* @conditional-compile-remove(rich-text-editor-image-upload) */
8519
+ const hasInlineImages = hasInlineImageContent(contentValue);
8520
+ return hasPlainText || /* @conditional-compile-remove(rich-text-editor-image-upload) */ hasInlineImages;
8280
8521
  }, [contentValue]);
8281
8522
  const sendMessageOnClick = React.useCallback(() => {
8523
+ /* @conditional-compile-remove(rich-text-editor-image-upload) */
8524
+ if (inlineImagesWithProgress && inlineImagesWithProgress.length > 0) {
8525
+ const contentWithUpdatedInlineImagesInfo = getContentWithUpdatedInlineImagesInfo(contentValue, inlineImagesWithProgress);
8526
+ const messageTooLong = isMessageTooLong(contentWithUpdatedInlineImagesInfo.length);
8527
+ // Set contentValueOverflow state to display the error bar
8528
+ setContentValueOverflow(messageTooLong);
8529
+ // The change from the setContentValueOverflow in the previous line will not kick in yet.
8530
+ // We need to relay on the local value of messageTooLong to return early if the message is too long.
8531
+ if (messageTooLong) {
8532
+ return;
8533
+ }
8534
+ }
8282
8535
  if (disabled || contentValueOverflow) {
8283
8536
  return;
8284
8537
  }
@@ -8286,7 +8539,7 @@ const RichTextSendBox = (props) => {
8286
8539
  /* @conditional-compile-remove(file-sharing-acs) */
8287
8540
  setAttachmentUploadsPendingError(undefined);
8288
8541
  /* @conditional-compile-remove(rich-text-editor-image-upload) */
8289
- const hasIncompleteImageUploads = hasIncompleteAttachmentUploads(inlineImages);
8542
+ const hasIncompleteImageUploads = hasIncompleteAttachmentUploads(inlineImagesWithProgress);
8290
8543
  /* @conditional-compile-remove(file-sharing-acs) */
8291
8544
  /* @conditional-compile-remove(rich-text-editor-image-upload) */
8292
8545
  if (
@@ -8308,9 +8561,7 @@ const RichTextSendBox = (props) => {
8308
8561
  }
8309
8562
  // we don't want to send empty messages including spaces, newlines, tabs
8310
8563
  // Message can be empty if there is a valid attachment upload
8311
- if (hasContent ||
8312
- /* @conditional-compile-remove(file-sharing-acs) */ isAttachmentUploadCompleted(attachments) ||
8313
- /* @conditional-compile-remove(rich-text-editor-image-upload) */ isAttachmentUploadCompleted(inlineImages)) {
8564
+ if (hasContent || /* @conditional-compile-remove(file-sharing-acs) */ isAttachmentUploadCompleted(attachments)) {
8314
8565
  const sendMessage = (content) => {
8315
8566
  var _a, _b;
8316
8567
  onSendMessage(content,
@@ -8325,14 +8576,9 @@ const RichTextSendBox = (props) => {
8325
8576
  (_a = editorComponentRef.current) === null || _a === void 0 ? void 0 : _a.setEmptyContent();
8326
8577
  (_b = editorComponentRef.current) === null || _b === void 0 ? void 0 : _b.focus();
8327
8578
  };
8328
- /* @conditional-compile-remove(rich-text-editor-image-upload) */
8329
- if (isAttachmentUploadCompleted(inlineImages)) {
8330
- insertImagesToContentString(contentValue, inlineImages, (content) => {
8331
- sendMessage(content);
8332
- });
8333
- return;
8334
- }
8335
- sendMessage(contentValue);
8579
+ modifyInlineImagesInContentString(contentValue, [], (content) => {
8580
+ sendMessage(content);
8581
+ });
8336
8582
  }
8337
8583
  }, [
8338
8584
  disabled,
@@ -8340,7 +8586,7 @@ const RichTextSendBox = (props) => {
8340
8586
  /* @conditional-compile-remove(file-sharing-acs) */
8341
8587
  attachments,
8342
8588
  /* @conditional-compile-remove(rich-text-editor-image-upload) */
8343
- inlineImages,
8589
+ inlineImagesWithProgress,
8344
8590
  contentValue,
8345
8591
  hasContent,
8346
8592
  /* @conditional-compile-remove(file-sharing-acs) */
@@ -8358,7 +8604,7 @@ const RichTextSendBox = (props) => {
8358
8604
  /* @conditional-compile-remove(file-sharing-acs) */
8359
8605
  !!((_a = attachments === null || attachments === void 0 ? void 0 : attachments.filter((attachmentUpload) => attachmentUpload.error).pop()) === null || _a === void 0 ? void 0 : _a.error) ||
8360
8606
  /* @conditional-compile-remove(rich-text-editor-image-upload) */
8361
- !!((_b = inlineImages === null || inlineImages === void 0 ? void 0 : inlineImages.filter((image) => image.error).pop()) === null || _b === void 0 ? void 0 : _b.error));
8607
+ !!((_b = inlineImagesWithProgress === null || inlineImagesWithProgress === void 0 ? void 0 : inlineImagesWithProgress.filter((image) => image.error).pop()) === null || _b === void 0 ? void 0 : _b.error));
8362
8608
  }, [
8363
8609
  /* @conditional-compile-remove(file-sharing-acs) */
8364
8610
  attachments,
@@ -8367,7 +8613,7 @@ const RichTextSendBox = (props) => {
8367
8613
  attachmentUploadsPendingError,
8368
8614
  systemMessage,
8369
8615
  /* @conditional-compile-remove(rich-text-editor-image-upload) */
8370
- inlineImages
8616
+ inlineImagesWithProgress
8371
8617
  ]);
8372
8618
  const onRenderSendIcon = React.useCallback((isHover) => {
8373
8619
  return (React.createElement(react.Icon, { iconName: isHover && hasContent ? 'SendBoxSendHovered' : 'SendBoxSend', className: sendIconStyle({
@@ -8385,7 +8631,7 @@ const RichTextSendBox = (props) => {
8385
8631
  /* @conditional-compile-remove(file-sharing-acs) */
8386
8632
  const uploadErrorMessage = (_b = (_a = attachments === null || attachments === void 0 ? void 0 : attachments.filter((attachmentUpload) => attachmentUpload.error).pop()) === null || _a === void 0 ? void 0 : _a.error) === null || _b === void 0 ? void 0 : _b.message;
8387
8633
  /* @conditional-compile-remove(rich-text-editor-image-upload) */
8388
- const imageUploadErrorMessage = (_d = (_c = inlineImages === null || inlineImages === void 0 ? void 0 : inlineImages.filter((image) => image.error).pop()) === null || _c === void 0 ? void 0 : _c.error) === null || _d === void 0 ? void 0 : _d.message;
8634
+ const imageUploadErrorMessage = (_d = (_c = inlineImagesWithProgress === null || inlineImagesWithProgress === void 0 ? void 0 : inlineImagesWithProgress.filter((image) => image.error).pop()) === null || _c === void 0 ? void 0 : _c.error) === null || _d === void 0 ? void 0 : _d.message;
8389
8635
  /* @conditional-compile-remove(file-sharing-acs) */
8390
8636
  const errorMessage = uploadErrorMessage || /* @conditional-compile-remove(rich-text-editor-image-upload) */ imageUploadErrorMessage;
8391
8637
  return {
@@ -8410,7 +8656,7 @@ const RichTextSendBox = (props) => {
8410
8656
  /* @conditional-compile-remove(file-sharing-acs) */
8411
8657
  attachmentUploadsPendingError,
8412
8658
  /* @conditional-compile-remove(rich-text-editor-image-upload) */
8413
- inlineImages,
8659
+ inlineImagesWithProgress,
8414
8660
  systemMessage
8415
8661
  ]);
8416
8662
  /* @conditional-compile-remove(file-sharing-acs) */
@@ -10473,7 +10719,7 @@ class _ErrorBoundary extends React.Component {
10473
10719
  // Copyright (c) Microsoft Corporation.
10474
10720
  // Licensed under the MIT License.
10475
10721
  /* @conditional-compile-remove(rich-text-editor) */
10476
- const ChatMessageComponentAsRichTextEditBox = React.lazy(() => Promise.resolve().then(function () { return require('./ChatMessageComponentAsRichTextEditBox-B0zbyF6Z.js'); }));
10722
+ const ChatMessageComponentAsRichTextEditBox = React.lazy(() => Promise.resolve().then(function () { return require('./ChatMessageComponentAsRichTextEditBox-DM13Kp5W.js'); }));
10477
10723
  /**
10478
10724
  * @private
10479
10725
  * Use this function to load RoosterJS dependencies early in the lifecycle.
@@ -10481,7 +10727,7 @@ const ChatMessageComponentAsRichTextEditBox = React.lazy(() => Promise.resolve()
10481
10727
  *
10482
10728
  * @conditional-compile-remove(rich-text-editor)
10483
10729
  */
10484
- const loadChatMessageComponentAsRichTextEditBox = () => Promise.resolve().then(function () { return require('./ChatMessageComponentAsRichTextEditBox-B0zbyF6Z.js'); });
10730
+ const loadChatMessageComponentAsRichTextEditBox = () => Promise.resolve().then(function () { return require('./ChatMessageComponentAsRichTextEditBox-DM13Kp5W.js'); });
10485
10731
  /**
10486
10732
  * @private
10487
10733
  */
@@ -10583,9 +10829,9 @@ const ChatMyMessageComponent = (props) => {
10583
10829
  /* @conditional-compile-remove(rich-text-editor-image-upload) */
10584
10830
  onInsertInlineImage: props.onInsertInlineImage,
10585
10831
  /* @conditional-compile-remove(rich-text-editor-image-upload) */
10586
- inlineImages: props.inlineImages,
10832
+ inlineImagesWithProgress: props.inlineImagesWithProgress,
10587
10833
  /* @conditional-compile-remove(rich-text-editor-image-upload) */
10588
- onCancelInlineImageUpload: props.onCancelInlineImageUpload }));
10834
+ onRemoveInlineImage: props.onRemoveInlineImage }));
10589
10835
  }
10590
10836
  else {
10591
10837
  return (React.createElement(ChatMyMessageComponentAsMessageBubble, Object.assign({}, props, { onRemoveClick: onRemoveClick, onEditClick: onEditClick, onResendClick: onResendClick, onRenderAvatar: props.onRenderAvatar,
@@ -10621,9 +10867,9 @@ const FluentChatMyMessageComponent = (props) => {
10621
10867
  /* @conditional-compile-remove(rich-text-editor-image-upload) */
10622
10868
  onPaste,
10623
10869
  /* @conditional-compile-remove(rich-text-editor-image-upload) */
10624
- inlineImages,
10870
+ inlineImagesWithProgress,
10625
10871
  /* @conditional-compile-remove(rich-text-editor-image-upload) */
10626
- onCancelInlineImageUpload,
10872
+ onRemoveInlineImage,
10627
10873
  /* @conditional-compile-remove(rich-text-editor-image-upload) */
10628
10874
  onInsertInlineImage } = props;
10629
10875
  const chatMessageRenderStyles = useChatMessageRenderStyles();
@@ -10655,11 +10901,11 @@ const FluentChatMyMessageComponent = (props) => {
10655
10901
  /* @conditional-compile-remove(rich-text-editor-image-upload) */
10656
10902
  onPaste: onPaste,
10657
10903
  /* @conditional-compile-remove(rich-text-editor-image-upload) */
10658
- onCancelInlineImageUpload: onCancelInlineImageUpload,
10904
+ onRemoveInlineImage: onRemoveInlineImage,
10659
10905
  /* @conditional-compile-remove(rich-text-editor-image-upload) */
10660
10906
  onInsertInlineImage: onInsertInlineImage,
10661
10907
  /* @conditional-compile-remove(rich-text-editor-image-upload) */
10662
- inlineImages: inlineImages })));
10908
+ inlineImagesWithProgress: inlineImagesWithProgress })));
10663
10909
  }
10664
10910
  return React.createElement(React.Fragment, null);
10665
10911
  }, [
@@ -10685,11 +10931,11 @@ const FluentChatMyMessageComponent = (props) => {
10685
10931
  /* @conditional-compile-remove(rich-text-editor-image-upload) */
10686
10932
  onPaste,
10687
10933
  /* @conditional-compile-remove(rich-text-editor-image-upload) */
10688
- onCancelInlineImageUpload,
10934
+ onRemoveInlineImage,
10689
10935
  /* @conditional-compile-remove(rich-text-editor-image-upload) */
10690
10936
  onInsertInlineImage,
10691
10937
  /* @conditional-compile-remove(rich-text-editor-image-upload) */
10692
- inlineImages
10938
+ inlineImagesWithProgress
10693
10939
  ]);
10694
10940
  const messageRenderer = React.useCallback((messageProps) => {
10695
10941
  return onRenderMessage === undefined
@@ -11515,10 +11761,10 @@ const MessageThreadWrapper = (props) => {
11515
11761
  /* @conditional-compile-remove(rich-text-editor-image-upload) */
11516
11762
  onInsertInlineImage: richTextEditorOptions === null || richTextEditorOptions === void 0 ? void 0 : richTextEditorOptions.onInsertInlineImage,
11517
11763
  /* @conditional-compile-remove(rich-text-editor-image-upload) */
11518
- inlineImages: (richTextEditorOptions === null || richTextEditorOptions === void 0 ? void 0 : richTextEditorOptions.messagesInlineImages) &&
11519
- (richTextEditorOptions === null || richTextEditorOptions === void 0 ? void 0 : richTextEditorOptions.messagesInlineImages[message.message.messageId]),
11764
+ inlineImagesWithProgress: (richTextEditorOptions === null || richTextEditorOptions === void 0 ? void 0 : richTextEditorOptions.messagesInlineImagesWithProgress) &&
11765
+ (richTextEditorOptions === null || richTextEditorOptions === void 0 ? void 0 : richTextEditorOptions.messagesInlineImagesWithProgress[message.message.messageId]),
11520
11766
  /* @conditional-compile-remove(rich-text-editor-image-upload) */
11521
- onCancelInlineImageUpload: richTextEditorOptions === null || richTextEditorOptions === void 0 ? void 0 : richTextEditorOptions.onCancelInlineImageUpload })));
11767
+ onRemoveInlineImage: richTextEditorOptions === null || richTextEditorOptions === void 0 ? void 0 : richTextEditorOptions.onRemoveInlineImage })));
11522
11768
  }))))));
11523
11769
  };
11524
11770
  const MemoChatMessageComponentWrapper = React.memo((obj) => {
@@ -21223,6 +21469,12 @@ const CHAT_CONTAINER_MIN_WIDTH_REM = 17.5;
21223
21469
  * @private
21224
21470
  */
21225
21471
  const SEND_BOX_UPLOADS_KEY_VALUE = 'send-box';
21472
+ /* @conditional-compile-remove(rich-text-editor-image-upload) */
21473
+ /**
21474
+ * Default rich text editor inline image file name
21475
+ * @internal
21476
+ */
21477
+ const _DEFAULT_INLINE_IMAGE_FILE_NAME = 'image.png';
21226
21478
 
21227
21479
  // Copyright (c) Microsoft Corporation.
21228
21480
  // Licensed under the MIT License.
@@ -22722,7 +22974,7 @@ const AttachmentDownloadErrorBar = (props) => {
22722
22974
  /**
22723
22975
  * Wrapper for RichTextSendBox component to allow us to use usePropsFor with richTextSendBox with lazy loading
22724
22976
  */
22725
- const RichTextSendBoxWrapper = React.lazy(() => Promise.resolve().then(function () { return require('./RichTextSendBoxWrapper-BVOysnsq.js'); }).then((module) => ({ default: module.RichTextSendBoxWrapper })));
22977
+ const RichTextSendBoxWrapper = React.lazy(() => Promise.resolve().then(function () { return require('./RichTextSendBoxWrapper-8FsFMpKF.js'); }).then((module) => ({ default: module.RichTextSendBoxWrapper })));
22726
22978
  /**
22727
22979
  * @private
22728
22980
  * Use this function to load RoosterJS dependencies early in the lifecycle.
@@ -22730,7 +22982,7 @@ const RichTextSendBoxWrapper = React.lazy(() => Promise.resolve().then(function
22730
22982
  *
22731
22983
  /* @conditional-compile-remove(rich-text-editor-composite-support)
22732
22984
  */
22733
- const loadRichTextSendBox = () => Promise.resolve().then(function () { return require('./RichTextSendBoxWrapper-BVOysnsq.js'); }).then((module) => ({ default: module.RichTextSendBoxWrapper }));
22985
+ const loadRichTextSendBox = () => Promise.resolve().then(function () { return require('./RichTextSendBoxWrapper-8FsFMpKF.js'); }).then((module) => ({ default: module.RichTextSendBoxWrapper }));
22734
22986
  /**
22735
22987
  * @private
22736
22988
  */
@@ -22738,7 +22990,7 @@ const SendBoxPicker = (props) => {
22738
22990
  /* @conditional-compile-remove(rich-text-editor-composite-support) */
22739
22991
  const { richTextEditorOptions } = props;
22740
22992
  /* @conditional-compile-remove(rich-text-editor-image-upload) */
22741
- const { onPaste, onInsertInlineImage, inlineImages, onCancelInlineImageUpload } = richTextEditorOptions || {};
22993
+ const { onPaste, onInsertInlineImage, inlineImagesWithProgress, onRemoveInlineImage } = richTextEditorOptions || {};
22742
22994
  const sendBoxProps = usePropsFor$2(SendBox);
22743
22995
  /* @conditional-compile-remove(rich-text-editor-composite-support) */
22744
22996
  const isRichTextEditorEnabled = React.useMemo(() => {
@@ -22755,9 +23007,9 @@ const SendBoxPicker = (props) => {
22755
23007
  /* @conditional-compile-remove(rich-text-editor-image-upload) */
22756
23008
  onInsertInlineImage: onInsertInlineImage,
22757
23009
  /* @conditional-compile-remove(rich-text-editor-image-upload) */
22758
- inlineImages: inlineImages,
23010
+ inlineImagesWithProgress: inlineImagesWithProgress,
22759
23011
  /* @conditional-compile-remove(rich-text-editor-image-upload) */
22760
- onCancelInlineImageUpload: onCancelInlineImageUpload })))));
23012
+ onRemoveInlineImage: onRemoveInlineImage })))));
22761
23013
  }
22762
23014
  return sendBox;
22763
23015
  };
@@ -22813,14 +23065,14 @@ const getEditBoxMessagesInlineImages = (editBoxInlineImageUploads) => {
22813
23065
  return;
22814
23066
  }
22815
23067
  const messageIds = Object.keys(editBoxInlineImageUploads || {});
22816
- const messagesInlineImages = {};
23068
+ const messagesInlineImagesWithProgress = {};
22817
23069
  messageIds.map((messageId) => {
22818
23070
  const messageUploads = editBoxInlineImageUploads[messageId].map((upload) => {
22819
23071
  return upload.metadata;
22820
23072
  });
22821
- messagesInlineImages[messageId] = messageUploads;
23073
+ messagesInlineImagesWithProgress[messageId] = messageUploads;
22822
23074
  });
22823
- return messagesInlineImages;
23075
+ return messagesInlineImagesWithProgress;
22824
23076
  };
22825
23077
  /* @conditional-compile-remove(rich-text-editor-image-upload) */
22826
23078
  /**
@@ -22855,7 +23107,10 @@ const inlineImageUploadHandler = (uploadTasks, adapter, strings) => __awaiter$G(
22855
23107
  }
22856
23108
  try {
22857
23109
  const response = yield adapter.uploadImage(image, (_c = task.metadata) === null || _c === void 0 ? void 0 : _c.name);
22858
- uploadTask.notifyUploadCompleted(response.id, task.metadata.url || '');
23110
+ // Use response id as the image src because we need to keep the original image id as a reference to find the image.
23111
+ // Also the html content we send to ChatSDK does not need image src,
23112
+ // it only need the response id to match the uploaded image, url is not needed.
23113
+ uploadTask.notifyUploadCompleted(task.metadata.id, response.id);
22859
23114
  }
22860
23115
  catch (error) {
22861
23116
  console.error(error);
@@ -22864,8 +23119,8 @@ const inlineImageUploadHandler = (uploadTasks, adapter, strings) => __awaiter$G(
22864
23119
  }
22865
23120
  });
22866
23121
  /* @conditional-compile-remove(rich-text-editor-image-upload) */
22867
- const generateUploadTask = (image, fileName, messageId, inlineImageUploadActionHandler) => __awaiter$G(void 0, void 0, void 0, function* () {
22868
- const imageData = yield getInlineImageData(image);
23122
+ const generateUploadTask = (imageAttributes, fileName, messageId, inlineImageUploadActionHandler) => __awaiter$G(void 0, void 0, void 0, function* () {
23123
+ const imageData = yield getInlineImageData(imageAttributes.src);
22869
23124
  if (!imageData) {
22870
23125
  return;
22871
23126
  }
@@ -22874,9 +23129,9 @@ const generateUploadTask = (image, fileName, messageId, inlineImageUploadActionH
22874
23129
  image: imageData,
22875
23130
  taskId,
22876
23131
  metadata: {
22877
- id: taskId,
23132
+ id: imageAttributes.id,
22878
23133
  name: fileName,
22879
- url: image,
23134
+ url: imageAttributes.src,
22880
23135
  progress: 0
22881
23136
  },
22882
23137
  notifyUploadProgressChanged: (value) => {
@@ -22911,8 +23166,8 @@ const generateUploadTask = (image, fileName, messageId, inlineImageUploadActionH
22911
23166
  /**
22912
23167
  * @internal
22913
23168
  */
22914
- const onInsertInlineImageForEditBox = (image, fileName, messageId, adapter, handleEditBoxInlineImageUploadAction, chatCompositeStrings) => __awaiter$G(void 0, void 0, void 0, function* () {
22915
- const uploadTask = yield generateUploadTask(image, fileName, messageId, handleEditBoxInlineImageUploadAction);
23169
+ const onInsertInlineImageForEditBox = (imageAttributes, fileName, messageId, adapter, handleEditBoxInlineImageUploadAction, chatCompositeStrings) => __awaiter$G(void 0, void 0, void 0, function* () {
23170
+ const uploadTask = yield generateUploadTask(imageAttributes, fileName, messageId, handleEditBoxInlineImageUploadAction);
22916
23171
  if (!uploadTask) {
22917
23172
  return;
22918
23173
  }
@@ -22927,8 +23182,8 @@ const onInsertInlineImageForEditBox = (image, fileName, messageId, adapter, hand
22927
23182
  /**
22928
23183
  * @internal
22929
23184
  */
22930
- const onInsertInlineImageForSendBox = (image, fileName, adapter, handleSendBoxInlineImageUploadAction, chatCompositeStrings) => __awaiter$G(void 0, void 0, void 0, function* () {
22931
- const uploadTask = yield generateUploadTask(image, fileName, SEND_BOX_UPLOADS_KEY_VALUE, handleSendBoxInlineImageUploadAction);
23185
+ const onInsertInlineImageForSendBox = (imageAttributes, fileName, adapter, handleSendBoxInlineImageUploadAction, chatCompositeStrings) => __awaiter$G(void 0, void 0, void 0, function* () {
23186
+ const uploadTask = yield generateUploadTask(imageAttributes, fileName, SEND_BOX_UPLOADS_KEY_VALUE, handleSendBoxInlineImageUploadAction);
22932
23187
  if (!uploadTask) {
22933
23188
  return;
22934
23189
  }
@@ -22943,8 +23198,14 @@ const onInsertInlineImageForSendBox = (image, fileName, adapter, handleSendBoxIn
22943
23198
  /**
22944
23199
  * @internal
22945
23200
  */
22946
- const cancelInlineImageUpload = (imageId, imageUpload, messageId, inlineImageUploadActionHandler, adapter) => {
23201
+ const cancelInlineImageUpload = (imageAttributes, imageUploads, messageId, inlineImageUploadActionHandler, adapter) => {
23202
+ if (!imageUploads || !imageUploads[messageId]) {
23203
+ deleteExistingInlineImageForEditBox(imageAttributes.id, messageId, adapter);
23204
+ return;
23205
+ }
23206
+ const imageUpload = imageUploads[messageId].find((upload) => upload.metadata.id === imageAttributes.id);
22947
23207
  if (!imageUpload || !(imageUpload === null || imageUpload === void 0 ? void 0 : imageUpload.metadata.id)) {
23208
+ deleteExistingInlineImageForEditBox(imageAttributes.id, messageId, adapter);
22948
23209
  return;
22949
23210
  }
22950
23211
  inlineImageUploadActionHandler({
@@ -22952,37 +23213,56 @@ const cancelInlineImageUpload = (imageId, imageUpload, messageId, inlineImageUpl
22952
23213
  id: imageUpload === null || imageUpload === void 0 ? void 0 : imageUpload.metadata.id,
22953
23214
  messageId
22954
23215
  });
22955
- // TODO: remove local blob
22956
23216
  if ((imageUpload === null || imageUpload === void 0 ? void 0 : imageUpload.metadata.progress) === 1) {
22957
- try {
22958
- adapter.deleteImage(imageId);
22959
- }
22960
- catch (error) {
22961
- console.error(error);
22962
- }
23217
+ deleteInlineImageFromServer(imageUpload === null || imageUpload === void 0 ? void 0 : imageUpload.metadata.id, adapter);
22963
23218
  }
22964
23219
  };
22965
23220
  /* @conditional-compile-remove(rich-text-editor-image-upload) */
23221
+ const deleteInlineImageFromServer = (imageId, adapter) => {
23222
+ try {
23223
+ adapter.deleteImage(imageId);
23224
+ }
23225
+ catch (error) {
23226
+ console.error(error);
23227
+ }
23228
+ };
23229
+ /* @conditional-compile-remove(rich-text-editor-image-upload) */
23230
+ // This function is used to delete the inline image that existed before editing starts
23231
+ const deleteExistingInlineImageForEditBox = (imageId, messageId, adapter) => {
23232
+ messageId !== SEND_BOX_UPLOADS_KEY_VALUE && deleteInlineImageFromServer(imageId, adapter);
23233
+ };
23234
+ /* @conditional-compile-remove(rich-text-editor-image-upload) */
22966
23235
  /**
22967
23236
  * @internal
22968
23237
  */
22969
- const onCancelInlineImageUploadHandlerForEditBox = (imageId, messageId, editBoxInlineImageUploads, adapter, handleEditBoxInlineImageUploadAction) => {
22970
- if (!editBoxInlineImageUploads) {
22971
- return;
23238
+ const updateContentStringWithUploadedInlineImages = (content, imageUploads, messageId = SEND_BOX_UPLOADS_KEY_VALUE) => {
23239
+ if (!imageUploads || !imageUploads[messageId]) {
23240
+ return content;
22972
23241
  }
22973
- const imageUpload = editBoxInlineImageUploads[messageId].find((upload) => upload.metadata.id === imageId);
22974
- cancelInlineImageUpload(imageId, imageUpload, messageId, handleEditBoxInlineImageUploadAction, adapter);
23242
+ const messageUploads = imageUploads[messageId];
23243
+ const document = new DOMParser().parseFromString(content !== null && content !== void 0 ? content : '', 'text/html');
23244
+ document.querySelectorAll('img').forEach((img) => {
23245
+ var _a;
23246
+ const uploadInlineImage = messageUploads.find((upload) => !upload.metadata.error && upload.metadata.progress === 1 && upload.metadata.id === img.id);
23247
+ if (uploadInlineImage) {
23248
+ // ChatSDK uses the respond id provided by the upload response. We store the response id in the image src attribute previously.
23249
+ img.id = (_a = uploadInlineImage.metadata.url) !== null && _a !== void 0 ? _a : img.id;
23250
+ img.src = '';
23251
+ }
23252
+ });
23253
+ content = document.body.innerHTML;
23254
+ return content;
22975
23255
  };
22976
23256
  /* @conditional-compile-remove(rich-text-editor-image-upload) */
22977
23257
  /**
22978
23258
  * @internal
22979
23259
  */
22980
- const onCancelInlineImageUploadHandlerForSendBox = (imageId, sendBoxInlineImageUploads, adapter, handleSendBoxInlineImageUploadAction) => {
22981
- if (!sendBoxInlineImageUploads) {
22982
- return;
23260
+ const getImageFileNameFromAttributes = (imageAttributes) => {
23261
+ const fileName = imageAttributes[_IMAGE_ATTRIBUTE_INLINE_IMAGE_FILE_NAME_KEY];
23262
+ if (!fileName || fileName === '' || fileName === 'undefined' || fileName === 'null') {
23263
+ return _DEFAULT_INLINE_IMAGE_FILE_NAME;
22983
23264
  }
22984
- const imageUpload = sendBoxInlineImageUploads[SEND_BOX_UPLOADS_KEY_VALUE].find((upload) => upload.metadata.id === imageId);
22985
- cancelInlineImageUpload(imageId, imageUpload, SEND_BOX_UPLOADS_KEY_VALUE, handleSendBoxInlineImageUploadAction, adapter);
23265
+ return fileName;
22986
23266
  };
22987
23267
 
22988
23268
  // Copyright (c) Microsoft Corporation.
@@ -23327,6 +23607,8 @@ const ChatScreen = (props) => {
23327
23607
  /* @conditional-compile-remove(file-sharing-acs) */ /* @conditional-compile-remove(rich-text-editor-composite-support) */ options) {
23328
23608
  return __awaiter$F(this, void 0, void 0, function* () {
23329
23609
  var _a;
23610
+ /* @conditional-compile-remove(rich-text-editor-image-upload) */
23611
+ content = updateContentStringWithUploadedInlineImages(content, sendBoxInlineImageUploads);
23330
23612
  /* @conditional-compile-remove(file-sharing-acs) */
23331
23613
  const attachments = (_a = options === null || options === void 0 ? void 0 : options.attachments) !== null && _a !== void 0 ? _a : [];
23332
23614
  /* @conditional-compile-remove(file-sharing-acs) */
@@ -23345,10 +23627,16 @@ const ChatScreen = (props) => {
23345
23627
  /* @conditional-compile-remove(file-sharing-acs) */
23346
23628
  return;
23347
23629
  });
23348
- }, [adapter, /* @conditional-compile-remove(rich-text-editor-image-upload) */ handleSendBoxInlineImageUploadAction]);
23630
+ }, [
23631
+ adapter,
23632
+ /* @conditional-compile-remove(rich-text-editor-image-upload) */ handleSendBoxInlineImageUploadAction,
23633
+ /* @conditional-compile-remove(rich-text-editor-image-upload) */ sendBoxInlineImageUploads
23634
+ ]);
23349
23635
  const onUpdateMessageHandler = React.useCallback(function (messageId, content,
23350
23636
  /* @conditional-compile-remove(file-sharing-acs) */ options) {
23351
23637
  return __awaiter$F(this, void 0, void 0, function* () {
23638
+ /* @conditional-compile-remove(rich-text-editor-image-upload) */
23639
+ content = updateContentStringWithUploadedInlineImages(content, editBoxInlineImageUploads, messageId);
23352
23640
  yield messageThreadProps.onUpdateMessage(messageId, content,
23353
23641
  /* @conditional-compile-remove(file-sharing-acs) */ options);
23354
23642
  /* @conditional-compile-remove(rich-text-editor-image-upload) */
@@ -23356,6 +23644,7 @@ const ChatScreen = (props) => {
23356
23644
  });
23357
23645
  }, [
23358
23646
  /* @conditional-compile-remove(rich-text-editor-image-upload) */ handleEditBoxInlineImageUploadAction,
23647
+ /* @conditional-compile-remove(rich-text-editor-image-upload) */ editBoxInlineImageUploads,
23359
23648
  messageThreadProps
23360
23649
  ]);
23361
23650
  /* @conditional-compile-remove(rich-text-editor-image-upload) */
@@ -23389,14 +23678,14 @@ const ChatScreen = (props) => {
23389
23678
  return (options === null || options === void 0 ? void 0 : options.richTextEditor)
23390
23679
  ? Object.assign(Object.assign({}, richTextEditorOptions), {
23391
23680
  /* @conditional-compile-remove(rich-text-editor-image-upload) */
23392
- onInsertInlineImage: (imageUrl, imageFileName, messageId) => {
23393
- onInsertInlineImageForEditBox(imageUrl, imageFileName, messageId, adapter, handleEditBoxInlineImageUploadAction, localeStrings.chat);
23681
+ onInsertInlineImage: (imageAttributes, messageId) => {
23682
+ onInsertInlineImageForEditBox(imageAttributes, getImageFileNameFromAttributes(imageAttributes), messageId, adapter, handleEditBoxInlineImageUploadAction, localeStrings.chat);
23394
23683
  },
23395
23684
  /* @conditional-compile-remove(rich-text-editor-image-upload) */
23396
- messagesInlineImages: getEditBoxMessagesInlineImages(editBoxInlineImageUploads),
23685
+ messagesInlineImagesWithProgress: getEditBoxMessagesInlineImages(editBoxInlineImageUploads),
23397
23686
  /* @conditional-compile-remove(rich-text-editor-image-upload) */
23398
- onCancelInlineImageUpload: (imageId, messageId) => {
23399
- onCancelInlineImageUploadHandlerForEditBox(imageId, messageId, editBoxInlineImageUploads, adapter, handleEditBoxInlineImageUploadAction);
23687
+ onRemoveInlineImage: (imageAttributes, messageId) => {
23688
+ cancelInlineImageUpload(imageAttributes, editBoxInlineImageUploads, messageId, handleEditBoxInlineImageUploadAction, adapter);
23400
23689
  } }) : undefined;
23401
23690
  }, [
23402
23691
  options === null || options === void 0 ? void 0 : options.richTextEditor,
@@ -23410,14 +23699,14 @@ const ChatScreen = (props) => {
23410
23699
  return (options === null || options === void 0 ? void 0 : options.richTextEditor)
23411
23700
  ? Object.assign(Object.assign({}, richTextEditorOptions), {
23412
23701
  /* @conditional-compile-remove(rich-text-editor-image-upload) */
23413
- onInsertInlineImage: (imageUrl, imageFileName) => {
23414
- onInsertInlineImageForSendBox(imageUrl, imageFileName, adapter, handleSendBoxInlineImageUploadAction, localeStrings.chat);
23702
+ onInsertInlineImage: (imageAttributes) => {
23703
+ onInsertInlineImageForSendBox(imageAttributes, getImageFileNameFromAttributes(imageAttributes), adapter, handleSendBoxInlineImageUploadAction, localeStrings.chat);
23415
23704
  },
23416
23705
  /* @conditional-compile-remove(rich-text-editor-image-upload) */
23417
- inlineImages: getSendBoxInlineImages(sendBoxInlineImageUploads),
23706
+ inlineImagesWithProgress: getSendBoxInlineImages(sendBoxInlineImageUploads),
23418
23707
  /* @conditional-compile-remove(rich-text-editor-image-upload) */
23419
- onCancelInlineImageUpload: (imageId) => {
23420
- onCancelInlineImageUploadHandlerForSendBox(imageId, sendBoxInlineImageUploads, adapter, handleSendBoxInlineImageUploadAction);
23708
+ onRemoveInlineImage: (imageAttributes) => {
23709
+ cancelInlineImageUpload(imageAttributes, sendBoxInlineImageUploads, SEND_BOX_UPLOADS_KEY_VALUE, handleSendBoxInlineImageUploadAction, adapter);
23421
23710
  } }) : undefined;
23422
23711
  }, [
23423
23712
  options === null || options === void 0 ? void 0 : options.richTextEditor,
@@ -38367,12 +38656,7 @@ const capabilitiesChangedInfoAndRoleSelector = reselect__namespace.createSelecto
38367
38656
  */
38368
38657
  const useTrackedCapabilityChangedNotifications = (capabilitiesChangedAndRoleInfo) => {
38369
38658
  const [trackedCapabilityChangedNotifications, setTrackedCapabilityChangedNotifications] = React.useState({});
38370
- // Initialize a share screen capability changed notification with 'RoleChanged' reason so that the initial
38371
- // share screen capability changed info from the Calling SDK when joining Teams interop will be ignored because
38372
- // being able to share screen is assumed by default. This is inline with what Teams is doing.
38373
- const activeNotifications = React.useRef({
38374
- shareScreen: { capabilityName: 'shareScreen', isPresent: true, changedReason: 'RoleChanged' }
38375
- });
38659
+ const activeNotifications = React.useRef({});
38376
38660
  React.useEffect(() => {
38377
38661
  activeNotifications.current = updateLatestCapabilityChangedNotificationMap(capabilitiesChangedAndRoleInfo, activeNotifications.current);
38378
38662
  setTrackedCapabilityChangedNotifications((prev) => updateTrackedCapabilityChangedNotificationsWithActiveNotifications(prev, Object.values(activeNotifications.current)));
@@ -38446,6 +38730,24 @@ const updateLatestCapabilityChangedNotificationMap = (capabilitiesChangedInfoAnd
38446
38730
  ((_b = activeNotifications[capabilityName]) === null || _b === void 0 ? void 0 : _b.changedReason)) {
38447
38731
  continue;
38448
38732
  }
38733
+ // All initial values of capabilities are not present with reason 'FeatureNotSupported'. So we should not show a
38734
+ // notification for them when they initially become present at the start of the call
38735
+ const oldCapabilityValue = capabilitiesChangedInfoAndRole.capabilitiesChangeInfo.oldValue[capabilityName];
38736
+ if (newCapabilityValue.isPresent === true &&
38737
+ (oldCapabilityValue === null || oldCapabilityValue === void 0 ? void 0 : oldCapabilityValue.isPresent) === false &&
38738
+ (oldCapabilityValue === null || oldCapabilityValue === void 0 ? void 0 : oldCapabilityValue.reason) === 'FeatureNotSupported' &&
38739
+ capabilitiesChangedInfoAndRole.capabilitiesChangeInfo.reason === 'MeetingOptionOrOrganizerPolicyChanged') {
38740
+ continue;
38741
+ }
38742
+ // Do not show the first time the screenshare capability is present when the user's role is resolved to mirror
38743
+ // Teams behaviour
38744
+ if (capabilityName === 'shareScreen' &&
38745
+ activeNotifications['shareScreen'] === undefined &&
38746
+ newCapabilityValue.isPresent === true &&
38747
+ (oldCapabilityValue === null || oldCapabilityValue === void 0 ? void 0 : oldCapabilityValue.isPresent) === false &&
38748
+ capabilitiesChangedInfoAndRole.capabilitiesChangeInfo.reason === 'RoleChanged') {
38749
+ continue;
38750
+ }
38449
38751
  const newCapabilityChangeNotification = {
38450
38752
  capabilityName: capabilityName,
38451
38753
  isPresent: newCapabilityValue.isPresent,
@@ -43227,7 +43529,6 @@ exports._IdentifierProvider = _IdentifierProvider;
43227
43529
  exports._formatString = _formatString;
43228
43530
  exports.attachmentMetadataReducer = attachmentMetadataReducer;
43229
43531
  exports.attachmentUploadCardsStyles = attachmentUploadCardsStyles;
43230
- exports.cancelInlineImageUpload = cancelInlineImageUpload$1;
43231
43532
  exports.createAzureCommunicationCallAdapter = createAzureCommunicationCallAdapter;
43232
43533
  exports.createAzureCommunicationCallAdapterFromClient = createAzureCommunicationCallAdapterFromClient;
43233
43534
  exports.createAzureCommunicationCallWithChatAdapter = createAzureCommunicationCallWithChatAdapter;
@@ -43247,19 +43548,21 @@ exports.doesMessageContainMultipleAttachments = doesMessageContainMultipleAttach
43247
43548
  exports.editBoxRichTextEditorStyle = editBoxRichTextEditorStyle;
43248
43549
  exports.editBoxWidthStyles = editBoxWidthStyles;
43249
43550
  exports.fromFlatCommunicationIdentifier = fromFlatCommunicationIdentifier;
43551
+ exports.getContentWithUpdatedInlineImagesInfo = getContentWithUpdatedInlineImagesInfo;
43250
43552
  exports.getMessageState = getMessageState;
43251
43553
  exports.getMessageWithAttachmentMetadata = getMessageWithAttachmentMetadata;
43554
+ exports.getPreviousInlineImages = getPreviousInlineImages;
43252
43555
  exports.getSelector = getSelector;
43253
43556
  exports.getSelector$1 = getSelector$1;
43254
43557
  exports.hasIncompleteAttachmentUploads = hasIncompleteAttachmentUploads;
43255
43558
  exports.imageOverlayTheme = imageOverlayTheme;
43256
- exports.insertImagesToContentString = insertImagesToContentString;
43257
- exports.isAttachmentUploadCompleted = isAttachmentUploadCompleted;
43559
+ exports.isMessageTooLong = isMessageTooLong;
43258
43560
  exports.lightTheme = lightTheme;
43259
43561
  exports.loadCallComposite = loadCallComposite;
43260
43562
  exports.loadCallWithChatComposite = loadCallWithChatComposite;
43261
43563
  exports.loadChatComposite = loadChatComposite;
43262
43564
  exports.loadOutboundCallComposite = loadOutboundCallComposite;
43565
+ exports.modifyInlineImagesInContentString = modifyInlineImagesInContentString;
43263
43566
  exports.onRenderCancelIcon = onRenderCancelIcon;
43264
43567
  exports.onRenderSubmitIcon = onRenderSubmitIcon;
43265
43568
  exports.onResolveVideoEffectDependency = onResolveVideoEffectDependency;
@@ -43287,4 +43590,4 @@ exports.useTeamsCall = useTeamsCall;
43287
43590
  exports.useTeamsCallAdapter = useTeamsCallAdapter;
43288
43591
  exports.useTeamsCallAgent = useTeamsCallAgent;
43289
43592
  exports.useTheme = useTheme;
43290
- //# sourceMappingURL=index-YIP5Cyt3.js.map
43593
+ //# sourceMappingURL=index-D84PSTZV.js.map