UNPKG

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
// 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