communication-react-19
Version:
React library for building modern communication user experiences utilizing Azure Communication Services (React 19 compatible fork)
221 lines • 9.06 kB
JavaScript
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
/**
* @private
*/
export const MAXIMUM_LENGTH_OF_MESSAGE = 8000;
const EMPTY_MESSAGE_REGEX = /^\s*$/;
/* @conditional-compile-remove(file-sharing-acs) */
/**
* @private
*/
export const hasIncompleteAttachmentUploads = (attachmentsWithProgress) => {
return !!((attachmentsWithProgress === null || attachmentsWithProgress === void 0 ? void 0 : attachmentsWithProgress.length) &&
!attachmentsWithProgress
.filter((attachmentUpload) => !attachmentUpload.error)
.every((attachmentUpload) => attachmentUpload.progress === 1 && attachmentUpload.progress !== undefined));
};
/* @conditional-compile-remove(file-sharing-acs) */
/**
* @private
*/
export const isAttachmentUploadCompleted = (attachmentsWithProgress) => {
return !!(attachmentsWithProgress === null || attachmentsWithProgress === void 0 ? void 0 : attachmentsWithProgress.find((attachment) => !attachment.error));
};
/* @conditional-compile-remove(rich-text-editor-image-upload) */
/**
* Obtain any image nodes from the content DOM passed in
* returns a list of image IDs
* @internal
*/
export const inlineImageIds = (content) => {
if (!content) {
return [];
}
const document = new DOMParser().parseFromString(content, 'text/html');
const imageTags = document.querySelectorAll('img');
const ids = [];
imageTags.forEach((node) => {
const id = node.id;
const url = node.src;
if (id) {
ids.push({ id, url });
}
});
return ids;
};
/* @conditional-compile-remove(rich-text-editor-image-upload) */
/**
* Check if the content has inline image.
* @internal
*/
export const hasInlineImageContent = (content) => {
return inlineImageIds(content).length > 0;
};
/* @conditional-compile-remove(rich-text-editor-image-upload) */
/**
* @internal
*
* @param message - The message content to update.
* @param initialInlineImages - The initial inline images that comes with the message before editing.
*
* @returns The updated message content.
*/
export const updateStylesOfInlineImages = (message, initialInlineImages) => __awaiter(void 0, void 0, void 0, function* () {
if (message === '') {
return message;
}
const initialInlineImagesIds = initialInlineImages.map((initialInlineImage) => initialInlineImage.id);
const document = new DOMParser().parseFromString(message !== null && message !== void 0 ? message : '', 'text/html');
const imagesPromise = Array.from(document.querySelectorAll('img')).map((img) => {
return new Promise((resolve, rejects) => {
// The message might content images that comes with the message before editing.
// This function should only modify the message content for images that are newly added.
if (initialInlineImagesIds.includes(img.id)) {
resolve();
return;
}
const imageElement = new Image();
imageElement.src = img.src;
imageElement.onload = () => {
// imageElement is a copy of original img element, so changes need to be made to the original img element
img.width = imageElement.width;
img.height = imageElement.height;
img.style.aspectRatio = `${imageElement.width} / ${imageElement.height}`;
// Clear maxWidth and maxHeight styles that are set by roosterJS.
// This is so that they can be set in messageThread styles without using the important flag.
img.style.maxWidth = '';
img.style.maxHeight = '';
resolve();
};
imageElement.onerror = () => {
rejects(`Error loading image ${img.id}`);
};
});
});
yield Promise.all(imagesPromise);
const newMessage = document.body.innerHTML;
return newMessage;
});
/**
* @private
*/
export const isMessageTooLong = (valueLength) => {
return valueLength > MAXIMUM_LENGTH_OF_MESSAGE;
};
/**
* @private
*/
export const sanitizeText = (message) => {
if (EMPTY_MESSAGE_REGEX.test(message)) {
return '';
}
else {
return message;
}
};
/**
* Determines whether the send box should be disabled.
*
* @param hasContent - Indicates whether the send box has content.
* @param hasCompletedAttachmentUploads - Indicates whether attachment uploads have completed.
* @param hasError - Indicates whether there is an error.
* @param disabled - Indicates whether the send box is disabled.
* @returns A boolean value indicating whether the send box should be disabled.
*/
export const isSendBoxButtonDisabled = ({ hasContent,
/* @conditional-compile-remove(file-sharing-acs) */
hasCompletedAttachmentUploads, hasError, disabled }) => {
return (
// no content
!(hasContent || /* @conditional-compile-remove(file-sharing-acs) */ hasCompletedAttachmentUploads) ||
//error message exists
hasError ||
disabled);
};
/* @conditional-compile-remove(file-sharing-acs) */
/**
* @internal
*/
export const toAttachmentMetadata = (attachmentsWithProgress) => {
return attachmentsWithProgress === null || attachmentsWithProgress === void 0 ? void 0 : attachmentsWithProgress.filter((attachment) => {
var _a;
return !('error' in attachment) && !((_a = attachment.error) === null || _a === void 0 ? void 0 : _a.message);
}).map((attachment) => {
var _a;
return {
id: attachment.id,
name: attachment.name,
url: (_a = attachment.url) !== null && _a !== void 0 ? _a : ''
};
});
};
/**
* @internal
*/
export const modifyInlineImagesInContentString = (content, initialInlineImages, onCompleted) => __awaiter(void 0, void 0, void 0, function* () {
let newContent = content;
/* @conditional-compile-remove(rich-text-editor-image-upload) */
try {
newContent = yield updateStylesOfInlineImages(content, initialInlineImages);
}
catch (error) {
console.error('Error updating inline images: ', error);
}
onCompleted === null || onCompleted === void 0 ? void 0 : onCompleted(newContent);
});
/* @conditional-compile-remove(rich-text-editor-image-upload) */
/**
* @internal
*/
export const removeBrokenImageContentAndClearImageSizeStyles = (content) => {
const document = new DOMParser().parseFromString(content, 'text/html');
document.querySelectorAll('img').forEach((img) => {
// Before submitting/resend the message, we need to trim the unnecessary attributes such as src,
// which is set to a local svg of a broken image icon at this point.
// Once message is submitted/resent, it will be fetched again and might not be a broken image anymore,
// That's why we need to remove the class and data-ui-id attribute of 'broken-image-wrapper'
if (img.className === 'broken-image-wrapper') {
img.removeAttribute('class');
img.removeAttribute('src');
img.removeAttribute('data-ui-id');
}
// Clear maxWidth and maxHeight styles that are set by roosterJS.
// Clear width and height styles as the width and height is set in attributes
// This is so that they can be set in messageThread styles without using the important flag.
img.style.width = '';
img.style.height = '';
img.style.maxWidth = '';
img.style.maxHeight = '';
});
return document.body.innerHTML;
};
/* @conditional-compile-remove(rich-text-editor-image-upload) */
/**
* @internal
*/
export const getContentWithUpdatedInlineImagesInfo = (content, inlineImageWithProgress) => {
if (!inlineImageWithProgress || inlineImageWithProgress.length <= 0) {
return content;
}
const document = new DOMParser().parseFromString(content, 'text/html');
document.querySelectorAll('img').forEach((img) => {
const imageId = img.id;
const inlineImage = inlineImageWithProgress.find((image) => !image.error && image.progress === 1 && image.id === imageId);
if (inlineImage) {
img.id = inlineImage.id;
img.src = inlineImage.url || img.src;
}
});
return document.body.innerHTML;
};
//# sourceMappingURL=SendBoxUtils.js.map