// Copyright 2019 Signal Messenger, LLC // SPDX-License-Identifier: AGPL-3.0-only import type { FunctionComponent, ReactNode } from 'react'; import React, { useCallback } from 'react'; import lodash from 'lodash'; import { ContactName } from '../conversation/ContactName.js'; import type { BodyRangesForDisplayType } from '../../types/BodyRange.js'; import { processBodyRangesForSearchResult } from '../../types/BodyRange.js'; import type { LocalizerType, ThemeType } from '../../types/Util.js'; import { BaseConversationListItem } from './BaseConversationListItem.js'; import type { ConversationType, ShowConversationType, } from '../../state/ducks/conversations.js'; import type { PreferredBadgeSelectorType } from '../../state/selectors/badges.js'; import { I18n } from '../I18n.js'; import { MessageTextRenderer, RenderLocation, } from '../conversation/MessageTextRenderer.js'; const { noop } = lodash; const EMPTY_OBJECT = Object.freeze(Object.create(null)); export type PropsDataType = { isSelected?: boolean; isSearchingInConversation?: boolean; id: string; conversationId: string; sentAt?: number; snippet: string; body: string; bodyRanges: BodyRangesForDisplayType; from: Pick< ConversationType, | 'acceptedMessageRequest' | 'avatarUrl' | 'badges' | 'color' | 'isMe' | 'phoneNumber' | 'profileName' | 'sharedGroupNames' | 'title' | 'type' >; to: Pick< ConversationType, 'isMe' | 'phoneNumber' | 'profileName' | 'title' | 'type' >; }; type PropsHousekeepingType = { getPreferredBadge: PreferredBadgeSelectorType; i18n: LocalizerType; showConversation: ShowConversationType; theme: ThemeType; }; export type PropsType = PropsDataType & PropsHousekeepingType; const renderPerson = ( i18n: LocalizerType, person: Readonly<{ isMe?: boolean; title: string; }> ): JSX.Element => person.isMe ? ( ) : ( ); export const MessageSearchResult: FunctionComponent = React.memo( function MessageSearchResult({ body, bodyRanges, conversationId, from, getPreferredBadge, i18n, id, sentAt, showConversation, snippet, theme, to, }) { const onClickItem = useCallback(() => { showConversation({ conversationId, messageId: id }); }, [showConversation, conversationId, id]); if (!from || !to) { // Note: mapStateToProps() may return null if the message is not found. return
; } const isNoteToSelf = from.isMe && to.isMe; let headerName: ReactNode; if (isNoteToSelf) { headerName = i18n('icu:noteToSelf'); } else if (from.isMe) { if (to.type === 'group') { headerName = ( ); } else { headerName = ( ); } } else { // eslint-disable-next-line no-lonely-if if (to.type === 'group') { headerName = ( ); } else { headerName = ( ); } } const { cleanedSnippet, bodyRanges: displayBodyRanges } = processBodyRangesForSearchResult({ snippet, body, bodyRanges }); const messageText = ( ); return ( ); } );