diff --git a/packages/react/src/views/AttachmentHandler/TextAttachment.js b/packages/react/src/views/AttachmentHandler/TextAttachment.js
index 73387c741..1bdd9b602 100644
--- a/packages/react/src/views/AttachmentHandler/TextAttachment.js
+++ b/packages/react/src/views/AttachmentHandler/TextAttachment.js
@@ -1,4 +1,5 @@
import React, { useState, useContext } from 'react';
+import { format } from 'date-fns';
import { css } from '@emotion/react';
import PropTypes from 'prop-types';
import { Box, Avatar, useTheme, Icon } from '@embeddedchat/ui-elements';
@@ -11,12 +12,11 @@ const FileAttachment = ({
attachment,
host,
type,
- author,
variantStyles = {},
msg,
}) => {
const { RCInstance } = useContext(RCContext);
- const { theme } = useTheme();
+ const { theme, mode } = useTheme();
const [isExpanded, setIsExpanded] = useState(true);
const getUserAvatarUrl = (icon) => {
@@ -28,6 +28,51 @@ const FileAttachment = ({
setIsExpanded((prevState) => !prevState);
};
+ const getMessageIdFromAttachment = (quoteAttachment) => {
+ const link = quoteAttachment?.title_link || quoteAttachment?.message_link;
+ if (!link) return null;
+
+ try {
+ const query = link.includes('?') ? link.split('?')[1] : '';
+ const params = new URLSearchParams(query);
+ return params.get('msg');
+ } catch {
+ return null;
+ }
+ };
+
+ const handleQuoteClick = (quoteAttachment) => {
+ const msgId = getMessageIdFromAttachment(quoteAttachment);
+ if (!msgId) return;
+
+ const element = document.getElementById(`ec-message-body-${msgId}`);
+ if (!element) return;
+
+ const container = element.closest('.ec-message');
+ if (!container) return;
+
+ container.scrollIntoView({ behavior: 'smooth', block: 'center' });
+
+ const highlightColor =
+ mode === 'light' ? theme.colors.warningForeground : theme.colors.warning;
+
+ container.style.transition = 'background-color 1s ease-out';
+ container.style.backgroundColor = highlightColor;
+
+ setTimeout(() => {
+ container.style.backgroundColor = '';
+ }, 2000);
+ };
+
+ const getTimeString = (ts) => {
+ if (!ts) return null;
+ if (typeof ts === 'object' && ts.$date) {
+ ts = ts.$date;
+ }
+ const date = new Date(ts);
+ return !Number.isNaN(date.getTime()) ? format(date, 'h:mm a') : ts;
+ };
+
const formatFileSize = (bytes) => {
if (!bytes || bytes === 0) return '0 B';
@@ -44,9 +89,9 @@ const FileAttachment = ({
return `${size.toFixed(decimals)} ${units[unitIndex]}`;
};
- const getFileSizeWithFormat = (size, format) => {
+ const getFileSizeWithFormat = (size, fileFormat) => {
const formattedSize = formatFileSize(size);
- return format ? `${formattedSize} - ${format}` : formattedSize;
+ return fileFormat ? `${formattedSize} - ${fileFormat}` : formattedSize;
};
return (
@@ -84,6 +129,21 @@ const FileAttachment = ({
size="1.2em"
/>
@{attachment?.author_name}
+ {getTimeString(attachment?.ts) && (
+ handleQuoteClick(attachment)}
+ css={css`
+ font-size: 0.75rem;
+ color: ${theme.colors.mutedForeground};
+ cursor: pointer;
+ &:hover {
+ text-decoration: underline;
+ }
+ `}
+ >
+ {getTimeString(attachment.ts)}
+
+ )}
)}
@@ -217,6 +277,21 @@ const FileAttachment = ({
size="1.2em"
/>
@{nestedAttachment?.author_name}
+ {getTimeString(nestedAttachment?.ts) && (
+ handleQuoteClick(nestedAttachment)}
+ css={css`
+ font-size: 0.75rem;
+ color: ${theme.colors.mutedForeground};
+ cursor: pointer;
+ &:hover {
+ text-decoration: underline;
+ }
+ `}
+ >
+ {getTimeString(nestedAttachment.ts)}
+
+ )}
>
)}
@@ -309,7 +384,6 @@ FileAttachment.propTypes = {
attachment: PropTypes.object,
host: PropTypes.string,
type: PropTypes.string,
- author: PropTypes.object,
variantStyles: PropTypes.object,
msg: PropTypes.object,
};