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