Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
F
frontend
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
vicotor
frontend
Commits
1484bb36
Commit
1484bb36
authored
Dec 26, 2023
by
tom
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch 'main' of github.com:blockscout/frontend into tom2drum/issue-1414
parents
f8d8b7f8
95243dc7
Changes
17
Show whitespace changes
Inline
Side-by-side
Showing
17 changed files
with
221 additions
and
109 deletions
+221
-109
cleanup.yml
.github/workflows/cleanup.yml
+1
-1
tasks.json
.vscode/tasks.json
+1
-0
.env.sepolia
configs/envs/.env.sepolia
+60
-0
index.tsx
pages/apps/index.tsx
+12
-1
ContractCode.pw.tsx
ui/address/contract/ContractCode.pw.tsx
+25
-0
ContractCode.tsx
ui/address/contract/ContractCode.tsx
+3
-4
ERC20TokensTableItem.tsx
ui/address/tokens/ERC20TokensTableItem.tsx
+8
-2
Marketplace.tsx
ui/pages/Marketplace.tsx
+1
-25
AddressAddToWallet.tsx
ui/shared/address/AddressAddToWallet.tsx
+1
-1
LayoutApp.tsx
ui/shared/layout/LayoutApp.tsx
+2
-1
ProfileMenuDesktop.tsx
ui/snippets/profileMenu/ProfileMenuDesktop.tsx
+1
-1
SearchBar.tsx
ui/snippets/searchBar/SearchBar.tsx
+48
-45
SearchBarInput.tsx
ui/snippets/searchBar/SearchBarInput.tsx
+16
-16
WalletMenuDesktop.tsx
ui/snippets/walletMenu/WalletMenuDesktop.tsx
+3
-1
WalletMenuMobile.tsx
ui/snippets/walletMenu/WalletMenuMobile.tsx
+3
-1
WalletTooltip.tsx
ui/snippets/walletMenu/WalletTooltip.tsx
+23
-8
TokensTableItem.tsx
ui/tokens/TokensTableItem.tsx
+13
-2
No files found.
.github/workflows/cleanup.yml
View file @
1484bb36
...
...
@@ -29,5 +29,5 @@ jobs:
cleanup_docker_image
:
uses
:
blockscout/blockscout-ci-cd/.github/workflows/cleanup_docker.yaml@master
with
:
dockerImage
:
prerelease
-$GITHUB_REF_NAME_SLUG
dockerImage
:
review
-$GITHUB_REF_NAME_SLUG
secrets
:
inherit
.vscode/tasks.json
View file @
1484bb36
...
...
@@ -318,6 +318,7 @@
"main.L2"
,
"poa_core"
,
"eth_goerli"
,
"sepolia"
,
"eth"
,
"rootstock"
,
"polygon"
,
...
...
configs/envs/.env.sepolia
0 → 100644
View file @
1484bb36
# Set of ENVs for Sepolia testnet network explorer
# https://eth-sepolia.blockscout.com/
# app configuration
NEXT_PUBLIC_APP_PROTOCOL=http
NEXT_PUBLIC_APP_HOST=localhost
NEXT_PUBLIC_APP_PORT=3000
# blockchain parameters
NEXT_PUBLIC_NETWORK_NAME=Sepolia
NEXT_PUBLIC_NETWORK_SHORT_NAME=Sepolia
NEXT_PUBLIC_NETWORK_ID=11155111
NEXT_PUBLIC_NETWORK_CURRENCY_NAME=Ether
NEXT_PUBLIC_NETWORK_CURRENCY_SYMBOL=ETH
NEXT_PUBLIC_NETWORK_CURRENCY_DECIMALS=18
NEXT_PUBLIC_NETWORK_VERIFICATION_TYPE=validation
NEXT_PUBLIC_NETWORK_RPC_URL=https://eth-sepolia.public.blastapi.io
NEXT_PUBLIC_IS_TESTNET=true
# api configuration
NEXT_PUBLIC_API_HOST=eth-sepolia.blockscout.com
NEXT_PUBLIC_API_BASE_PATH=/
# ui config
## homepage
NEXT_PUBLIC_HOMEPAGE_CHARTS=['daily_txs']
NEXT_PUBLIC_HOMEPAGE_PLATE_BACKGROUND='rgba(51, 53, 67, 1)'
NEXT_PUBLIC_HOMEPAGE_PLATE_TEXT_COLOR='rgba(165, 252, 122, 1)'
## sidebar
NEXT_PUBLIC_FEATURED_NETWORKS=https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/featured-networks/eth-sepolia.json
NEXT_PUBLIC_NETWORK_LOGO=https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/network-logos/sepolia.svg
NEXT_PUBLIC_NETWORK_LOGO_DARK=https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/network-logos/sepolia.svg
NEXT_PUBLIC_NETWORK_ICON=https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/network-icons/sepolia.png
NEXT_PUBLIC_NETWORK_ICON_DARK=https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/network-icons/sepolia.png
NEXT_PUBLIC_OTHER_LINKS=[{'url':'https://sepolia.drpc.org?ref=559183','text':'Public RPC'}]
## footer
NEXT_PUBLIC_FOOTER_LINKS=https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/footer-links/sepolia.json
##views
NEXT_PUBLIC_VIEWS_NFT_MARKETPLACES=[{'name':'LooksRare','collection_url':'https://sepolia.looksrare.org/collections/{hash}','instance_url':'https://sepolia.looksrare.org/collections/{hash}/{id}','logo_url':'https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/nft-marketplace-logos/looks-rare.png'}]
## misc
NEXT_PUBLIC_NETWORK_EXPLORERS=[{'title':'Etherscan','baseUrl':'https://sepolia.etherscan.io/','paths':{'tx':'/tx','address':'/address','token':'/token','block':'/block'}},{'title':'Tenderly','baseUrl':'https://dashboard.tenderly.co','paths':{'tx':'/tx/sepolia'}}]
# app features
NEXT_PUBLIC_APP_ENV=development
NEXT_PUBLIC_GRAPHIQL_TRANSACTION=0xbf69c7abc4fee283b59a9633dadfdaedde5c5ee0fba3e80a08b5b8a3acbd4363
NEXT_PUBLIC_IS_ACCOUNT_SUPPORTED=true
NEXT_PUBLIC_AUTH_URL=http://localhost:3000
NEXT_PUBLIC_LOGOUT_URL=https://blockscout-goerli.us.auth0.com/v2/logout
NEXT_PUBLIC_MARKETPLACE_CONFIG_URL=https://raw.githubusercontent.com/blockscout/frontend-configs/dev/configs/marketplace/eth-goerli.json
NEXT_PUBLIC_MARKETPLACE_SUBMIT_FORM=https://airtable.com/shrqUAcjgGJ4jU88C
NEXT_PUBLIC_STATS_API_HOST=https://stats-sepolia.k8s-dev.blockscout.com
NEXT_PUBLIC_VISUALIZE_API_HOST=https://visualizer.services.blockscout.com
NEXT_PUBLIC_CONTRACT_INFO_API_HOST=https://contracts-info.services.blockscout.com
NEXT_PUBLIC_ADMIN_SERVICE_API_HOST=https://admin-rs.services.blockscout.com
NEXT_PUBLIC_WEB3_WALLETS=['token_pocket','metamask']
NEXT_PUBLIC_VIEWS_CONTRACT_SOLIDITYSCAN_ENABLED=true
NEXT_PUBLIC_HAS_BEACON_CHAIN=true
#meta
NEXT_PUBLIC_OG_IMAGE_URL=https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/og-images/sepolia-testnet.png
pages/apps/index.tsx
View file @
1484bb36
...
...
@@ -4,15 +4,26 @@ import React from 'react';
import
PageNextJs
from
'
nextjs/PageNextJs
'
;
import
config
from
'
configs/app
'
;
import
LinkExternal
from
'
ui/shared/LinkExternal
'
;
import
PageTitle
from
'
ui/shared/Page/PageTitle
'
;
const
feature
=
config
.
features
.
marketplace
;
const
Marketplace
=
dynamic
(()
=>
import
(
'
ui/pages/Marketplace
'
),
{
ssr
:
false
});
const
Page
:
NextPage
=
()
=>
{
return
(
<
PageNextJs
pathname=
"/apps"
>
<>
<
PageTitle
title=
"DAppscout"
/>
<
PageTitle
title=
"DAppscout"
contentAfter=
{
feature
.
isEnabled
&&
(
<
LinkExternal
href=
{
feature
.
submitFormUrl
}
variant=
"subtle"
fontSize=
"sm"
lineHeight=
{
5
}
ml=
"auto"
>
Submit app
</
LinkExternal
>
)
}
/>
<
Marketplace
/>
</>
</
PageNextJs
>
...
...
ui/address/contract/ContractCode.pw.tsx
View file @
1484bb36
...
...
@@ -78,6 +78,31 @@ test('verified with changed byte code socket', async({ mount, page, createSocket
await
expect
(
component
).
toHaveScreenshot
();
});
test
(
'
verified via lookup in eth_bytecode_db
'
,
async
({
mount
,
page
,
createSocket
})
=>
{
await
page
.
route
(
CONTRACT_API_URL
,
(
route
)
=>
route
.
fulfill
({
status
:
200
,
body
:
JSON
.
stringify
(
contractMock
.
nonVerified
),
}));
await
page
.
route
(
'
https://cdn.jsdelivr.net/npm/monaco-editor@0.33.0/**
'
,
(
route
)
=>
route
.
abort
());
await
mount
(
<
TestApp
withSocket
>
<
ContractCode
addressHash=
{
addressHash
}
/>
</
TestApp
>,
{
hooksConfig
},
);
const
socket
=
await
createSocket
();
const
channel
=
await
socketServer
.
joinChannel
(
socket
,
'
addresses:
'
+
addressHash
.
toLowerCase
());
await
page
.
waitForResponse
(
CONTRACT_API_URL
);
socketServer
.
sendMessage
(
socket
,
channel
,
'
smart_contract_was_verified
'
,
{});
const
request
=
await
page
.
waitForRequest
(
CONTRACT_API_URL
);
expect
(
request
).
toBeTruthy
();
});
test
(
'
verified with multiple sources
'
,
async
({
mount
,
page
})
=>
{
await
page
.
route
(
CONTRACT_API_URL
,
(
route
)
=>
route
.
fulfill
({
status
:
200
,
...
...
ui/address/contract/ContractCode.tsx
View file @
1484bb36
...
...
@@ -38,7 +38,6 @@ const ContractCode = ({ addressHash, noSocket }: Props) => {
const
[
isChangedBytecodeSocket
,
setIsChangedBytecodeSocket
]
=
React
.
useState
<
boolean
>
();
const
queryClient
=
useQueryClient
();
const
refetchQueries
=
queryClient
.
refetchQueries
;
const
addressInfo
=
queryClient
.
getQueryData
<
AddressInfo
>
(
getResourceKey
(
'
address
'
,
{
pathParams
:
{
hash
:
addressHash
}
}));
const
{
data
,
isPlaceholderData
,
isError
}
=
useApiQuery
(
'
contract
'
,
{
...
...
@@ -55,13 +54,13 @@ const ContractCode = ({ addressHash, noSocket }: Props) => {
},
[
]);
const
handleContractWasVerifiedMessage
:
SocketMessage
.
SmartContractWasVerified
[
'
handler
'
]
=
React
.
useCallback
(()
=>
{
refetchQueries
({
queryClient
.
refetchQueries
({
queryKey
:
getResourceKey
(
'
address
'
,
{
pathParams
:
{
hash
:
addressHash
}
}),
});
refetchQueries
({
queryClient
.
refetchQueries
({
queryKey
:
getResourceKey
(
'
contract
'
,
{
pathParams
:
{
hash
:
addressHash
}
}),
});
},
[
addressHash
,
refetchQueries
]);
},
[
addressHash
,
queryClient
]);
const
enableQuery
=
React
.
useCallback
(()
=>
setIsQueryEnabled
(
true
),
[]);
...
...
ui/address/tokens/ERC20TokensTableItem.tsx
View file @
1484bb36
...
...
@@ -22,7 +22,13 @@ const ERC20TokensTableItem = ({
}
=
getCurrencyValue
({
value
:
value
,
exchangeRate
:
token
.
exchange_rate
,
decimals
:
token
.
decimals
,
accuracy
:
8
,
accuracyUsd
:
2
});
return
(
<
Tr
>
<
Tr
sx=
{
{
'
&:hover [aria-label="Add token to wallet"]
'
:
{
opacity
:
1
,
},
}
}
>
<
Td
verticalAlign=
"middle"
>
<
TokenEntity
token=
{
token
}
...
...
@@ -39,7 +45,7 @@ const ERC20TokensTableItem = ({
isLoading=
{
isLoading
}
noIcon
/>
<
AddressAddToWallet
token=
{
token
}
ml=
{
4
}
isLoading=
{
isLoading
}
/>
<
AddressAddToWallet
token=
{
token
}
ml=
{
4
}
isLoading=
{
isLoading
}
opacity=
"0"
/>
</
Flex
>
</
Td
>
<
Td
isNumeric
verticalAlign=
"middle"
>
...
...
ui/pages/Marketplace.tsx
View file @
1484bb36
import
{
Box
,
Link
,
Skeleton
}
from
'
@chakra-ui/react
'
;
import
{
Box
}
from
'
@chakra-ui/react
'
;
import
React
from
'
react
'
;
import
config
from
'
configs/app
'
;
...
...
@@ -7,7 +7,6 @@ import MarketplaceCategoriesMenu from 'ui/marketplace/MarketplaceCategoriesMenu'
import
MarketplaceDisclaimerModal
from
'
ui/marketplace/MarketplaceDisclaimerModal
'
;
import
MarketplaceList
from
'
ui/marketplace/MarketplaceList
'
;
import
FilterInput
from
'
ui/shared/filters/FilterInput
'
;
import
IconSvg
from
'
ui/shared/IconSvg
'
;
import
useMarketplace
from
'
../marketplace/useMarketplace
'
;
const
feature
=
config
.
features
.
marketplace
;
...
...
@@ -91,29 +90,6 @@ const Marketplace = () => {
appId=
{
selectedApp
.
id
}
/>
)
}
<
Skeleton
isLoaded=
{
!
isPlaceholderData
}
marginTop=
{
{
base
:
8
,
sm
:
16
}
}
display=
"inline-block"
>
<
Link
fontWeight=
"bold"
display=
"inline-flex"
alignItems=
"baseline"
href=
{
feature
.
submitFormUrl
}
isExternal
>
<
IconSvg
name=
"plus"
w=
{
3
}
h=
{
3
}
mr=
{
2
}
/>
Submit an app
</
Link
>
</
Skeleton
>
</>
);
};
...
...
ui/shared/address/AddressAddToWallet.tsx
View file @
1484bb36
...
...
@@ -107,7 +107,7 @@ const AddressAddToWallet = ({ className, token, isLoading, variant = 'icon', ico
return
(
<
Tooltip
label=
{
`Add token to ${ WALLETS_INFO[wallet].name }`
}
>
<
Box
className=
{
className
}
display=
"inline-flex"
cursor=
"pointer"
onClick=
{
handleClick
}
flexShrink=
{
0
}
>
<
Box
className=
{
className
}
display=
"inline-flex"
cursor=
"pointer"
onClick=
{
handleClick
}
flexShrink=
{
0
}
aria
-
label=
"Add token to wallet"
>
<
IconSvg
name=
{
WALLETS_INFO
[
wallet
].
icon
}
boxSize=
{
iconSize
}
/>
</
Box
>
</
Tooltip
>
...
...
ui/shared/layout/LayoutApp.tsx
View file @
1484bb36
...
...
@@ -12,10 +12,11 @@ import * as Layout from './components';
const
LayoutDefault
=
({
children
}:
Props
)
=>
{
return
(
<
Layout
.
Container
>
<
Layout
.
TopRow
/>
<
HeaderMobile
/>
<
Layout
.
MainArea
>
<
Layout
.
MainColumn
paddingTop=
{
{
base
:
'
138px
'
,
lg
:
6
}
}
paddingTop=
{
{
base
:
16
,
lg
:
6
}
}
paddingX=
{
{
base
:
4
,
lg
:
6
}
}
>
<
HeaderAlert
/>
...
...
ui/snippets/profileMenu/ProfileMenuDesktop.tsx
View file @
1484bb36
...
...
@@ -76,7 +76,7 @@ const ProfileMenuDesktop = ({ isHomePage }: Props) => {
textAlign=
"center"
padding=
{
2
}
isDisabled=
{
hasMenu
}
openDelay=
{
3
00
}
openDelay=
{
5
00
}
>
<
Box
>
<
PopoverTrigger
>
...
...
ui/snippets/searchBar/SearchBar.tsx
View file @
1484bb36
import
{
Box
,
Po
pover
,
PopoverTrigger
,
PopoverContent
,
PopoverBody
,
useDisclosure
,
PopoverFooter
}
from
'
@chakra-ui/react
'
;
import
{
Box
,
Po
rtal
,
Popover
,
PopoverTrigger
,
PopoverContent
,
PopoverBody
,
useDisclosure
,
PopoverFooter
,
useOutsideClick
}
from
'
@chakra-ui/react
'
;
import
_debounce
from
'
lodash/debounce
'
;
import
{
useRouter
}
from
'
next/router
'
;
import
type
{
FormEvent
,
FocusEvent
}
from
'
react
'
;
import
type
{
FormEvent
}
from
'
react
'
;
import
React
from
'
react
'
;
import
{
Element
}
from
'
react-scroll
'
;
...
...
@@ -59,13 +59,15 @@ const SearchBar = ({ isHomepage }: Props) => {
inputRef
.
current
?.
querySelector
(
'
input
'
)?.
blur
();
},
[
onClose
]);
const
handle
Blur
=
React
.
useCallback
((
event
:
FocusEvent
<
HTMLFormElement
>
)
=>
{
const
isFocusIn
Menu
=
menuRef
.
current
?.
contains
(
event
.
relatedTarget
);
const
isFocusInInput
=
inputRef
.
current
?.
contains
(
event
.
relatedTarget
);
if
(
!
isFocusIn
Menu
&&
!
isFocusIn
Input
)
{
onClos
e
();
const
handle
OutsideClick
=
React
.
useCallback
((
event
:
Event
)
=>
{
const
isFocusIn
Input
=
inputRef
.
current
?.
contains
(
event
.
target
as
Node
);
if
(
!
isFocusInInput
)
{
handelHid
e
();
}
},
[
onClose
]);
},
[
handelHide
]);
useOutsideClick
({
ref
:
menuRef
,
handler
:
handleOutsideClick
});
const
handleClear
=
React
.
useCallback
(()
=>
{
handleSearchTermChange
(
''
);
...
...
@@ -118,13 +120,13 @@ const SearchBar = ({ isHomepage }: Props) => {
onChange=
{
handleSearchTermChange
}
onSubmit=
{
handleSubmit
}
onFocus=
{
handleFocus
}
onBlur=
{
handleBlur
}
onHide=
{
handelHide
}
onClear=
{
handleClear
}
isHomepage=
{
isHomepage
}
value=
{
searchTerm
}
/>
</
PopoverTrigger
>
<
Portal
>
<
PopoverContent
w=
{
`${ menuWidth.current }px`
}
ref=
{
menuRef
}
...
...
@@ -165,6 +167,7 @@ const SearchBar = ({ isHomepage }: Props) => {
</
PopoverFooter
>
)
}
</
PopoverContent
>
</
Portal
>
</
Popover
>
);
};
...
...
ui/snippets/searchBar/SearchBarInput.tsx
View file @
1484bb36
...
...
@@ -20,25 +20,33 @@ interface Props {
}
const
SearchBarInput
=
({
onChange
,
onSubmit
,
isHomepage
,
onFocus
,
onBlur
,
onHide
,
onClear
,
value
}:
Props
,
ref
:
React
.
ForwardedRef
<
HTMLFormElement
>
)
=>
{
const
innerRef
=
React
.
useRef
<
HTMLFormElement
>
(
null
);
React
.
useImperativeHandle
(
ref
,
()
=>
innerRef
.
current
as
HTMLFormElement
,
[]);
const
[
isSticky
,
setIsSticky
]
=
React
.
useState
(
false
);
const
scrollDirection
=
useScrollDirection
();
const
isMobile
=
useIsMobile
();
const
handleScroll
=
React
.
useCallback
(()
=>
{
const
TOP_BAR_HEIGHT
=
36
;
if
(
window
.
pageYOffset
>=
TOP_BAR_HEIGHT
)
{
if
(
!
isHomepage
)
{
if
(
window
.
scrollY
>=
TOP_BAR_HEIGHT
)
{
setIsSticky
(
true
);
}
else
{
setIsSticky
(
false
);
}
},
[
]);
}
const
clientRect
=
isMobile
&&
innerRef
?.
current
?.
getBoundingClientRect
();
if
(
clientRect
&&
clientRect
.
y
<
TOP_BAR_HEIGHT
)
{
onHide
?.();
}
},
[
isMobile
,
onHide
,
isHomepage
]);
const
handleChange
=
React
.
useCallback
((
event
:
ChangeEvent
<
HTMLInputElement
>
)
=>
{
onChange
(
event
.
target
.
value
);
},
[
onChange
]);
React
.
useEffect
(()
=>
{
if
(
!
isMobile
||
isHomepage
)
{
if
(
!
isMobile
)
{
return
;
}
const
throttledHandleScroll
=
throttle
(
handleScroll
,
300
);
...
...
@@ -48,22 +56,14 @@ const SearchBarInput = ({ onChange, onSubmit, isHomepage, onFocus, onBlur, onHid
return
()
=>
{
window
.
removeEventListener
(
'
scroll
'
,
throttledHandleScroll
);
};
// replicate componentDidMount
// eslint-disable-next-line react-hooks/exhaustive-deps
},
[
isMobile
]);
},
[
isMobile
,
handleScroll
]);
const
bgColor
=
useColorModeValue
(
'
white
'
,
'
black
'
);
const
transformMobile
=
scrollDirection
!==
'
down
'
?
'
translateY(0)
'
:
'
translateY(-100%)
'
;
React
.
useEffect
(()
=>
{
if
(
isMobile
&&
scrollDirection
===
'
down
'
)
{
onHide
?.();
}
},
[
scrollDirection
,
onHide
,
isMobile
]);
return
(
<
chakra
.
form
ref=
{
r
ef
}
ref=
{
innerR
ef
}
noValidate
onSubmit=
{
onSubmit
}
onBlur=
{
onBlur
}
...
...
ui/snippets/walletMenu/WalletMenuDesktop.tsx
View file @
1484bb36
...
...
@@ -2,6 +2,7 @@ import type { ButtonProps } from '@chakra-ui/react';
import
{
Popover
,
PopoverContent
,
PopoverBody
,
PopoverTrigger
,
Button
,
Box
,
useBoolean
}
from
'
@chakra-ui/react
'
;
import
React
from
'
react
'
;
import
useIsMobile
from
'
lib/hooks/useIsMobile
'
;
import
AddressIdenticon
from
'
ui/shared/entities/address/AddressIdenticon
'
;
import
HashStringShorten
from
'
ui/shared/HashStringShorten
'
;
import
useWallet
from
'
ui/snippets/walletMenu/useWallet
'
;
...
...
@@ -18,6 +19,7 @@ const WalletMenuDesktop = ({ isHomePage }: Props) => {
const
{
isWalletConnected
,
address
,
connect
,
disconnect
,
isModalOpening
,
isModalOpen
}
=
useWallet
();
const
{
themedBackground
,
themedBorderColor
,
themedColor
}
=
useMenuButtonColors
();
const
[
isPopoverOpen
,
setIsPopoverOpen
]
=
useBoolean
(
false
);
const
isMobile
=
useIsMobile
();
const
variant
=
React
.
useMemo
(()
=>
{
if
(
isWalletConnected
)
{
...
...
@@ -55,7 +57,7 @@ const WalletMenuDesktop = ({ isHomePage }: Props) => {
isOpen=
{
isPopoverOpen
}
onClose=
{
setIsPopoverOpen
.
off
}
>
<
WalletTooltip
isDisabled=
{
isWalletConnected
}
>
<
WalletTooltip
isDisabled=
{
isWalletConnected
||
isMobile
===
undefined
||
isMobile
}
>
<
Box
ml=
{
2
}
>
<
PopoverTrigger
>
<
Button
...
...
ui/snippets/walletMenu/WalletMenuMobile.tsx
View file @
1484bb36
import
{
Drawer
,
DrawerOverlay
,
DrawerContent
,
DrawerBody
,
useDisclosure
,
IconButton
}
from
'
@chakra-ui/react
'
;
import
React
from
'
react
'
;
import
useIsMobile
from
'
lib/hooks/useIsMobile
'
;
import
AddressIdenticon
from
'
ui/shared/entities/address/AddressIdenticon
'
;
import
IconSvg
from
'
ui/shared/IconSvg
'
;
import
useWallet
from
'
ui/snippets/walletMenu/useWallet
'
;
...
...
@@ -13,10 +14,11 @@ const WalletMenuMobile = () => {
const
{
isOpen
,
onOpen
,
onClose
}
=
useDisclosure
();
const
{
isWalletConnected
,
address
,
connect
,
disconnect
,
isModalOpening
,
isModalOpen
}
=
useWallet
();
const
{
themedBackground
,
themedBorderColor
,
themedColor
}
=
useMenuButtonColors
();
const
isMobile
=
useIsMobile
();
return
(
<>
<
WalletTooltip
isDisabled=
{
isWalletConnected
}
isMobile
>
<
WalletTooltip
isDisabled=
{
isWalletConnected
||
isMobile
===
undefined
||
!
isMobile
}
isMobile
>
<
IconButton
aria
-
label=
"wallet menu"
icon=
{
isWalletConnected
?
...
...
ui/snippets/walletMenu/WalletTooltip.tsx
View file @
1484bb36
import
{
Tooltip
,
useBoolean
}
from
'
@chakra-ui/react
'
;
import
{
Tooltip
,
useBoolean
,
useOutsideClick
}
from
'
@chakra-ui/react
'
;
import
{
useRouter
}
from
'
next/router
'
;
import
React
from
'
react
'
;
type
Props
=
{
...
...
@@ -8,27 +9,41 @@ type Props = {
};
const
WalletTooltip
=
({
children
,
isDisabled
,
isMobile
}:
Props
)
=>
{
const
router
=
useRouter
();
const
[
isTooltipShown
,
setIsTooltipShown
]
=
useBoolean
(
false
);
const
ref
=
React
.
useRef
(
null
);
useOutsideClick
({
ref
,
handler
:
setIsTooltipShown
.
off
});
const
{
defaultLabel
,
label
,
localStorageKey
}
=
React
.
useMemo
(()
=>
{
const
isAppPage
=
router
.
pathname
===
'
/apps/[id]
'
;
const
defaultLabel
=
<
span
>
Your wallet is used to interact with
<
br
/>
apps and contracts in the explorer
</
span
>;
const
label
=
isAppPage
?
<
span
>
Connect once to use your wallet with
<
br
/>
all apps in the DAppscout marketplace!
</
span
>
:
defaultLabel
;
const
localStorageKey
=
`
${
isAppPage
?
'
dapp-
'
:
''
}
wallet-connect-tooltip-shown`
;
return
{
defaultLabel
,
label
,
localStorageKey
};
},
[
router
.
pathname
]);
React
.
useEffect
(()
=>
{
const
key
=
`wallet-connect-tooltip-shown-
${
isMobile
?
'
mobile
'
:
'
desktop
'
}
`
;
const
wasShown
=
window
.
localStorage
.
getItem
(
key
);
if
(
!
wasShown
)
{
const
wasShown
=
window
.
localStorage
.
getItem
(
localStorageKey
);
if
(
!
isDisabled
&&
!
wasShown
)
{
setIsTooltipShown
.
on
();
window
.
localStorage
.
setItem
(
key
,
'
true
'
);
window
.
localStorage
.
setItem
(
localStorageKey
,
'
true
'
);
setTimeout
(()
=>
setIsTooltipShown
.
off
(),
3000
);
}
},
[
setIsTooltipShown
,
isMobile
]);
},
[
setIsTooltipShown
,
localStorageKey
,
isDisabled
]);
return
(
<
Tooltip
label=
{
<
span
>
Your wallet is used to interact with
<
br
/>
apps and contracts in the explorer
</
span
>
}
label=
{
isTooltipShown
?
label
:
defaultLabel
}
textAlign=
"center"
padding=
{
2
}
isDisabled=
{
isDisabled
}
openDelay=
{
3
00
}
openDelay=
{
5
00
}
isOpen=
{
isTooltipShown
||
(
isMobile
?
false
:
undefined
)
}
onClose=
{
setIsTooltipShown
.
off
}
display=
{
isMobile
?
{
base
:
'
flex
'
,
lg
:
'
none
'
}
:
{
base
:
'
none
'
,
lg
:
'
flex
'
}
}
ref=
{
ref
}
>
{
children
}
</
Tooltip
>
...
...
ui/tokens/TokensTableItem.tsx
View file @
1484bb36
...
...
@@ -51,7 +51,13 @@ const TokensTableItem = ({
};
return
(
<
Tr
>
<
Tr
sx=
{
{
'
&:hover [aria-label="Add token to wallet"]
'
:
{
opacity
:
1
,
},
}
}
>
<
Td
>
<
Flex
alignItems=
"flex-start"
>
<
Skeleton
...
...
@@ -81,7 +87,12 @@ const TokensTableItem = ({
fontSize=
"sm"
fontWeight=
{
500
}
/>
<
AddressAddToWallet
token=
{
token
}
isLoading=
{
isLoading
}
iconSize=
{
5
}
/>
<
AddressAddToWallet
token=
{
token
}
isLoading=
{
isLoading
}
iconSize=
{
5
}
opacity=
{
0
}
/>
</
Flex
>
<
Flex
columnGap=
{
1
}
>
<
Tag
isLoading=
{
isLoading
}
>
{
type
}
</
Tag
>
...
...
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