communication-react-19
Version:
React library for building modern communication user experiences utilizing Azure Communication Services (React 19 compatible fork)
116 lines • 7.19 kB
JavaScript
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
import React, { useCallback, useMemo } from 'react';
import { gutterWithAvatar, gutterWithHiddenAvatar, useChatMessageRenderStyles } from '../../styles/MessageThread.styles';
import { PersonaSize, mergeStyles, Persona } from '@fluentui/react';
import { mergeClasses } from '@fluentui/react-components';
import { createStyleFromV8Style } from '../../styles/v8StyleShim';
import { ChatMessage as FluentChatMessage } from '@fluentui-contrib/react-chat';
import { getFluentUIAttachedValue, removeFluentUIKeyboardNavigationStyles } from '../../utils/ChatMessageComponentUtils';
import { ChatMessageComponentAsMessageBubble } from './ChatMessageComponentAsMessageBubble';
/**
* 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 FluentChatMessageComponent = (props) => {
const { message, styles, shouldOverlapAvatarAndMessage, onRenderMessage, onRenderAvatar,
/* @conditional-compile-remove(date-time-customization) */
onDisplayDateTimeString, inlineImageOptions, actionsForAttachment, userId, onRenderAttachmentDownloads,
/* @conditional-compile-remove(mention) */
mentionOptions } = 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(ChatMessageComponentAsMessageBubble, Object.assign({}, messageProps, { onRenderAttachmentDownloads: onRenderAttachmentDownloads, strings: messageProps.strings, message: messageProps.message, userId: userId, shouldOverlapAvatarAndMessage: shouldOverlapAvatarAndMessage,
/* @conditional-compile-remove(date-time-customization) */
onDisplayDateTimeString: onDisplayDateTimeString, inlineImageOptions: inlineImageOptions, actionsForAttachment: actionsForAttachment,
/* @conditional-compile-remove(mention) */
mentionDisplayOptions: mentionOptions === null || mentionOptions === void 0 ? void 0 : mentionOptions.displayOptions })));
}
return React.createElement(React.Fragment, null);
}, [
onRenderAttachmentDownloads,
userId,
shouldOverlapAvatarAndMessage,
/* @conditional-compile-remove(date-time-customization) */
onDisplayDateTimeString,
inlineImageOptions,
actionsForAttachment,
/* @conditional-compile-remove(mention) */
mentionOptions === null || mentionOptions === void 0 ? void 0 : mentionOptions.displayOptions
]);
const messageRenderer = useCallback((messageProps) => {
return onRenderMessage === undefined
? defaultChatMessageRenderer(Object.assign({}, messageProps))
: onRenderMessage(messageProps, defaultChatMessageRenderer);
}, [defaultChatMessageRenderer, onRenderMessage]);
const shouldShowAvatar = useMemo(() => {
return message.attached === 'top' || message.attached === false;
}, [message.attached]);
const attached = useMemo(() => {
return getFluentUIAttachedValue(message.attached);
}, [message.attached]);
const messageRootProps = useMemo(() => {
return { className: mergeClasses(chatMessageRenderStyles.rootMessage, chatMessageRenderStyles.rootCommon) };
}, [chatMessageRenderStyles.rootCommon, chatMessageRenderStyles.rootMessage]);
const avatar = useMemo(() => {
const chatAvatarStyle = shouldShowAvatar ? gutterWithAvatar : gutterWithHiddenAvatar;
const personaOptions = {
hidePersonaDetails: true,
size: PersonaSize.size32,
text: message.senderDisplayName,
showOverflowTooltip: false
};
let renderedAvatar;
if (onRenderAvatar) {
const avatarComponent = onRenderAvatar === null || onRenderAvatar === void 0 ? void 0 : onRenderAvatar(message.senderId, personaOptions);
if (!avatarComponent) {
return undefined;
}
else {
renderedAvatar = avatarComponent;
}
}
return (React.createElement("div", { className: mergeStyles(chatAvatarStyle) }, renderedAvatar ? renderedAvatar : React.createElement(Persona, Object.assign({}, personaOptions))));
}, [message.senderDisplayName, message.senderId, onRenderAvatar, shouldShowAvatar]);
const setMessageContainerRef = useCallback((node) => {
removeFluentUIKeyboardNavigationStyles(node);
}, []);
const messageBodyProps = useMemo(() => {
return {
ref: setMessageContainerRef,
// chatItemMessageContainer used in className and style prop as style prop can't handle CSS selectors
className: mergeClasses(chatMessageRenderStyles.bodyCommon, !shouldShowAvatar
? avatar
? chatMessageRenderStyles.bodyWithoutAvatar
: chatMessageRenderStyles.bodyHiddenAvatar
: chatMessageRenderStyles.bodyWithAvatar, shouldOverlapAvatarAndMessage ? chatMessageRenderStyles.avatarOverlap : chatMessageRenderStyles.avatarNoOverlap, mergeStyles(styles === null || styles === void 0 ? void 0 : styles.chatItemMessageContainer)),
style: (styles === null || styles === void 0 ? void 0 : styles.chatItemMessageContainer) !== undefined ? createStyleFromV8Style(styles === null || styles === void 0 ? void 0 : styles.chatItemMessageContainer) : {}
};
}, [
setMessageContainerRef,
chatMessageRenderStyles.bodyCommon,
chatMessageRenderStyles.bodyWithoutAvatar,
chatMessageRenderStyles.bodyHiddenAvatar,
chatMessageRenderStyles.bodyWithAvatar,
chatMessageRenderStyles.avatarOverlap,
chatMessageRenderStyles.avatarNoOverlap,
shouldShowAvatar,
avatar,
shouldOverlapAvatarAndMessage,
styles === null || styles === void 0 ? void 0 : styles.chatItemMessageContainer
]);
// 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.
// Avatar should be shown for both custom and default renderers.
return (React.createElement(FluentChatMessage, { attached: attached, root: messageRootProps, body: messageBodyProps, avatar: avatar }, messageRenderer(Object.assign({}, props))));
};
//# sourceMappingURL=FluentChatMessageComponent.js.map