Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 36 additions & 2 deletions packages/react/src/views/AttachmentHandler/Attachment.js
Original file line number Diff line number Diff line change
Expand Up @@ -34,14 +34,48 @@ const Attachment = ({ attachment, host, type, variantStyles = {}, msg }) => {
/>
);
}
if (attachment && attachment.image_url) {
if (attachment && (attachment.image_url || attachment.title_link)) {
const url = attachment.image_url || attachment.title_link;

const isGif =
url &&
(url.toLowerCase().endsWith('.gif') ||
(attachment.image_type &&
attachment.image_type.toLowerCase() === 'image/gif') ||
(attachment.description &&
attachment.description.toLowerCase().includes('gif')));

const imageUrl = url.startsWith('http') ? url : host + url;

if (url && url.includes('/file-upload/')) {
const fullUrl = `${host}/file-upload/${url.split('/file-upload/')[1]}`;

return (
<ImageAttachment
attachment={{
...attachment,
image_url: fullUrl,
}}
host={host}
author={author}
variantStyles={variantStyles}
msg={msg}
isGif={isGif}
/>
);
}

return (
<ImageAttachment
attachment={attachment}
attachment={{
...attachment,
image_url: imageUrl,
}}
host={host}
author={author}
variantStyles={variantStyles}
msg={msg}
isGif={isGif}
/>
);
}
Expand Down
79 changes: 65 additions & 14 deletions packages/react/src/views/AttachmentHandler/ImageAttachment.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { Box, Avatar, useTheme } from '@embeddedchat/ui-elements';
import AttachmentMetadata from './AttachmentMetadata';
import ImageGallery from '../ImageGallery/ImageGallery';
import RCContext from '../../context/RCInstance';
import { imageWrapper, imageStyles } from './ImageAttachment.styles';

const ImageAttachment = ({
attachment,
Expand All @@ -13,9 +14,12 @@ const ImageAttachment = ({
author,
variantStyles = {},
msg,
isGif = false,
}) => {
const { RCInstance } = useContext(RCContext);
const [showGallery, setShowGallery] = useState(false);
const [imageError, setImageError] = useState(false);

const getUserAvatarUrl = (icon) => {
const instanceHost = RCInstance.getHost();
const URL = `${instanceHost}${icon}`;
Expand All @@ -35,6 +39,20 @@ const ImageAttachment = ({
setIsExpanded((prevState) => !prevState);
};

const handleImageClick = (e) => {
if (isGif) {
e.stopPropagation();
return;
}
setShowGallery(true);
};

const handleKeyPress = (e) => {
if (e.key === 'Enter' || e.key === ' ') {
handleImageClick(e);
}
};

return (
<Box css={variantStyles.imageAttachmentContainer}>
<Box
Expand Down Expand Up @@ -73,9 +91,7 @@ const ImageAttachment = ({
<Box>@{authorName}</Box>
</Box>
</>
) : (
''
)}
) : null}
<Box
css={css`
align-items: center;
Expand All @@ -94,23 +110,57 @@ const ImageAttachment = ({
/>
</Box>
{isExpanded && (
<Box onClick={() => setShowGallery(true)}>
<button
type="button"
onClick={handleImageClick}
onKeyPress={handleKeyPress}
css={[
imageWrapper({ isGif, theme }),
css`
border: none;
background: none;
padding: 0;
cursor: ${!isGif ? 'pointer' : 'default'};
&:focus {
outline: 2px solid ${theme.colors.primary};
outline-offset: 2px;
}
`,
]}
>
<img
src={host + attachment.image_url}
style={{
maxWidth: '100%',
objectFit: 'contain',
borderBottomLeftRadius: 'inherit',
borderBottomRightRadius: 'inherit',
src={attachment.image_url}
style={imageStyles({ isGif })}
onError={() => {
setImageError(true);
}}
alt={attachment.description || 'Attached image'}
/>
</Box>
{imageError && (
<Box
css={css`
color: ${theme.colors.danger};
padding: 8px;
font-size: 12px;
`}
>
Failed to load image. URL: {host + attachment.image_url}
</Box>
)}
</button>
)}
{attachment.attachments &&
attachment.attachments.map((nestedAttachment, index) => (
<Box css={variantStyles.imageAttachmentContainer} key={index}>
<Box
role="button"
tabIndex={0}
onClick={() => setShowGallery(true)}
onKeyPress={(e) => {
if (e.key === 'Enter' || e.key === ' ') {
setShowGallery(true);
}
}}
css={[
css`
cursor: pointer;
Expand Down Expand Up @@ -148,9 +198,7 @@ const ImageAttachment = ({
<Box>@{nestedAttachment.author_name}</Box>
</Box>
</>
) : (
''
)}
) : null}
<AttachmentMetadata
attachment={nestedAttachment}
url={
Expand All @@ -167,6 +215,9 @@ const ImageAttachment = ({
borderBottomLeftRadius: 'inherit',
borderBottomRightRadius: 'inherit',
}}
alt={
nestedAttachment.description || 'Nested attachment image'
}
/>
</Box>
{showGallery && (
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import { css } from '@emotion/react';

export const imageWrapper = ({ isGif, theme }) => css`
width: ${isGif ? '200px' : '300px'};
height: ${isGif ? '200px' : 'auto'};
overflow: hidden;
border-radius: inherit;
display: flex;
align-items: center;
justify-content: center;
background-color: ${theme.colors.surface};
`;

export const imageStyles = ({ isGif }) => ({
width: isGif ? '200px' : '100%',
height: isGif ? '200px' : 'auto',
maxHeight: isGif ? '200px' : '200px',
objectFit: isGif ? 'cover' : 'scale-down',
borderRadius: 'inherit',
imageRendering: isGif ? 'auto' : 'inherit',
});