remove EbeddedContact components
parent
02fb5783a4
commit
3d47d7d0e8
@ -0,0 +1,107 @@
|
|||||||
|
const { omit, compact, map } = require('lodash');
|
||||||
|
|
||||||
|
const { toLogFormat } = require('./errors');
|
||||||
|
const { SignalService } = require('../../../ts/protobuf');
|
||||||
|
const { parse: parsePhoneNumber } = require('../../../ts/types/PhoneNumber');
|
||||||
|
|
||||||
|
const DEFAULT_PHONE_TYPE = SignalService.DataMessage.Contact.Phone.Type.HOME;
|
||||||
|
|
||||||
|
exports.parseAndWriteAvatar = upgradeAttachment => async (
|
||||||
|
contact,
|
||||||
|
context = {}
|
||||||
|
) => {
|
||||||
|
const { message, logger } = context;
|
||||||
|
const { avatar } = contact;
|
||||||
|
|
||||||
|
// This is to ensure that an omit() call doesn't pull in prototype props/methods
|
||||||
|
const contactShallowCopy = Object.assign({}, contact);
|
||||||
|
|
||||||
|
const contactWithUpdatedAvatar =
|
||||||
|
avatar && avatar.avatar
|
||||||
|
? Object.assign({}, contactShallowCopy, {
|
||||||
|
avatar: Object.assign({}, avatar, {
|
||||||
|
avatar: await upgradeAttachment(avatar.avatar, context),
|
||||||
|
}),
|
||||||
|
})
|
||||||
|
: omit(contactShallowCopy, ['avatar']);
|
||||||
|
|
||||||
|
// eliminates empty numbers, emails, and addresses; adds type if not provided
|
||||||
|
const parsedContact = parseContact(contactWithUpdatedAvatar);
|
||||||
|
|
||||||
|
const error = exports._validate(parsedContact, {
|
||||||
|
messageId: idForLogging(message),
|
||||||
|
});
|
||||||
|
if (error) {
|
||||||
|
logger.error(
|
||||||
|
'Contact.parseAndWriteAvatar: contact was malformed.',
|
||||||
|
toLogFormat(error)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return parsedContact;
|
||||||
|
};
|
||||||
|
|
||||||
|
function parseContact(contact) {
|
||||||
|
const boundParsePhone = phoneNumber => parsePhoneItem(phoneNumber);
|
||||||
|
|
||||||
|
return Object.assign(
|
||||||
|
{},
|
||||||
|
omit(contact, ['avatar', 'number', 'email', 'address']),
|
||||||
|
parseAvatar(contact.avatar),
|
||||||
|
createArrayKey('number', compact(map(contact.number, boundParsePhone)))
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
function idForLogging(message) {
|
||||||
|
return `${message.source}.${message.sourceDevice} ${message.sent_at}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
exports._validate = (contact, options = {}) => {
|
||||||
|
const { messageId } = options;
|
||||||
|
const { name, number, organization } = contact;
|
||||||
|
|
||||||
|
if ((!name || !name.displayName) && !organization) {
|
||||||
|
return new Error(
|
||||||
|
`Message ${messageId}: Contact had neither 'displayName' nor 'organization'`
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!number || !number.length) {
|
||||||
|
return new Error(`Message ${messageId}: Contact had no included numbers`);
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
};
|
||||||
|
|
||||||
|
function parsePhoneItem(item) {
|
||||||
|
if (!item.value) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return Object.assign({}, item, {
|
||||||
|
type: item.type || DEFAULT_PHONE_TYPE,
|
||||||
|
value: parsePhoneNumber(item.value),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function parseAvatar(avatar) {
|
||||||
|
if (!avatar) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
avatar: Object.assign({}, avatar, {
|
||||||
|
isProfile: avatar.isProfile || false,
|
||||||
|
}),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
function createArrayKey(key, array) {
|
||||||
|
if (!array || !array.length) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
[key]: array,
|
||||||
|
};
|
||||||
|
}
|
@ -1,57 +0,0 @@
|
|||||||
import React from 'react';
|
|
||||||
import classNames from 'classnames';
|
|
||||||
|
|
||||||
import { Contact } from '../../types/Contact';
|
|
||||||
|
|
||||||
import { LocalizerType } from '../../types/Util';
|
|
||||||
import {
|
|
||||||
renderAvatar,
|
|
||||||
renderContactShorthand,
|
|
||||||
renderName,
|
|
||||||
} from './_contactUtil';
|
|
||||||
|
|
||||||
interface Props {
|
|
||||||
contact: Contact;
|
|
||||||
i18n: LocalizerType;
|
|
||||||
isIncoming: boolean;
|
|
||||||
withContentAbove: boolean;
|
|
||||||
withContentBelow: boolean;
|
|
||||||
onClick?: () => void;
|
|
||||||
}
|
|
||||||
|
|
||||||
export class EmbeddedContact extends React.Component<Props> {
|
|
||||||
public render() {
|
|
||||||
const {
|
|
||||||
contact,
|
|
||||||
i18n,
|
|
||||||
isIncoming,
|
|
||||||
onClick,
|
|
||||||
withContentAbove,
|
|
||||||
withContentBelow,
|
|
||||||
} = this.props;
|
|
||||||
const module = 'embedded-contact';
|
|
||||||
const direction = isIncoming ? 'incoming' : 'outgoing';
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div
|
|
||||||
className={classNames(
|
|
||||||
'module-embedded-contact',
|
|
||||||
withContentAbove
|
|
||||||
? 'module-embedded-contact--with-content-above'
|
|
||||||
: null,
|
|
||||||
withContentBelow
|
|
||||||
? 'module-embedded-contact--with-content-below'
|
|
||||||
: null
|
|
||||||
)}
|
|
||||||
role="button"
|
|
||||||
onClick={onClick}
|
|
||||||
>
|
|
||||||
{renderAvatar({ contact, i18n, size: 36, direction })}
|
|
||||||
<div className="module-embedded-contact__text-container">
|
|
||||||
{renderName({ contact, isIncoming, module })}
|
|
||||||
{renderContactShorthand({ contact, isIncoming, module })}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,88 +0,0 @@
|
|||||||
import React from 'react';
|
|
||||||
import classNames from 'classnames';
|
|
||||||
|
|
||||||
import { Avatar } from '../Avatar';
|
|
||||||
import { Spinner } from '../Spinner';
|
|
||||||
|
|
||||||
import { LocalizerType } from '../../types/Util';
|
|
||||||
import { Contact, getName } from '../../types/Contact';
|
|
||||||
|
|
||||||
// This file starts with _ to keep it from showing up in the StyleGuide.
|
|
||||||
|
|
||||||
export function renderAvatar({
|
|
||||||
contact,
|
|
||||||
i18n,
|
|
||||||
size,
|
|
||||||
direction,
|
|
||||||
}: {
|
|
||||||
contact: Contact;
|
|
||||||
i18n: LocalizerType;
|
|
||||||
size: number;
|
|
||||||
direction?: string;
|
|
||||||
}) {
|
|
||||||
const { avatar } = contact;
|
|
||||||
|
|
||||||
const avatarPath = avatar && avatar.avatar && avatar.avatar.path;
|
|
||||||
const pending = avatar && avatar.avatar && avatar.avatar.pending;
|
|
||||||
const name = getName(contact) || '';
|
|
||||||
const spinnerSize = size < 50 ? 'small' : 'normal';
|
|
||||||
|
|
||||||
if (pending) {
|
|
||||||
return (
|
|
||||||
<div className="module-embedded-contact__spinner-container">
|
|
||||||
<Spinner size={spinnerSize} direction={direction} />
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
const pubkey = contact.name?.givenName || '0';
|
|
||||||
return (
|
|
||||||
<Avatar avatarPath={avatarPath} name={name} size={size} pubkey={pubkey} />
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
export function renderName({
|
|
||||||
contact,
|
|
||||||
isIncoming,
|
|
||||||
module,
|
|
||||||
}: {
|
|
||||||
contact: Contact;
|
|
||||||
isIncoming: boolean;
|
|
||||||
module: string;
|
|
||||||
}) {
|
|
||||||
return (
|
|
||||||
<div
|
|
||||||
className={classNames(
|
|
||||||
`module-${module}__contact-name`,
|
|
||||||
isIncoming ? `module-${module}__contact-name--incoming` : null
|
|
||||||
)}
|
|
||||||
>
|
|
||||||
{getName(contact)}
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
export function renderContactShorthand({
|
|
||||||
contact,
|
|
||||||
isIncoming,
|
|
||||||
module,
|
|
||||||
}: {
|
|
||||||
contact: Contact;
|
|
||||||
isIncoming: boolean;
|
|
||||||
module: string;
|
|
||||||
}) {
|
|
||||||
const { number: phoneNumber, email } = contact;
|
|
||||||
const firstNumber = phoneNumber && phoneNumber[0] && phoneNumber[0].value;
|
|
||||||
const firstEmail = email && email[0] && email[0].value;
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div
|
|
||||||
className={classNames(
|
|
||||||
`module-${module}__contact-method`,
|
|
||||||
isIncoming ? `module-${module}__contact-method--incoming` : null
|
|
||||||
)}
|
|
||||||
>
|
|
||||||
{firstNumber || firstEmail}
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
Loading…
Reference in New Issue