aboutsummaryrefslogtreecommitdiffstats
path: root/ui/app/pages/settings/contact-list-tab/add-contact
diff options
context:
space:
mode:
authorDan J Miller <danjm.com@gmail.com>2019-08-01 03:56:44 +0800
committerGitHub <noreply@github.com>2019-08-01 03:56:44 +0800
commite9c7df28ed88f6dc3a5074cf873f3920429d1803 (patch)
tree6075769d6a43cda8ce7de0a141b8f55065f05727 /ui/app/pages/settings/contact-list-tab/add-contact
parent1fd3dc9ecf16f00d721078e114138e529a7b8e16 (diff)
downloadtangerine-wallet-browser-e9c7df28ed88f6dc3a5074cf873f3920429d1803.tar.gz
tangerine-wallet-browser-e9c7df28ed88f6dc3a5074cf873f3920429d1803.tar.zst
tangerine-wallet-browser-e9c7df28ed88f6dc3a5074cf873f3920429d1803.zip
Address book send plus contact list (#6914)
* Style Send Header * Move Send to-row to send view and restyle * Add "Recents" group to select recipient view * Rename SendToRow to AddRecipient * Basic UI and Layout * New ENSInput component * wip - fuzzy search for input * small refactor * Add Dialog * contact list initial * initial error on invalid address * clean up edit * Click to open modal * Create AddToAddressBookModal component * Modal styling and layout * modal i18n * Add to Addressbook * ens wip * ens wip * ENS Resolution * Reset input * Send to explicit address * Happy Path Complete * Add back error checking * Reset send-to when emptying input * Add back warning object * Fix linter * Fix unit test #1 - fix import paths * Remove dead tests * One more to go * Fix all unit tests * add unit test for reducers and actions * test rendering AddRecipient * Add tests for dialog boxes in AddRecipient * Add test for validating * Fix linter * Fix e2e tests * Token send e2e fix * Style View Contact * Style edit-contact * Fix e2e * Fix from-import-beta-ui e2e spec * Make section header say "add recipient” by default * Auto-focus add recipient input * Update placeholder text * Update input title font size * Auto advance to next step if user paste a valid address * Ellipsify address when recipient is selected * Fix app header background color on desktop * Give each form row a margin of 16px * Use .container/.component naming pattern for ens-input * Auto-focus on input when add to addressbook modal is opened; Save on Enter * Fix and add unit test * Fix selectors name in e2e tests * Correct e2e test token amount for address-book-send changes * Adds e2e test for editing a transaction * Delete test/integration/lib/send-new-ui.js * Add tests for amount max button and high value error on send screen to test/e2e/metamask-ui.spec.js * lint and revert to address as object keys * add chainId based on current network to address book entry * fix test * only display contacts for the current network * Improve ENS message when not found on current network * Add error to indicate when network does not support ENS * bump gaba * address book, resolve comments * Move contact-list to its own component * De-duplicate getaddressbook selector and refactor name selection logic in contact-list-tab/ * Use contact-list component in contact-list-tab.component (i.e. in settings) * Improve/fix settings headers for popup and browser views * Lint fixes related to address book updates * Add 'My accounts' page to settings address book * Update add new contact button in settings to match floating circular design * Improve styles of view contact page * Improve styles and labels of the add-contact.component * Further lint fixes related to address book updates * Update unit tests as per address book updates * Ensure that contact list groups are sorted alphabetically * Refactor settings component to use a container for connection to redux; allow display of addressbook name in settings header * Decouple ens-input.component from send context * Add ens resolution to add contact screen in settings * Switching networks when an ens address is shown on send form removes the ens address. * Resolve send screen search for ensAddress to matching address book entry if it exists * Show resolved ens icon and address if exists (settings: add-contact.component) * Make the displayed and copied address in view-contact.component the checksummed address * Default alias state prop in AddToAddressBookModal to empty string * Use keyCode to detect enter key in AddToAddressBookModal * Ensure add-contact component properly updates after QR code detection * Fix display of all recents after clicking 'Load More' in contact list * Fix send screen contact searching after network switching * Code cleanup related to address book changes * Update unit tests for address book changes * Update ENS name not found on network message * Add ens registration error message * Cancel on edit mode takes user back to view screen * Adds support for memo to settings contact list view and edit screens * Modify designs of edit and view contact in popup environment * Update settings content list UX to show split columns in fullscreen and proper internal navigation * Correct background address book API usages in UI
Diffstat (limited to 'ui/app/pages/settings/contact-list-tab/add-contact')
-rw-r--r--ui/app/pages/settings/contact-list-tab/add-contact/add-contact.component.js131
-rw-r--r--ui/app/pages/settings/contact-list-tab/add-contact/add-contact.container.js30
-rw-r--r--ui/app/pages/settings/contact-list-tab/add-contact/index.js1
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'