/* eslint-disable react/destructuring-assignment */ import React, { MouseEventHandler, useMemo } from 'react'; import { IEventWithRoomId, JoinRule, RelationType, Room } from 'matrix-js-sdk'; import { HTMLReactParserOptions } from 'html-react-parser'; import { Avatar, Box, Chip, Header, Icon, Icons, Text, config } from 'folds'; import { Opts as LinkifyOpts } from 'linkifyjs'; import { useMatrixClient } from '../../hooks/useMatrixClient'; import { factoryRenderLinkifyWithMention, getReactCustomHtmlParser, LINKIFY_OPTS, makeHighlightRegex, makeMentionCustomProps, renderMatrixMention, } from '../../plugins/react-custom-html-parser'; import { getMxIdLocalPart, mxcUrlToHttp } from '../../utils/matrix'; import { useMatrixEventRenderer } from '../../hooks/useMatrixEventRenderer'; import { GetContentCallback, MessageEvent, StateEvent } from '../../../types/matrix/room'; import { AvatarBase, ImageContent, MSticker, ModernLayout, RedactedContent, Reply, Time, Username, UsernameBold, } from '../../components/message'; import { RenderMessageContent } from '../../components/RenderMessageContent'; import { Image } from '../../components/media'; import { ImageViewer } from '../../components/image-viewer'; import * as customHtmlCss from '../../styles/CustomHtml.css'; import { RoomAvatar, RoomIcon } from '../../components/room-avatar'; import { getMemberAvatarMxc, getMemberDisplayName, getRoomAvatarUrl } from '../../utils/room'; import { ResultItem } from './useMessageSearch'; import { SequenceCard } from '../../components/sequence-card'; import { UserAvatar } from '../../components/user-avatar'; import { useMentionClickHandler } from '../../hooks/useMentionClickHandler'; import { useSpoilerClickHandler } from '../../hooks/useSpoilerClickHandler'; import { useMediaAuthentication } from '../../hooks/useMediaAuthentication'; import { usePowerLevels, usePowerLevelsAPI } from '../../hooks/usePowerLevels'; import { getTagIconSrc, useAccessibleTagColors, usePowerLevelTags, } from '../../hooks/usePowerLevelTags'; import { useTheme } from '../../hooks/useTheme'; import { PowerIcon } from '../../components/power'; import colorMXID from '../../../util/colorMXID'; type SearchResultGroupProps = { room: Room; highlights: string[]; items: ResultItem[]; mediaAutoLoad?: boolean; urlPreview?: boolean; onOpen: (roomId: string, eventId: string) => void; legacyUsernameColor?: boolean; hour24Clock: boolean; dateFormatString: string; }; export function SearchResultGroup({ room, highlights, items, mediaAutoLoad, urlPreview, onOpen, legacyUsernameColor, hour24Clock, dateFormatString, }: SearchResultGroupProps) { const mx = useMatrixClient(); const useAuthentication = useMediaAuthentication(); const highlightRegex = useMemo(() => makeHighlightRegex(highlights), [highlights]); const powerLevels = usePowerLevels(room); const { getPowerLevel } = usePowerLevelsAPI(powerLevels); const [powerLevelTags, getPowerLevelTag] = usePowerLevelTags(room, powerLevels); const theme = useTheme(); const accessibleTagColors = useAccessibleTagColors(theme.kind, powerLevelTags); const mentionClickHandler = useMentionClickHandler(room.roomId); const spoilerClickHandler = useSpoilerClickHandler(); const linkifyOpts = useMemo( () => ({ ...LINKIFY_OPTS, render: factoryRenderLinkifyWithMention((href) => renderMatrixMention(mx, room.roomId, href, makeMentionCustomProps(mentionClickHandler)) ), }), [mx, room, mentionClickHandler] ); const htmlReactParserOptions = useMemo( () => getReactCustomHtmlParser(mx, room.roomId, { linkifyOpts, highlightRegex, useAuthentication, handleSpoilerClick: spoilerClickHandler, handleMentionClick: mentionClickHandler, }), [ mx, room, linkifyOpts, highlightRegex, mentionClickHandler, spoilerClickHandler, useAuthentication, ] ); const renderMatrixEvent = useMatrixEventRenderer<[IEventWithRoomId, string, GetContentCallback]>( { [MessageEvent.RoomMessage]: (event, displayName, getContent) => { if (event.unsigned?.redacted_because) { return ; } return ( ); }, [MessageEvent.Reaction]: (event, displayName, getContent) => { if (event.unsigned?.redacted_because) { return ; } return ( ( } renderViewer={(p) => } /> )} /> ); }, [StateEvent.RoomTombstone]: (event) => { const { content } = event; return ( Room Tombstone. {content.body} ); }, }, undefined, (event) => { if (event.unsigned?.redacted_because) { return ; } return ( {event.type} {' event'} ); } ); const handleOpenClick: MouseEventHandler = (evt) => { const eventId = evt.currentTarget.getAttribute('data-event-id'); if (!eventId) return; onOpen(room.roomId, eventId); }; return (
( )} /> {room.name}
{items.map((item) => { const { event } = item; const displayName = getMemberDisplayName(room, event.sender) ?? getMxIdLocalPart(event.sender) ?? event.sender; const senderAvatarMxc = getMemberAvatarMxc(room, event.sender); const relation = event.content['m.relates_to']; const mainEventId = relation?.rel_type === RelationType.Replace ? relation.event_id : event.event_id; const getContent = (() => event.content['m.new_content'] ?? event.content) as GetContentCallback; const replyEventId = relation?.['m.in_reply_to']?.event_id; const threadRootId = relation?.rel_type === RelationType.Thread ? relation.event_id : undefined; const senderPowerLevel = getPowerLevel(event.sender); const powerLevelTag = getPowerLevelTag(senderPowerLevel); const tagColor = powerLevelTag?.color ? accessibleTagColors?.get(powerLevelTag.color) : undefined; const tagIconSrc = powerLevelTag?.icon ? getTagIconSrc(mx, useAuthentication, powerLevelTag.icon) : undefined; const usernameColor = legacyUsernameColor ? colorMXID(event.sender) : tagColor; return ( } /> } > {displayName} {tagIconSrc && } Open {replyEventId && ( )} {renderMatrixEvent(event.type, false, event, displayName, getContent)} ); })}
); }