Bug #523: Filtering contacts (#568)

Works fine for me:

- The address book selector displays 
- Typing the name/address will filter
- Not case sensitive
- Deleted won't show anymore. New added addresses will show and filter
- Works for regular Tx and Custom Tx

This is out of the scope of this issue, but worth mentioning: the issue reported in #482 is still here: the custom Tx still show addresses that are not valid (non contract addresses).
This commit is contained in:
Agustin Pane 2020-02-17 09:51:36 -03:00 committed by GitHub
parent 504770d4cd
commit d51303f348
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

View File

@ -1,22 +1,20 @@
// @flow // @flow
import React, { useEffect, useState } from 'react' import React, { useEffect, useState } from 'react'
import { import { withStyles } from '@material-ui/core/styles'
withStyles,
} from '@material-ui/core/styles'
import { useSelector } from 'react-redux' import { useSelector } from 'react-redux'
import Autocomplete from '@material-ui/lab/Autocomplete' import Autocomplete from '@material-ui/lab/Autocomplete'
import TextField from '@material-ui/core/TextField' import TextField from '@material-ui/core/TextField'
import makeStyles from '@material-ui/core/styles/makeStyles' import makeStyles from '@material-ui/core/styles/makeStyles'
import { List } from 'immutable' import { List } from 'immutable'
import { styles } from './style' import { styles } from './style'
import { getAddressBookListSelector } from '~/logic/addressBook/store/selectors'
import { import {
getAddressBookListSelector, mustBeEthereumAddress,
} from '~/logic/addressBook/store/selectors' mustBeEthereumContractAddress,
import { mustBeEthereumAddress, mustBeEthereumContractAddress } from '~/components/forms/validator' } from '~/components/forms/validator'
import Identicon from '~/components/Identicon' import Identicon from '~/components/Identicon'
import { getAddressFromENS } from '~/logic/wallets/getWeb3' import { getAddressFromENS } from '~/logic/wallets/getWeb3'
type Props = { type Props = {
classes: Object, classes: Object,
fieldMutator: Function, fieldMutator: Function,
@ -27,7 +25,6 @@ type Props = {
pristine: boolean, pristine: boolean,
} }
const textFieldLabelStyle = makeStyles(() => ({ const textFieldLabelStyle = makeStyles(() => ({
root: { root: {
overflow: 'hidden', overflow: 'hidden',
@ -44,10 +41,16 @@ const textFieldInputStyle = makeStyles(() => ({
}, },
})) }))
const isValidEnsName = (name) => /^([\w-]+\.)+(eth|test|xyz|luxe)$/.test(name) const isValidEnsName = name => /^([\w-]+\.)+(eth|test|xyz|luxe)$/.test(name)
const AddressBookInput = ({ const AddressBookInput = ({
classes, fieldMutator, isCustomTx, recipientAddress, setSelectedEntry, pristine, setIsValidAddress, classes,
fieldMutator,
isCustomTx,
recipientAddress,
setSelectedEntry,
pristine,
setIsValidAddress,
}: Props) => { }: Props) => {
const addressBook = useSelector(getAddressBookListSelector) const addressBook = useSelector(getAddressBookListSelector)
const [isValidForm, setIsValidForm] = useState(true) const [isValidForm, setIsValidForm] = useState(true)
@ -58,7 +61,7 @@ const AddressBookInput = ({
const [inputAddValue, setInputAddValue] = useState(recipientAddress) const [inputAddValue, setInputAddValue] = useState(recipientAddress)
const onAddressInputChanged = async (addressValue) => { const onAddressInputChanged = async addressValue => {
setInputAddValue(addressValue) setInputAddValue(addressValue)
let resolvedAddress = addressValue let resolvedAddress = addressValue
let isValidText let isValidText
@ -77,6 +80,16 @@ const AddressBookInput = ({
if (isCustomTx && isValidText === undefined) { if (isCustomTx && isValidText === undefined) {
isValidText = await mustBeEthereumContractAddress(resolvedAddress) isValidText = await mustBeEthereumContractAddress(resolvedAddress)
} }
// Filters the entries based on the input of the user
const filteredADBK = addressBook.filter(adbkEntry => {
const { name, address } = adbkEntry
return (
name.toLowerCase().includes(addressValue.toLowerCase()) ||
address.toLowerCase().includes(addressValue.toLowerCase())
)
})
setADBKList(filteredADBK)
} }
setIsValidForm(isValidText === undefined) setIsValidForm(isValidText === undefined)
setValidationText(isValidText) setValidationText(isValidText)
@ -90,8 +103,15 @@ const AddressBookInput = ({
setADBKList(addressBook) setADBKList(addressBook)
return return
} }
const abFlags = await Promise.all(addressBook.map(async ({ address }) => mustBeEthereumContractAddress(address) === undefined)) const abFlags = await Promise.all(
const filteredADBK = addressBook.filter((adbkEntry, index) => abFlags[index]) addressBook.map(
async ({ address }) =>
mustBeEthereumContractAddress(address) === undefined
)
)
const filteredADBK = addressBook.filter(
(adbkEntry, index) => abFlags[index]
)
setADBKList(filteredADBK) setADBKList(filteredADBK)
} }
filterAdbkContractAddresses() filterAdbkContractAddresses()
@ -112,14 +132,17 @@ const AddressBookInput = ({
options={adbkList.toArray()} options={adbkList.toArray()}
style={{ display: 'flex', flexGrow: 1 }} style={{ display: 'flex', flexGrow: 1 }}
closeIcon={null} closeIcon={null}
filterOptions={(optionsArray, { inputValue }) => optionsArray.filter((item) => { filterOptions={(optionsArray, { inputValue }) =>
const inputLowerCase = inputValue.toLowerCase() optionsArray.filter(item => {
const foundName = item.name.toLowerCase() const inputLowerCase = inputValue.toLowerCase()
.includes(inputLowerCase) const foundName = item.name.toLowerCase().includes(inputLowerCase)
const foundAddress = item.address.toLowerCase().includes(inputLowerCase) const foundAddress = item.address
return foundName || foundAddress .toLowerCase()
})} .includes(inputLowerCase)
getOptionLabel={(adbkEntry) => adbkEntry.address || ''} return foundName || foundAddress
})
}
getOptionLabel={adbkEntry => adbkEntry.address || ''}
onOpen={() => { onOpen={() => {
setSelectedEntry(null) setSelectedEntry(null)
setBlurred(false) setBlurred(false)
@ -136,7 +159,7 @@ const AddressBookInput = ({
setSelectedEntry({ address, name }) setSelectedEntry({ address, name })
fieldMutator(address) fieldMutator(address)
}} }}
renderOption={(adbkEntry) => { renderOption={adbkEntry => {
const { name, address } = adbkEntry const { name, address } = adbkEntry
return ( return (
<div className={classes.itemOptionList}> <div className={classes.itemOptionList}>
@ -150,7 +173,7 @@ const AddressBookInput = ({
</div> </div>
) )
}} }}
renderInput={(params) => ( renderInput={params => (
<TextField <TextField
{...params} {...params}
label={!isValidForm ? validationText : 'Recipient'} label={!isValidForm ? validationText : 'Recipient'}
@ -160,18 +183,16 @@ const AddressBookInput = ({
variant="filled" variant="filled"
id="filled-error-helper-text" id="filled-error-helper-text"
value={{ address: inputAddValue }} value={{ address: inputAddValue }}
onChange={(event) => { onChange={event => {
setInputTouched(true) setInputTouched(true)
onAddressInputChanged(event.target.value) onAddressInputChanged(event.target.value)
}} }}
InputProps={ InputProps={{
{ ...params.InputProps,
...params.InputProps, classes: {
classes: { ...txInputStyling,
...txInputStyling, },
}, }}
}
}
InputLabelProps={{ InputLabelProps={{
shrink: true, shrink: true,
required: true, required: true,