2021-02-04 19:15:23 +01:00
|
|
|
import React, { Component } from 'react';
|
|
|
|
import PropTypes from 'prop-types';
|
|
|
|
import classnames from 'classnames';
|
|
|
|
|
2022-06-28 18:51:09 +02:00
|
|
|
import { addHexPrefix } from '../../../../../app/scripts/lib/util';
|
2021-05-17 21:00:59 +02:00
|
|
|
import { isValidDomainName } from '../../../../helpers/utils/util';
|
|
|
|
import {
|
|
|
|
isBurnAddress,
|
|
|
|
isValidHexAddress,
|
|
|
|
} from '../../../../../shared/modules/hexstring-utils';
|
2023-01-31 15:47:23 +01:00
|
|
|
import {
|
|
|
|
ButtonIcon,
|
|
|
|
ICON_NAMES,
|
|
|
|
} from '../../../../components/component-library';
|
2023-02-02 21:15:26 +01:00
|
|
|
import { IconColor } from '../../../../helpers/constants/design-system';
|
2019-07-31 21:56:44 +02:00
|
|
|
|
2022-11-21 16:19:11 +01:00
|
|
|
export default class DomainInput extends Component {
|
2019-07-31 21:56:44 +02:00
|
|
|
static contextTypes = {
|
|
|
|
t: PropTypes.func,
|
2021-06-23 23:35:25 +02:00
|
|
|
metricsEvent: PropTypes.func,
|
2021-02-04 19:15:23 +01:00
|
|
|
};
|
2019-07-31 21:56:44 +02:00
|
|
|
|
|
|
|
static propTypes = {
|
|
|
|
className: PropTypes.string,
|
|
|
|
selectedAddress: PropTypes.string,
|
|
|
|
selectedName: PropTypes.string,
|
|
|
|
scanQrCode: PropTypes.func,
|
|
|
|
onPaste: PropTypes.func,
|
2019-08-03 01:00:50 +02:00
|
|
|
onValidAddressTyped: PropTypes.func,
|
2020-11-07 00:16:51 +01:00
|
|
|
internalSearch: PropTypes.bool,
|
2021-06-23 23:35:25 +02:00
|
|
|
userInput: PropTypes.string,
|
|
|
|
onChange: PropTypes.func.isRequired,
|
|
|
|
onReset: PropTypes.func.isRequired,
|
|
|
|
lookupEnsName: PropTypes.func.isRequired,
|
2022-11-21 16:19:11 +01:00
|
|
|
initializeDomainSlice: PropTypes.func.isRequired,
|
|
|
|
resetDomainResolution: PropTypes.func.isRequired,
|
2021-02-04 19:15:23 +01:00
|
|
|
};
|
2019-07-31 21:56:44 +02:00
|
|
|
|
2020-11-03 00:41:28 +01:00
|
|
|
componentDidMount() {
|
2022-11-21 16:19:11 +01:00
|
|
|
this.props.initializeDomainSlice();
|
2019-07-31 21:56:44 +02:00
|
|
|
}
|
|
|
|
|
2020-02-15 21:34:12 +01:00
|
|
|
onPaste = (event) => {
|
2021-08-13 00:30:07 +02:00
|
|
|
if (event.clipboardData.items?.length) {
|
|
|
|
const clipboardItem = event.clipboardData.items[0];
|
|
|
|
clipboardItem?.getAsString((text) => {
|
|
|
|
const input = text.trim();
|
|
|
|
if (
|
|
|
|
!isBurnAddress(input) &&
|
|
|
|
isValidHexAddress(input, { mixedCaseUseChecksum: true })
|
|
|
|
) {
|
2022-06-28 18:51:09 +02:00
|
|
|
this.props.onPaste(addHexPrefix(input));
|
2021-08-13 00:30:07 +02:00
|
|
|
}
|
|
|
|
});
|
|
|
|
}
|
2021-02-04 19:15:23 +01:00
|
|
|
};
|
2019-07-31 21:56:44 +02:00
|
|
|
|
2021-07-27 16:53:13 +02:00
|
|
|
onChange = ({ target: { value } }) => {
|
2020-11-03 00:41:28 +01:00
|
|
|
const {
|
|
|
|
onValidAddressTyped,
|
2020-11-07 00:16:51 +01:00
|
|
|
internalSearch,
|
2021-06-23 23:35:25 +02:00
|
|
|
onChange,
|
|
|
|
lookupEnsName,
|
2022-11-21 16:19:11 +01:00
|
|
|
resetDomainResolution,
|
2021-02-04 19:15:23 +01:00
|
|
|
} = this.props;
|
2021-07-27 16:53:13 +02:00
|
|
|
const input = value.trim();
|
2019-07-31 21:56:44 +02:00
|
|
|
|
2021-06-23 23:35:25 +02:00
|
|
|
onChange(input);
|
2020-11-07 00:16:51 +01:00
|
|
|
if (internalSearch) {
|
2021-02-04 19:15:23 +01:00
|
|
|
return null;
|
2020-11-07 00:16:51 +01:00
|
|
|
}
|
2019-07-31 21:56:44 +02:00
|
|
|
// Empty ENS state if input is empty
|
|
|
|
// maybe scan ENS
|
2020-02-18 02:20:01 +01:00
|
|
|
if (isValidDomainName(input)) {
|
2021-06-23 23:35:25 +02:00
|
|
|
lookupEnsName(input);
|
2019-07-31 21:56:44 +02:00
|
|
|
} else {
|
2022-11-21 16:19:11 +01:00
|
|
|
resetDomainResolution();
|
2021-07-09 16:17:02 +02:00
|
|
|
if (
|
|
|
|
onValidAddressTyped &&
|
|
|
|
!isBurnAddress(input) &&
|
|
|
|
isValidHexAddress(input, { mixedCaseUseChecksum: true })
|
|
|
|
) {
|
2022-06-28 18:51:09 +02:00
|
|
|
onValidAddressTyped(addHexPrefix(input));
|
2021-07-09 16:17:02 +02:00
|
|
|
}
|
2019-07-31 21:56:44 +02:00
|
|
|
}
|
2021-07-09 16:17:02 +02:00
|
|
|
|
2021-02-04 19:15:23 +01:00
|
|
|
return null;
|
|
|
|
};
|
2019-07-31 21:56:44 +02:00
|
|
|
|
2020-11-03 00:41:28 +01:00
|
|
|
render() {
|
2021-02-04 19:15:23 +01:00
|
|
|
const { t } = this.context;
|
2021-06-23 23:35:25 +02:00
|
|
|
const { className, selectedAddress, selectedName, userInput } = this.props;
|
2019-07-31 21:56:44 +02:00
|
|
|
|
2021-06-23 23:35:25 +02:00
|
|
|
const hasSelectedAddress = Boolean(selectedAddress);
|
2019-07-31 21:56:44 +02:00
|
|
|
|
|
|
|
return (
|
2020-03-01 11:14:16 +01:00
|
|
|
<div className={classnames('ens-input', className)}>
|
2019-07-31 21:56:44 +02:00
|
|
|
<div
|
2020-03-01 11:14:16 +01:00
|
|
|
className={classnames('ens-input__wrapper', {
|
2019-07-31 21:56:44 +02:00
|
|
|
'ens-input__wrapper__status-icon--error': false,
|
|
|
|
'ens-input__wrapper__status-icon--valid': false,
|
2021-06-23 23:35:25 +02:00
|
|
|
'ens-input__wrapper--valid': hasSelectedAddress,
|
2019-07-31 21:56:44 +02:00
|
|
|
})}
|
|
|
|
>
|
2022-03-23 16:45:52 +01:00
|
|
|
<i
|
|
|
|
className={classnames('ens-input__wrapper__status-icon', 'fa', {
|
|
|
|
'fa-check-circle': hasSelectedAddress,
|
|
|
|
'fa-search': !hasSelectedAddress,
|
2019-07-31 21:56:44 +02:00
|
|
|
})}
|
2022-03-23 16:45:52 +01:00
|
|
|
style={{
|
|
|
|
color: hasSelectedAddress
|
|
|
|
? 'var(--color-success-default)'
|
|
|
|
: 'var(--color-icon-muted)',
|
|
|
|
}}
|
2019-07-31 21:56:44 +02:00
|
|
|
/>
|
2021-06-23 23:35:25 +02:00
|
|
|
{hasSelectedAddress ? (
|
|
|
|
<>
|
|
|
|
<div className="ens-input__wrapper__input ens-input__wrapper__input--selected">
|
|
|
|
<div className="ens-input__selected-input__title">
|
2021-11-04 07:58:32 +01:00
|
|
|
{selectedName || selectedAddress}
|
2021-06-23 23:35:25 +02:00
|
|
|
</div>
|
2021-11-04 07:58:32 +01:00
|
|
|
{selectedName !== selectedAddress && (
|
2021-06-23 23:35:25 +02:00
|
|
|
<div className="ens-input__selected-input__subtitle">
|
|
|
|
{selectedAddress}
|
|
|
|
</div>
|
|
|
|
)}
|
2020-11-03 00:41:28 +01:00
|
|
|
</div>
|
2022-03-23 16:45:52 +01:00
|
|
|
<button
|
2021-06-23 23:35:25 +02:00
|
|
|
onClick={this.props.onReset}
|
2022-03-23 16:45:52 +01:00
|
|
|
className="ens-input__wrapper__action-icon-button"
|
|
|
|
>
|
|
|
|
<i
|
|
|
|
className="fa fa-times"
|
|
|
|
style={{
|
|
|
|
color: 'var(--color-icon-default)',
|
|
|
|
}}
|
|
|
|
title={t('close')}
|
|
|
|
/>
|
|
|
|
</button>
|
2021-06-23 23:35:25 +02:00
|
|
|
</>
|
|
|
|
) : (
|
|
|
|
<>
|
|
|
|
<input
|
|
|
|
className="ens-input__wrapper__input"
|
|
|
|
type="text"
|
|
|
|
dir="auto"
|
|
|
|
placeholder={t('recipientAddressPlaceholder')}
|
|
|
|
onChange={this.onChange}
|
|
|
|
onPaste={this.onPaste}
|
2021-08-29 04:16:19 +02:00
|
|
|
spellCheck="false"
|
2021-06-23 23:35:25 +02:00
|
|
|
value={selectedAddress || userInput}
|
|
|
|
autoFocus
|
|
|
|
data-testid="ens-input"
|
|
|
|
/>
|
2023-01-31 15:47:23 +01:00
|
|
|
<ButtonIcon
|
2022-03-23 16:45:52 +01:00
|
|
|
className="ens-input__wrapper__action-icon-button"
|
2021-06-23 23:35:25 +02:00
|
|
|
onClick={() => {
|
|
|
|
if (userInput) {
|
|
|
|
this.props.onReset();
|
|
|
|
} else {
|
|
|
|
this.props.scanQrCode();
|
|
|
|
}
|
|
|
|
}}
|
2023-01-31 15:47:23 +01:00
|
|
|
iconName={
|
|
|
|
userInput ? ICON_NAMES.CLOSE : ICON_NAMES.SCAN_BARCODE
|
|
|
|
}
|
|
|
|
ariaLabel={t(userInput ? 'close' : 'scanQrCode')}
|
2023-02-02 21:15:26 +01:00
|
|
|
color={
|
|
|
|
userInput ? IconColor.iconDefault : IconColor.primaryDefault
|
|
|
|
}
|
2023-01-31 15:47:23 +01:00
|
|
|
/>
|
2021-06-23 23:35:25 +02:00
|
|
|
</>
|
|
|
|
)}
|
2019-07-31 21:56:44 +02:00
|
|
|
</div>
|
|
|
|
</div>
|
2021-02-04 19:15:23 +01:00
|
|
|
);
|
2019-07-31 21:56:44 +02:00
|
|
|
}
|
|
|
|
}
|