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.
session-desktop/ts/components/leftpane/overlay/choose-action/ContactsListWithBreaks.tsx

130 lines
3.8 KiB
TypeScript

import { isString } from 'lodash';
import { useSelector } from 'react-redux';
import { AutoSizer, Index, List, ListRowProps } from 'react-virtualized';
import styled, { CSSProperties } from 'styled-components';
import {
DirectContactsByNameType,
getContactsCount,
getSortedContactsWithBreaks,
} from '../../../../state/selectors/conversations';
import { leftPaneListWidth } from '../../LeftPane';
import { StyledLeftPaneList } from '../../LeftPaneList';
import { StyledChooseActionTitle } from './ActionRow';
import { ContactRow, ContactRowBreak } from './ContactRow';
import { getThemeValue, pxValueToNumber } from '../../../../themes/globals';
import { SearchResultsMergedListItem } from '../../../../state/selectors/search';
const StyledContactSection = styled.div`
display: flex;
flex-direction: column;
overflow: hidden;
flex: 1;
width: 100%;
.module-conversation-list-item __header__date,
.module-conversation-list-item __message {
display: none;
}
.module-conversation-list-item __buttons {
display: flex;
.session-button {
font-size: var(--font-size-xs);
padding: 6px;
height: auto;
margin: 0px;
line-height: 14px;
}
}
`;
const StyledContactsTitle = styled(StyledChooseActionTitle)`
padding: var(--margins-xs) var(--margins-lg);
`;
const StyledContactsEmpty = styled.div`
color: var(--text-secondary-color);
padding: var(--margins-xs) var(--margins-lg);
`;
const renderRow = (props: ListRowProps) => {
const { index, key, style, parent } = props;
// 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 contactsByNameWithBreaks = (parent as any).props.contactsByNameWithBreaks as Array<
DirectContactsByNameType | string
>;
const item = contactsByNameWithBreaks?.[index];
if (!item) {
return null;
}
if (isString(item)) {
return <ContactRowBreak style={style as CSSProperties} key={key} char={item} />;
}
return <ContactRow style={style as CSSProperties} key={key} {...item} />;
};
export function calcContactRowHeight(
items: Array<SearchResultsMergedListItem | string | DirectContactsByNameType>,
params: Index,
overrides?: {
rowHeight?: number;
breakRowHeight?: number;
}
) {
return isString(items[params.index])
? overrides?.breakRowHeight || pxValueToNumber(getThemeValue('--contact-row-break-height'))
: overrides?.rowHeight || pxValueToNumber(getThemeValue('--contact-row-height'));
}
const ContactListItemSection = () => {
const contactsByNameWithBreaks = useSelector(getSortedContactsWithBreaks);
if (!contactsByNameWithBreaks) {
return null;
}
const length = Number(contactsByNameWithBreaks.length);
return (
<StyledLeftPaneList key={0} style={{ width: '100%' }}>
<AutoSizer>
{({ height }) => {
return (
<List
className="module-left-pane__virtual-list"
height={height}
rowCount={length}
rowHeight={params => calcContactRowHeight(contactsByNameWithBreaks, params)}
contactsByNameWithBreaks={contactsByNameWithBreaks}
rowRenderer={renderRow}
width={leftPaneListWidth}
autoHeight={false}
/>
);
}}
</AutoSizer>
</StyledLeftPaneList>
);
};
export const ContactsListWithBreaks = () => {
const contactsCount = useSelector(getContactsCount);
return (
<StyledContactSection>
<StyledContactsTitle tabIndex={0}>{window.i18n('contactContacts')}</StyledContactsTitle>
{contactsCount > 0 ? (
<ContactListItemSection />
) : (
<StyledContactsEmpty>{window.i18n('contactsNone')}</StyledContactsEmpty>
)}
</StyledContactSection>
);
};