add countdown to refetch and refetch button
This commit is contained in:
parent
03fe88f012
commit
726863e053
|
@ -0,0 +1,49 @@
|
|||
type CircularProgressProps = {
|
||||
className?: string
|
||||
size: number
|
||||
progress: number
|
||||
trackWidth: number
|
||||
indicatorWidth: number
|
||||
}
|
||||
|
||||
const CircularProgress = ({
|
||||
className,
|
||||
indicatorWidth,
|
||||
progress,
|
||||
size,
|
||||
trackWidth,
|
||||
}: CircularProgressProps) => {
|
||||
const center = size / 2,
|
||||
radius =
|
||||
center - (trackWidth > indicatorWidth ? trackWidth : indicatorWidth),
|
||||
dashArray = 2 * Math.PI * radius,
|
||||
dashOffset = dashArray * ((100 - progress) / 100)
|
||||
|
||||
return (
|
||||
<>
|
||||
<div
|
||||
className={`relative ${className}`}
|
||||
style={{ width: size, height: size }}
|
||||
>
|
||||
<svg
|
||||
className="-rotate-90 fill-transparent stroke-th-fgd-4"
|
||||
style={{ width: size, height: size }}
|
||||
>
|
||||
<circle cx={center} cy={center} r={radius} strokeWidth={trackWidth} />
|
||||
<circle
|
||||
className="fill-transparent stroke-th-active"
|
||||
cx={center}
|
||||
cy={center}
|
||||
r={radius}
|
||||
strokeDasharray={dashArray}
|
||||
strokeDashoffset={dashOffset}
|
||||
strokeLinecap="round"
|
||||
strokeWidth={indicatorWidth}
|
||||
/>
|
||||
</svg>
|
||||
</div>
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
export default CircularProgress
|
|
@ -81,7 +81,11 @@ const MarketSwapForm = ({
|
|||
const { mangoAccount } = useMangoAccount()
|
||||
const quoteAmount =
|
||||
swapMode === 'ExactIn' ? amountInFormValue : amountOutFormValue
|
||||
const { bestRoute } = useQuoteRoutes({
|
||||
const {
|
||||
bestRoute,
|
||||
isFetching: fetchingRoute,
|
||||
refetch: refetchRoute,
|
||||
} = useQuoteRoutes({
|
||||
inputMint: inputBank?.mint.toString(),
|
||||
outputMint: outputBank?.mint.toString(),
|
||||
amount: quoteAmount,
|
||||
|
@ -296,8 +300,10 @@ const MarketSwapForm = ({
|
|||
<>
|
||||
<SwapReviewRouteInfo
|
||||
amountIn={amountInAsDecimal}
|
||||
loadingRoute={fetchingRoute}
|
||||
onClose={() => setShowConfirm(false)}
|
||||
onSuccess={onSuccess}
|
||||
refetchRoute={refetchRoute}
|
||||
routes={bestRoute ? [bestRoute] : undefined}
|
||||
selectedRoute={selectedRoute}
|
||||
setSelectedRoute={setSelectedRoute}
|
||||
|
|
|
@ -27,6 +27,7 @@ import {
|
|||
ArrowsRightLeftIcon,
|
||||
ArrowRightIcon,
|
||||
ChevronDownIcon,
|
||||
ArrowPathIcon,
|
||||
} from '@heroicons/react/20/solid'
|
||||
import { useTranslation } from 'next-i18next'
|
||||
import { formatNumericValue } from '../../utils/numbers'
|
||||
|
@ -54,14 +55,28 @@ import {
|
|||
TransactionErrors,
|
||||
parseTxForKnownErrors,
|
||||
} from '@blockworks-foundation/mango-v4'
|
||||
import CircularProgress from '@components/shared/CircularProgress'
|
||||
import {
|
||||
QueryObserverResult,
|
||||
RefetchOptions,
|
||||
RefetchQueryFilters,
|
||||
} from '@tanstack/react-query'
|
||||
|
||||
const set = mangoStore.getState().set
|
||||
|
||||
type JupiterRouteInfoProps = {
|
||||
amountIn: Decimal
|
||||
loadingRoute: boolean
|
||||
isWalletSwap?: boolean
|
||||
onClose: () => void
|
||||
onSuccess?: () => void
|
||||
refetchRoute:
|
||||
| (<TPageData>(
|
||||
options?: (RefetchOptions & RefetchQueryFilters<TPageData>) | undefined,
|
||||
) => Promise<
|
||||
QueryObserverResult<{ bestRoute: JupiterV6RouteInfo | null }, Error>
|
||||
>)
|
||||
| undefined
|
||||
routes: JupiterV6RouteInfo[] | undefined
|
||||
selectedRoute: JupiterV6RouteInfo | undefined | null
|
||||
setSelectedRoute: Dispatch<
|
||||
|
@ -217,9 +232,11 @@ const successSound = new Howl({
|
|||
|
||||
const SwapReviewRouteInfo = ({
|
||||
amountIn,
|
||||
loadingRoute,
|
||||
isWalletSwap,
|
||||
onClose,
|
||||
onSuccess,
|
||||
refetchRoute,
|
||||
routes,
|
||||
selectedRoute,
|
||||
setSelectedRoute,
|
||||
|
@ -243,6 +260,22 @@ const SwapReviewRouteInfo = ({
|
|||
)
|
||||
const focusRef = useRef<HTMLButtonElement>(null)
|
||||
|
||||
const [refetchRoutePercentage, setRefetchRoutePercentage] = useState(0)
|
||||
|
||||
useEffect(() => {
|
||||
let currentPercentage = 0
|
||||
const countdownInterval = setInterval(() => {
|
||||
if (currentPercentage < 100) {
|
||||
currentPercentage += 5 // 5% increment per second
|
||||
setRefetchRoutePercentage(currentPercentage)
|
||||
}
|
||||
}, 1000)
|
||||
|
||||
return () => {
|
||||
clearInterval(countdownInterval)
|
||||
}
|
||||
}, [selectedRoute])
|
||||
|
||||
const amountOut = useMemo(() => {
|
||||
if (!selectedRoute?.outAmount || !outputTokenInfo) return
|
||||
return new Decimal(selectedRoute.outAmount.toString()).div(
|
||||
|
@ -489,15 +522,40 @@ const SwapReviewRouteInfo = ({
|
|||
>
|
||||
<div className="thin-scroll flex h-full flex-col justify-between overflow-y-auto">
|
||||
<div>
|
||||
<div className="flex items-center justify-between px-4 pt-4">
|
||||
<IconButton
|
||||
className="absolute left-4 top-4 mr-3 text-th-fgd-2"
|
||||
className="text-th-fgd-2"
|
||||
onClick={onClose}
|
||||
size="small"
|
||||
ref={focusRef}
|
||||
>
|
||||
<ArrowLeftIcon className="h-5 w-5" />
|
||||
</IconButton>
|
||||
<div className="flex justify-center bg-th-bkg-1 p-6 pb-0">
|
||||
<div className="relative h-8 w-8">
|
||||
<CircularProgress
|
||||
size={32}
|
||||
indicatorWidth={1}
|
||||
trackWidth={1}
|
||||
progress={refetchRoutePercentage}
|
||||
/>
|
||||
{refetchRoute ? (
|
||||
<IconButton
|
||||
className="absolute bottom-0 left-0 right-0 top-0 text-th-fgd-2"
|
||||
hideBg
|
||||
onClick={() => refetchRoute()}
|
||||
size="small"
|
||||
ref={focusRef}
|
||||
>
|
||||
<ArrowPathIcon
|
||||
className={`h-5 w-5 ${
|
||||
loadingRoute ? 'animate-spin' : null
|
||||
}`}
|
||||
/>
|
||||
</IconButton>
|
||||
) : null}
|
||||
</div>
|
||||
</div>
|
||||
<div className="flex justify-center bg-th-bkg-1 px-6 pt-2">
|
||||
<div className="mb-3 flex w-full flex-col items-center border-b border-th-bkg-3 pb-4">
|
||||
<div className="relative mb-2 w-[72px]">
|
||||
<TokenLogo bank={inputBank} size={40} />
|
||||
|
|
|
@ -63,7 +63,11 @@ const WalletSwapForm = ({ setShowTokenSelect }: WalletSwapFormProps) => {
|
|||
const { connected, publicKey } = useWallet()
|
||||
const quoteAmount =
|
||||
swapMode === 'ExactIn' ? amountInFormValue : amountOutFormValue
|
||||
const { bestRoute } = useQuoteRoutes({
|
||||
const {
|
||||
bestRoute,
|
||||
isFetching: fetchingRoute,
|
||||
refetch: refetchRoute,
|
||||
} = useQuoteRoutes({
|
||||
inputMint: inputBank?.mint.toString(),
|
||||
outputMint: outputBank?.mint.toString(),
|
||||
amount: quoteAmount,
|
||||
|
@ -298,8 +302,10 @@ const WalletSwapForm = ({ setShowTokenSelect }: WalletSwapFormProps) => {
|
|||
<>
|
||||
<SwapReviewRouteInfo
|
||||
amountIn={amountInAsDecimal}
|
||||
loadingRoute={fetchingRoute}
|
||||
isWalletSwap
|
||||
onClose={() => setShowConfirm(false)}
|
||||
refetchRoute={refetchRoute}
|
||||
routes={bestRoute ? [bestRoute] : undefined}
|
||||
selectedRoute={selectedRoute}
|
||||
setSelectedRoute={setSelectedRoute}
|
||||
|
|
|
@ -256,14 +256,18 @@ const useQuoteRoutes = ({
|
|||
routes: [],
|
||||
bestRoute: undefined,
|
||||
}),
|
||||
isFetching: res.isFetching,
|
||||
isLoading: res.isLoading,
|
||||
isInitialLoading: res.isInitialLoading,
|
||||
refetch: res.refetch,
|
||||
}
|
||||
: {
|
||||
routes: [],
|
||||
bestRoute: undefined,
|
||||
isFetching: false,
|
||||
isLoading: false,
|
||||
isInitialLoading: false,
|
||||
refetch: undefined,
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue