Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
I
interface
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
LuckySwap
interface
Commits
85d52b34
Unverified
Commit
85d52b34
authored
May 22, 2020
by
Moody Salem
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
perf(search modal): refactor before more dramatic changes
parent
219de1f4
Changes
5
Show whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
243 additions
and
250 deletions
+243
-250
index.tsx
src/components/CurrencyInputPanel/index.tsx
+0
-3
TokenSortButton.tsx
src/components/SearchModal/TokenSortButton.tsx
+24
-0
index.tsx
src/components/SearchModal/index.tsx
+70
-247
sorting.ts
src/components/SearchModal/sorting.ts
+41
-0
styleds.tsx
src/components/SearchModal/styleds.tsx
+108
-0
No files found.
src/components/CurrencyInputPanel/index.tsx
View file @
85d52b34
...
@@ -125,7 +125,6 @@ interface CurrencyInputPanelProps {
...
@@ -125,7 +125,6 @@ interface CurrencyInputPanelProps {
onMax
?:
()
=>
void
onMax
?:
()
=>
void
showMaxButton
:
boolean
showMaxButton
:
boolean
label
?:
string
label
?:
string
urlAddedTokens
?:
Token
[]
onTokenSelection
?:
(
tokenAddress
:
string
)
=>
void
onTokenSelection
?:
(
tokenAddress
:
string
)
=>
void
token
?:
Token
|
null
token
?:
Token
|
null
disableTokenSelect
?:
boolean
disableTokenSelect
?:
boolean
...
@@ -145,7 +144,6 @@ export default function CurrencyInputPanel({
...
@@ -145,7 +144,6 @@ export default function CurrencyInputPanel({
onMax
,
onMax
,
showMaxButton
,
showMaxButton
,
label
=
'
Input
'
,
label
=
'
Input
'
,
urlAddedTokens
=
[],
// used
onTokenSelection
=
null
,
onTokenSelection
=
null
,
token
=
null
,
token
=
null
,
disableTokenSelect
=
false
,
disableTokenSelect
=
false
,
...
@@ -246,7 +244,6 @@ export default function CurrencyInputPanel({
...
@@ -246,7 +244,6 @@ export default function CurrencyInputPanel({
setModalOpen
(
false
)
setModalOpen
(
false
)
}
}
}
}
filterType=
"tokens"
filterType=
"tokens"
urlAddedTokens=
{
urlAddedTokens
}
onTokenSelect=
{
onTokenSelection
}
onTokenSelect=
{
onTokenSelection
}
showSendWithSwap=
{
showSendWithSwap
}
showSendWithSwap=
{
showSendWithSwap
}
hiddenToken=
{
token
?.
address
}
hiddenToken=
{
token
?.
address
}
...
...
src/components/SearchModal/TokenSortButton.tsx
0 → 100644
View file @
85d52b34
import
React
from
'
react
'
import
{
Text
}
from
'
rebass
'
import
{
FilterWrapper
}
from
'
./styleds
'
export
function
TokenSortButton
({
title
,
toggleSortOrder
,
invertSearchOrder
}:
{
title
:
string
toggleSortOrder
:
()
=>
void
invertSearchOrder
:
boolean
})
{
return
(
<
FilterWrapper
onClick=
{
toggleSortOrder
}
>
<
Text
fontSize=
{
14
}
fontWeight=
{
500
}
>
{
title
}
</
Text
>
<
Text
fontSize=
{
14
}
fontWeight=
{
500
}
>
{
!
invertSearchOrder
?
'
↓
'
:
'
↑
'
}
</
Text
>
</
FilterWrapper
>
)
}
src/components/SearchModal/index.tsx
View file @
85d52b34
import
React
,
{
useState
,
useRef
,
useMemo
,
useEffect
,
useContext
}
from
'
react
'
import
'
@reach/tooltip/styles.css
'
import
'
@reach/tooltip/styles.css
'
import
styled
,
{
ThemeContext
}
from
'
styled-components
'
import
{
ChainId
,
JSBI
,
Token
,
WETH
}
from
'
@uniswap/sdk
'
import
{
JSBI
,
Token
,
WETH
}
from
'
@uniswap/sdk
'
import
React
,
{
useContext
,
useEffect
,
useMemo
,
useRef
,
useState
}
from
'
react
'
import
{
isMobile
}
from
'
react-device-detect
'
import
{
isMobile
}
from
'
react-device-detect
'
import
{
ArrowLeft
}
from
'
react-feather
'
import
{
useTranslation
}
from
'
react-i18next
'
import
{
RouteComponentProps
,
withRouter
}
from
'
react-router-dom
'
import
{
RouteComponentProps
,
withRouter
}
from
'
react-router-dom
'
import
{
Text
}
from
'
rebass
'
import
{
ThemeContext
}
from
'
styled-components
'
import
Circle
from
'
../../assets/images/circle.svg
'
import
Card
from
'
../../components/Card
'
import
{
COMMON_BASES
}
from
'
../../constants
'
import
{
COMMON_BASES
}
from
'
../../constants
'
import
{
ALL_TOKENS
}
from
'
../../constants/tokens
'
import
{
useActiveWeb3React
}
from
'
../../hooks
'
import
{
useAllTokens
,
useTokenByAddressAndAutomaticallyAdd
}
from
'
../../hooks/Tokens
'
import
{
useAllDummyPairs
,
useRemoveUserAddedToken
,
useUserAddedTokens
}
from
'
../../state/user/hooks
'
import
{
useAllTokenBalancesTreatingWETHasETH
}
from
'
../../state/wallet/hooks
'
import
{
useAllTokenBalancesTreatingWETHasETH
}
from
'
../../state/wallet/hooks
'
import
{
Link
as
StyledLink
}
from
'
../../theme/components
'
import
{
CursorPointer
,
TYPE
}
from
'
../../theme
'
import
{
CloseIcon
,
Link
as
StyledLink
}
from
'
../../theme/components
'
import
Card
from
'
../../components/Card
'
import
{
escapeRegExp
,
isAddress
}
from
'
../../utils
'
import
{
ButtonPrimary
,
ButtonSecondary
}
from
'
../Button
'
import
Column
,
{
AutoColumn
}
from
'
../Column
'
import
DoubleTokenLogo
from
'
../DoubleLogo
'
import
Modal
from
'
../Modal
'
import
Modal
from
'
../Modal
'
import
Circle
from
'
../../assets/images/circle.svg
'
import
QuestionHelper
from
'
../Question
'
import
{
AutoRow
,
RowBetween
,
RowFixed
}
from
'
../Row
'
import
TokenLogo
from
'
../TokenLogo
'
import
TokenLogo
from
'
../TokenLogo
'
import
DoubleTokenLogo
from
'
../DoubleLogo
'
import
{
useTokenComparator
}
from
'
./sorting
'
import
Column
,
{
AutoColumn
}
from
'
../Column
'
import
{
Text
}
from
'
rebass
'
import
{
CursorPointer
}
from
'
../../theme
'
import
{
ArrowLeft
}
from
'
react-feather
'
import
{
CloseIcon
}
from
'
../../theme/components
'
import
{
ButtonPrimary
,
ButtonSecondary
}
from
'
../../components/Button
'
import
{
Spinner
,
TYPE
}
from
'
../../theme
'
import
{
RowBetween
,
RowFixed
,
AutoRow
}
from
'
../Row
'
import
{
isAddress
,
escapeRegExp
}
from
'
../../utils
'
import
{
useActiveWeb3React
}
from
'
../../hooks
'
import
{
import
{
useAllDummyPairs
,
BaseWrapper
,
useFetchTokenByAddress
,
FadedSpan
,
useAddUserToken
,
GreySpan
,
useRemoveUserAddedToken
,
Input
,
useUserAddedTokens
ItemList
,
}
from
'
../../state/user/hooks
'
MenuItem
,
import
{
useTranslation
}
from
'
react-i18next
'
PaddedColumn
,
import
{
useToken
,
useAllTokens
}
from
'
../../hooks/Tokens
'
SpinnerWrapper
,
import
QuestionHelper
from
'
../Question
'
TokenModalInfo
}
from
'
./styleds
'
const
TokenModalInfo
=
styled
.
div
`
import
{
TokenSortButton
}
from
'
./TokenSortButton
'
${({
theme
})
=>
theme
.
flexRowNoWrap
}
align-items: center;
interface
SearchModalProps
extends
RouteComponentProps
{
padding: 1rem 1rem;
margin: 0.25rem 0.5rem;
justify-content: center;
user-select: none;
min-height: 200px;
`
const
ItemList
=
styled
.
div
`
flex-grow: 1;
height: 254px;
overflow-y: scroll;
-webkit-overflow-scrolling: touch;
`
const
FadedSpan
=
styled
(
RowFixed
)
`
color:
${({
theme
})
=>
theme
.
primary1
}
;
font-size: 14px;
`
const
GreySpan
=
styled
.
span
`
color:
${({
theme
})
=>
theme
.
text3
}
;
font-weight: 400;
`
const
SpinnerWrapper
=
styled
(
Spinner
)
`
margin: 0 0.25rem 0 0.25rem;
color:
${({
theme
})
=>
theme
.
text4
}
;
opacity: 0.6;
`
const
Input
=
styled
.
input
`
position: relative;
display: flex;
padding: 16px;
align-items: center;
width: 100%;
white-space: nowrap;
background: none;
border: none;
outline: none;
border-radius: 20px;
color:
${({
theme
})
=>
theme
.
text1
}
;
border-style: solid;
border: 1px solid
${({
theme
})
=>
theme
.
bg3
}
;
-webkit-appearance: none;
font-size: 18px;
::placeholder {
color:
${({
theme
})
=>
theme
.
text3
}
;
}
`
const
FilterWrapper
=
styled
(
RowFixed
)
`
padding: 8px;
background-color:
${({
selected
,
theme
})
=>
selected
&&
theme
.
bg2
}
;
color:
${({
selected
,
theme
})
=>
(
selected
?
theme
.
text1
:
theme
.
text2
)}
;
border-radius: 8px;
user-select: none;
& > * {
user-select: none;
}
:hover {
cursor: pointer;
}
`
const
PaddedColumn
=
styled
(
AutoColumn
)
`
padding: 20px;
padding-bottom: 12px;
`
const
PaddedItem
=
styled
(
RowBetween
)
`
padding: 4px 20px;
height: 56px;
`
const
MenuItem
=
styled
(
PaddedItem
)
`
cursor:
${({
disabled
})
=>
!
disabled
&&
'
pointer
'
}
;
pointer-events:
${({
disabled
})
=>
disabled
&&
'
none
'
}
;
:hover {
background-color:
${({
theme
,
disabled
})
=>
!
disabled
&&
theme
.
bg2
}
;
}
opacity:
${({
disabled
,
selected
})
=>
(
disabled
||
selected
?
0.5
:
1
)}
;
`
const
BaseWrapper
=
styled
(
AutoRow
)
<
{
disable
?:
boolean
}
>
`
border: 1px solid
${({
theme
,
disable
})
=>
(
disable
?
'
transparent
'
:
theme
.
bg3
)}
;
padding: 0 6px;
border-radius: 10px;
width: 120px;
:hover {
cursor:
${({
disable
})
=>
!
disable
&&
'
pointer
'
}
;
background-color:
${({
theme
,
disable
})
=>
!
disable
&&
theme
.
bg2
}
;
}
background-color:
${({
theme
,
disable
})
=>
disable
&&
theme
.
bg3
}
;
opacity:
${({
disable
})
=>
disable
&&
'
0.4
'
}
;
`
// filters on results
const
FILTERS
=
{
VOLUME
:
'
VOLUME
'
,
LIQUIDITY
:
'
LIQUIDITY
'
,
BALANCES
:
'
BALANCES
'
}
interface
SearchModalProps
extends
RouteComponentProps
<
{}
>
{
isOpen
?:
boolean
isOpen
?:
boolean
onDismiss
?:
()
=>
void
onDismiss
?:
()
=>
void
filterType
?:
'
tokens
'
filterType
?:
'
tokens
'
hiddenToken
?:
string
hiddenToken
?:
string
showSendWithSwap
?:
boolean
showSendWithSwap
?:
boolean
onTokenSelect
?:
(
address
:
string
)
=>
void
onTokenSelect
?:
(
address
:
string
)
=>
void
urlAddedTokens
?:
Token
[]
otherSelectedTokenAddress
?:
string
otherSelectedTokenAddress
?:
string
otherSelectedText
?:
string
otherSelectedText
?:
string
showCommonBases
?:
boolean
showCommonBases
?:
boolean
}
}
function
isDefaultToken
(
tokenAddress
:
string
,
chainId
?:
number
):
boolean
{
const
address
=
isAddress
(
tokenAddress
)
return
Boolean
(
chainId
&&
address
&&
ALL_TOKENS
[
chainId
as
ChainId
]?.[
tokenAddress
])
}
function
SearchModal
({
function
SearchModal
({
history
,
history
,
isOpen
,
isOpen
,
onDismiss
,
onDismiss
,
onTokenSelect
,
onTokenSelect
,
urlAddedTokens
,
filterType
,
filterType
,
hiddenToken
,
hiddenToken
,
showSendWithSwap
,
showSendWithSwap
,
...
@@ -184,16 +80,10 @@ function SearchModal({
...
@@ -184,16 +80,10 @@ function SearchModal({
const
[
invertSearchOrder
,
setInvertSearchOrder
]
=
useState
(
false
)
const
[
invertSearchOrder
,
setInvertSearchOrder
]
=
useState
(
false
)
const
userAddedTokens
=
useUserAddedTokens
()
const
userAddedTokens
=
useUserAddedTokens
()
const
fetchTokenByAddress
=
useFetchTokenByAddress
()
const
addToken
=
useAddUserToken
()
const
removeTokenByAddress
=
useRemoveUserAddedToken
()
const
removeTokenByAddress
=
useRemoveUserAddedToken
()
// if the current input is an address, and we don't have the token in context, try to fetch it
// if the current input is an address, and we don't have the token in context, try to fetch it
const
token
=
useToken
(
searchQuery
)
const
searchQueryToken
=
useTokenByAddressAndAutomaticallyAdd
(
searchQuery
)
const
[
temporaryToken
,
setTemporaryToken
]
=
useState
<
Token
|
null
>
()
// filters for ordering
const
[
activeFilter
,
setActiveFilter
]
=
useState
(
FILTERS
.
BALANCES
)
// toggle specific token import view
// toggle specific token import view
const
[
showTokenImport
,
setShowTokenImport
]
=
useState
(
false
)
const
[
showTokenImport
,
setShowTokenImport
]
=
useState
(
false
)
...
@@ -201,22 +91,6 @@ function SearchModal({
...
@@ -201,22 +91,6 @@ function SearchModal({
// used to help scanning on results, put token found from input on left
// used to help scanning on results, put token found from input on left
const
[
identifiedToken
,
setIdentifiedToken
]
=
useState
<
Token
>
()
const
[
identifiedToken
,
setIdentifiedToken
]
=
useState
<
Token
>
()
useEffect
(()
=>
{
const
address
=
isAddress
(
searchQuery
)
if
(
address
&&
!
token
)
{
let
stale
=
false
fetchTokenByAddress
(
address
).
then
(
token
=>
{
if
(
!
stale
)
{
setTemporaryToken
(
token
)
}
})
return
()
=>
{
stale
=
true
setTemporaryToken
(
null
)
}
}
},
[
searchQuery
,
token
,
fetchTokenByAddress
])
// reset view on close
// reset view on close
useEffect
(()
=>
{
useEffect
(()
=>
{
if
(
!
isOpen
)
{
if
(
!
isOpen
)
{
...
@@ -224,45 +98,24 @@ function SearchModal({
...
@@ -224,45 +98,24 @@ function SearchModal({
}
}
},
[
isOpen
])
},
[
isOpen
])
const
tokenList
=
useMemo
(()
=>
{
const
tokenComparator
=
useTokenComparator
(
invertSearchOrder
)
return
Object
.
keys
(
allTokens
)
.
sort
((
tokenAddressA
,
tokenAddressB
):
number
=>
{
// -1 = a is first
// 1 = b is first
// sort ETH first
const
a
=
allTokens
[
tokenAddressA
]
const
b
=
allTokens
[
tokenAddressB
]
if
(
a
.
equals
(
WETH
[
chainId
]))
return
-
1
if
(
b
.
equals
(
WETH
[
chainId
]))
return
1
// sort by balances
const
balanceA
=
allBalances
[
account
]?.[
tokenAddressA
]
const
balanceB
=
allBalances
[
account
]?.[
tokenAddressB
]
if
(
balanceA
?.
greaterThan
(
'
0
'
)
&&
!
balanceB
?.
greaterThan
(
'
0
'
))
return
!
invertSearchOrder
?
-
1
:
1
if
(
!
balanceA
?.
greaterThan
(
'
0
'
)
&&
balanceB
?.
greaterThan
(
'
0
'
))
return
!
invertSearchOrder
?
1
:
-
1
if
(
balanceA
?.
greaterThan
(
'
0
'
)
&&
balanceB
?.
greaterThan
(
'
0
'
))
{
return
balanceA
.
greaterThan
(
balanceB
)
?
(
!
invertSearchOrder
?
-
1
:
1
)
:
!
invertSearchOrder
?
1
:
-
1
}
// sort by symbol
const
sortedTokenList
=
useMemo
(()
=>
{
return
a
.
symbol
.
toLowerCase
()
<
b
.
symbol
.
toLowerCase
()
?
-
1
:
1
return
Object
.
values
(
allTokens
)
})
.
sort
(
tokenComparator
)
.
map
(
tokenAddress
=>
{
.
map
(
token
=>
{
const
token
=
allTokens
[
tokenAddress
]
return
{
return
{
name
:
token
.
name
,
name
:
token
.
name
,
symbol
:
token
.
symbol
,
symbol
:
token
.
symbol
,
address
:
isAddress
(
tokenAddress
)
as
string
,
address
:
token
.
address
,
balance
:
allBalances
?.[
account
]?.[
tokenA
ddress
]
balance
:
allBalances
[
account
]?.[
token
.
a
ddress
]
}
}
})
})
},
[
allTokens
,
chainId
,
allBalances
,
account
,
invertSearchOrder
])
},
[
allTokens
,
tokenComparator
,
allBalances
,
account
])
const
filteredTokenList
=
useMemo
(()
=>
{
const
filteredTokenList
=
useMemo
(()
=>
{
return
tokenList
.
filter
(
tokenEntry
=>
{
return
sortedTokenList
.
filter
(
tokenEntry
=>
{
const
urlAdded
=
urlAddedTokens
?.
some
(
token
=>
token
.
address
===
tokenEntry
.
address
)
const
customAdded
=
!
isDefaultToken
(
tokenEntry
.
address
,
chainId
)
const
customAdded
=
userAddedTokens
?.
some
(
token
=>
token
.
address
===
tokenEntry
.
address
)
&&
!
urlAdded
// if token import page dont show preset list, else show all
// if token import page dont show preset list, else show all
const
include
=
!
showTokenImport
||
(
showTokenImport
&&
customAdded
&&
searchQuery
!==
''
)
const
include
=
!
showTokenImport
||
(
showTokenImport
&&
customAdded
&&
searchQuery
!==
''
)
...
@@ -285,7 +138,7 @@ function SearchModal({
...
@@ -285,7 +138,7 @@ function SearchModal({
})
})
return
regexMatches
.
some
(
m
=>
m
)
return
regexMatches
.
some
(
m
=>
m
)
})
})
},
[
tokenList
,
urlAddedTokens
,
userAddedTokens
,
showTokenImport
,
searchQuery
])
},
[
sortedTokenList
,
chainId
,
showTokenImport
,
searchQuery
])
function
_onTokenSelect
(
address
)
{
function
_onTokenSelect
(
address
)
{
setSearchQuery
(
''
)
setSearchQuery
(
''
)
...
@@ -313,18 +166,14 @@ function SearchModal({
...
@@ -313,18 +166,14 @@ function SearchModal({
// try to find an exact match by address
// try to find an exact match by address
if
(
searchQueryIsAddress
)
{
if
(
searchQueryIsAddress
)
{
const
identifiedTokenByAddress
=
Object
.
values
(
allTokens
).
filter
(
token
=>
{
const
identifiedTokenByAddress
=
Object
.
values
(
allTokens
).
filter
(
token
=>
{
if
(
searchQueryIsAddress
&&
token
.
address
===
isAddress
(
searchQuery
))
{
return
searchQueryIsAddress
&&
token
.
address
===
isAddress
(
searchQuery
)
return
true
}
return
false
})
})
if
(
identifiedTokenByAddress
.
length
>
0
)
setIdentifiedToken
(
identifiedTokenByAddress
[
0
])
if
(
identifiedTokenByAddress
.
length
>
0
)
setIdentifiedToken
(
identifiedTokenByAddress
[
0
])
}
}
// try to find an exact match by symbol
// try to find an exact match by symbol
else
{
else
{
const
identifiedTokenBySymbol
=
Object
.
values
(
allTokens
).
filter
(
token
=>
{
const
identifiedTokenBySymbol
=
Object
.
values
(
allTokens
).
filter
(
token
=>
{
if
(
token
.
symbol
.
slice
(
0
,
searchQuery
.
length
).
toLowerCase
()
===
searchQuery
.
toLowerCase
())
return
true
return
token
.
symbol
.
slice
(
0
,
searchQuery
.
length
).
toLowerCase
()
===
searchQuery
.
toLowerCase
()
return
false
})
})
if
(
identifiedTokenBySymbol
.
length
>
0
)
setIdentifiedToken
(
identifiedTokenBySymbol
[
0
])
if
(
identifiedTokenBySymbol
.
length
>
0
)
setIdentifiedToken
(
identifiedTokenBySymbol
[
0
])
}
}
...
@@ -423,25 +272,22 @@ function SearchModal({
...
@@ -423,25 +272,22 @@ function SearchModal({
function
renderTokenList
()
{
function
renderTokenList
()
{
if
(
filteredTokenList
.
length
===
0
)
{
if
(
filteredTokenList
.
length
===
0
)
{
if
(
isAddress
(
searchQuery
))
{
if
(
isAddress
(
searchQuery
))
{
if
(
temporaryToken
===
undefined
)
{
if
(
!
searchQueryToken
)
{
return
<
TokenModalInfo
>
Searching for Token...
</
TokenModalInfo
>
return
<
TokenModalInfo
>
Searching...
</
TokenModalInfo
>
}
else
if
(
temporaryToken
===
null
)
{
return
<
TokenModalInfo
>
Address is not a valid ERC-20 token.
</
TokenModalInfo
>
}
else
{
}
else
{
// a user found a token by search that isn't yet added to localstorage
// a user found a token by search that isn't yet added to localstorage
return
(
return
(
<
MenuItem
<
MenuItem
key=
{
tempora
ryToken
.
address
}
key=
{
searchQue
ryToken
.
address
}
className=
{
`temporary-token-${
temporaryToken
}`
}
className=
{
`temporary-token-${
searchQueryToken.address
}`
}
onClick=
{
()
=>
{
onClick=
{
()
=>
{
addToken
(
temporaryToken
)
_onTokenSelect
(
searchQueryToken
.
address
)
_onTokenSelect
(
temporaryToken
.
address
)
}
}
}
}
>
>
<
RowFixed
>
<
RowFixed
>
<
TokenLogo
address=
{
tempora
ryToken
.
address
}
size=
{
'
24px
'
}
style=
{
{
marginRight
:
'
14px
'
}
}
/>
<
TokenLogo
address=
{
searchQue
ryToken
.
address
}
size=
{
'
24px
'
}
style=
{
{
marginRight
:
'
14px
'
}
}
/>
<
Column
>
<
Column
>
<
Text
fontWeight=
{
500
}
>
{
tempora
ryToken
.
symbol
}
</
Text
>
<
Text
fontWeight=
{
500
}
>
{
searchQue
ryToken
.
symbol
}
</
Text
>
<
FadedSpan
>
(Found by search)
</
FadedSpan
>
<
FadedSpan
>
(Found by search)
</
FadedSpan
>
</
Column
>
</
Column
>
</
RowFixed
>
</
RowFixed
>
...
@@ -453,8 +299,7 @@ function SearchModal({
...
@@ -453,8 +299,7 @@ function SearchModal({
}
}
}
else
{
}
else
{
return
filteredTokenList
.
map
(({
address
,
symbol
,
balance
})
=>
{
return
filteredTokenList
.
map
(({
address
,
symbol
,
balance
})
=>
{
const
urlAdded
=
urlAddedTokens
?.
some
(
token
=>
token
.
address
===
address
)
const
customAdded
=
!
isDefaultToken
(
address
,
chainId
)
const
customAdded
=
userAddedTokens
?.
some
(
token
=>
token
.
address
===
address
)
&&
!
urlAdded
const
zeroBalance
=
balance
&&
JSBI
.
equal
(
JSBI
.
BigInt
(
0
),
balance
.
raw
)
const
zeroBalance
=
balance
&&
JSBI
.
equal
(
JSBI
.
BigInt
(
0
),
balance
.
raw
)
...
@@ -475,10 +320,7 @@ function SearchModal({
...
@@ -475,10 +320,7 @@ function SearchModal({
{
otherSelectedTokenAddress
===
address
&&
<
GreySpan
>
(
{
otherSelectedText
}
)
</
GreySpan
>
}
{
otherSelectedTokenAddress
===
address
&&
<
GreySpan
>
(
{
otherSelectedText
}
)
</
GreySpan
>
}
</
Text
>
</
Text
>
<
FadedSpan
>
<
FadedSpan
>
<
TYPE
.
main
fontWeight=
{
500
}
>
<
TYPE
.
main
fontWeight=
{
500
}
>
{
customAdded
&&
'
Added by user
'
}
</
TYPE
.
main
>
{
urlAdded
&&
'
Added by URL
'
}
{
customAdded
&&
'
Added by user
'
}
</
TYPE
.
main
>
{
customAdded
&&
(
{
customAdded
&&
(
<
div
<
div
onClick=
{
event
=>
{
onClick=
{
event
=>
{
...
@@ -522,27 +364,6 @@ function SearchModal({
...
@@ -522,27 +364,6 @@ function SearchModal({
}
}
}
}
const
Filter
=
({
title
,
filter
,
filterType
}:
{
title
:
string
;
filter
:
string
;
filterType
:
string
})
=>
{
return
(
<
FilterWrapper
onClick=
{
()
=>
{
setActiveFilter
(
filter
)
setInvertSearchOrder
(
invertSearchOrder
=>
!
invertSearchOrder
)
}
}
selected=
{
filter
===
activeFilter
}
>
<
Text
fontSize=
{
14
}
fontWeight=
{
500
}
>
{
title
}
</
Text
>
{
filter
===
activeFilter
&&
filterType
===
'
tokens
'
&&
(
<
Text
fontSize=
{
14
}
fontWeight=
{
500
}
>
{
!
invertSearchOrder
?
'
↓
'
:
'
↑
'
}
</
Text
>
)
}
</
FilterWrapper
>
)
}
return
(
return
(
<
Modal
<
Modal
isOpen=
{
isOpen
}
isOpen=
{
isOpen
}
...
@@ -578,7 +399,7 @@ function SearchModal({
...
@@ -578,7 +399,7 @@ function SearchModal({
<
PaddedColumn
gap=
"20px"
>
<
PaddedColumn
gap=
"20px"
>
<
RowBetween
>
<
RowBetween
>
<
Text
fontWeight=
{
500
}
fontSize=
{
16
}
>
<
Text
fontWeight=
{
500
}
fontSize=
{
16
}
>
{
filterType
===
'
tokens
'
?
'
Select
A Token
'
:
'
Select A P
ool
'
}
{
filterType
===
'
tokens
'
?
'
Select
a token
'
:
'
Select a p
ool
'
}
</
Text
>
</
Text
>
<
CloseIcon
onClick=
{
onDismiss
}
/>
<
CloseIcon
onClick=
{
onDismiss
}
/>
</
RowBetween
>
</
RowBetween
>
...
@@ -621,11 +442,13 @@ function SearchModal({
...
@@ -621,11 +442,13 @@ function SearchModal({
<
Text
fontSize=
{
14
}
fontWeight=
{
500
}
>
<
Text
fontSize=
{
14
}
fontWeight=
{
500
}
>
{
filterType
===
'
tokens
'
?
'
Token Name
'
:
'
Pool Name
'
}
{
filterType
===
'
tokens
'
?
'
Token Name
'
:
'
Pool Name
'
}
</
Text
>
</
Text
>
<
Filter
{
filterType
===
'
tokens
'
&&
(
<
TokenSortButton
invertSearchOrder=
{
invertSearchOrder
}
toggleSortOrder=
{
()
=>
setInvertSearchOrder
(
iso
=>
!
iso
)
}
title=
{
filterType
===
'
tokens
'
?
'
Your Balances
'
:
'
'
}
title=
{
filterType
===
'
tokens
'
?
'
Your Balances
'
:
'
'
}
filter=
{
FILTERS
.
BALANCES
}
filterType=
{
filterType
}
/>
/>
)
}
</
RowBetween
>
</
RowBetween
>
</
PaddedColumn
>
</
PaddedColumn
>
)
}
)
}
...
...
src/components/SearchModal/sorting.ts
0 → 100644
View file @
85d52b34
import
{
Token
,
TokenAmount
,
WETH
}
from
'
@uniswap/sdk
'
import
{
useMemo
}
from
'
react
'
import
{
useActiveWeb3React
}
from
'
../../hooks
'
import
{
useAllTokenBalancesTreatingWETHasETH
}
from
'
../../state/wallet/hooks
'
function
getTokenComparator
(
weth
:
Token
|
undefined
,
balances
:
{
[
tokenAddress
:
string
]:
TokenAmount
},
invertSearchOrder
:
boolean
):
(
tokenA
:
Token
,
tokenB
:
Token
)
=>
number
{
return
function
sortTokens
(
tokenA
:
Token
,
tokenB
:
Token
):
number
{
// -1 = a is first
// 1 = b is first
// sort ETH first
if
(
weth
)
{
if
(
tokenA
.
equals
(
weth
))
return
-
1
if
(
tokenB
.
equals
(
weth
))
return
1
}
// sort by balances
const
balanceA
=
balances
[
tokenA
.
address
]
const
balanceB
=
balances
[
tokenB
.
address
]
if
(
balanceA
?.
greaterThan
(
'
0
'
)
&&
!
balanceB
?.
greaterThan
(
'
0
'
))
return
!
invertSearchOrder
?
-
1
:
1
if
(
!
balanceA
?.
greaterThan
(
'
0
'
)
&&
balanceB
?.
greaterThan
(
'
0
'
))
return
!
invertSearchOrder
?
1
:
-
1
if
(
balanceA
?.
greaterThan
(
'
0
'
)
&&
balanceB
?.
greaterThan
(
'
0
'
))
{
return
balanceA
.
greaterThan
(
balanceB
)
?
(
!
invertSearchOrder
?
-
1
:
1
)
:
!
invertSearchOrder
?
1
:
-
1
}
// sort by symbol
return
tokenA
.
symbol
.
toLowerCase
()
<
tokenB
.
symbol
.
toLowerCase
()
?
-
1
:
1
}
}
export
function
useTokenComparator
(
inverted
:
boolean
):
(
tokenA
:
Token
,
tokenB
:
Token
)
=>
number
{
const
{
account
,
chainId
}
=
useActiveWeb3React
()
const
weth
=
WETH
[
chainId
]
const
balances
=
useAllTokenBalancesTreatingWETHasETH
()
return
useMemo
(()
=>
getTokenComparator
(
weth
,
balances
[
account
]
??
{},
inverted
),
[
account
,
balances
,
inverted
,
weth
])
}
src/components/SearchModal/styleds.tsx
0 → 100644
View file @
85d52b34
import
styled
from
'
styled-components
'
import
{
Spinner
}
from
'
../../theme
'
import
{
AutoColumn
}
from
'
../Column
'
import
{
AutoRow
,
RowBetween
,
RowFixed
}
from
'
../Row
'
export
const
TokenModalInfo
=
styled
.
div
`
${({
theme
})
=>
theme
.
flexRowNoWrap
}
align-items: center;
padding: 1rem 1rem;
margin: 0.25rem 0.5rem;
justify-content: center;
user-select: none;
min-height: 200px;
`
export
const
ItemList
=
styled
.
div
`
flex-grow: 1;
height: 254px;
overflow-y: scroll;
-webkit-overflow-scrolling: touch;
`
export
const
FadedSpan
=
styled
(
RowFixed
)
`
color:
${({
theme
})
=>
theme
.
primary1
}
;
font-size: 14px;
`
export
const
GreySpan
=
styled
.
span
`
color:
${({
theme
})
=>
theme
.
text3
}
;
font-weight: 400;
`
export
const
SpinnerWrapper
=
styled
(
Spinner
)
`
margin: 0 0.25rem 0 0.25rem;
color:
${({
theme
})
=>
theme
.
text4
}
;
opacity: 0.6;
`
export
const
Input
=
styled
.
input
`
position: relative;
display: flex;
padding: 16px;
align-items: center;
width: 100%;
white-space: nowrap;
background: none;
border: none;
outline: none;
border-radius: 20px;
color:
${({
theme
})
=>
theme
.
text1
}
;
border-style: solid;
border: 1px solid
${({
theme
})
=>
theme
.
bg3
}
;
-webkit-appearance: none;
font-size: 18px;
::placeholder {
color:
${({
theme
})
=>
theme
.
text3
}
;
}
`
export
const
FilterWrapper
=
styled
(
RowFixed
)
`
padding: 8px;
background-color:
${({
selected
,
theme
})
=>
selected
&&
theme
.
bg2
}
;
color:
${({
selected
,
theme
})
=>
(
selected
?
theme
.
text1
:
theme
.
text2
)}
;
border-radius: 8px;
user-select: none;
& > * {
user-select: none;
}
:hover {
cursor: pointer;
}
`
export
const
PaddedColumn
=
styled
(
AutoColumn
)
`
padding: 20px;
padding-bottom: 12px;
`
const
PaddedItem
=
styled
(
RowBetween
)
`
padding: 4px 20px;
height: 56px;
`
export
const
MenuItem
=
styled
(
PaddedItem
)
`
cursor:
${({
disabled
})
=>
!
disabled
&&
'
pointer
'
}
;
pointer-events:
${({
disabled
})
=>
disabled
&&
'
none
'
}
;
:hover {
background-color:
${({
theme
,
disabled
})
=>
!
disabled
&&
theme
.
bg2
}
;
}
opacity:
${({
disabled
,
selected
})
=>
(
disabled
||
selected
?
0.5
:
1
)}
;
`
export
const
BaseWrapper
=
styled
(
AutoRow
)
<
{
disable
?:
boolean
}
>
`
border: 1px solid
${({
theme
,
disable
})
=>
(
disable
?
'
transparent
'
:
theme
.
bg3
)}
;
padding: 0 6px;
border-radius: 10px;
width: 120px;
:hover {
cursor:
${({
disable
})
=>
!
disable
&&
'
pointer
'
}
;
background-color:
${({
theme
,
disable
})
=>
!
disable
&&
theme
.
bg2
}
;
}
background-color:
${({
theme
,
disable
})
=>
disable
&&
theme
.
bg3
}
;
opacity:
${({
disable
})
=>
disable
&&
'
0.4
'
}
;
`
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment