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.
		
		
		
		
		
			
		
			
				
	
	
		
			210 lines
		
	
	
		
			5.7 KiB
		
	
	
	
		
			TypeScript
		
	
			
		
		
	
	
			210 lines
		
	
	
		
			5.7 KiB
		
	
	
	
		
			TypeScript
		
	
import React from 'react';
 | 
						|
import classNames from 'classnames';
 | 
						|
import moment from 'moment';
 | 
						|
 | 
						|
import { ContactName } from './ContactName';
 | 
						|
import { Message, Props as MessageProps } from './Message';
 | 
						|
import { Localizer } from '../../types/Util';
 | 
						|
 | 
						|
interface Contact {
 | 
						|
  status: string;
 | 
						|
  phoneNumber: string;
 | 
						|
  name?: string;
 | 
						|
  profileName?: string;
 | 
						|
  avatarPath?: string;
 | 
						|
  color: string;
 | 
						|
  isOutgoingKeyError: boolean;
 | 
						|
 | 
						|
  errors?: Array<Error>;
 | 
						|
  onSendAnyway: () => void;
 | 
						|
  onShowSafetyNumber: () => void;
 | 
						|
}
 | 
						|
 | 
						|
interface Props {
 | 
						|
  sentAt: number;
 | 
						|
  receivedAt: number;
 | 
						|
 | 
						|
  message: MessageProps;
 | 
						|
  errors: Array<Error>;
 | 
						|
  contacts: Array<Contact>;
 | 
						|
 | 
						|
  i18n: Localizer;
 | 
						|
}
 | 
						|
 | 
						|
function getInitial(name: string): string {
 | 
						|
  return name.trim()[0] || '#';
 | 
						|
}
 | 
						|
 | 
						|
export class MessageDetail extends React.Component<Props> {
 | 
						|
  public renderAvatar(contact: Contact) {
 | 
						|
    const { i18n } = this.props;
 | 
						|
    const { avatarPath, color, phoneNumber, name, profileName } = contact;
 | 
						|
 | 
						|
    if (!avatarPath) {
 | 
						|
      const initial = getInitial(name || '');
 | 
						|
 | 
						|
      return (
 | 
						|
        <div
 | 
						|
          className={classNames(
 | 
						|
            'module-message-detail__contact__avatar',
 | 
						|
            'module-message-detail__contact__default-avatar',
 | 
						|
            `module-message-detail__contact__default-avatar--${color}`
 | 
						|
          )}
 | 
						|
        >
 | 
						|
          {initial}
 | 
						|
        </div>
 | 
						|
      );
 | 
						|
    }
 | 
						|
 | 
						|
    const title = `${name || phoneNumber}${
 | 
						|
      !name && profileName ? ` ~${profileName}` : ''
 | 
						|
    }`;
 | 
						|
 | 
						|
    return (
 | 
						|
      <img
 | 
						|
        className="module-message-detail__contact__avatar"
 | 
						|
        alt={i18n('contactAvatarAlt', [title])}
 | 
						|
        src={avatarPath}
 | 
						|
      />
 | 
						|
    );
 | 
						|
  }
 | 
						|
 | 
						|
  public renderDeleteButton() {
 | 
						|
    const { i18n, message } = this.props;
 | 
						|
 | 
						|
    return (
 | 
						|
      <div className="module-message-detail__delete-button-container">
 | 
						|
        <button
 | 
						|
          onClick={message.onDelete}
 | 
						|
          className="module-message-detail__delete-button"
 | 
						|
        >
 | 
						|
          {i18n('deleteThisMessage')}
 | 
						|
        </button>
 | 
						|
      </div>
 | 
						|
    );
 | 
						|
  }
 | 
						|
 | 
						|
  public renderContact(contact: Contact) {
 | 
						|
    const { i18n } = this.props;
 | 
						|
    const errors = contact.errors || [];
 | 
						|
 | 
						|
    const errorComponent = contact.isOutgoingKeyError ? (
 | 
						|
      <div className="module-message-detail__contact__error-buttons">
 | 
						|
        <button
 | 
						|
          className="module-message-detail__contact__show-safety-number"
 | 
						|
          onClick={contact.onShowSafetyNumber}
 | 
						|
        >
 | 
						|
          {i18n('showSafetyNumber')}
 | 
						|
        </button>
 | 
						|
        <button
 | 
						|
          className="module-message-detail__contact__send-anyway"
 | 
						|
          onClick={contact.onSendAnyway}
 | 
						|
        >
 | 
						|
          {i18n('sendAnyway')}
 | 
						|
        </button>
 | 
						|
      </div>
 | 
						|
    ) : null;
 | 
						|
    const statusComponent = !contact.isOutgoingKeyError ? (
 | 
						|
      <div
 | 
						|
        className={classNames(
 | 
						|
          'module-message-detail__contact__status-icon',
 | 
						|
          `module-message-detail__contact__status-icon--${contact.status}`
 | 
						|
        )}
 | 
						|
      />
 | 
						|
    ) : null;
 | 
						|
 | 
						|
    return (
 | 
						|
      <div key={contact.phoneNumber} className="module-message-detail__contact">
 | 
						|
        {this.renderAvatar(contact)}
 | 
						|
        <div className="module-message-detail__contact__text">
 | 
						|
          <div className="module-message-detail__contact__name">
 | 
						|
            <ContactName
 | 
						|
              phoneNumber={contact.phoneNumber}
 | 
						|
              name={contact.name}
 | 
						|
              profileName={contact.profileName}
 | 
						|
              i18n={i18n}
 | 
						|
            />
 | 
						|
          </div>
 | 
						|
          {errors.map((error, index) => (
 | 
						|
            <div key={index} className="module-message-detail__contact__error">
 | 
						|
              {error.message}
 | 
						|
            </div>
 | 
						|
          ))}
 | 
						|
        </div>
 | 
						|
        {errorComponent}
 | 
						|
        {statusComponent}
 | 
						|
      </div>
 | 
						|
    );
 | 
						|
  }
 | 
						|
 | 
						|
  public renderContacts() {
 | 
						|
    const { contacts } = this.props;
 | 
						|
 | 
						|
    if (!contacts || !contacts.length) {
 | 
						|
      return null;
 | 
						|
    }
 | 
						|
 | 
						|
    return (
 | 
						|
      <div className="module-message-detail__contact-container">
 | 
						|
        {contacts.map(contact => this.renderContact(contact))}
 | 
						|
      </div>
 | 
						|
    );
 | 
						|
  }
 | 
						|
 | 
						|
  public render() {
 | 
						|
    const { errors, message, receivedAt, sentAt, i18n } = this.props;
 | 
						|
 | 
						|
    return (
 | 
						|
      <div className="module-message-detail">
 | 
						|
        <div className="module-message-detail__message-container">
 | 
						|
          <Message i18n={i18n} {...message} />
 | 
						|
        </div>
 | 
						|
        <table className="module-message-detail__info">
 | 
						|
          <tbody>
 | 
						|
            {(errors || []).map((error, index) => (
 | 
						|
              <tr key={index}>
 | 
						|
                <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}
 | 
						|
            <tr>
 | 
						|
              <td className="module-message-detail__label">
 | 
						|
                {message.direction === 'incoming' ? i18n('from') : i18n('to')}
 | 
						|
              </td>
 | 
						|
            </tr>
 | 
						|
          </tbody>
 | 
						|
        </table>
 | 
						|
        {this.renderContacts()}
 | 
						|
        {this.renderDeleteButton()}
 | 
						|
      </div>
 | 
						|
    );
 | 
						|
  }
 | 
						|
}
 |