mirror of
https://github.com/kremalicious/metamask-extension.git
synced 2024-12-23 09:52:26 +01:00
Add sort and search to AddRecipient accounts list (#9257)
* sort and search accounts in AddRecipient component * Update AddRecipient unit test Co-authored-by: Erik Marks <rekmarks@protonmail.com>
This commit is contained in:
parent
ee205b893f
commit
128efc5b52
@ -22,6 +22,7 @@ export default class AddRecipient extends Component {
|
|||||||
addressBookEntryName: PropTypes.string,
|
addressBookEntryName: PropTypes.string,
|
||||||
contacts: PropTypes.array,
|
contacts: PropTypes.array,
|
||||||
nonContacts: PropTypes.array,
|
nonContacts: PropTypes.array,
|
||||||
|
setInternalSearch: PropTypes.func,
|
||||||
}
|
}
|
||||||
|
|
||||||
constructor(props) {
|
constructor(props) {
|
||||||
@ -140,15 +141,28 @@ export default class AddRecipient extends Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
renderTransfer() {
|
renderTransfer() {
|
||||||
const { ownedAccounts } = this.props
|
let { ownedAccounts } = this.props
|
||||||
|
const { query, setInternalSearch } = this.props
|
||||||
const { t } = this.context
|
const { t } = this.context
|
||||||
|
const { isShowingTransfer } = this.state
|
||||||
|
|
||||||
|
if (isShowingTransfer && query) {
|
||||||
|
ownedAccounts = ownedAccounts.filter(
|
||||||
|
(item) =>
|
||||||
|
item.name.toLowerCase().indexOf(query.toLowerCase()) > -1 ||
|
||||||
|
item.address.toLowerCase().indexOf(query.toLowerCase()) > -1,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="send__select-recipient-wrapper__list">
|
<div className="send__select-recipient-wrapper__list">
|
||||||
<Button
|
<Button
|
||||||
type="link"
|
type="link"
|
||||||
className="send__select-recipient-wrapper__list__link"
|
className="send__select-recipient-wrapper__list__link"
|
||||||
onClick={() => this.setState({ isShowingTransfer: false })}
|
onClick={() => {
|
||||||
|
setInternalSearch(false)
|
||||||
|
this.setState({ isShowingTransfer: false })
|
||||||
|
}}
|
||||||
>
|
>
|
||||||
<div className="send__select-recipient-wrapper__list__back-caret" />
|
<div className="send__select-recipient-wrapper__list__back-caret" />
|
||||||
{t('backToAll')}
|
{t('backToAll')}
|
||||||
@ -164,7 +178,12 @@ export default class AddRecipient extends Component {
|
|||||||
|
|
||||||
renderMain() {
|
renderMain() {
|
||||||
const { t } = this.context
|
const { t } = this.context
|
||||||
const { query, ownedAccounts = [], addressBook } = this.props
|
const {
|
||||||
|
query,
|
||||||
|
ownedAccounts = [],
|
||||||
|
addressBook,
|
||||||
|
setInternalSearch,
|
||||||
|
} = this.props
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="send__select-recipient-wrapper__list">
|
<div className="send__select-recipient-wrapper__list">
|
||||||
@ -178,7 +197,10 @@ export default class AddRecipient extends Component {
|
|||||||
<Button
|
<Button
|
||||||
type="link"
|
type="link"
|
||||||
className="send__select-recipient-wrapper__list__link"
|
className="send__select-recipient-wrapper__list__link"
|
||||||
onClick={() => this.setState({ isShowingTransfer: true })}
|
onClick={() => {
|
||||||
|
setInternalSearch(true)
|
||||||
|
this.setState({ isShowingTransfer: true })
|
||||||
|
}}
|
||||||
>
|
>
|
||||||
{t('transferBetweenAccounts')}
|
{t('transferBetweenAccounts')}
|
||||||
</Button>
|
</Button>
|
||||||
|
@ -23,14 +23,18 @@ function mapStateToProps(state) {
|
|||||||
|
|
||||||
const addressBook = getAddressBook(state)
|
const addressBook = getAddressBook(state)
|
||||||
|
|
||||||
|
const ownedAccounts = accountsWithSendEtherInfoSelector(state).sort((a, b) =>
|
||||||
|
a.name.localeCompare(b.name),
|
||||||
|
)
|
||||||
|
|
||||||
return {
|
return {
|
||||||
ownedAccounts: accountsWithSendEtherInfoSelector(state),
|
|
||||||
addressBook,
|
addressBook,
|
||||||
ensResolution,
|
|
||||||
addressBookEntryName,
|
addressBookEntryName,
|
||||||
ensResolutionError: getSendEnsResolutionError(state),
|
|
||||||
contacts: addressBook.filter(({ name }) => Boolean(name)),
|
contacts: addressBook.filter(({ name }) => Boolean(name)),
|
||||||
|
ensResolution,
|
||||||
|
ensResolutionError: getSendEnsResolutionError(state),
|
||||||
nonContacts: addressBook.filter(({ name }) => !name),
|
nonContacts: addressBook.filter(({ name }) => !name),
|
||||||
|
ownedAccounts,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -38,6 +38,7 @@ export default class EnsInput extends Component {
|
|||||||
onValidAddressTyped: PropTypes.func,
|
onValidAddressTyped: PropTypes.func,
|
||||||
contact: PropTypes.object,
|
contact: PropTypes.object,
|
||||||
value: PropTypes.string,
|
value: PropTypes.string,
|
||||||
|
internalSearch: PropTypes.bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
state = {
|
state = {
|
||||||
@ -47,11 +48,11 @@ export default class EnsInput extends Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
componentDidMount() {
|
componentDidMount() {
|
||||||
const { network } = this.props
|
const { network, internalSearch } = this.props
|
||||||
const networkHasEnsSupport = getNetworkEnsSupport(network)
|
const networkHasEnsSupport = getNetworkEnsSupport(network)
|
||||||
this.setState({ ensResolution: ZERO_ADDRESS })
|
this.setState({ ensResolution: ZERO_ADDRESS })
|
||||||
|
|
||||||
if (networkHasEnsSupport) {
|
if (networkHasEnsSupport && !internalSearch) {
|
||||||
const provider = global.ethereumProvider
|
const provider = global.ethereumProvider
|
||||||
this.ens = new ENS({ provider, network })
|
this.ens = new ENS({ provider, network })
|
||||||
this.checkName = debounce(this.lookupEnsName, 200)
|
this.checkName = debounce(this.lookupEnsName, 200)
|
||||||
@ -60,7 +61,7 @@ export default class EnsInput extends Component {
|
|||||||
|
|
||||||
componentDidUpdate(prevProps) {
|
componentDidUpdate(prevProps) {
|
||||||
const { input } = this.state
|
const { input } = this.state
|
||||||
const { network, value } = this.props
|
const { network, value, internalSearch } = this.props
|
||||||
|
|
||||||
let newValue
|
let newValue
|
||||||
|
|
||||||
@ -81,6 +82,9 @@ export default class EnsInput extends Component {
|
|||||||
if (newValue !== undefined) {
|
if (newValue !== undefined) {
|
||||||
this.onChange({ target: { value: newValue } })
|
this.onChange({ target: { value: newValue } })
|
||||||
}
|
}
|
||||||
|
if (!internalSearch && prevProps.internalSearch) {
|
||||||
|
this.resetInput()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
resetInput = () => {
|
resetInput = () => {
|
||||||
@ -143,12 +147,15 @@ export default class EnsInput extends Component {
|
|||||||
updateEnsResolution,
|
updateEnsResolution,
|
||||||
updateEnsResolutionError,
|
updateEnsResolutionError,
|
||||||
onValidAddressTyped,
|
onValidAddressTyped,
|
||||||
|
internalSearch,
|
||||||
} = this.props
|
} = this.props
|
||||||
const input = e.target.value
|
const input = e.target.value
|
||||||
const networkHasEnsSupport = getNetworkEnsSupport(network)
|
const networkHasEnsSupport = getNetworkEnsSupport(network)
|
||||||
|
|
||||||
this.setState({ input }, () => onChange(input))
|
this.setState({ input }, () => onChange(input))
|
||||||
|
if (internalSearch) {
|
||||||
|
return null
|
||||||
|
}
|
||||||
// Empty ENS state if input is empty
|
// Empty ENS state if input is empty
|
||||||
// maybe scan ENS
|
// maybe scan ENS
|
||||||
|
|
||||||
@ -161,7 +168,7 @@ export default class EnsInput extends Component {
|
|||||||
updateEnsResolutionError(
|
updateEnsResolutionError(
|
||||||
networkHasEnsSupport ? '' : 'Network does not support ENS',
|
networkHasEnsSupport ? '' : 'Network does not support ENS',
|
||||||
)
|
)
|
||||||
return
|
return null
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isValidDomainName(input)) {
|
if (isValidDomainName(input)) {
|
||||||
@ -172,6 +179,7 @@ export default class EnsInput extends Component {
|
|||||||
updateEnsResolution('')
|
updateEnsResolution('')
|
||||||
updateEnsResolutionError('')
|
updateEnsResolutionError('')
|
||||||
}
|
}
|
||||||
|
return null
|
||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
|
@ -22,8 +22,10 @@ proxyquire('../add-recipient.container.js', {
|
|||||||
getSendEnsResolutionError: (s) => `mockSendEnsResolutionError:${s}`,
|
getSendEnsResolutionError: (s) => `mockSendEnsResolutionError:${s}`,
|
||||||
getAddressBook: (s) => [{ name: `mockAddressBook:${s}` }],
|
getAddressBook: (s) => [{ name: `mockAddressBook:${s}` }],
|
||||||
getAddressBookEntry: (s) => `mockAddressBookEntry:${s}`,
|
getAddressBookEntry: (s) => `mockAddressBookEntry:${s}`,
|
||||||
accountsWithSendEtherInfoSelector: (s) =>
|
accountsWithSendEtherInfoSelector: (s) => [
|
||||||
`mockAccountsWithSendEtherInfoSelector:${s}`,
|
{ name: `account2:${s}` },
|
||||||
|
{ name: `account1:${s}` },
|
||||||
|
],
|
||||||
},
|
},
|
||||||
'../../../../store/actions': actionSpies,
|
'../../../../store/actions': actionSpies,
|
||||||
})
|
})
|
||||||
@ -36,7 +38,10 @@ describe('add-recipient container', function () {
|
|||||||
contacts: [{ name: 'mockAddressBook:mockState' }],
|
contacts: [{ name: 'mockAddressBook:mockState' }],
|
||||||
ensResolution: 'mockSendEnsResolution:mockState',
|
ensResolution: 'mockSendEnsResolution:mockState',
|
||||||
ensResolutionError: 'mockSendEnsResolutionError:mockState',
|
ensResolutionError: 'mockSendEnsResolutionError:mockState',
|
||||||
ownedAccounts: 'mockAccountsWithSendEtherInfoSelector:mockState',
|
ownedAccounts: [
|
||||||
|
{ name: `account1:mockState` },
|
||||||
|
{ name: `account2:mockState` },
|
||||||
|
],
|
||||||
addressBookEntryName: undefined,
|
addressBookEntryName: undefined,
|
||||||
nonContacts: [],
|
nonContacts: [],
|
||||||
})
|
})
|
||||||
|
@ -63,6 +63,7 @@ export default class SendTransactionScreen extends Component {
|
|||||||
query: '',
|
query: '',
|
||||||
toError: null,
|
toError: null,
|
||||||
toWarning: null,
|
toWarning: null,
|
||||||
|
internalSearch: false,
|
||||||
}
|
}
|
||||||
|
|
||||||
constructor(props) {
|
constructor(props) {
|
||||||
@ -204,21 +205,30 @@ export default class SendTransactionScreen extends Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
onRecipientInputChange = (query) => {
|
onRecipientInputChange = (query) => {
|
||||||
if (query) {
|
const { internalSearch } = this.state
|
||||||
this.dValidate(query)
|
|
||||||
} else {
|
if (!internalSearch) {
|
||||||
this.validate(query)
|
if (query) {
|
||||||
|
this.dValidate(query)
|
||||||
|
} else {
|
||||||
|
this.dValidate.cancel()
|
||||||
|
this.validate(query)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
this.setState({
|
this.setState({ query })
|
||||||
query,
|
}
|
||||||
})
|
|
||||||
|
setInternalSearch(internalSearch) {
|
||||||
|
this.setState({ query: '', internalSearch })
|
||||||
}
|
}
|
||||||
|
|
||||||
validate(query) {
|
validate(query) {
|
||||||
const { hasHexData, tokens, sendToken, network } = this.props
|
const { hasHexData, tokens, sendToken, network } = this.props
|
||||||
|
|
||||||
if (!query) {
|
const { internalSearch } = this.state
|
||||||
|
|
||||||
|
if (!query || internalSearch) {
|
||||||
this.setState({ toError: '', toWarning: '' })
|
this.setState({ toError: '', toWarning: '' })
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -293,6 +303,7 @@ export default class SendTransactionScreen extends Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
renderInput() {
|
renderInput() {
|
||||||
|
const { internalSearch } = this.state
|
||||||
return (
|
return (
|
||||||
<EnsInput
|
<EnsInput
|
||||||
className="send__to-row"
|
className="send__to-row"
|
||||||
@ -314,6 +325,7 @@ export default class SendTransactionScreen extends Component {
|
|||||||
onReset={() => this.props.updateSendTo('', '')}
|
onReset={() => this.props.updateSendTo('', '')}
|
||||||
updateEnsResolution={this.props.updateSendEnsResolution}
|
updateEnsResolution={this.props.updateSendEnsResolution}
|
||||||
updateEnsResolutionError={this.props.updateSendEnsResolutionError}
|
updateEnsResolutionError={this.props.updateSendEnsResolutionError}
|
||||||
|
internalSearch={internalSearch}
|
||||||
/>
|
/>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@ -327,6 +339,9 @@ export default class SendTransactionScreen extends Component {
|
|||||||
}
|
}
|
||||||
query={this.state.query}
|
query={this.state.query}
|
||||||
toError={toError}
|
toError={toError}
|
||||||
|
setInternalSearch={(internalSearch) =>
|
||||||
|
this.setInternalSearch(internalSearch)
|
||||||
|
}
|
||||||
/>
|
/>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -435,6 +435,7 @@ describe('Send Component', function () {
|
|||||||
)
|
)
|
||||||
|
|
||||||
assert.deepEqual(instance.state, {
|
assert.deepEqual(instance.state, {
|
||||||
|
internalSearch: false,
|
||||||
query: '0x80F061544cC398520615B5d3e7A3BedD70cd4510',
|
query: '0x80F061544cC398520615B5d3e7A3BedD70cd4510',
|
||||||
toError: null,
|
toError: null,
|
||||||
toWarning: null,
|
toWarning: null,
|
||||||
@ -449,6 +450,7 @@ describe('Send Component', function () {
|
|||||||
|
|
||||||
clock.tick(1001)
|
clock.tick(1001)
|
||||||
assert.deepEqual(instance.state, {
|
assert.deepEqual(instance.state, {
|
||||||
|
internalSearch: false,
|
||||||
query: '0x80F061544cC398520615B5d3e7a3BedD70cd4510',
|
query: '0x80F061544cC398520615B5d3e7a3BedD70cd4510',
|
||||||
toError: 'invalidAddressRecipient',
|
toError: 'invalidAddressRecipient',
|
||||||
toWarning: null,
|
toWarning: null,
|
||||||
@ -464,6 +466,7 @@ describe('Send Component', function () {
|
|||||||
|
|
||||||
clock.tick(1001)
|
clock.tick(1001)
|
||||||
assert.deepEqual(instance.state, {
|
assert.deepEqual(instance.state, {
|
||||||
|
internalSearch: false,
|
||||||
query: '0x80F061544cC398520615B5d3e7a3BedD70cd4510',
|
query: '0x80F061544cC398520615B5d3e7a3BedD70cd4510',
|
||||||
toError: 'invalidAddressRecipientNotEthNetwork',
|
toError: 'invalidAddressRecipientNotEthNetwork',
|
||||||
toWarning: null,
|
toWarning: null,
|
||||||
@ -479,6 +482,7 @@ describe('Send Component', function () {
|
|||||||
|
|
||||||
clock.tick(1001)
|
clock.tick(1001)
|
||||||
assert.deepEqual(instance.state, {
|
assert.deepEqual(instance.state, {
|
||||||
|
internalSearch: false,
|
||||||
query: '0x80F061544cC398520615B5d3e7a3BedD70cd4510',
|
query: '0x80F061544cC398520615B5d3e7a3BedD70cd4510',
|
||||||
toError: 'invalidAddressRecipientNotEthNetwork',
|
toError: 'invalidAddressRecipientNotEthNetwork',
|
||||||
toWarning: null,
|
toWarning: null,
|
||||||
@ -486,6 +490,7 @@ describe('Send Component', function () {
|
|||||||
|
|
||||||
instance.onRecipientInputChange('')
|
instance.onRecipientInputChange('')
|
||||||
assert.deepEqual(instance.state, {
|
assert.deepEqual(instance.state, {
|
||||||
|
internalSearch: false,
|
||||||
query: '',
|
query: '',
|
||||||
toError: '',
|
toError: '',
|
||||||
toWarning: '',
|
toWarning: '',
|
||||||
@ -501,6 +506,7 @@ describe('Send Component', function () {
|
|||||||
|
|
||||||
clock.tick(1001)
|
clock.tick(1001)
|
||||||
assert.deepEqual(instance.state, {
|
assert.deepEqual(instance.state, {
|
||||||
|
internalSearch: false,
|
||||||
query: '0x13cb85823f78Cff38f0B0E90D3e975b8CB3AAd64',
|
query: '0x13cb85823f78Cff38f0B0E90D3e975b8CB3AAd64',
|
||||||
toError: null,
|
toError: null,
|
||||||
toWarning: 'knownAddressRecipient',
|
toWarning: 'knownAddressRecipient',
|
||||||
|
Loading…
x
Reference in New Issue
Block a user