| 
									
										
										
										
											2021-03-24 17:06:12 -05:00
										 |  |  | // Copyright 2018-2021 Signal Messenger, LLC
 | 
					
						
							| 
									
										
										
										
											2020-10-30 15:34:04 -05:00
										 |  |  | // SPDX-License-Identifier: AGPL-3.0-only
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-07-20 14:56:50 -05:00
										 |  |  | import React, { ReactChild, ReactNode } from 'react'; | 
					
						
							| 
									
										
										
										
											2018-07-09 14:29:13 -07:00
										 |  |  | import classNames from 'classnames'; | 
					
						
							|  |  |  | import moment from 'moment'; | 
					
						
							| 
									
										
										
										
											2021-06-17 10:15:10 -07:00
										 |  |  | import { noop } from 'lodash'; | 
					
						
							| 
									
										
										
										
											2018-07-09 14:29:13 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-07-20 14:56:50 -05:00
										 |  |  | import { Avatar, AvatarSize } from '../Avatar'; | 
					
						
							| 
									
										
										
										
											2018-07-09 14:29:13 -07:00
										 |  |  | import { ContactName } from './ContactName'; | 
					
						
							| 
									
										
										
										
											2021-03-24 17:06:12 -05:00
										 |  |  | import { | 
					
						
							|  |  |  |   Message, | 
					
						
							|  |  |  |   Props as MessagePropsType, | 
					
						
							|  |  |  |   PropsData as MessagePropsDataType, | 
					
						
							|  |  |  | } from './Message'; | 
					
						
							| 
									
										
										
										
											2020-08-13 13:53:45 -07:00
										 |  |  | import { LocalizerType } from '../../types/Util'; | 
					
						
							| 
									
										
										
										
											2021-05-07 17:21:10 -05:00
										 |  |  | import { ConversationType } from '../../state/ducks/conversations'; | 
					
						
							| 
									
										
										
										
											2021-07-20 14:56:50 -05:00
										 |  |  | import { groupBy } from '../../util/mapUtil'; | 
					
						
							| 
									
										
										
										
											2021-06-07 12:50:18 -04:00
										 |  |  | import { ContactNameColorType } from '../../types/Colors'; | 
					
						
							| 
									
										
										
										
											2021-07-19 17:44:49 -05:00
										 |  |  | import { SendStatus } from '../../messages/MessageSendState'; | 
					
						
							| 
									
										
										
										
											2021-09-17 14:27:53 -04:00
										 |  |  | import * as log from '../../logging/log'; | 
					
						
							| 
									
										
										
										
											2018-07-09 14:29:13 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-05-07 17:21:10 -05:00
										 |  |  | export type Contact = Pick< | 
					
						
							|  |  |  |   ConversationType, | 
					
						
							|  |  |  |   | 'acceptedMessageRequest' | 
					
						
							|  |  |  |   | 'avatarPath' | 
					
						
							|  |  |  |   | 'color' | 
					
						
							| 
									
										
										
										
											2021-06-15 17:44:14 -07:00
										 |  |  |   | 'id' | 
					
						
							| 
									
										
										
										
											2021-05-07 17:21:10 -05:00
										 |  |  |   | 'isMe' | 
					
						
							|  |  |  |   | 'name' | 
					
						
							|  |  |  |   | 'phoneNumber' | 
					
						
							|  |  |  |   | 'profileName' | 
					
						
							|  |  |  |   | 'sharedGroupNames' | 
					
						
							|  |  |  |   | 'title' | 
					
						
							|  |  |  |   | 'unblurredAvatarPath' | 
					
						
							|  |  |  | > & { | 
					
						
							| 
									
										
										
										
											2021-07-20 14:56:50 -05:00
										 |  |  |   status?: SendStatus; | 
					
						
							| 
									
										
										
										
											2020-07-23 18:35:32 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-07-09 14:29:13 -07:00
										 |  |  |   isOutgoingKeyError: boolean; | 
					
						
							| 
									
										
										
										
											2018-10-17 18:01:21 -07:00
										 |  |  |   isUnidentifiedDelivery: boolean; | 
					
						
							| 
									
										
										
										
											2018-07-09 14:29:13 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  |   errors?: Array<Error>; | 
					
						
							| 
									
										
										
										
											2021-01-14 12:07:05 -06:00
										 |  |  | }; | 
					
						
							| 
									
										
										
										
											2018-07-09 14:29:13 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-08-30 14:32:56 -07:00
										 |  |  | export type PropsData = { | 
					
						
							| 
									
										
										
										
											2021-07-20 14:56:50 -05:00
										 |  |  |   // An undefined status means they were the sender and it's an incoming message. If
 | 
					
						
							|  |  |  |   //   `undefined` is a status, there should be no other items in the array; if there are
 | 
					
						
							|  |  |  |   //   any defined statuses, `undefined` shouldn't be present.
 | 
					
						
							|  |  |  |   contacts: ReadonlyArray<Contact>; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-06-07 12:50:18 -04:00
										 |  |  |   contactNameColor?: ContactNameColorType; | 
					
						
							| 
									
										
										
										
											2021-03-24 17:06:12 -05:00
										 |  |  |   errors: Array<Error>; | 
					
						
							| 
									
										
										
										
											2021-06-29 12:58:29 -07:00
										 |  |  |   message: Omit<MessagePropsDataType, 'renderingContext'>; | 
					
						
							| 
									
										
										
										
											2021-03-24 17:06:12 -05:00
										 |  |  |   receivedAt: number; | 
					
						
							|  |  |  |   sentAt: number; | 
					
						
							| 
									
										
										
										
											2018-07-09 14:29:13 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-06-15 17:44:14 -07:00
										 |  |  |   showSafetyNumber: (contactId: string) => void; | 
					
						
							| 
									
										
										
										
											2019-01-14 13:49:58 -08:00
										 |  |  |   i18n: LocalizerType; | 
					
						
							| 
									
										
										
										
											2021-08-30 14:32:56 -07:00
										 |  |  | } & Pick<MessagePropsType, 'interactionMode'>; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | export type PropsBackboneActions = Pick< | 
					
						
							| 
									
										
										
										
											2021-03-24 17:06:12 -05:00
										 |  |  |   MessagePropsType, | 
					
						
							|  |  |  |   | 'displayTapToViewMessage' | 
					
						
							|  |  |  |   | 'kickOffAttachmentDownload' | 
					
						
							|  |  |  |   | 'markAttachmentAsCorrupted' | 
					
						
							| 
									
										
										
										
											2021-08-12 13:15:55 -05:00
										 |  |  |   | 'markViewed' | 
					
						
							| 
									
										
										
										
											2021-03-24 17:06:12 -05:00
										 |  |  |   | 'openConversation' | 
					
						
							|  |  |  |   | 'openLink' | 
					
						
							|  |  |  |   | 'reactToMessage' | 
					
						
							|  |  |  |   | 'renderAudioAttachment' | 
					
						
							|  |  |  |   | 'renderEmojiPicker' | 
					
						
							| 
									
										
										
										
											2021-09-10 13:00:31 -05:00
										 |  |  |   | 'renderReactionPicker' | 
					
						
							| 
									
										
										
										
											2021-03-24 17:06:12 -05:00
										 |  |  |   | 'replyToMessage' | 
					
						
							|  |  |  |   | 'retrySend' | 
					
						
							|  |  |  |   | 'showContactDetail' | 
					
						
							|  |  |  |   | 'showContactModal' | 
					
						
							|  |  |  |   | 'showExpiredIncomingTapToViewToast' | 
					
						
							|  |  |  |   | 'showExpiredOutgoingTapToViewToast' | 
					
						
							| 
									
										
										
										
											2021-04-27 15:35:35 -07:00
										 |  |  |   | 'showForwardMessageModal' | 
					
						
							| 
									
										
										
										
											2021-03-24 17:06:12 -05:00
										 |  |  |   | 'showVisualAttachment' | 
					
						
							|  |  |  | >; | 
					
						
							| 
									
										
										
										
											2018-07-09 14:29:13 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-08-30 14:32:56 -07:00
										 |  |  | export type PropsReduxActions = Pick< | 
					
						
							|  |  |  |   MessagePropsType, | 
					
						
							|  |  |  |   | 'clearSelectedMessage' | 
					
						
							|  |  |  |   | 'doubleCheckMissingQuoteReference' | 
					
						
							|  |  |  |   | 'checkForAccount' | 
					
						
							|  |  |  | >; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | export type ExternalProps = PropsData & PropsBackboneActions; | 
					
						
							|  |  |  | export type Props = PropsData & PropsBackboneActions & PropsReduxActions; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-07-20 14:56:50 -05:00
										 |  |  | const contactSortCollator = new Intl.Collator(); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-09-14 12:51:27 -07:00
										 |  |  | const _keyForError = (error: Error): string => { | 
					
						
							|  |  |  |   return `${error.name}-${error.message}`; | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-07-09 14:29:13 -07:00
										 |  |  | export class MessageDetail extends React.Component<Props> { | 
					
						
							| 
									
										
										
										
											2019-11-21 11:16:06 -08:00
										 |  |  |   private readonly focusRef = React.createRef<HTMLDivElement>(); | 
					
						
							| 
									
										
										
										
											2019-11-07 13:36:16 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-08-20 14:36:27 -05:00
										 |  |  |   private readonly messageContainerRef = React.createRef<HTMLDivElement>(); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-09-14 12:51:27 -07:00
										 |  |  |   public componentDidMount(): void { | 
					
						
							| 
									
										
										
										
											2019-11-07 13:36:16 -08:00
										 |  |  |     // When this component is created, it's initially not part of the DOM, and then it's
 | 
					
						
							|  |  |  |     //   added off-screen and animated in. This ensures that the focus takes.
 | 
					
						
							|  |  |  |     setTimeout(() => { | 
					
						
							|  |  |  |       if (this.focusRef.current) { | 
					
						
							|  |  |  |         this.focusRef.current.focus(); | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-09-14 12:51:27 -07:00
										 |  |  |   public renderAvatar(contact: Contact): JSX.Element { | 
					
						
							| 
									
										
										
										
											2018-07-09 14:29:13 -07:00
										 |  |  |     const { i18n } = this.props; | 
					
						
							| 
									
										
										
										
											2020-07-23 18:35:32 -07:00
										 |  |  |     const { | 
					
						
							| 
									
										
										
										
											2021-05-04 18:19:36 -05:00
										 |  |  |       acceptedMessageRequest, | 
					
						
							| 
									
										
										
										
											2020-07-23 18:35:32 -07:00
										 |  |  |       avatarPath, | 
					
						
							|  |  |  |       color, | 
					
						
							| 
									
										
										
										
											2021-05-07 17:21:10 -05:00
										 |  |  |       isMe, | 
					
						
							| 
									
										
										
										
											2020-07-23 18:35:32 -07:00
										 |  |  |       name, | 
					
						
							| 
									
										
										
										
											2021-05-04 18:19:36 -05:00
										 |  |  |       phoneNumber, | 
					
						
							| 
									
										
										
										
											2020-07-23 18:35:32 -07:00
										 |  |  |       profileName, | 
					
						
							| 
									
										
										
										
											2021-05-04 18:19:36 -05:00
										 |  |  |       sharedGroupNames, | 
					
						
							| 
									
										
										
										
											2020-07-23 18:35:32 -07:00
										 |  |  |       title, | 
					
						
							| 
									
										
										
										
											2021-05-04 18:19:36 -05:00
										 |  |  |       unblurredAvatarPath, | 
					
						
							| 
									
										
										
										
											2020-07-23 18:35:32 -07:00
										 |  |  |     } = contact; | 
					
						
							| 
									
										
										
										
											2018-07-09 14:29:13 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  |     return ( | 
					
						
							| 
									
										
										
										
											2018-09-26 17:23:17 -07:00
										 |  |  |       <Avatar | 
					
						
							| 
									
										
										
										
											2021-05-04 18:19:36 -05:00
										 |  |  |         acceptedMessageRequest={acceptedMessageRequest} | 
					
						
							| 
									
										
										
										
											2018-09-26 17:23:17 -07:00
										 |  |  |         avatarPath={avatarPath} | 
					
						
							|  |  |  |         color={color} | 
					
						
							|  |  |  |         conversationType="direct" | 
					
						
							|  |  |  |         i18n={i18n} | 
					
						
							| 
									
										
										
										
											2021-05-07 17:21:10 -05:00
										 |  |  |         isMe={isMe} | 
					
						
							| 
									
										
										
										
											2018-09-26 17:23:17 -07:00
										 |  |  |         name={name} | 
					
						
							|  |  |  |         phoneNumber={phoneNumber} | 
					
						
							|  |  |  |         profileName={profileName} | 
					
						
							| 
									
										
										
										
											2020-07-23 18:35:32 -07:00
										 |  |  |         title={title} | 
					
						
							| 
									
										
										
										
											2021-05-04 18:19:36 -05:00
										 |  |  |         sharedGroupNames={sharedGroupNames} | 
					
						
							| 
									
										
										
										
											2021-07-20 14:56:50 -05:00
										 |  |  |         size={AvatarSize.THIRTY_SIX} | 
					
						
							| 
									
										
										
										
											2021-05-04 18:19:36 -05:00
										 |  |  |         unblurredAvatarPath={unblurredAvatarPath} | 
					
						
							| 
									
										
										
										
											2018-07-09 14:29:13 -07:00
										 |  |  |       /> | 
					
						
							|  |  |  |     ); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-09-14 12:51:27 -07:00
										 |  |  |   public renderContact(contact: Contact): JSX.Element { | 
					
						
							| 
									
										
										
										
											2021-08-31 15:58:39 -05:00
										 |  |  |     const { i18n, showSafetyNumber } = this.props; | 
					
						
							| 
									
										
										
										
											2018-07-09 14:29:13 -07:00
										 |  |  |     const errors = contact.errors || []; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     const errorComponent = contact.isOutgoingKeyError ? ( | 
					
						
							|  |  |  |       <div className="module-message-detail__contact__error-buttons"> | 
					
						
							|  |  |  |         <button | 
					
						
							| 
									
										
										
										
											2020-09-14 12:51:27 -07:00
										 |  |  |           type="button" | 
					
						
							| 
									
										
										
										
											2018-07-09 14:29:13 -07:00
										 |  |  |           className="module-message-detail__contact__show-safety-number" | 
					
						
							| 
									
										
										
										
											2021-06-15 17:44:14 -07:00
										 |  |  |           onClick={() => showSafetyNumber(contact.id)} | 
					
						
							| 
									
										
										
										
											2018-07-09 14:29:13 -07:00
										 |  |  |         > | 
					
						
							|  |  |  |           {i18n('showSafetyNumber')} | 
					
						
							|  |  |  |         </button> | 
					
						
							|  |  |  |       </div> | 
					
						
							|  |  |  |     ) : null; | 
					
						
							| 
									
										
										
										
											2018-10-17 18:01:21 -07:00
										 |  |  |     const unidentifiedDeliveryComponent = contact.isUnidentifiedDelivery ? ( | 
					
						
							|  |  |  |       <div className="module-message-detail__contact__unidentified-delivery-icon" /> | 
					
						
							|  |  |  |     ) : null; | 
					
						
							| 
									
										
										
										
											2018-07-09 14:29:13 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  |     return ( | 
					
						
							| 
									
										
										
										
											2021-07-20 14:56:50 -05:00
										 |  |  |       <div key={contact.id} className="module-message-detail__contact"> | 
					
						
							| 
									
										
										
										
											2018-07-09 14:29:13 -07:00
										 |  |  |         {this.renderAvatar(contact)} | 
					
						
							|  |  |  |         <div className="module-message-detail__contact__text"> | 
					
						
							|  |  |  |           <div className="module-message-detail__contact__name"> | 
					
						
							| 
									
										
										
										
											2021-09-16 11:15:43 -05:00
										 |  |  |             <ContactName title={contact.title} /> | 
					
						
							| 
									
										
										
										
											2018-07-09 14:29:13 -07:00
										 |  |  |           </div> | 
					
						
							| 
									
										
										
										
											2020-09-14 12:51:27 -07:00
										 |  |  |           {errors.map(error => ( | 
					
						
							|  |  |  |             <div | 
					
						
							|  |  |  |               key={_keyForError(error)} | 
					
						
							|  |  |  |               className="module-message-detail__contact__error" | 
					
						
							|  |  |  |             > | 
					
						
							| 
									
										
										
										
											2018-07-09 14:29:13 -07:00
										 |  |  |               {error.message} | 
					
						
							|  |  |  |             </div> | 
					
						
							|  |  |  |           ))} | 
					
						
							|  |  |  |         </div> | 
					
						
							|  |  |  |         {errorComponent} | 
					
						
							| 
									
										
										
										
											2018-10-17 18:01:21 -07:00
										 |  |  |         {unidentifiedDeliveryComponent} | 
					
						
							| 
									
										
										
										
											2018-07-09 14:29:13 -07:00
										 |  |  |       </div> | 
					
						
							|  |  |  |     ); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-07-20 14:56:50 -05:00
										 |  |  |   private renderContactGroup( | 
					
						
							|  |  |  |     sendStatus: undefined | SendStatus, | 
					
						
							|  |  |  |     contacts: undefined | ReadonlyArray<Contact> | 
					
						
							|  |  |  |   ): ReactNode { | 
					
						
							|  |  |  |     const { i18n } = this.props; | 
					
						
							| 
									
										
										
										
											2018-07-09 14:29:13 -07:00
										 |  |  |     if (!contacts || !contacts.length) { | 
					
						
							|  |  |  |       return null; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-07-20 14:56:50 -05:00
										 |  |  |     const i18nKey = | 
					
						
							|  |  |  |       sendStatus === undefined ? 'from' : `MessageDetailsHeader--${sendStatus}`; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     const sortedContacts = [...contacts].sort((a, b) => | 
					
						
							|  |  |  |       contactSortCollator.compare(a.title, b.title) | 
					
						
							|  |  |  |     ); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     return ( | 
					
						
							|  |  |  |       <div key={i18nKey} className="module-message-detail__contact-group"> | 
					
						
							|  |  |  |         <div | 
					
						
							|  |  |  |           className={classNames( | 
					
						
							|  |  |  |             'module-message-detail__contact-group__header', | 
					
						
							|  |  |  |             sendStatus && | 
					
						
							|  |  |  |               `module-message-detail__contact-group__header--${sendStatus}` | 
					
						
							|  |  |  |           )} | 
					
						
							|  |  |  |         > | 
					
						
							|  |  |  |           {i18n(i18nKey)} | 
					
						
							|  |  |  |         </div> | 
					
						
							|  |  |  |         {sortedContacts.map(contact => this.renderContact(contact))} | 
					
						
							|  |  |  |       </div> | 
					
						
							|  |  |  |     ); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   private renderContacts(): ReactChild { | 
					
						
							|  |  |  |     // This assumes that the list either contains one sender (a status of `undefined`) or
 | 
					
						
							|  |  |  |     //   1+ contacts with `SendStatus`es, but it doesn't check that assumption.
 | 
					
						
							|  |  |  |     const { contacts } = this.props; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     const contactsBySendStatus = groupBy(contacts, contact => contact.status); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-07-09 14:29:13 -07:00
										 |  |  |     return ( | 
					
						
							|  |  |  |       <div className="module-message-detail__contact-container"> | 
					
						
							| 
									
										
										
										
											2021-07-20 14:56:50 -05:00
										 |  |  |         {[ | 
					
						
							|  |  |  |           undefined, | 
					
						
							|  |  |  |           SendStatus.Failed, | 
					
						
							|  |  |  |           SendStatus.Viewed, | 
					
						
							|  |  |  |           SendStatus.Read, | 
					
						
							|  |  |  |           SendStatus.Delivered, | 
					
						
							|  |  |  |           SendStatus.Sent, | 
					
						
							|  |  |  |           SendStatus.Pending, | 
					
						
							|  |  |  |         ].map(sendStatus => | 
					
						
							|  |  |  |           this.renderContactGroup( | 
					
						
							|  |  |  |             sendStatus, | 
					
						
							|  |  |  |             contactsBySendStatus.get(sendStatus) | 
					
						
							|  |  |  |           ) | 
					
						
							|  |  |  |         )} | 
					
						
							| 
									
										
										
										
											2018-07-09 14:29:13 -07:00
										 |  |  |       </div> | 
					
						
							|  |  |  |     ); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-09-14 12:51:27 -07:00
										 |  |  |   public render(): JSX.Element { | 
					
						
							| 
									
										
										
										
											2021-03-24 17:06:12 -05:00
										 |  |  |     const { | 
					
						
							|  |  |  |       errors, | 
					
						
							|  |  |  |       message, | 
					
						
							|  |  |  |       receivedAt, | 
					
						
							|  |  |  |       sentAt, | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-06-17 10:15:10 -07:00
										 |  |  |       checkForAccount, | 
					
						
							| 
									
										
										
										
											2021-03-24 17:06:12 -05:00
										 |  |  |       clearSelectedMessage, | 
					
						
							| 
									
										
										
										
											2021-06-07 12:50:18 -04:00
										 |  |  |       contactNameColor, | 
					
						
							| 
									
										
										
										
											2021-03-24 17:06:12 -05:00
										 |  |  |       displayTapToViewMessage, | 
					
						
							| 
									
										
										
										
											2021-06-17 10:15:10 -07:00
										 |  |  |       doubleCheckMissingQuoteReference, | 
					
						
							| 
									
										
										
										
											2021-03-24 17:06:12 -05:00
										 |  |  |       i18n, | 
					
						
							|  |  |  |       interactionMode, | 
					
						
							|  |  |  |       kickOffAttachmentDownload, | 
					
						
							|  |  |  |       markAttachmentAsCorrupted, | 
					
						
							| 
									
										
										
										
											2021-08-12 13:15:55 -05:00
										 |  |  |       markViewed, | 
					
						
							| 
									
										
										
										
											2021-03-24 17:06:12 -05:00
										 |  |  |       openConversation, | 
					
						
							|  |  |  |       openLink, | 
					
						
							|  |  |  |       reactToMessage, | 
					
						
							|  |  |  |       renderAudioAttachment, | 
					
						
							|  |  |  |       renderEmojiPicker, | 
					
						
							| 
									
										
										
										
											2021-09-10 13:00:31 -05:00
										 |  |  |       renderReactionPicker, | 
					
						
							| 
									
										
										
										
											2021-03-24 17:06:12 -05:00
										 |  |  |       replyToMessage, | 
					
						
							|  |  |  |       retrySend, | 
					
						
							|  |  |  |       showContactDetail, | 
					
						
							|  |  |  |       showContactModal, | 
					
						
							|  |  |  |       showExpiredIncomingTapToViewToast, | 
					
						
							|  |  |  |       showExpiredOutgoingTapToViewToast, | 
					
						
							| 
									
										
										
										
											2021-04-27 15:35:35 -07:00
										 |  |  |       showForwardMessageModal, | 
					
						
							| 
									
										
										
										
											2021-03-24 17:06:12 -05:00
										 |  |  |       showVisualAttachment, | 
					
						
							|  |  |  |     } = this.props; | 
					
						
							| 
									
										
										
										
											2018-07-09 14:29:13 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  |     return ( | 
					
						
							| 
									
										
										
										
											2020-09-14 12:51:27 -07:00
										 |  |  |       // eslint-disable-next-line jsx-a11y/no-noninteractive-tabindex
 | 
					
						
							| 
									
										
										
										
											2019-11-07 13:36:16 -08:00
										 |  |  |       <div className="module-message-detail" tabIndex={0} ref={this.focusRef}> | 
					
						
							| 
									
										
										
										
											2021-08-20 14:36:27 -05:00
										 |  |  |         <div | 
					
						
							|  |  |  |           className="module-message-detail__message-container" | 
					
						
							|  |  |  |           ref={this.messageContainerRef} | 
					
						
							|  |  |  |         > | 
					
						
							| 
									
										
										
										
											2021-06-29 12:58:29 -07:00
										 |  |  |           <Message | 
					
						
							|  |  |  |             {...message} | 
					
						
							|  |  |  |             renderingContext="conversation/MessageDetail" | 
					
						
							|  |  |  |             checkForAccount={checkForAccount} | 
					
						
							|  |  |  |             clearSelectedMessage={clearSelectedMessage} | 
					
						
							|  |  |  |             contactNameColor={contactNameColor} | 
					
						
							| 
									
										
										
										
											2021-08-20 14:36:27 -05:00
										 |  |  |             containerElementRef={this.messageContainerRef} | 
					
						
							| 
									
										
										
										
											2021-08-30 14:32:56 -07:00
										 |  |  |             deleteMessage={() => | 
					
						
							| 
									
										
										
										
											2021-09-17 14:27:53 -04:00
										 |  |  |               log.warn('MessageDetail: deleteMessage called!') | 
					
						
							| 
									
										
										
										
											2021-08-30 14:32:56 -07:00
										 |  |  |             } | 
					
						
							|  |  |  |             deleteMessageForEveryone={() => | 
					
						
							| 
									
										
										
										
											2021-09-17 14:27:53 -04:00
										 |  |  |               log.warn('MessageDetail: deleteMessageForEveryone called!') | 
					
						
							| 
									
										
										
										
											2021-08-30 14:32:56 -07:00
										 |  |  |             } | 
					
						
							| 
									
										
										
										
											2021-06-29 12:58:29 -07:00
										 |  |  |             disableMenu | 
					
						
							|  |  |  |             disableScroll | 
					
						
							|  |  |  |             displayTapToViewMessage={displayTapToViewMessage} | 
					
						
							| 
									
										
										
										
											2021-08-30 14:32:56 -07:00
										 |  |  |             downloadAttachment={() => | 
					
						
							| 
									
										
										
										
											2021-09-17 14:27:53 -04:00
										 |  |  |               log.warn('MessageDetail: deleteMessageForEveryone called!') | 
					
						
							| 
									
										
										
										
											2021-08-30 14:32:56 -07:00
										 |  |  |             } | 
					
						
							| 
									
										
										
										
											2021-06-29 12:58:29 -07:00
										 |  |  |             doubleCheckMissingQuoteReference={doubleCheckMissingQuoteReference} | 
					
						
							|  |  |  |             i18n={i18n} | 
					
						
							|  |  |  |             interactionMode={interactionMode} | 
					
						
							|  |  |  |             kickOffAttachmentDownload={kickOffAttachmentDownload} | 
					
						
							|  |  |  |             markAttachmentAsCorrupted={markAttachmentAsCorrupted} | 
					
						
							| 
									
										
										
										
											2021-08-12 13:15:55 -05:00
										 |  |  |             markViewed={markViewed} | 
					
						
							| 
									
										
										
										
											2021-06-29 12:58:29 -07:00
										 |  |  |             onHeightChange={noop} | 
					
						
							|  |  |  |             openConversation={openConversation} | 
					
						
							|  |  |  |             openLink={openLink} | 
					
						
							|  |  |  |             reactToMessage={reactToMessage} | 
					
						
							|  |  |  |             renderAudioAttachment={renderAudioAttachment} | 
					
						
							|  |  |  |             renderEmojiPicker={renderEmojiPicker} | 
					
						
							| 
									
										
										
										
											2021-09-10 13:00:31 -05:00
										 |  |  |             renderReactionPicker={renderReactionPicker} | 
					
						
							| 
									
										
										
										
											2021-06-29 12:58:29 -07:00
										 |  |  |             replyToMessage={replyToMessage} | 
					
						
							|  |  |  |             retrySend={retrySend} | 
					
						
							|  |  |  |             showForwardMessageModal={showForwardMessageModal} | 
					
						
							|  |  |  |             scrollToQuotedMessage={() => { | 
					
						
							| 
									
										
										
										
											2021-09-17 14:27:53 -04:00
										 |  |  |               log.warn('MessageDetail: scrollToQuotedMessage called!'); | 
					
						
							| 
									
										
										
										
											2021-06-29 12:58:29 -07:00
										 |  |  |             }} | 
					
						
							|  |  |  |             showContactDetail={showContactDetail} | 
					
						
							|  |  |  |             showContactModal={showContactModal} | 
					
						
							|  |  |  |             showExpiredIncomingTapToViewToast={ | 
					
						
							|  |  |  |               showExpiredIncomingTapToViewToast | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |             showExpiredOutgoingTapToViewToast={ | 
					
						
							|  |  |  |               showExpiredOutgoingTapToViewToast | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |             showMessageDetail={() => { | 
					
						
							| 
									
										
										
										
											2021-09-17 14:27:53 -04:00
										 |  |  |               log.warn('MessageDetail: deleteMessageForEveryone called!'); | 
					
						
							| 
									
										
										
										
											2021-06-29 12:58:29 -07:00
										 |  |  |             }} | 
					
						
							|  |  |  |             showVisualAttachment={showVisualAttachment} | 
					
						
							|  |  |  |           /> | 
					
						
							| 
									
										
										
										
											2018-07-09 14:29:13 -07:00
										 |  |  |         </div> | 
					
						
							|  |  |  |         <table className="module-message-detail__info"> | 
					
						
							|  |  |  |           <tbody> | 
					
						
							| 
									
										
										
										
											2020-09-14 12:51:27 -07:00
										 |  |  |             {(errors || []).map(error => ( | 
					
						
							|  |  |  |               <tr key={_keyForError(error)}> | 
					
						
							| 
									
										
										
										
											2018-07-09 14:29:13 -07:00
										 |  |  |                 <td className="module-message-detail__label"> | 
					
						
							|  |  |  |                   {i18n('error')} | 
					
						
							|  |  |  |                 </td> | 
					
						
							|  |  |  |                 <td> | 
					
						
							|  |  |  |                   {' '} | 
					
						
							|  |  |  |                   <span className="error-message">{error.message}</span>{' '} | 
					
						
							|  |  |  |                 </td> | 
					
						
							|  |  |  |               </tr> | 
					
						
							|  |  |  |             ))} | 
					
						
							|  |  |  |             <tr> | 
					
						
							|  |  |  |               <td className="module-message-detail__label">{i18n('sent')}</td> | 
					
						
							|  |  |  |               <td> | 
					
						
							|  |  |  |                 {moment(sentAt).format('LLLL')}{' '} | 
					
						
							|  |  |  |                 <span className="module-message-detail__unix-timestamp"> | 
					
						
							|  |  |  |                   ({sentAt}) | 
					
						
							|  |  |  |                 </span> | 
					
						
							|  |  |  |               </td> | 
					
						
							|  |  |  |             </tr> | 
					
						
							|  |  |  |             {receivedAt ? ( | 
					
						
							|  |  |  |               <tr> | 
					
						
							|  |  |  |                 <td className="module-message-detail__label"> | 
					
						
							|  |  |  |                   {i18n('received')} | 
					
						
							|  |  |  |                 </td> | 
					
						
							|  |  |  |                 <td> | 
					
						
							|  |  |  |                   {moment(receivedAt).format('LLLL')}{' '} | 
					
						
							|  |  |  |                   <span className="module-message-detail__unix-timestamp"> | 
					
						
							|  |  |  |                     ({receivedAt}) | 
					
						
							|  |  |  |                   </span> | 
					
						
							|  |  |  |                 </td> | 
					
						
							|  |  |  |               </tr> | 
					
						
							|  |  |  |             ) : null} | 
					
						
							|  |  |  |           </tbody> | 
					
						
							|  |  |  |         </table> | 
					
						
							|  |  |  |         {this.renderContacts()} | 
					
						
							|  |  |  |       </div> | 
					
						
							|  |  |  |     ); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | } |