diff options
Diffstat (limited to 'ui/app/pages/settings/contact-list-tab/add-contact')
3 files changed, 162 insertions, 0 deletions
diff --git a/ui/app/pages/settings/contact-list-tab/add-contact/add-contact.component.js b/ui/app/pages/settings/contact-list-tab/add-contact/add-contact.component.js new file mode 100644 index 000000000..871b2128b --- /dev/null +++ b/ui/app/pages/settings/contact-list-tab/add-contact/add-contact.component.js @@ -0,0 +1,131 @@ +import React, { PureComponent } from 'react' +import PropTypes from 'prop-types' +import Identicon from '../../../../components/ui/identicon' +import TextField from '../../../../components/ui/text-field' +import { CONTACT_LIST_ROUTE } from '../../../../helpers/constants/routes' +import { isValidAddress, isValidENSAddress } from '../../../../helpers/utils/util' +import EnsInput from '../../../../pages/send/send-content/add-recipient/ens-input' +import PageContainerFooter from '../../../../components/ui/page-container/page-container-footer' +import debounce from 'lodash.debounce' + +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, + qrCodeDetected: PropTypes.func, + } + + state = { + nickname: '', + ethAddress: '', + ensAddress: '', + error: '', + ensError: '', + } + + constructor (props) { + super(props) + this.dValidate = debounce(this.validate, 1000) + } + + componentWillReceiveProps (nextProps) { + if (nextProps.qrCodeData) { + if (nextProps.qrCodeData.type === 'address') { + const scannedAddress = nextProps.qrCodeData.values.address.toLowerCase() + const currentAddress = this.state.ensAddress || this.state.ethAddress + if (currentAddress.toLowerCase() !== scannedAddress) { + this.setState({ ethAddress: scannedAddress, ensAddress: '' }) + // Clean up QR code data after handling + this.props.qrCodeDetected(null) + } + } + } + } + + validate = address => { + const valid = isValidAddress(address) + const validEnsAddress = isValidENSAddress(address) + if (valid || validEnsAddress || address === '') { + this.setState({ error: '', ethAddress: address }) + } else { + this.setState({ error: 'Invalid Address' }) + } + } + + renderInput () { + return ( + <EnsInput + className="send__to-row" + scanQrCode={_ => { this.props.scanQrCode() }} + onChange={this.dValidate} + onPaste={text => this.setState({ ethAddress: text })} + onReset={() => this.setState({ ethAddress: '', ensAddress: '' })} + updateEnsResolution={address => { + this.setState({ ensAddress: address, error: '', ensError: '' }) + }} + updateEnsResolutionError={message => this.setState({ ensError: message })} + /> + ) + } + + render () { + const { t } = this.context + const { history, addToAddressBook } = this.props + + const errorToRender = this.state.ensError || this.state.error + + return ( + <div className="settings-page__content-row address-book__add-contact"> + {this.state.ensAddress && <div className="address-book__view-contact__group"> + <Identicon address={this.state.ensAddress} diameter={60} /> + <div className="address-book__view-contact__group__value"> + { this.state.ensAddress } + </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">{errorToRender}</div>} + </div> + </div> + <PageContainerFooter + cancelText={this.context.t('cancel')} + disabled={Boolean(this.state.error)} + onSubmit={() => { + addToAddressBook(this.state.ensAddress || this.state.ethAddress, this.state.newName) + history.push(CONTACT_LIST_ROUTE) + }} + onCancel={() => { + history.push(CONTACT_LIST_ROUTE) + }} + submitText={this.context.t('save')} + submitButtonType={'confirm'} + /> + </div> + ) + } +} diff --git a/ui/app/pages/settings/contact-list-tab/add-contact/add-contact.container.js b/ui/app/pages/settings/contact-list-tab/add-contact/add-contact.container.js new file mode 100644 index 000000000..0a0fc450c --- /dev/null +++ b/ui/app/pages/settings/contact-list-tab/add-contact/add-contact.container.js @@ -0,0 +1,30 @@ +import AddContact from './add-contact.component' +import { compose } from 'recompose' +import { connect } from 'react-redux' +import { withRouter } from 'react-router-dom' +import { addToAddressBook, showQrScanner, qrCodeDetected } from '../../../../store/actions' +import { + CONTACT_ADD_ROUTE, +} from '../../../../helpers/constants/routes' +import { + getQrCodeData, +} from '../../../../pages/send/send.selectors' + +const mapStateToProps = state => { + return { + qrCodeData: getQrCodeData(state), + } +} + +const mapDispatchToProps = dispatch => { + return { + addToAddressBook: (recipient, nickname) => dispatch(addToAddressBook(recipient, nickname)), + scanQrCode: () => dispatch(showQrScanner(CONTACT_ADD_ROUTE)), + qrCodeDetected: (data) => dispatch(qrCodeDetected(data)), + } +} + +export default compose( + withRouter, + connect(mapStateToProps, mapDispatchToProps) +)(AddContact) diff --git a/ui/app/pages/settings/contact-list-tab/add-contact/index.js b/ui/app/pages/settings/contact-list-tab/add-contact/index.js new file mode 100644 index 000000000..ce73025a3 --- /dev/null +++ b/ui/app/pages/settings/contact-list-tab/add-contact/index.js @@ -0,0 +1 @@ +export { default } from './add-contact.container' |