communication-react-19
Version:
React library for building modern communication user experiences utilizing Azure Communication Services (React 19 compatible fork)
137 lines • 8.86 kB
JavaScript
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
import React, { useCallback, useMemo } from 'react';
import { noMessageStatusStyle, useChatMessageRenderStyles } from '../../styles/MessageThread.styles';
import { mergeStyles } from '@fluentui/react';
import { mergeClasses } from '@fluentui/react-components';
import { createStyleFromV8Style } from '../../styles/v8StyleShim';
import { ChatMyMessageComponent } from './ChatMyMessageComponent';
import { ChatMyMessage as FluentChatMyMessage } from '@fluentui-contrib/react-chat';
import { getFluentUIAttachedValue, removeFluentUIKeyboardNavigationStyles } from '../../utils/ChatMessageComponentUtils';
/**
* The component for rendering a chat message using Fluent UI components
* and handling default and custom renderers.
* This component handles rendering for chat message body, avatar and message status.
* The chat message body, avatar and message status should be shown for both default and custom renderers.
*
* @private
*/
export const FluentChatMyMessageComponent = (props) => {
const { message, styles, shouldOverlapAvatarAndMessage, onRenderMessage, onRenderAvatar, showMessageStatus, onRenderMessageStatus, participantCount, readCount, onActionButtonClick,
/* @conditional-compile-remove(date-time-customization) */
onDisplayDateTimeString, inlineImageOptions,
/* @conditional-compile-remove(mention) */
mentionOptions, userId, defaultStatusRenderer, statusToRender, actionsForAttachment, onRenderAttachmentDownloads,
/* @conditional-compile-remove(rich-text-editor) */
isRichTextEditorEnabled,
/* @conditional-compile-remove(rich-text-editor-image-upload) */
onPaste,
/* @conditional-compile-remove(rich-text-editor-image-upload) */
inlineImagesWithProgress,
/* @conditional-compile-remove(rich-text-editor-image-upload) */
onRemoveInlineImage,
/* @conditional-compile-remove(rich-text-editor-image-upload) */
onInsertInlineImage } = props;
const chatMessageRenderStyles = useChatMessageRenderStyles();
// To rerender the defaultChatMessageRenderer if app running across days(every new day chat time stamp
// needs to be regenerated), the dependency on "new Date().toDateString()"" is added.
const defaultChatMessageRenderer = useCallback((messageProps) => {
if (messageProps.message.messageType === 'chat' ||
/* @conditional-compile-remove(data-loss-prevention) */ messageProps.message.messageType === 'blocked') {
return (React.createElement(ChatMyMessageComponent, Object.assign({}, messageProps, { onRenderAttachmentDownloads: onRenderAttachmentDownloads, strings: messageProps.strings, message: messageProps.message, userId: userId, remoteParticipantsCount: participantCount ? participantCount - 1 : 0, shouldOverlapAvatarAndMessage: shouldOverlapAvatarAndMessage, onRenderAvatar: onRenderAvatar, showMessageStatus: showMessageStatus, messageStatus: messageProps.message.status, onActionButtonClick: onActionButtonClick,
/* @conditional-compile-remove(date-time-customization) */
onDisplayDateTimeString: onDisplayDateTimeString, inlineImageOptions: inlineImageOptions,
/* @conditional-compile-remove(mention) */
mentionOptions: mentionOptions, actionsForAttachment: actionsForAttachment,
/* @conditional-compile-remove(rich-text-editor) */
isRichTextEditorEnabled: isRichTextEditorEnabled,
/* @conditional-compile-remove(rich-text-editor-image-upload) */
onPaste: onPaste,
/* @conditional-compile-remove(rich-text-editor-image-upload) */
onRemoveInlineImage: onRemoveInlineImage,
/* @conditional-compile-remove(rich-text-editor-image-upload) */
onInsertInlineImage: onInsertInlineImage,
/* @conditional-compile-remove(rich-text-editor-image-upload) */
inlineImagesWithProgress: inlineImagesWithProgress })));
}
return React.createElement(React.Fragment, null);
}, [
onActionButtonClick,
onRenderAvatar,
participantCount,
shouldOverlapAvatarAndMessage,
showMessageStatus,
userId,
/* @conditional-compile-remove(date-time-customization) */
onDisplayDateTimeString,
inlineImageOptions,
/* @conditional-compile-remove(mention) */
mentionOptions,
onRenderAttachmentDownloads,
actionsForAttachment,
// eslint-disable-next-line react-hooks/exhaustive-deps
new Date().toDateString(),
/* @conditional-compile-remove(rich-text-editor) */
isRichTextEditorEnabled,
/* @conditional-compile-remove(rich-text-editor-image-upload) */
onPaste,
/* @conditional-compile-remove(rich-text-editor-image-upload) */
onRemoveInlineImage,
/* @conditional-compile-remove(rich-text-editor-image-upload) */
onInsertInlineImage,
/* @conditional-compile-remove(rich-text-editor-image-upload) */
inlineImagesWithProgress
]);
const messageRenderer = useCallback((messageProps) => {
return onRenderMessage === undefined
? defaultChatMessageRenderer(Object.assign({}, messageProps))
: onRenderMessage(messageProps, defaultChatMessageRenderer);
}, [defaultChatMessageRenderer, onRenderMessage]);
const messageStatusRenderer = useCallback((onRenderMessageStatus, defaultStatusRenderer, showMessageStatus, participantCount, readCount) => {
return showMessageStatus && statusToRender ? (onRenderMessageStatus ? (onRenderMessageStatus({ status: message.status })) : (defaultStatusRenderer(message, participantCount !== null && participantCount !== void 0 ? participantCount : 0, readCount !== null && readCount !== void 0 ? readCount : 0, message.status))) : (React.createElement("div", { className: mergeStyles(noMessageStatusStyle) }));
}, [message, statusToRender]);
const attached = useMemo(() => {
return getFluentUIAttachedValue(message.attached);
}, [message.attached]);
const myMessageRootProps = useMemo(() => {
return {
// myChatItemMessageContainer used in className and style prop as style prop can't handle CSS selectors
className: mergeClasses(chatMessageRenderStyles.rootMyMessage, chatMessageRenderStyles.rootCommon, mergeStyles(styles === null || styles === void 0 ? void 0 : styles.myChatItemMessageContainer)),
style: (styles === null || styles === void 0 ? void 0 : styles.myChatItemMessageContainer) !== undefined
? createStyleFromV8Style(styles === null || styles === void 0 ? void 0 : styles.myChatItemMessageContainer)
: {},
role: 'none'
};
}, [chatMessageRenderStyles.rootCommon, chatMessageRenderStyles.rootMyMessage, styles === null || styles === void 0 ? void 0 : styles.myChatItemMessageContainer]);
const setMessageContainerRef = useCallback((node) => {
removeFluentUIKeyboardNavigationStyles(node);
}, []);
const myMessageBodyProps = useMemo(() => {
return {
className: mergeClasses(chatMessageRenderStyles.bodyCommon, chatMessageRenderStyles.bodyMyMessage),
ref: setMessageContainerRef
};
}, [chatMessageRenderStyles.bodyCommon, chatMessageRenderStyles.bodyMyMessage, setMessageContainerRef]);
const myMessageStatusIcon = useMemo(() => {
var _a;
return (React.createElement("div", { className: mergeStyles({ paddingLeft: '0.25rem' }, (styles === null || styles === void 0 ? void 0 : styles.messageStatusContainer) ? styles.messageStatusContainer((_a = message.mine) !== null && _a !== void 0 ? _a : false) : '') }, message.status
? messageStatusRenderer(onRenderMessageStatus, defaultStatusRenderer, showMessageStatus, participantCount, readCount)
: undefined));
}, [
defaultStatusRenderer,
message.mine,
message.status,
messageStatusRenderer,
onRenderMessageStatus,
participantCount,
readCount,
showMessageStatus,
styles
]);
// Fluent UI message components are used here as for default message renderer,
// timestamp and author name should be shown but they aren't shown for custom renderer.
// More investigations are needed to check if this can be simplified with states.
// Status and avatar should be shown for both custom and default renderers.
return (React.createElement(FluentChatMyMessage, { attached: attached, root: myMessageRootProps, body: myMessageBodyProps, statusIcon: myMessageStatusIcon }, messageRenderer(Object.assign({}, props))));
};
//# sourceMappingURL=FluentChatMyMessageComponent.js.map