1
0
mirror of https://github.com/kremalicious/metamask-extension.git synced 2024-11-30 08:09:15 +01:00
metamask-extension/ui/pages/settings/contact-list-tab/add-contact/add-contact.component.js

163 lines
5.0 KiB
JavaScript

import React, { PureComponent } from 'react';
import PropTypes from 'prop-types';
import { debounce } from 'lodash';
import Identicon from '../../../../components/ui/identicon';
import TextField from '../../../../components/ui/text-field';
import { CONTACT_LIST_ROUTE } from '../../../../helpers/constants/routes';
import { isValidDomainName } from '../../../../helpers/utils/util';
import DomainInput from '../../../send/send-content/add-recipient/domain-input';
import PageContainerFooter from '../../../../components/ui/page-container/page-container-footer';
import {
isBurnAddress,
isValidHexAddress,
} from '../../../../../shared/modules/hexstring-utils';
import { INVALID_RECIPIENT_ADDRESS_ERROR } from '../../../send/send.constants';
export default class AddContact extends PureComponent {
static contextTypes = {
t: PropTypes.func,
};
static propTypes = {
addToAddressBook: PropTypes.func,
history: PropTypes.object,
scanQrCode: PropTypes.func,
qrCodeData:
PropTypes.object /* eslint-disable-line react/no-unused-prop-types */,
qrCodeDetected: PropTypes.func,
domainResolution: PropTypes.string,
domainError: PropTypes.string,
resetDomainResolution: PropTypes.func,
};
state = {
newName: '',
ethAddress: '',
error: '',
input: '',
};
constructor(props) {
super(props);
this.dValidate = debounce(this.validate, 500);
}
UNSAFE_componentWillReceiveProps(nextProps) {
if (nextProps.qrCodeData) {
if (nextProps.qrCodeData.type === 'address') {
const { domainResolution } = this.props;
const scannedAddress =
nextProps.qrCodeData.values.address.toLowerCase();
const currentAddress = domainResolution || this.state.ethAddress;
if (currentAddress.toLowerCase() !== scannedAddress) {
this.setState({ input: scannedAddress });
this.validate(scannedAddress);
// Clean up QR code data after handling
this.props.qrCodeDetected(null);
}
}
}
}
validate = (address) => {
const valid =
!isBurnAddress(address) &&
isValidHexAddress(address, { mixedCaseUseChecksum: true });
const validEnsAddress = isValidDomainName(address);
if (valid || validEnsAddress || address === '') {
this.setState({ error: '', ethAddress: address });
} else {
this.setState({ error: INVALID_RECIPIENT_ADDRESS_ERROR });
}
};
onChange = (input) => {
this.setState({ input });
this.dValidate(input);
};
renderInput() {
return (
<DomainInput
scanQrCode={(_) => {
this.props.scanQrCode();
}}
onChange={this.onChange}
onPaste={(text) => {
this.setState({ input: text });
this.validate(text);
}}
onReset={() => {
this.props.resetDomainResolution();
this.setState({ ethAddress: '', input: '' });
}}
userInput={this.state.input}
/>
);
}
render() {
const { t } = this.context;
const { history, addToAddressBook, domainError, domainResolution } =
this.props;
const errorToRender = domainError || this.state.error;
return (
<div className="settings-page__content-row address-book__add-contact">
{domainResolution && (
<div className="address-book__view-contact__group">
<Identicon address={domainResolution} diameter={60} />
<div className="address-book__view-contact__group__value">
{domainResolution}
</div>
</div>
)}
<div className="address-book__add-contact__content">
<div className="address-book__view-contact__group">
<div className="address-book__view-contact__group__label">
{t('userName')}
</div>
<TextField
type="text"
id="nickname"
value={this.state.newName}
onChange={(e) => this.setState({ newName: e.target.value })}
fullWidth
margin="dense"
/>
</div>
<div className="address-book__view-contact__group">
<div className="address-book__view-contact__group__label">
{t('ethereumPublicAddress')}
</div>
{this.renderInput()}
{errorToRender && (
<div className="address-book__add-contact__error">
{t(errorToRender)}
</div>
)}
</div>
</div>
<PageContainerFooter
cancelText={this.context.t('cancel')}
disabled={Boolean(this.state.error || !this.state.ethAddress)}
onSubmit={async () => {
await addToAddressBook(
domainResolution || this.state.ethAddress,
this.state.newName,
);
history.push(CONTACT_LIST_ROUTE);
}}
onCancel={() => {
history.push(CONTACT_LIST_ROUTE);
}}
submitText={this.context.t('save')}
/>
</div>
);
}
}