// Copyright 2018-2020 Signal Messenger, LLC // SPDX-License-Identifier: AGPL-3.0-only import React, { CSSProperties } from 'react'; import classNames from 'classnames'; import { isNumber } from 'lodash'; import { Avatar } from './Avatar'; import { MessageBody } from './conversation/MessageBody'; import { Timestamp } from './conversation/Timestamp'; import { ContactName } from './conversation/ContactName'; import { TypingAnimation } from './conversation/TypingAnimation'; import { cleanId } from './_util'; import { LocalizerType } from '../types/Util'; import { ColorType } from '../types/Colors'; export const MessageStatuses = [ 'sending', 'sent', 'delivered', 'read', 'error', 'partial-sent', ] as const; export type MessageStatusType = typeof MessageStatuses[number]; export type PropsData = { id: string; phoneNumber?: string; color?: ColorType; profileName?: string; title: string; name?: string; type: 'group' | 'direct'; avatarPath?: string; isMe?: boolean; muteExpiresAt?: number; lastUpdated?: number; unreadCount?: number; markedUnread?: boolean; isSelected: boolean; acceptedMessageRequest?: boolean; draftPreview?: string; shouldShowDraft?: boolean; typingContact?: unknown; lastMessage?: { status: MessageStatusType; text: string; deletedForEveryone?: boolean; }; isPinned?: boolean; }; type PropsHousekeeping = { i18n: LocalizerType; style?: CSSProperties; onClick?: (id: string) => void; }; export type Props = PropsData & PropsHousekeeping; export class ConversationListItem extends React.PureComponent { public renderAvatar(): JSX.Element { const { avatarPath, color, type, i18n, isMe, name, phoneNumber, profileName, title, } = this.props; return (
{this.renderUnread()}
); } isUnread(): boolean { const { markedUnread, unreadCount } = this.props; return Boolean((isNumber(unreadCount) && unreadCount > 0) || markedUnread); } public renderUnread(): JSX.Element | null { const { unreadCount } = this.props; if (this.isUnread()) { return (
{unreadCount || ''}
); } return null; } public renderHeader(): JSX.Element { const { i18n, isMe, lastUpdated, name, phoneNumber, profileName, title, } = this.props; return (
{isMe ? ( i18n('noteToSelf') ) : ( )}
); } public renderMessage(): JSX.Element | null { const { draftPreview, i18n, acceptedMessageRequest, lastMessage, muteExpiresAt, shouldShowDraft, typingContact, } = this.props; if (!lastMessage && !typingContact) { return null; } const messageBody = lastMessage ? lastMessage.text : ''; const showingDraft = shouldShowDraft && draftPreview; const deletedForEveryone = Boolean( lastMessage && lastMessage.deletedForEveryone ); /* eslint-disable no-nested-ternary */ return (
{muteExpiresAt && Date.now() < muteExpiresAt && ( )} {!acceptedMessageRequest ? ( {i18n('ConversationListItem--message-request')} ) : typingContact ? ( ) : ( <> {showingDraft ? ( <> {i18n('ConversationListItem--draft-prefix')} ) : deletedForEveryone ? ( {i18n('message--deletedForEveryone')} ) : ( )} )}
{!showingDraft && lastMessage && lastMessage.status ? (
) : null}
); } /* eslint-enable no-nested-ternary */ public render(): JSX.Element { const { id, isSelected, onClick, style } = this.props; return ( ); } }