import React, { ReactNode } from 'react'; import { Box, Text } from 'folds'; import { MatrixEvent, Room } from 'matrix-js-sdk'; import { useTranslation } from 'react-i18next'; import { ChannelLayout, ChannelMessageAvatar, StreamLayout, Time, Username, UsernameBold, } from '../../../components/message'; import { Event } from './Message'; import { useMatrixClient } from '../../../hooks/useMatrixClient'; import { useDotColor } from '../../../hooks/useDotColor'; import { ScreenSize, useScreenSizeContext } from '../../../hooks/useScreenSize'; import { getMemberDisplayName } from '../../../utils/room'; import { getMxIdLocalPart } from '../../../utils/matrix'; export type SyslineMessageProps = { room: Room; mEvent: MatrixEvent; // Pre-rendered body — already includes any sender names / interpolation // the per-type renderer wants to show. The sysline bubble adds no extra // header or icon, so the body is the only visible content. body: ReactNode; highlight: boolean; canDelete?: boolean; hideReadReceipts?: boolean; showDeveloperTools?: boolean; streamRailStart?: boolean; streamRailEnd?: boolean; layout?: 'stream' | 'channel'; channelHeaderInBubble?: boolean; // Spread onto Event wrapper (data-message-item / data-message-id) so the // virtual paginator can locate the row. [dataAttr: `data-${string}`]: string | number | undefined; }; export function SyslineMessage({ room, mEvent, body, highlight, canDelete, hideReadReceipts, showDeveloperTools, streamRailStart, streamRailEnd, layout = 'stream', channelHeaderInBubble, ...rest }: SyslineMessageProps) { const { t } = useTranslation(); const mx = useMatrixClient(); const isMobile = useScreenSizeContext() === ScreenSize.Mobile; const dot = useDotColor(room, mEvent, true, hideReadReceipts); const senderId = mEvent.getSender() ?? ''; const isOwnMessage = !!mx.getUserId() && senderId === mx.getUserId(); const peerBg = !isOwnMessage; const senderName = getMemberDisplayName(room, senderId) || getMxIdLocalPart(senderId) || senderId; const bubbleBody = ( {body} ); return ( {layout === 'channel' ? ( } header={ <> {isOwnMessage ? t('Direct.message_me_label') : senderName} ) : ( } dotColor={dot.color} dotOpacity={dot.opacity} isOwn={isOwnMessage} peerBg={peerBg} compact={isMobile} railStart={streamRailStart} railEnd={streamRailEnd} > {bubbleBody} )} ); }