diff --git a/packages/react/src/views/AttachmentHandler/Attachment.js b/packages/react/src/views/AttachmentHandler/Attachment.js index bc07a740c..9e4b21cee 100644 --- a/packages/react/src/views/AttachmentHandler/Attachment.js +++ b/packages/react/src/views/AttachmentHandler/Attachment.js @@ -8,12 +8,17 @@ import VideoAttachment from './VideoAttachment'; import TextAttachment from './TextAttachment'; const Attachment = ({ attachment, host, type, variantStyles = {} }) => { + const author = { + authorIcon: attachment?.author_icon, + authorName: attachment?.author_name, + }; if (attachment && attachment.audio_url) { return ( ); } @@ -23,6 +28,7 @@ const Attachment = ({ attachment, host, type, variantStyles = {} }) => { attachment={attachment} host={host} variantStyles={variantStyles} + author={author} /> ); } @@ -30,8 +36,10 @@ const Attachment = ({ attachment, host, type, variantStyles = {} }) => { return ( ); } @@ -44,6 +52,39 @@ const Attachment = ({ attachment, host, type, variantStyles = {} }) => { /> ); } + if (attachment && attachment.attachments[0]?.image_url) { + return ( + + ); + } + if (attachment && attachment.attachments[0]?.audio_url) { + return ( + + ); + } + if (attachment && attachment.attachments[0]?.video_url) { + return ( + + ); + } return ( ( - - - - -); +const AudioAttachment = ({ attachment, host, type, author, variantStyles }) => { + const { RCInstance } = useContext(RCContext); + const { colors } = useTheme(); + const getUserAvatarUrl = (icon) => { + const instanceHost = RCInstance.getHost(); + const URL = `${instanceHost}${icon}`; + return URL; + }; + const { authorIcon, authorName } = author; + return ( + + + {type === 'file' ? ( + <> + + + @{authorName} + + > + ) : ( + '' + )} + + + + {attachment.attachments ? ( + + + {attachment.attachments[0].type === 'file' ? ( + <> + + + @{attachment.author_name} + + > + ) : ( + '' + )} + + + + + ) : ( + <>> + )} + + + ); +}; export default AudioAttachment; diff --git a/packages/react/src/views/AttachmentHandler/ImageAttachment.js b/packages/react/src/views/AttachmentHandler/ImageAttachment.js index 893778256..2da14885e 100644 --- a/packages/react/src/views/AttachmentHandler/ImageAttachment.js +++ b/packages/react/src/views/AttachmentHandler/ImageAttachment.js @@ -1,32 +1,81 @@ -import React, { useState } from 'react'; +import React, { useState, useContext } from 'react'; import { css } from '@emotion/react'; import PropTypes from 'prop-types'; -import { Box } from '@embeddedchat/ui-elements'; +import { Box, Avatar, useTheme } from '@embeddedchat/ui-elements'; import AttachmentMetadata from './AttachmentMetadata'; import ImageGallery from '../ImageGallery/ImageGallery'; +import RCContext from '../../context/RCInstance'; -const ImageAttachment = ({ attachment, host, variantStyles = {} }) => { +const ImageAttachment = ({ + attachment, + host, + type, + author, + variantStyles = {}, +}) => { + const { RCInstance } = useContext(RCContext); const [showGallery, setShowGallery] = useState(false); + const getUserAvatarUrl = (icon) => { + const instanceHost = RCInstance.getHost(); + const URL = `${instanceHost}${icon}`; + return URL; + }; const extractIdFromUrl = (url) => { const match = url.match(/\/file-upload\/(.*?)\//); return match ? match[1] : null; }; + const { theme } = useTheme(); + + const { authorIcon, authorName } = author; + return ( - setShowGallery(true)} - css={css` - cursor: pointer; - border-radius: inherit; - line-height: 0; - `} + css={[ + css` + cursor: pointer; + border-radius: inherit; + line-height: 0; + padding: 0.5rem; + `, + (type ? variantStyles.pinnedContainer : '') || + css` + ${type === 'file' + ? `border: 2px solid ${theme.colors.border};` + : ''} + `, + ]} > + {type === 'file' ? ( + <> + + + @{authorName} + + > + ) : ( + '' + )} + { borderBottomRightRadius: 'inherit', }} /> + {attachment.attachments ? ( + + setShowGallery(true)} + css={[ + css` + cursor: pointer; + border-radius: inherit; + line-height: 0; + padding: 0.5rem; + `, + (attachment.attachments[0].type + ? variantStyles.pinnedContainer + : variantStyles.quoteContainer) || + css` + ${attachment.attachments[0].type === 'file' + ? `border: 2px solid ${theme.colors.border};` + : ''} + `, + ]} + > + {attachment.attachments[0].type === 'file' ? ( + <> + + + @{attachment.author_name} + + > + ) : ( + '' + )} + + + + {showGallery && ( + + )} + + ) : ( + <>> + )} {showGallery && ( { white-space: pre-line; `} > - {attachmentText} + {attachment?.text + ? attachment.text[0] === '[' + ? attachment.text.match(/\n(.*)/)[1] + : attachment.text + : ''} + {attachment?.attachments && attachment.attachments.length > 0 ? ( + + + {attachment.attachments[0]?.author_name && ( + <> + + @{attachment.attachments[0]?.author_name} + > + )} + + + {attachment.attachments[0]?.text + ? attachment.attachments[0].text[0] === '[' + ? attachment.attachments[0].text.match(/\n(.*)/)[1] + : attachment.attachments[0].text + : ''} + + + ) : ( + <>> + )} ); diff --git a/packages/react/src/views/AttachmentHandler/VideoAttachment.js b/packages/react/src/views/AttachmentHandler/VideoAttachment.js index 0472d34c2..074b1fd8f 100644 --- a/packages/react/src/views/AttachmentHandler/VideoAttachment.js +++ b/packages/react/src/views/AttachmentHandler/VideoAttachment.js @@ -1,8 +1,9 @@ -import React from 'react'; +import React, { useContext } from 'react'; import PropTypes from 'prop-types'; import { css } from '@emotion/react'; -import { Box } from '@embeddedchat/ui-elements'; +import { Box, Avatar, useTheme } from '@embeddedchat/ui-elements'; import AttachmentMetadata from './AttachmentMetadata'; +import RCContext from '../../context/RCInstance'; const userAgentMIMETypeFallback = (type) => { const userAgent = navigator.userAgent.toLocaleLowerCase(); @@ -14,35 +15,154 @@ const userAgentMIMETypeFallback = (type) => { return type; }; -const VideoAttachment = ({ attachment, host, variantStyles = {} }) => ( - - - - { + const { RCInstance } = useContext(RCContext); + const { theme } = useTheme(); + const getUserAvatarUrl = (icon) => { + const instanceHost = RCInstance.getHost(); + const URL = `${instanceHost}${icon}`; + return URL; + }; + const { authorIcon, authorName } = author; + return ( + + - + + + @{authorName} + + > + ) : ( + '' + )} + - + + + + {attachment.attachments ? ( + + + {attachment.attachments[0].type === 'file' ? ( + <> + + + @{authorName} + + > + ) : ( + '' + )} + + + + + + + ) : ( + <>> + )} + - -); + ); +}; export default VideoAttachment; diff --git a/packages/react/src/views/Message/BubbleVariant/Bubble.styles.js b/packages/react/src/views/Message/BubbleVariant/Bubble.styles.js index 42f978f9e..5f87c0b5e 100644 --- a/packages/react/src/views/Message/BubbleVariant/Bubble.styles.js +++ b/packages/react/src/views/Message/BubbleVariant/Bubble.styles.js @@ -94,7 +94,7 @@ export const getBubbleStyles = (theme) => { overflow: hidden; `, pinnedContainer: css` - max-width: 80%; + max-width: 100%; `, quoteContainer: css` @@ -112,7 +112,7 @@ export const getBubbleStyles = (theme) => { `, attachmentMetaContainer: css` - padding: 2.5% 2.5% 0; + padding: 2.5% 0 0; `, emojiPickerStyles: css` @@ -172,7 +172,7 @@ export const getBubbleStylesMe = (theme) => { pinnedContainerMe: css` border-inline-start: none; - border-inline-end: 3px solid ${theme.colors.border}; + border-inline-end: none; `, textUserInfoMe: css` diff --git a/packages/react/src/views/QuoteMessage/QuoteMessage.js b/packages/react/src/views/QuoteMessage/QuoteMessage.js index fab425eba..f472b3405 100644 --- a/packages/react/src/views/QuoteMessage/QuoteMessage.js +++ b/packages/react/src/views/QuoteMessage/QuoteMessage.js @@ -11,12 +11,13 @@ import { import RCContext from '../../context/RCInstance'; import { useMessageStore } from '../../store'; import getQuoteMessageStyles from './QuoteMessage.styles'; +import Attachment from '../AttachmentHandler/Attachment'; const QuoteMessage = ({ className = '', style = {}, message }) => { const { RCInstance } = useContext(RCContext); + const instanceHost = RCInstance.getHost(); const getUserAvatarUrl = (username) => { - const host = RCInstance.getHost(); - const URL = `${host}/avatar/${username}`; + const URL = `${instanceHost}/avatar/${username}`; return URL; }; const { theme } = useTheme(); @@ -24,6 +25,7 @@ const QuoteMessage = ({ className = '', style = {}, message }) => { const setQuoteMessage = useMessageStore((state) => state.setQuoteMessage); const { classNames, styleOverrides } = useComponentOverrides('QuoteMessage'); + return ( { {format(new Date(message.ts), 'h:mm a')} - {message.msg - ? message.msg - : `${message.file?.name} (${ - message.file?.size ? (message.file.size / 1024).toFixed(2) : 0 - } kB)`} + {message.file ? ( + message.file.type.startsWith('image/') ? ( + + + {`${message.file.name} (${(message.file.size / 1024).toFixed( + 2 + )} kB)`} + + ) : message.file.type.startsWith('video/') ? ( + + + Your browser does not support the video tag. + + ) : message.file.type.startsWith('audio/') ? ( + + + Your browser does not support the audio element. + + ) : ( + + {message.msg + ? message.msg + : `${message.file?.name} (${ + message.file?.size + ? (message.file.size / 1024).toFixed(2) + : 0 + } kB)`} + + ) + ) : message?.msg[0] === '[' ? ( + message?.msg.match(/\n(.*)/)[1] + ) : ( + message?.msg + )} + {message.attachments && + message.attachments.length > 0 && + message.attachments[0].attachments ? ( + + ) : null} );