1
0
mirror of https://github.com/kremalicious/metamask-extension.git synced 2024-11-28 23:06:37 +01:00
metamask-extension/ui/app/pages/send/send-content/add-recipient/add-recipient.component.js
Mark Stacey 0f7e2dbf20
Show warnings on Add Recipient page of Send flow (#10530)
Warnings were not shown on the Add Recipient page of the send flow. Now
any send warnings will be shown. This can be tested using an ENS name
with a confusable character in it (the confusable character warning
will be shown).

A condition was also removed that prevented any warnings or errors from
rendering when the user had non-zero contacts or recent addresses. I
have no idea why you'd want to hide warnings or errors if the user had
no contacts or recent addresses. None of these errors even pertain to
contacts or recent addresses.
2021-03-01 09:47:22 -03:30

247 lines
6.5 KiB
JavaScript

import React, { Component } from 'react';
import PropTypes from 'prop-types';
import Fuse from 'fuse.js';
import Identicon from '../../../../components/ui/identicon';
import { isValidAddress } from '../../../../helpers/utils/util';
import Dialog from '../../../../components/ui/dialog';
import ContactList from '../../../../components/app/contact-list';
import RecipientGroup from '../../../../components/app/contact-list/recipient-group/recipient-group.component';
import { ellipsify } from '../../send.utils';
import Button from '../../../../components/ui/button';
import Confusable from '../../../../components/ui/confusable';
export default class AddRecipient extends Component {
static propTypes = {
query: PropTypes.string,
ownedAccounts: PropTypes.array,
addressBook: PropTypes.array,
updateGas: PropTypes.func,
updateSendTo: PropTypes.func,
ensResolution: PropTypes.string,
toError: PropTypes.string,
toWarning: PropTypes.string,
ensResolutionError: PropTypes.string,
addressBookEntryName: PropTypes.string,
contacts: PropTypes.array,
nonContacts: PropTypes.array,
setInternalSearch: PropTypes.func,
};
constructor(props) {
super(props);
this.recentFuse = new Fuse(props.nonContacts, {
shouldSort: true,
threshold: 0.45,
location: 0,
distance: 100,
maxPatternLength: 32,
minMatchCharLength: 1,
keys: [{ name: 'address', weight: 0.5 }],
});
this.contactFuse = new Fuse(props.contacts, {
shouldSort: true,
threshold: 0.45,
location: 0,
distance: 100,
maxPatternLength: 32,
minMatchCharLength: 1,
keys: [
{ name: 'name', weight: 0.5 },
{ name: 'address', weight: 0.5 },
],
});
}
static contextTypes = {
t: PropTypes.func,
metricsEvent: PropTypes.func,
};
state = {
isShowingTransfer: false,
};
selectRecipient = (to, nickname = '') => {
const { updateSendTo, updateGas } = this.props;
updateSendTo(to, nickname);
updateGas({ to });
};
searchForContacts = () => {
const { query, contacts } = this.props;
let _contacts = contacts;
if (query) {
this.contactFuse.setCollection(contacts);
_contacts = this.contactFuse.search(query);
}
return _contacts;
};
searchForRecents = () => {
const { query, nonContacts } = this.props;
let _nonContacts = nonContacts;
if (query) {
this.recentFuse.setCollection(nonContacts);
_nonContacts = this.recentFuse.search(query);
}
return _nonContacts;
};
render() {
const { ensResolution, query, addressBookEntryName } = this.props;
const { isShowingTransfer } = this.state;
let content;
if (isValidAddress(query)) {
content = this.renderExplicitAddress(query);
} else if (ensResolution) {
content = this.renderExplicitAddress(
ensResolution,
addressBookEntryName || query,
);
} else if (isShowingTransfer) {
content = this.renderTransfer();
}
return (
<div className="send__select-recipient-wrapper">
{this.renderDialogs()}
{content || this.renderMain()}
</div>
);
}
renderExplicitAddress(address, name) {
return (
<div
key={address}
className="send__select-recipient-wrapper__group-item"
onClick={() => this.selectRecipient(address, name)}
>
<Identicon address={address} diameter={28} />
<div className="send__select-recipient-wrapper__group-item__content">
<div className="send__select-recipient-wrapper__group-item__title">
{name ? <Confusable input={name} /> : ellipsify(address)}
</div>
{name && (
<div className="send__select-recipient-wrapper__group-item__subtitle">
{ellipsify(address)}
</div>
)}
</div>
</div>
);
}
renderTransfer() {
let { ownedAccounts } = this.props;
const { query, setInternalSearch } = this.props;
const { t } = this.context;
const { isShowingTransfer } = this.state;
if (isShowingTransfer && query) {
ownedAccounts = ownedAccounts.filter(
(item) =>
item.name.toLowerCase().indexOf(query.toLowerCase()) > -1 ||
item.address.toLowerCase().indexOf(query.toLowerCase()) > -1,
);
}
return (
<div className="send__select-recipient-wrapper__list">
<Button
type="link"
className="send__select-recipient-wrapper__list__link"
onClick={() => {
setInternalSearch(false);
this.setState({ isShowingTransfer: false });
}}
>
<div className="send__select-recipient-wrapper__list__back-caret" />
{t('backToAll')}
</Button>
<RecipientGroup
label={t('myAccounts')}
items={ownedAccounts}
onSelect={this.selectRecipient}
/>
</div>
);
}
renderMain() {
const { t } = this.context;
const {
query,
ownedAccounts = [],
addressBook,
setInternalSearch,
} = this.props;
return (
<div className="send__select-recipient-wrapper__list">
<ContactList
addressBook={addressBook}
searchForContacts={this.searchForContacts.bind(this)}
searchForRecents={this.searchForRecents.bind(this)}
selectRecipient={this.selectRecipient.bind(this)}
>
{ownedAccounts && ownedAccounts.length > 1 && !query && (
<Button
type="link"
className="send__select-recipient-wrapper__list__link"
onClick={() => {
setInternalSearch(true);
this.setState({ isShowingTransfer: true });
}}
>
{t('transferBetweenAccounts')}
</Button>
)}
</ContactList>
</div>
);
}
renderDialogs() {
const {
toError,
toWarning,
ensResolutionError,
ensResolution,
} = this.props;
const { t } = this.context;
if (ensResolutionError) {
return (
<Dialog type="error" className="send__error-dialog">
{ensResolutionError}
</Dialog>
);
} else if (toError && toError !== 'required' && !ensResolution) {
return (
<Dialog type="error" className="send__error-dialog">
{t(toError)}
</Dialog>
);
} else if (toWarning) {
return (
<Dialog type="warning" className="send__error-dialog">
{t(toWarning)}
</Dialog>
);
}
return null;
}
}