import React, { useCallback, useEffect, useState } from 'react'; import { IconChevronRight, useUIKit } from '@tencentcloud/uikit-base-component-react'; import { VariantType, SearchType } from '../../../types/search'; import { EmptyResult } from './EmptyResult'; import { Loading } from './Loading'; import styles from './SearchResults.module.scss'; import DefaultSearchResultsItem from './SearchResultsItem'; import type { SearchResultsProps, SearchResultItemType, } from '../../../types/search'; import type { MessageInfo, MessageSearchResultItem, } from 'tuikit-atomicx-react/chat'; export function SearchResults({ results, isLoading, error, keyword, typeLabels, onLoadMore, onResultItemClick, SearchResultsLoading = Loading, SearchResultsPresearch, SearchResultsEmpty = EmptyResult, SearchResultItem = DefaultSearchResultsItem, variant = VariantType.STANDARD, searchType = 'all', }: SearchResultsProps) { const defaultMiniInitLimits = new Map([ [SearchType.MESSAGE, 3], [SearchType.USER, 3], [SearchType.GROUP, 3], ]); const { t } = useUIKit(); const [ miniInitLimits, setMiniInitLimits, ] = useState>(defaultMiniInitLimits); const [loadingType, setLoadingType] = useState(''); // Active conversation ID is derived from CHAT_MESSAGE result; tracked here so the // right-hand chat-message detail panel can render alongside the main list. const [activeConversationID, setActiveConversationID] = useState(undefined); useEffect(() => { const chatMessageData = ( results?.get(SearchType.CHAT_MESSAGE)?.resultList[0] || {}) as MessageSearchResultItem; const chatConversationID = chatMessageData?.conversationID; const { resultList = [] } = results?.get(SearchType.MESSAGE) || {}; const existConversation = resultList.find((item: MessageSearchResultItem) => item.conversationID === chatConversationID); const showStandardMessageList = variant === VariantType.STANDARD && (searchType === SearchType.MESSAGE); const isEmbedded = variant === VariantType.EMBEDDED; const shouldSetConversation = showStandardMessageList && existConversation; const currentConversationID = (shouldSetConversation || isEmbedded) ? chatConversationID : undefined; setActiveConversationID(currentConversationID); }, [searchType, variant, results]); useEffect(() => { if (variant === VariantType.MINI) { setMiniInitLimits(defaultMiniInitLimits); } }, [keyword]); useEffect(() => { if (isLoading === false) { setLoadingType(''); } }, [isLoading]); const handleLoadMore = useCallback((type: SearchType) => { if (variant === VariantType.MINI) { setMiniInitLimits(prev => new Map(prev).set(type, 0)); } setLoadingType(type); onLoadMore?.(type); }, [onLoadMore]); const handleClickItem = useCallback((data: SearchResultItemType, type: SearchType) => { if (type === SearchType.MESSAGE) { setLoadingType(SearchType.CHAT_MESSAGE); } onResultItemClick?.(data, type); }, [onResultItemClick]); const filteredResults = useCallback(() => { if (!results || variant === VariantType.EMBEDDED) { return new Map(); } if (variant === VariantType.MINI) { const limitedResults = new Map(); results.forEach((value, key) => { const limitedNum: number = miniInitLimits.get(key) || 0; if (key !== SearchType.CHAT_MESSAGE) { limitedResults.set(key, { ...value, resultList: limitedNum !== 0 ? value.resultList.slice(0, limitedNum) : value.resultList, hasMore: limitedNum !== 0 ? value.resultList.length > limitedNum : value.hasMore, }); } }); return limitedResults; } const filtered = new Map(); if (searchType === 'all') { results.forEach((value, key) => { if (key !== SearchType.CHAT_MESSAGE) { filtered.set(key, value); } }); } else if (results.has(searchType)) { filtered.set(searchType, results.get(searchType)); } else if (searchType === SearchType.MESSAGE && results.has(SearchType.CHAT_MESSAGE)) { filtered.set(searchType, results.get(SearchType.CHAT_MESSAGE)); } return filtered; }, [results, variant, searchType, miniInitLimits]); const getLoadMoreText = useCallback((type: SearchType) => { if (type === SearchType.CHAT_MESSAGE) { return t('Search.Load More Messages'); } if (type === SearchType.MESSAGE) { return t('Search.Load More Messages'); } if (type === SearchType.USER) { return t('Search.Load More Users'); } if (type === SearchType.GROUP) { return t('Search.Load More Groups'); } return t('Search.Load More'); }, [t]); const currentResults = filteredResults(); const chatMessageResult = results?.get(SearchType.CHAT_MESSAGE) ?.resultList[0] as unknown as MessageSearchResultItem | undefined; const generateActiveItemClassName = (type: SearchType, item: SearchResultItemType) => { if (type !== SearchType.MESSAGE || !chatMessageResult) { return ''; } const itemConvID = (item as MessageSearchResultItem).conversationID; const currentConvID = chatMessageResult.conversationID; return itemConvID === currentConvID ? styles['SearchResults__item--active'] : ''; }; if (!keyword) { return SearchResultsPresearch ? : ; } if (keyword && error) { return
{error.message}
; } if (keyword && isLoading) { return ; } if (keyword && !results?.size && !isLoading) { return ; } if (results && results.size > 0) { const allZero = Array.from(results.values()).every(value => value.totalCount === 0); if (allZero) { return ; } } if (keyword && searchType !== 'all') { const searchTypeResult = results?.get(searchType); const chatMessageResult = searchType === SearchType.MESSAGE ? results?.get(SearchType.CHAT_MESSAGE) : undefined; const searchTypeTotalCount = searchTypeResult?.totalCount ?? chatMessageResult?.totalCount ?? 0; if (searchTypeTotalCount === 0) { return ; } } let renderOrder = [SearchType.USER, SearchType.GROUP]; if (variant !== VariantType.EXACT) { renderOrder = [SearchType.MESSAGE, SearchType.USER, SearchType.GROUP]; } return (
{currentResults?.size > 0 && (
{renderOrder.map((type) => { const result = currentResults.get(type); if (!result || result.totalCount === 0) { return null; } return (
{searchType === 'all' && (

{t(typeLabels[type])}

)}
{result.resultList.map((item: SearchResultItemType, index: number) => (
))}
{result.hasMore && (
)}
); })}
)} {activeConversationID && (
{ loadingType === SearchType.CHAT_MESSAGE ? : ( <> {variant === VariantType.STANDARD && (
{t('Search.Texts Related to', { count: results?.get(SearchType.CHAT_MESSAGE)?.totalCount || 0, })}   {keyword}   {t('Search.Texts Related to Suffix')}
)}
{chatMessageResult?.messageList.map((item: MessageInfo, index: number) => (
))}
{results?.get(SearchType.CHAT_MESSAGE)?.hasMore && (
)} )}
)}
); } export default React.memo(SearchResults);