You cannot select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
				
	
	
		
			123 lines
		
	
	
		
			3.3 KiB
		
	
	
	
		
			TypeScript
		
	
			
		
		
	
	
			123 lines
		
	
	
		
			3.3 KiB
		
	
	
	
		
			TypeScript
		
	
import { isString } from 'lodash';
 | 
						|
import { useSelector } from 'react-redux';
 | 
						|
import { AutoSizer, List } from 'react-virtualized';
 | 
						|
import styled, { CSSProperties } from 'styled-components';
 | 
						|
 | 
						|
import { ConversationListItem } from '../leftpane/conversation-list-item/ConversationListItem';
 | 
						|
import { MessageSearchResult } from './MessageSearchResults';
 | 
						|
 | 
						|
import {
 | 
						|
  SearchResultsMergedListItem,
 | 
						|
  getHasSearchResults,
 | 
						|
  getSearchResultsList,
 | 
						|
  getSearchTerm,
 | 
						|
} from '../../state/selectors/search';
 | 
						|
import { calcContactRowHeight } from '../leftpane/overlay/choose-action/ContactsListWithBreaks';
 | 
						|
 | 
						|
const StyledSeparatorSection = styled.div<{ isSubtitle: boolean }>`
 | 
						|
  height: 36px;
 | 
						|
  line-height: 36px;
 | 
						|
  letter-spacing: 0;
 | 
						|
 | 
						|
  margin-inline-start: 16px;
 | 
						|
  font-weight: 400;
 | 
						|
 | 
						|
  ${props =>
 | 
						|
    props.isSubtitle
 | 
						|
      ? 'color: var(--text-secondary-color); font-size: var(--font-size-sm);'
 | 
						|
      : 'color: var(--text-primary-color); font-size: var(--font-size-lg);'}
 | 
						|
`;
 | 
						|
 | 
						|
const SearchResultsContainer = styled.div`
 | 
						|
  overflow-y: auto;
 | 
						|
  max-height: 100%;
 | 
						|
  color: var(--text-secondary-color);
 | 
						|
  flex-grow: 1;
 | 
						|
  width: -webkit-fill-available;
 | 
						|
`;
 | 
						|
 | 
						|
const NoResults = styled.div`
 | 
						|
  width: 100%;
 | 
						|
  padding: var(--margins-xl) var(--margins-sm) 0;
 | 
						|
  text-align: center;
 | 
						|
`;
 | 
						|
 | 
						|
const SectionHeader = ({
 | 
						|
  title,
 | 
						|
  isSubtitle,
 | 
						|
  style,
 | 
						|
}: {
 | 
						|
  title: string;
 | 
						|
  isSubtitle: boolean;
 | 
						|
  style: CSSProperties;
 | 
						|
}) => {
 | 
						|
  return (
 | 
						|
    <StyledSeparatorSection isSubtitle={isSubtitle} style={style}>
 | 
						|
      {title}
 | 
						|
    </StyledSeparatorSection>
 | 
						|
  );
 | 
						|
};
 | 
						|
 | 
						|
function isContact(item: SearchResultsMergedListItem): item is { contactConvoId: string } {
 | 
						|
  return (item as any).contactConvoId !== undefined;
 | 
						|
}
 | 
						|
 | 
						|
const VirtualizedList = () => {
 | 
						|
  const searchResultList = useSelector(getSearchResultsList);
 | 
						|
 | 
						|
  return (
 | 
						|
    <AutoSizer>
 | 
						|
      {({ height, width }) => (
 | 
						|
        <List
 | 
						|
          height={height}
 | 
						|
          rowCount={searchResultList.length}
 | 
						|
          rowHeight={params =>
 | 
						|
            calcContactRowHeight(searchResultList, params, { breakRowHeight: 36 })
 | 
						|
          }
 | 
						|
          rowRenderer={({ index, key, style }) => {
 | 
						|
            const row = searchResultList[index];
 | 
						|
            if (!row) {
 | 
						|
              return null;
 | 
						|
            }
 | 
						|
            if (isString(row)) {
 | 
						|
              return (
 | 
						|
                <SectionHeader
 | 
						|
                  key={key}
 | 
						|
                  title={row}
 | 
						|
                  isSubtitle={
 | 
						|
                    row !== window.i18n('sessionConversations') && row !== window.i18n('messages')
 | 
						|
                  }
 | 
						|
                  style={style as CSSProperties}
 | 
						|
                />
 | 
						|
              );
 | 
						|
            }
 | 
						|
            if (isContact(row)) {
 | 
						|
              return (
 | 
						|
                <ConversationListItem conversationId={row.contactConvoId} style={style} key={key} />
 | 
						|
              );
 | 
						|
            }
 | 
						|
            return <MessageSearchResult style={style as CSSProperties} key={key} {...row} />;
 | 
						|
          }}
 | 
						|
          width={width}
 | 
						|
          autoHeight={false}
 | 
						|
        />
 | 
						|
      )}
 | 
						|
    </AutoSizer>
 | 
						|
  );
 | 
						|
};
 | 
						|
 | 
						|
export const SearchResults = () => {
 | 
						|
  const query = useSelector(getSearchTerm);
 | 
						|
  const hasSearchResults = useSelector(getHasSearchResults);
 | 
						|
 | 
						|
  return (
 | 
						|
    <SearchResultsContainer>
 | 
						|
      {!hasSearchResults ? (
 | 
						|
        <NoResults>{window.i18n('searchMatchesNoneSpecific', { query })}</NoResults>
 | 
						|
      ) : (
 | 
						|
        <VirtualizedList />
 | 
						|
      )}
 | 
						|
    </SearchResultsContainer>
 | 
						|
  );
 | 
						|
};
 |