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.
149 lines
4.7 KiB
TypeScript
149 lines
4.7 KiB
TypeScript
import React from 'react';
|
|
import classNames from 'classnames';
|
|
import moment from 'moment';
|
|
|
|
import { Avatar, AvatarSize } from '../Avatar';
|
|
import { ContactName } from './ContactName';
|
|
import { Message } from './Message';
|
|
import { useSelector } from 'react-redux';
|
|
import { ContactPropsMessageDetail } from '../../state/ducks/conversations';
|
|
import {
|
|
getMessageDetailsViewProps,
|
|
getMessageIsDeletable,
|
|
} from '../../state/selectors/conversations';
|
|
import { deleteMessagesById } from '../../interactions/conversations/unsendingInteractions';
|
|
|
|
const AvatarItem = (props: { contact: ContactPropsMessageDetail }) => {
|
|
const { avatarPath, pubkey, name, profileName } = props.contact;
|
|
const userName = name || profileName || pubkey;
|
|
|
|
return <Avatar avatarPath={avatarPath} name={userName} size={AvatarSize.S} pubkey={pubkey} />;
|
|
};
|
|
|
|
const DeleteButtonItem = (props: { messageId: string; convoId: string; isDeletable: boolean }) => {
|
|
const { i18n } = window;
|
|
|
|
return props.isDeletable ? (
|
|
<div className="module-message-detail__delete-button-container">
|
|
<button
|
|
onClick={async () => {
|
|
await deleteMessagesById([props.messageId], props.convoId);
|
|
}}
|
|
className="module-message-detail__delete-button"
|
|
>
|
|
{i18n('delete')}
|
|
</button>
|
|
</div>
|
|
) : null;
|
|
};
|
|
|
|
const ContactsItem = (props: { contacts: Array<ContactPropsMessageDetail> }) => {
|
|
const { contacts } = props;
|
|
|
|
if (!contacts || !contacts.length) {
|
|
return null;
|
|
}
|
|
|
|
return (
|
|
<div className="module-message-detail__contact-container">
|
|
{contacts.map(contact => (
|
|
<ContactItem key={contact.pubkey} contact={contact} />
|
|
))}
|
|
</div>
|
|
);
|
|
};
|
|
|
|
const ContactItem = (props: { contact: ContactPropsMessageDetail }) => {
|
|
const { contact } = props;
|
|
const errors = contact.errors || [];
|
|
|
|
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.pubkey} className="module-message-detail__contact">
|
|
<AvatarItem contact={contact} />
|
|
<div className="module-message-detail__contact__text">
|
|
<div className="module-message-detail__contact__name">
|
|
<ContactName
|
|
pubkey={contact.pubkey}
|
|
name={contact.name}
|
|
profileName={contact.profileName}
|
|
shouldShowPubkey={true}
|
|
/>
|
|
</div>
|
|
{errors.map((error, index) => (
|
|
<div key={index} className="module-message-detail__contact__error">
|
|
{error.message}
|
|
</div>
|
|
))}
|
|
</div>
|
|
{statusComponent}
|
|
</div>
|
|
);
|
|
};
|
|
|
|
export const MessageDetail = () => {
|
|
const { i18n } = window;
|
|
|
|
const messageDetailProps = useSelector(getMessageDetailsViewProps);
|
|
const isDeletable = useSelector(state =>
|
|
getMessageIsDeletable(state as any, messageDetailProps?.messageId || '')
|
|
);
|
|
if (!messageDetailProps) {
|
|
return null;
|
|
}
|
|
|
|
const { errors, receivedAt, sentAt, convoId, direction, messageId } = messageDetailProps;
|
|
|
|
return (
|
|
<div className="message-detail-wrapper">
|
|
<div className="module-message-detail">
|
|
<div className="module-message-detail__message-container">
|
|
<Message messageId={messageId} isDetailView={true} />
|
|
</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>({sentAt})</span>
|
|
</td>
|
|
</tr>
|
|
{receivedAt ? (
|
|
<tr>
|
|
<td className="module-message-detail__label">{i18n('received')}</td>
|
|
<td>
|
|
{moment(receivedAt).format('LLLL')} <span>({receivedAt})</span>
|
|
</td>
|
|
</tr>
|
|
) : null}
|
|
<tr>
|
|
<td className="module-message-detail__label">
|
|
{direction === 'incoming' ? i18n('from') : i18n('to')}
|
|
</td>
|
|
</tr>
|
|
</tbody>
|
|
</table>
|
|
<ContactsItem contacts={messageDetailProps.contacts} />
|
|
<DeleteButtonItem convoId={convoId} messageId={messageId} isDeletable={isDeletable} />
|
|
</div>
|
|
</div>
|
|
);
|
|
};
|