feat: implements LoadingModal that can be triggered for any loading functionality (#416)

Co-authored-by: Gancho Radkov <ganchoradkov@gmail.com>
This commit is contained in:
Gancho Radkov 2024-01-16 13:09:41 +02:00 committed by GitHub
parent da6f16a3ff
commit 06984232dc
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 102 additions and 39 deletions

View File

@ -16,6 +16,7 @@ import { Modal as NextModal } from '@nextui-org/react'
import { useSnapshot } from 'valtio' import { useSnapshot } from 'valtio'
import { useCallback, useMemo } from 'react' import { useCallback, useMemo } from 'react'
import AuthRequestModal from '@/views/AuthRequestModal' import AuthRequestModal from '@/views/AuthRequestModal'
import LoadingModal from '@/views/LoadingModal'
export default function Modal() { export default function Modal() {
const { open, view } = useSnapshot(ModalStore.state) const { open, view } = useSnapshot(ModalStore.state)
@ -56,6 +57,8 @@ export default function Modal() {
return <SessionSignKadenaModal /> return <SessionSignKadenaModal />
case 'AuthRequestModal': case 'AuthRequestModal':
return <AuthRequestModal /> return <AuthRequestModal />
case 'LoadingModal':
return <LoadingModal />
default: default:
return null return null
} }

View File

@ -3,7 +3,7 @@ import PageHeader from '@/components/PageHeader'
import QrReader from '@/components/QrReader' import QrReader from '@/components/QrReader'
import { web3wallet } from '@/utils/WalletConnectUtil' import { web3wallet } from '@/utils/WalletConnectUtil'
import { Button, Input, Loading, Text } from '@nextui-org/react' import { Button, Input, Loading, Text } from '@nextui-org/react'
import { Fragment, useMemo, useState } from 'react' import { Fragment, useEffect, useState } from 'react'
import { styledToast } from '@/utils/HelperUtil' import { styledToast } from '@/utils/HelperUtil'
import ModalStore from '@/store/ModalStore' import ModalStore from '@/store/ModalStore'
@ -27,7 +27,6 @@ export default function WalletConnectPage(params: { deepLink?: string }) {
}) })
try { try {
setLoading(true) setLoading(true)
ModalStore.open('SessionProposalModal', {})
web3wallet.core.pairing.events.on('pairing_expire', pairingExpiredListener) web3wallet.core.pairing.events.on('pairing_expire', pairingExpiredListener)
await web3wallet.pair({ uri }) await web3wallet.pair({ uri })
} catch (error) { } catch (error) {
@ -39,7 +38,7 @@ export default function WalletConnectPage(params: { deepLink?: string }) {
} }
} }
useMemo(() => { useEffect(() => {
if (deepLink) { if (deepLink) {
onConnect(deepLink) onConnect(deepLink)
} }
@ -48,34 +47,35 @@ export default function WalletConnectPage(params: { deepLink?: string }) {
return ( return (
<Fragment> <Fragment>
<PageHeader title="WalletConnect" /> <PageHeader title="WalletConnect" />
<>
<QrReader onConnect={onConnect} />
<QrReader onConnect={onConnect} /> <Text size={13} css={{ textAlign: 'center', marginTop: '$10', marginBottom: '$10' }}>
or use walletconnect uri
</Text>
<Text size={13} css={{ textAlign: 'center', marginTop: '$10', marginBottom: '$10' }}> <Input
or use walletconnect uri css={{ width: '100%' }}
</Text> bordered
aria-label="wc url connect input"
<Input placeholder="e.g. wc:a281567bb3e4..."
css={{ width: '100%' }} onChange={e => setUri(e.target.value)}
bordered value={uri}
aria-label="wc url connect input" data-testid="uri-input"
placeholder="e.g. wc:a281567bb3e4..." contentRight={
onChange={e => setUri(e.target.value)} <Button
value={uri} size="xs"
data-testid="uri-input" disabled={!uri}
contentRight={ css={{ marginLeft: -60 }}
<Button onClick={() => onConnect(uri)}
size="xs" color="gradient"
disabled={!uri} data-testid="uri-connect-button"
css={{ marginLeft: -60 }} >
onClick={() => onConnect(uri)} {loading ? <Loading size="md" type="points" color={'white'} /> : 'Connect'}
color="gradient" </Button>
data-testid="uri-connect-button" }
> />
{loading ? <Loading size="md" type="points" color={'white'} /> : 'Connect'} </>
</Button>
}
/>
</Fragment> </Fragment>
) )
} }

View File

@ -1,14 +1,46 @@
import { Text } from '@nextui-org/react' import { Text } from '@nextui-org/react'
import { Fragment } from 'react' import { Fragment, useCallback, useEffect, useState } from 'react'
import { useRouter } from 'next/router' import { useRouter } from 'next/router'
import WalletConnectPage from './walletconnect' import WalletConnectPage from './walletconnect'
import ModalStore from '@/store/ModalStore'
import { useSnapshot } from 'valtio'
export default function DeepLinkPairingPage() { export default function DeepLinkPairingPage() {
const state = useSnapshot(ModalStore.state)
const router = useRouter() const router = useRouter()
const [loadingMessage, setLoadingMessage] = useState<string>('')
const [requestTimeout, setRequestTimeout] = useState<NodeJS.Timeout | null>(null)
const uri = router.query.uri as string const uri = router.query.uri as string
const requestId = router.query.requestId as string const requestId = router.query.requestId as string
const removeTimeout = useCallback(() => {
if (requestTimeout) {
clearTimeout(requestTimeout)
}
}, [requestTimeout])
useEffect(() => {
if (state.view == 'LoadingModal') {
const timeout = setTimeout(() => {
setLoadingMessage('Your request is taking longer than usual. Feel free to try again.')
}, 15_000)
setRequestTimeout(timeout)
} else if (state.view) {
removeTimeout()
}
}, [state.view])
useEffect(() => {
if (requestId) {
ModalStore.open('LoadingModal', { loadingMessage })
}
if (uri) {
ModalStore.open('LoadingModal', { loadingMessage })
}
}, [uri, requestId, loadingMessage])
if (!uri && !requestId) { if (!uri && !requestId) {
return ( return (
<Fragment> <Fragment>

View File

@ -10,6 +10,7 @@ interface ModalData {
requestEvent?: SignClientTypes.EventArguments['session_request'] requestEvent?: SignClientTypes.EventArguments['session_request']
requestSession?: SessionTypes.Struct requestSession?: SessionTypes.Struct
request?: Web3WalletTypes.AuthRequest request?: Web3WalletTypes.AuthRequest
loadingMessage?: string
} }
interface State { interface State {
@ -29,6 +30,7 @@ interface State {
| 'SessionSignTezosModal' | 'SessionSignTezosModal'
| 'SessionSignKadenaModal' | 'SessionSignKadenaModal'
| 'AuthRequestModal' | 'AuthRequestModal'
| 'LoadingModal'
data?: ModalData data?: ModalData
} }

View File

@ -0,0 +1,34 @@
import { Col, Divider, Link, Loading, Row, Text, styled } from '@nextui-org/react'
import { CoreTypes } from '@walletconnect/types'
import NewReleasesIcon from '@mui/icons-material/NewReleases'
import RequestModalContainer from '@/components/RequestModalContainer'
import { useSnapshot } from 'valtio'
import ModalStore from '@/store/ModalStore'
export default function LoadingModal() {
const state = useSnapshot(ModalStore.state)
const message = state.data?.loadingMessage
return (
<RequestModalContainer title="">
<div style={{ textAlign: 'center', padding: '20px' }}>
<Row>
<Col>
<Loading size="lg" />
</Col>
</Row>
<Row align="center">
<Col>
<Text h3>Loading your request...</Text>
</Col>
</Row>
{message ? (
<div style={{ textAlign: 'center' }}>
<Divider y={1} />
<Text>{message}</Text>
</div>
) : null}
</div>
</RequestModalContainer>
)
}

View File

@ -1,4 +1,3 @@
/* eslint-disable react-hooks/rules-of-hooks */
import { Col, Grid, Loading, Row, Text, styled } from '@nextui-org/react' import { Col, Grid, Loading, Row, Text, styled } from '@nextui-org/react'
import { useCallback, useMemo, useState } from 'react' import { useCallback, useMemo, useState } from 'react'
import { buildApprovedNamespaces, getSdkError } from '@walletconnect/utils' import { buildApprovedNamespaces, getSdkError } from '@walletconnect/utils'
@ -265,14 +264,7 @@ export default function SessionProposalModal() {
ModalStore.close() ModalStore.close()
}, [proposal]) }, [proposal])
return !proposal ? ( return (
<>
<br />
<Loading size="lg" color="primary" type="default" />
<Text>Attempting to pair...</Text>
<br />
</>
) : (
<RequestModal <RequestModal
metadata={proposal.params.proposer.metadata} metadata={proposal.params.proposer.metadata}
onApprove={onApprove} onApprove={onApprove}