import React from 'react'; import { AutoSizer, List } from 'react-virtualized'; import { ConversationListItemProps, MemoConversationListItemWithDetails, } from './conversation-list-item/ConversationListItem'; import { ReduxConversationType } from '../../state/ducks/conversations'; import { SearchResults, SearchResultsProps } from '../search/SearchResults'; import { UserUtils } from '../../session/utils'; import { LeftPaneSectionHeader } from './LeftPaneSectionHeader'; import autoBind from 'auto-bind'; import { clearSearch, search, updateSearchTerm } from '../../state/ducks/search'; import _ from 'lodash'; import { MessageRequestsBanner } from './MessageRequestsBanner'; import { cleanSearchTerm } from '../../util/cleanSearchTerm'; import { SessionButton, SessionButtonColor, SessionButtonType } from '../basic/SessionButton'; import { SessionSearchInput } from '../SessionSearchInput'; import { RowRendererParamsType } from './LeftPane'; import { OverlayOpenGroup } from './overlay/OverlayOpenGroup'; import { OverlayMessageRequest } from './overlay/OverlayMessageRequest'; import { OverlayMessage } from './overlay/OverlayMessage'; import { OverlayClosedGroup } from './overlay/OverlayClosedGroup'; import { OverlayMode, setOverlayMode } from '../../state/ducks/section'; export interface Props { searchTerm: string; contacts: Array; conversations?: Array; searchResults?: SearchResultsProps; messageRequestsEnabled?: boolean; overlayMode: OverlayMode; } export class LeftPaneMessageSection extends React.Component { private readonly debouncedSearch: (searchTerm: string) => void; public constructor(props: Props) { super(props); autoBind(this); this.debouncedSearch = _.debounce(this.search.bind(this), 20); } public renderRow = ({ index, key, style }: RowRendererParamsType): JSX.Element | null => { const { conversations } = this.props; //assume conversations that have been marked unapproved should be filtered out by selector. if (!conversations) { throw new Error('renderRow: Tried to render without conversations'); } const conversation = conversations[index]; if (!conversation) { throw new Error('renderRow: conversations selector returned element containing falsy value.'); } return ; }; public renderList(): JSX.Element | Array { const { conversations, searchResults } = this.props; const contacts = searchResults?.contacts || []; if (searchResults) { return ; } if (!conversations) { throw new Error('render: must provided conversations if no search results are provided'); } const length = conversations.length; const listKey = 0; // 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 render(): JSX.Element { const { overlayMode } = this.props; return (
{ window.inboxStore?.dispatch(setOverlayMode('message')); }} /> {overlayMode ? this.renderClosableOverlay() : this.renderConversations()}
); } public renderConversations() { return (
{window.lokiFeatureFlags.useMessageRequests ? ( { window.inboxStore?.dispatch(setOverlayMode('message-requests')); }} /> ) : null} {this.renderList()} {this.renderBottomButtons()}
); } public updateSearch(searchTerm: string) { if (!searchTerm) { window.inboxStore?.dispatch(clearSearch()); return; } // reset our pubKeyPasted, we can either have a pasted sessionID or a sessionID got from a search this.setState({ valuePasted: '' }); window.inboxStore?.dispatch(updateSearchTerm(searchTerm)); if (searchTerm.length < 2) { return; } const cleanedTerm = cleanSearchTerm(searchTerm); if (!cleanedTerm) { return; } this.debouncedSearch(cleanedTerm); } public clearSearch() { window.inboxStore?.dispatch(clearSearch()); } public search() { const { searchTerm } = this.props; window.inboxStore?.dispatch( search(searchTerm, { noteToSelf: window.i18n('noteToSelf').toLowerCase(), ourNumber: UserUtils.getOurPubKeyStrFromCache(), }) ); } private renderClosableOverlay() { const { overlayMode } = this.props; switch (overlayMode) { case 'open-group': return ; case 'closed-group': return ; case 'message': return ; case 'message-requests': return ; default: return null; } } private renderBottomButtons(): JSX.Element { const joinOpenGroup = window.i18n('joinOpenGroup'); const newClosedGroup = window.i18n('newClosedGroup'); return (
{ window.inboxStore?.dispatch(setOverlayMode('open-group')); }} /> { window.inboxStore?.dispatch(setOverlayMode('closed-group')); }} />
); } }