import React from 'react'; import { PropsData as ConversationListItemPropsType } from '../ConversationListItem'; import { PropsData as SearchResultsProps } from '../SearchResults'; import { debounce } from 'lodash'; import { cleanSearchTerm } from '../../util/cleanSearchTerm'; import { SearchOptions } from '../../types/Search'; import { LeftPane } from '../LeftPane'; import { SessionButton, SessionButtonType, SessionButtonColor, } from './SessionButton'; import { AutoSizer, List } from 'react-virtualized'; import { validateNumber } from '../../types/PhoneNumber'; export interface Props { searchTerm: string; isSecondaryDevice: boolean; conversations?: Array; searchResults?: SearchResultsProps; updateSearchTerm: (searchTerm: string) => void; search: (query: string, options: SearchOptions) => void; openConversationInternal: (id: string, messageId?: string) => void; clearSearch: () => void; } export class LeftPaneContactSection extends React.Component { private readonly debouncedSearch: (searchTerm: string) => void; public constructor(props: Props) { super(props); this.state = { showAddContactView: false, selectedTab: 0, addContactRecipientID: '', }; this.debouncedSearch = debounce(this.search.bind(this), 20); this.handleTabSelected = this.handleTabSelected.bind(this); this.handleToggleOverlay = this.handleToggleOverlay.bind(this); this.handleOnAddContact = this.handleOnAddContact.bind(this); this.handleRecipientSessionIDChanged = this.handleRecipientSessionIDChanged.bind( this ); } public componentWillUnmount() { this.updateSearch(''); this.setState({ addContactRecipientID: '' }); } public handleTabSelected(tabType: number) { this.setState({ selectedTab: tabType, showAddContactView: false }); } public renderHeader(): JSX.Element | undefined { const labels = [window.i18n('contactsHeader'), window.i18n('lists')]; return LeftPane.renderHeader( labels, this.handleTabSelected, undefined, null ); } public render(): JSX.Element { return (
{this.renderHeader()} {this.state.showAddContactView ? LeftPane.renderClosableOverlay( true, this.handleRecipientSessionIDChanged, this.handleToggleOverlay, this.handleOnAddContact, '' ) : this.renderContacts()}
); } private handleToggleOverlay() { this.setState((prevState: { showAddContactView: any }) => ({ showAddContactView: !prevState.showAddContactView, })); } private handleOnAddContact() { const sessionID = this.state.addContactRecipientID; const error = validateNumber(sessionID, window.i18n); if (error) { window.pushToast({ title: error, type: 'error', id: 'addContact', }); } else { window.Whisper.events.trigger('showConversation', sessionID); } } private handleRecipientSessionIDChanged(event: any) { if (event.target.innerHTML) { // remove br elements or div elements const cleanText = event.target.innerHTML.replace(/<\/?[^>]+(>|$)/g, ''); this.setState({ addContactRecipientID: cleanText }); } } private renderContacts() { return (
{this.renderList()} {this.renderBottomButtons()}
); } private renderBottomButtons(): JSX.Element { const { selectedTab } = this.state; const edit = window.i18n('edit'); const addContact = window.i18n('addContact'); const createGroup = window.i18n('createGroup'); return (
{selectedTab === 0 ? ( ) : ( )}
); } public getCurrentConversations(): | Array | undefined { const { conversations } = this.props; let conversationList = conversations; if (conversationList !== undefined) { conversationList = conversationList.filter( conversation => !conversation.isSecondary ); } return conversationList; } private renderList() { const conversations = this.getCurrentConversations(); if (!conversations) { throw new Error( 'render: must provided conversations if no search results are provided' ); } console.log('conversations length;', conversations.length); // Note: conversations is not a known prop for List, but it is required to ensure that // it re-renders when our conversation data changes. Otherwise it would just render // on startup and scroll. const list = (
{({ height, width }) => ( )}
); return [list]; } public renderRow() { return undefined; } // public renderRow = ({ // , // }: // index, // key, // style, // RowRendererParamsType): JSX.Element | undefined => { // const { openConversationInternal } = this.props; // const conversations = this.getCurrentConversations(); // if (!conversations) { // throw new Error('renderRow: Tried to render without conversations'); // } // const conversation = conversations[index]; // return ( // // ); // return undefined; // }; public updateSearch(searchTerm: string) { const { updateSearchTerm, clearSearch } = this.props; if (!searchTerm) { clearSearch(); return; } // reset our pubKeyPasted, we can either have a pasted sessionID or a sessionID got from a search this.setState({ pubKeyPasted: '' }, () => { window.Session.emptyContentEditableDivs(); }); if (updateSearchTerm) { updateSearchTerm(searchTerm); } if (searchTerm.length < 2) { return; } const cleanedTerm = cleanSearchTerm(searchTerm); if (!cleanedTerm) { return; } this.debouncedSearch(cleanedTerm); } public clearSearch() { this.props.clearSearch(); //this.setFocus(); } public search() { const { search } = this.props; const { searchTerm, isSecondaryDevice } = this.props; if (search) { search(searchTerm, { noteToSelf: window.i18n('noteToSelf').toLowerCase(), ourNumber: window.textsecure.storage.user.getNumber(), regionCode: '', isSecondaryDevice, }); } } }