Merge pull request #18 from yamijuan/transfer-ui

Added virtualized list and debounce search on token modal
This commit is contained in:
B 2021-03-10 14:08:20 -06:00 committed by GitHub
commit 4b7176302d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 86 additions and 39 deletions

View File

@ -20,6 +20,7 @@
"@types/chart.js": "^2.9.29", "@types/chart.js": "^2.9.29",
"@types/echarts": "^4.9.0", "@types/echarts": "^4.9.0",
"@types/react-router-dom": "^5.1.6", "@types/react-router-dom": "^5.1.6",
"@types/react-virtualized": "^9.21.11",
"@types/testing-library__react": "^10.2.0", "@types/testing-library__react": "^10.2.0",
"@uniswap/token-lists": "^1.0.0-beta.19", "@uniswap/token-lists": "^1.0.0-beta.19",
"@walletconnect/client": "^1.3.6", "@walletconnect/client": "^1.3.6",
@ -52,6 +53,7 @@
"react-router-dom": "^5.2.0", "react-router-dom": "^5.2.0",
"react-scripts": "3.4.3", "react-scripts": "3.4.3",
"react-three-fiber": "^5.3.18", "react-three-fiber": "^5.3.18",
"react-virtualized": "^9.22.3",
"three": "^0.125.2", "three": "^0.125.2",
"typescript": "^4.1.3", "typescript": "^4.1.3",
"use-wallet": "^0.8.1" "use-wallet": "^0.8.1"

View File

@ -10,7 +10,7 @@
.multichain-option-name { .multichain-option-name {
display: flex; display: flex;
flex-direction: row; flex-direction: column;
} }
.ccy-input { .ccy-input {

View File

@ -1,4 +1,7 @@
import React, { useMemo, useState } from 'react'; import React, { useMemo, useState } from 'react';
import List from 'react-virtualized/dist/commonjs/List';
import AutoSizer from 'react-virtualized/dist/commonjs/AutoSizer';
import _ from 'lodash';
import './style.less'; import './style.less';
import { Modal, Input } from 'antd'; import { Modal, Input } from 'antd';
import { useEthereum } from '../../contexts'; import { useEthereum } from '../../contexts';
@ -15,6 +18,18 @@ export const TokenSelectModal = (props: {
const [selected, setSelected] = useState<string>(''); const [selected, setSelected] = useState<string>('');
const [search, setSearch] = useState<string>(''); const [search, setSearch] = useState<string>('');
const tokenList = useMemo(() => {
if (tokens && search) {
return tokens.filter(token => {
return (
(token.tags?.indexOf('longList') || -1) < 0 &&
token.symbol.includes(search.toUpperCase())
);
});
}
return tokens;
}, [tokens, search]);
const showModal = () => { const showModal = () => {
setIsModalVisible(true); setIsModalVisible(true);
}; };
@ -29,43 +44,38 @@ export const TokenSelectModal = (props: {
return tokens.find(el => el.address === selected); return tokens.find(el => el.address === selected);
}, [selected, tokens, props.asset]); }, [selected, tokens, props.asset]);
const renderTokensChain = useMemo(() => { const delayedSearchChange = _.debounce(val => {
return tokens setSearch(val);
.filter( });
t =>
(t.tags?.indexOf('longList') || -1) < 0 && const rowRender = (rowProps: { index: number; key: string; style: any }) => {
search && const token = tokenList[rowProps.index];
search.length >= 3 && const mint = token.address;
t.symbol.includes(search.toUpperCase()), return (
) <div
.map(token => { key={rowProps.key}
const mint = token.address; className="multichain-option"
return ( title={token.name}
onClick={() => {
props.onSelectToken(mint);
setSelected(mint);
hideModal();
}}
style={{ ...rowProps.style, cursor: 'pointer' }}
>
<div className="multichain-option-content">
<TokenDisplay asset={props.asset} token={token} chain={props.chain} />
<div <div
key={mint} className="multichain-option-name"
className="multichain-option" style={{ marginLeft: '20px' }}
title={token.name}
onClick={() => {
props.onSelectToken(mint);
setSelected(mint);
hideModal();
}}
style={{ cursor: 'pointer' }}
> >
<div className="multichain-option-content"> <em className={'token-symbol'}>{token.symbol}</em>
<TokenDisplay <span className={'token-name'}>{token.name}</span>
asset={props.asset}
token={token}
chain={props.chain}
/>
<div className="multichain-option-name">
<span className={'token-name'}>{token.symbol}</span>
</div>
</div>
</div> </div>
); </div>
}); </div>
}, [search, tokens]); );
};
return ( return (
<> <>
@ -93,11 +103,28 @@ export const TokenSelectModal = (props: {
> >
<Input <Input
className={'input-token-search'} className={'input-token-search'}
placeholder={'ETH, SOL, ... etc'} placeholder={'SOL, SRM, ... etc'}
value={search} value={search}
onChange={e => setSearch(e.target.value)} onChange={e => {
e.persist();
delayedSearchChange(e.target.value);
}}
/> />
<div className={'assets-scroll'}>{[...renderTokensChain]}</div> <div style={{ height: '90%' }}>
<AutoSizer>
{({ width, height }) => (
<List
ref="List"
height={height}
rowHeight={70}
rowCount={tokenList.length || 0}
rowRenderer={rowRender}
width={width}
/>
)}
</AutoSizer>
</div>
{/*<div className={'assets-scroll'}>{[...renderTokensChain]}</div>*/}
</Modal> </Modal>
</> </>
); );

View File

@ -5,3 +5,21 @@
height: 60vh; height: 60vh;
overflow: auto; overflow: auto;
} }
.ant-modal-body {
height: 80vh;
::-webkit-scrollbar-track {
border-radius: 5px;
background-color: transparent;
}
::-webkit-scrollbar {
width: 7px;
background-color: transparent;
}
::-webkit-scrollbar-thumb {
border-radius: 5px;
height: 50px;
-webkit-box-shadow: inset 0 0 30px rgba(0,0,0,.3);
background-color: #555;
}
}

View File

@ -53,7 +53,7 @@ export const EthereumProvider: FunctionComponent = ({ children }) => {
fetch('https://gateway.ipfs.io/ipns/tokens.uniswap.org').then(_ => fetch('https://gateway.ipfs.io/ipns/tokens.uniswap.org').then(_ =>
_.json(), _.json(),
), ),
fetch('https://tokenlist.aave.eth.link/').then(_ => _.json()), //fetch('https://tokenlist.aave.eth.link/').then(_ => _.json()),
fetch('https://tokens.coingecko.com/uniswap/all.json').then(_ => fetch('https://tokens.coingecko.com/uniswap/all.json').then(_ =>
_.json(), _.json(),
), ),