import { Box, Icon, Icons, Text, as, color, toRem } from 'folds'; import { EventTimelineSet, Room } from 'matrix-js-sdk'; import React, { MouseEventHandler, ReactNode, useCallback, useMemo } from 'react'; import classNames from 'classnames'; import { getMemberDisplayName, trimReplyFromBody } from '../../utils/room'; import { getMxIdLocalPart } from '../../utils/matrix'; import { LinePlaceholder } from './placeholder'; import { randomNumberBetween } from '../../utils/common'; import * as css from './Reply.css'; import { MessageBadEncryptedContent, MessageDeletedContent, MessageFailedContent } from './content'; import { scaleSystemEmoji } from '../../plugins/react-custom-html-parser'; import { useRoomEvent } from '../../hooks/useRoomEvent'; import colorMXID from '../../../util/colorMXID'; import { GetMemberPowerTag } from '../../hooks/useMemberPowerTag'; type ReplyLayoutProps = { userColor?: string; username?: ReactNode; }; export const ReplyLayout = as<'div', ReplyLayoutProps>( ({ username, userColor, className, children, ...props }, ref) => ( {username} {children} ) ); export const ThreadIndicator = as<'div'>(({ ...props }, ref) => ( Thread )); type ReplyProps = { room: Room; timelineSet?: EventTimelineSet | undefined; replyEventId: string; threadRootId?: string | undefined; onClick?: MouseEventHandler | undefined; getMemberPowerTag?: GetMemberPowerTag; accessibleTagColors?: Map; legacyUsernameColor?: boolean; }; export const Reply = as<'div', ReplyProps>( ( { room, timelineSet, replyEventId, threadRootId, onClick, getMemberPowerTag, accessibleTagColors, legacyUsernameColor, ...props }, ref ) => { const placeholderWidth = useMemo(() => randomNumberBetween(40, 400), []); const getFromLocalTimeline = useCallback( () => timelineSet?.findEventById(replyEventId), [timelineSet, replyEventId] ); const replyEvent = useRoomEvent(room, replyEventId, getFromLocalTimeline); const { body } = replyEvent?.getContent() ?? {}; const sender = replyEvent?.getSender(); const powerTag = sender ? getMemberPowerTag?.(sender) : undefined; const tagColor = powerTag?.color ? accessibleTagColors?.get(powerTag.color) : undefined; const usernameColor = legacyUsernameColor ? colorMXID(sender ?? replyEventId) : tagColor; const fallbackBody = replyEvent?.isRedacted() ? ( ) : ( ); const badEncryption = replyEvent?.getContent().msgtype === 'm.bad.encrypted'; const bodyJSX = body ? scaleSystemEmoji(trimReplyFromBody(body)) : fallbackBody; return ( {threadRootId && ( )} {getMemberDisplayName(room, sender) ?? getMxIdLocalPart(sender)} ) } data-event-id={replyEventId} onClick={onClick} > {replyEvent !== undefined ? ( {badEncryption ? : bodyJSX} ) : ( )} ); } );