diff --git a/ts/components/leftpane/overlay/choose-action/ContactsListWithBreaks.tsx b/ts/components/leftpane/overlay/choose-action/ContactsListWithBreaks.tsx index 63bba6c16..be0148205 100644 --- a/ts/components/leftpane/overlay/choose-action/ContactsListWithBreaks.tsx +++ b/ts/components/leftpane/overlay/choose-action/ContactsListWithBreaks.tsx @@ -5,14 +5,13 @@ import { AutoSizer, Index, List, ListRowProps } from 'react-virtualized'; import styled, { CSSProperties } from 'styled-components'; import { DirectContactsByNameType, - getDirectContactsByName, getContactsCount, + getSortedContactsWithBreaks, } from '../../../../state/selectors/conversations'; import { leftPaneListWidth } from '../../LeftPane'; import { StyledLeftPaneList } from '../../LeftPaneList'; import { StyledChooseActionTitle } from './ActionRow'; import { ContactRow, ContactRowBreak } from './ContactRow'; -import { UserUtils } from '../../../../session/utils'; import { getThemeValue, pxValueToNumber } from '../../../../themes/globals'; import { SearchResultsMergedListItem } from '../../../../state/selectors/search'; @@ -55,9 +54,10 @@ const renderRow = (props: ListRowProps) => { // ugly, but it seems react-virtualized does not support very well functional components just yet // https://stackoverflow.com/questions/54488954/how-to-pass-prop-into-rowrender-of-react-virtualized - const directContactsByNameWithBreaks = (parent as any).props - .directContactsByNameWithBreaks as Array; - const item = directContactsByNameWithBreaks?.[index]; + const contactsByNameWithBreaks = (parent as any).props.contactsByNameWithBreaks as Array< + DirectContactsByNameType | string + >; + const item = contactsByNameWithBreaks?.[index]; if (!item) { return null; } @@ -82,53 +82,14 @@ export function calcContactRowHeight( : overrides?.rowHeight || pxValueToNumber(getThemeValue('--contact-row-height')); } -const unknownSection = 'unknown'; - const ContactListItemSection = () => { - const directContactsByName = useSelector(getDirectContactsByName); + const contactsByNameWithBreaks = useSelector(getSortedContactsWithBreaks); - if (!directContactsByName) { + if (!contactsByNameWithBreaks) { return null; } - // add a break wherever needed - let currentChar = ''; - // if the item is a string we consider it to be a break of that string - const directContactsByNameWithBreaks: Array = []; - const directContactsStartingWithANumber: Array = []; - directContactsByName.forEach(m => { - if ( - m.displayName && - m.displayName[0].toLowerCase() !== currentChar && - !m.displayName[0].match(/^[0-9]+$/) - ) { - currentChar = m.displayName[0].toLowerCase(); - directContactsByNameWithBreaks.push(currentChar.toUpperCase()); - } else if (!m.displayName && currentChar !== unknownSection) { - currentChar = unknownSection; - directContactsByNameWithBreaks.push('#'); - } - - if (m.displayName && !!m.displayName[0].match(/^[0-9]+$/)) { - directContactsStartingWithANumber.push(m); - } else { - directContactsByNameWithBreaks.push(m); - } - }); - - directContactsByNameWithBreaks.unshift({ - id: UserUtils.getOurPubKeyStrFromCache(), - displayName: window.i18n('noteToSelf'), - }); - - if (directContactsStartingWithANumber.length) { - if (currentChar !== unknownSection) { - directContactsByNameWithBreaks.push('#'); - } - directContactsByNameWithBreaks.push(...directContactsStartingWithANumber); - } - - const length = Number(directContactsByNameWithBreaks.length); + const length = Number(contactsByNameWithBreaks.length); return ( @@ -139,8 +100,8 @@ const ContactListItemSection = () => { className="module-left-pane__virtual-list" height={height} rowCount={length} - rowHeight={params => calcContactRowHeight(directContactsByNameWithBreaks, params)} - directContactsByNameWithBreaks={directContactsByNameWithBreaks} + rowHeight={params => calcContactRowHeight(contactsByNameWithBreaks, params)} + contactsByNameWithBreaks={contactsByNameWithBreaks} rowRenderer={renderRow} width={leftPaneListWidth} autoHeight={false} diff --git a/ts/state/selectors/conversations.ts b/ts/state/selectors/conversations.ts index 86999952e..5473c6e55 100644 --- a/ts/state/selectors/conversations.ts +++ b/ts/state/selectors/conversations.ts @@ -462,7 +462,7 @@ export type DirectContactsByNameType = { }; // make sure that createSelector is called here so this function is memoized -export const getDirectContactsByName = createSelector( +export const getSortedContacts = createSelector( getContacts, (contacts: Array): Array => { const us = UserUtils.getOurPubKeyStrFromCache(); @@ -475,21 +475,60 @@ export const getDirectContactsByName = createSelector( }; }); - const extractedContactsNoDisplayName = sortBy( - extractedContacts.filter(m => !m.displayName), - 'id' + const contactsStartingWithANumber = sortBy( + extractedContacts.filter( + m => !m.displayName || (m.displayName && m.displayName[0].match(/^[0-9]+$/)) + ), + m => m.displayName || m.id ); - const extractedContactsWithDisplayName = sortBy( - extractedContacts.filter(m => Boolean(m.displayName)), + const contactsWithDisplayName = sortBy( + extractedContacts.filter(m => !!m.displayName && !m.displayName[0].match(/^[0-9]+$/)), m => m.displayName?.toLowerCase() ); - return [...extractedContactsWithDisplayName, ...extractedContactsNoDisplayName]; + return [...contactsWithDisplayName, ...contactsStartingWithANumber]; } ); -export const getPrivateContactsPubkeys = createSelector(getDirectContactsByName, state => +export const getSortedContactsWithBreaks = createSelector( + getSortedContacts, + (contacts: Array): Array => { + // add a break wherever needed + const unknownSection = 'unknown'; + let currentChar = ''; + // if the item is a string we consider it to be a break of that string + const contactsWithBreaks: Array = []; + + contacts.forEach(m => { + if ( + !!m.displayName && + m.displayName[0].toLowerCase() !== currentChar && + !m.displayName[0].match(/^[0-9]+$/) + ) { + currentChar = m.displayName[0].toLowerCase(); + contactsWithBreaks.push(currentChar.toUpperCase()); + } else if ( + ((m.displayName && m.displayName[0].match(/^[0-9]+$/)) || !m.displayName) && + currentChar !== unknownSection + ) { + currentChar = unknownSection; + contactsWithBreaks.push('#'); + } + + contactsWithBreaks.push(m); + }); + + contactsWithBreaks.unshift({ + id: UserUtils.getOurPubKeyStrFromCache(), + displayName: window.i18n('noteToSelf'), + }); + + return contactsWithBreaks; + } +); + +export const getPrivateContactsPubkeys = createSelector(getSortedContacts, state => state.map(m => m.id) );