make reply username and content clickable

This commit is contained in:
Ajay Bura 2026-08-16 22:07:42 +05:30
commit 3ea993dcef
6 changed files with 51 additions and 16 deletions

View file

@ -46,7 +46,7 @@ export function RenderReplyContent({
}
if (eventType !== MessageEvent.RoomMessage) {
return <UnsupportedContent size="T300" />;
return <UnsupportedContent size="T300" eventType={eventType} />;
}
const msgType = rContent.msgtype(content);

View file

@ -13,6 +13,7 @@ import {
MessageBrokenContent,
MessageDeletedContent,
MessageEditedContent,
UnsupportedMessageEventType,
MessageUnsupportedContent,
VideoContent,
} from './content';
@ -49,10 +50,14 @@ export function RedactedContent({ size, reason }: RedactedContentProps) {
);
}
export function UnsupportedContent({ size }: TextProps) {
export function UnsupportedContent({ size, eventType }: TextProps & { eventType?: string }) {
return (
<Text size={size}>
<MessageUnsupportedContent />
{eventType ? (
<UnsupportedMessageEventType eventType={eventType} />
) : (
<MessageUnsupportedContent />
)}
</Text>
);
}

View file

@ -57,13 +57,15 @@ export function ReplyMessage({
if (messageLayout === MessageLayout.Compact) {
return (
<CompactLayout before={msgBarJSX} {...commonProps}>
<CompactLayout before={msgBarJSX}>
<Box grow="Yes" direction="Column">
<Box alignItems="Center" shrink="No" gap="200">
<Box shrink="No" style={{ maxWidth: toRem(200) }}>
<Box shrink="No" style={{ maxWidth: toRem(100) }}>
{username}
</Box>
{children}
<Box shrink="Yes" {...commonProps}>
{children}
</Box>
{time}
</Box>
</Box>
@ -73,12 +75,14 @@ export function ReplyMessage({
if (messageLayout === MessageLayout.Bubble) {
return (
<BubbleLayout hideBubble before={msgBarJSX} {...commonProps}>
<BubbleLayout hideBubble before={msgBarJSX}>
<Box alignItems="Center" shrink="No" gap="200">
<Box shrink="No" style={{ maxWidth: toRem(200) }}>
<Box shrink="No" style={{ maxWidth: toRem(100) }}>
{username}
</Box>
{children}
<Box shrink="Yes" {...commonProps}>
{children}
</Box>
{time}
</Box>
</BubbleLayout>
@ -86,12 +90,14 @@ export function ReplyMessage({
}
return (
<ModernLayout before={msgBarJSX} {...commonProps}>
<ModernLayout before={msgBarJSX}>
<Box alignItems="Center" shrink="No" gap="200">
<Box shrink="No" style={{ maxWidth: toRem(200) }}>
<Box shrink="No" style={{ maxWidth: toRem(100) }}>
{username}
</Box>
{children}
<Box shrink="Yes" {...commonProps}>
{children}
</Box>
{time}
</Box>
</ModernLayout>
@ -102,6 +108,8 @@ type ReplyProps = {
roomId: string;
eventId: string;
onClick?: (replyId: string) => void;
onUserClick?: MouseEventHandler<HTMLButtonElement>;
onUsernameClick?: MouseEventHandler<HTMLButtonElement>;
getMemberPowerTag?: GetMemberPowerTag;
accessibleTagColors?: Map<string, string>;
legacyUsernameColor?: boolean;
@ -114,13 +122,14 @@ type ReplyProps = {
messageLayout: MessageLayout;
dateFormatString: string;
messageSpacing: MessageSpacing;
mediaAutoLoad?: boolean;
};
export function Reply({
roomId,
eventId,
onClick,
onUserClick,
onUsernameClick,
getMemberPowerTag,
accessibleTagColors,
legacyUsernameColor,
@ -133,7 +142,6 @@ export function Reply({
dateFormatString,
messageLayout,
messageSpacing,
mediaAutoLoad,
}: ReplyProps) {
const placeholderWidth = useMemo(() => randomNumberBetween(40, 400), []);
const replyEvent = useRoomEvent(
@ -158,7 +166,16 @@ export function Reply({
messageLayout={messageLayout}
username={
sender && (
<Text style={{ color: usernameColor }} size="T300" truncate>
<Text
as="button"
onClick={onUsernameClick}
onContextMenu={onUserClick}
className={HoverUnderline}
style={{ color: usernameColor, cursor: 'pointer' }}
data-user-id={sender}
size="T300"
truncate
>
<b>{getMemberName(sender)}</b>
</Text>
)

View file

@ -1,5 +1,6 @@
import { Box, Icon, Icons, Text, as, color, config } from 'folds';
import React from 'react';
import { Code } from '../../../styles/CustomHtml.css';
const warningStyle = { color: color.Warning.Main, opacity: config.opacity.P300 };
const criticalStyle = { color: color.Critical.Main, opacity: config.opacity.P300 };
@ -24,6 +25,15 @@ export const MessageUnsupportedContent = as<'div', { children?: never }>(({ ...p
</Box>
));
export const UnsupportedMessageEventType = as<'div', { eventType: string; children?: never }>(
({ eventType, ...props }, ref) => (
<Box as="span" alignItems="Center" gap="100" {...props} ref={ref}>
<Icon size="50" src={Icons.Code} />
Unsupported <code className={Code}>{eventType}</code> event
</Box>
)
);
export const MessageFailedContent = as<'div', { children?: never }>(({ ...props }, ref) => (
<Box as="span" alignItems="Center" gap="100" style={criticalStyle} {...props} ref={ref}>
<Icon size="50" src={Icons.Warning} />

View file

@ -496,6 +496,8 @@ export function RoomTimeline({ eventId, roomInputRef, editor, timeline }: RoomTi
roomId={roomId}
eventId={replyEventId}
onClick={handleOpenReply}
onUserClick={handleUserClick}
onUsernameClick={handleUsernameClick}
getMemberPowerTag={getMemberPowerTag}
accessibleTagColors={accessiblePowerTagColors}
legacyUsernameColor={legacyUsernameColor || direct}
@ -508,7 +510,6 @@ export function RoomTimeline({ eventId, roomInputRef, editor, timeline }: RoomTi
dateFormatString={dateFormatString}
messageLayout={messageLayout}
messageSpacing={messageSpacing}
mediaAutoLoad={mediaAutoLoad}
/>
) : null;

View file

@ -392,6 +392,8 @@ export function TimelineView({ threadTimeline }: TimelineViewProps) {
roomId={roomId}
eventId={replyEventId}
onClick={handleOpenReply}
onUserClick={handleUserClick}
onUsernameClick={handleUsernameClick}
getMemberPowerTag={getMemberPowerTag}
accessibleTagColors={accessiblePowerTagColors}
legacyUsernameColor={legacyUsernameColor || direct}