Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Resuming deposit modal #138

Merged
merged 11 commits into from
Jan 29, 2024
16 changes: 16 additions & 0 deletions dapp/src/assets/icons/Pause.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import React from "react"
import { createIcon } from "@chakra-ui/react"

export const PauseIcon = createIcon({
displayName: "PauseIcon",
viewBox: "0 0 18 20",
path: (
<path
d="M2 18V2M16 18V2"
stroke="currentColor"
strokeWidth="3"
strokeLinecap="round"
strokeLinejoin="round"
/>
),
})
1 change: 1 addition & 0 deletions dapp/src/assets/icons/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,3 +9,4 @@ export * from "./ConnectBTCAccount"
export * from "./ConnectETHAccount"
export * from "./AlertInfo"
export * from "./ShieldPlus"
export * from "./Pause"
12 changes: 9 additions & 3 deletions dapp/src/components/Modals/Staking/DepositBTC.tsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,18 @@
import React from "react"
import React, { useCallback } from "react"
import { useDepositBTCTransaction, useModalFlowContext } from "#/hooks"
import Alert from "#/components/shared/Alert"
import { TextMd } from "#/components/shared/Typography"
import StakingSteps from "./components/StakingSteps"

export default function DepositBTC() {
const { goNext } = useModalFlowContext()
const { depositBTC } = useDepositBTCTransaction(goNext)
const { goNext, endTransactionProcess } = useModalFlowContext()

const onDepositSuccess = useCallback(() => {
endTransactionProcess()
goNext()
}, [endTransactionProcess, goNext])

const { depositBTC } = useDepositBTCTransaction(onDepositSuccess)

return (
<StakingSteps buttonText="Deposit BTC" activeStep={1} onClick={depositBTC}>
Expand Down
8 changes: 6 additions & 2 deletions dapp/src/components/Modals/Staking/SignMessage.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import React from "react"
import React, { useEffect } from "react"
import { Highlight } from "@chakra-ui/react"
import { useModalFlowContext, useSignMessage } from "#/hooks"
import Alert from "#/components/shared/Alert"
Expand All @@ -7,9 +7,13 @@ import { asyncWrapper } from "#/utils"
import StakingSteps from "./components/StakingSteps"

export default function SignMessage() {
const { goNext } = useModalFlowContext()
const { goNext, startTransactionProcess } = useModalFlowContext()
const { signMessage } = useSignMessage(goNext)

useEffect(() => {
startTransactionProcess()
}, [startTransactionProcess])

const handleClick = () => {
asyncWrapper(signMessage())
}
Expand Down
42 changes: 42 additions & 0 deletions dapp/src/components/Modals/Support/ResumeModal.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
import React from "react"
import {
ModalHeader,
ModalBody,
ModalFooter,
Button,
HStack,
} from "@chakra-ui/react"

import Spinner from "#/components/shared/Spinner"
import { PauseIcon } from "#/assets/icons"
import { TextMd } from "#/components/shared/Typography"

export default function ResumeModal({
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we can only name it as Resume. We are in the modals directory so it seems redundant to me. We had the same approach with MissingAccount or other modals declared here. The same goes for the file name.

Suggested change
export default function ResumeModal({
export default function Resume({

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We can keep the file name without the suffix modal because we are in the modals directory, but I recommend staying with the current naming convention of components because such a name says more about the component type and will not be confused with the name of a function or other component if it appears and is not modal. I would even recommend such a change in other places as eg: MissingAccountModal.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Discussion moved to discord

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The suffix may be useful when we import this modal and use it elsewhere, it adds clarity.
On the other hand we've already got bunch of components that don't have the suffixes:
ActionForm, Overview, etc.
Also let's take Details list, should it be renamed to DetailsList?
Should Pause icon become a PauseIcon?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It feels like a deeper discussion to establish the common patterns, that we shouldn't block this PR with, unless we agree on the pattern and decide to refactor it across the board in a follow-up.

Copy link
Collaborator

@Shadowfiend Shadowfiend Jan 24, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(I left some much more detailed thoughts in the Discord thread, but quick answers on the above two examples: Pause should be PauseIcon, and Details should have a more descriptive name than Details or DetailsList! Details of what?)

onResume,
onClose,
}: {
onResume: () => void
onClose: () => void
}) {
return (
<>
<ModalHeader>Paused</ModalHeader>
<ModalBody textAlign="start" py={6} mx={3}>
<HStack position="relative" justifyContent="center">
<Spinner size="xl" />
<PauseIcon position="absolute" boxSize={6} color="brand.400" />
</HStack>

<TextMd>Are your sure you want to cancel?</TextMd>
</ModalBody>
<ModalFooter flexDirection="column" gap={2}>
<Button size="lg" width="100%" onClick={onResume}>
Resume deposit
</Button>
<Button size="lg" width="100%" variant="outline" onClick={onClose}>
Yes, cancel
</Button>
</ModalFooter>
</>
)
}
7 changes: 7 additions & 0 deletions dapp/src/components/Modals/Support/index.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
import React from "react"
import {
useModalFlowContext,
useRequestBitcoinAccount,
useRequestEthereumAccount,
useWalletContext,
} from "#/hooks"
import { ConnectBTCAccount, ConnectETHAccount } from "#/assets/icons"
import MissingAccount from "./MissingAccount"
import ResumeModal from "./ResumeModal"

export default function SupportWrapper({
children,
Expand All @@ -15,6 +17,7 @@ export default function SupportWrapper({
const { btcAccount, ethAccount } = useWalletContext()
const { requestAccount: requestBitcoinAccount } = useRequestBitcoinAccount()
const { requestAccount: requestEthereumAccount } = useRequestEthereumAccount()
const { isPaused, onClose, onResume } = useModalFlowContext()

if (!btcAccount)
return (
Expand All @@ -34,5 +37,9 @@ export default function SupportWrapper({
/>
)

if (isPaused) {
return <ResumeModal onClose={onClose} onResume={onResume} />
}

return children
}
40 changes: 36 additions & 4 deletions dapp/src/components/TransactionModal/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -24,17 +24,37 @@ export default function TransactionModal({
const { onOpen: openSideBar, onClose: closeSidebar } = useSidebar()

const [activeStep, setActiveStep] = useState(defaultStep)
const [isPaused, setIsPaused] = useState(false)
const [isPendingTransaction, setIsPendingTransaction] = useState(false)

const handleResume = useCallback(() => {
setIsPaused(false)
}, [])

const handleGoNext = useCallback(() => {
setActiveStep((prevStep) => prevStep + 1)
}, [])

const handleClose = useCallback(() => {
onClose()
}, [onClose])
if (!isPaused && isPendingTransaction) {
setIsPaused(true)
} else {
onClose()
}
}, [isPaused, isPendingTransaction, onClose])

const handleStartTransactionProcess = useCallback(() => {
setIsPendingTransaction(true)
}, [setIsPendingTransaction])

const handleStopTransactionProcess = useCallback(() => {
setIsPendingTransaction(false)
}, [setIsPendingTransaction])

const resetState = useCallback(() => {
setActiveStep(defaultStep)
setIsPaused(false)
setIsPendingTransaction(false)
}, [defaultStep])

useEffect(() => {
Expand All @@ -58,14 +78,26 @@ export default function TransactionModal({
const contextValue: ModalFlowContextValue = useMemo<ModalFlowContextValue>(
() => ({
activeStep,
isPaused,
onClose: handleClose,
onResume: handleResume,
goNext: handleGoNext,
startTransactionProcess: handleStartTransactionProcess,
endTransactionProcess: handleStopTransactionProcess,
}),
[activeStep, handleGoNext, handleClose],
[
activeStep,
isPaused,
handleGoNext,
handleClose,
handleResume,
handleStartTransactionProcess,
handleStopTransactionProcess,
],
)

return (
<ModalBase isOpen={isOpen} onClose={onClose}>
<ModalBase isOpen={isOpen} onClose={handleClose}>
<TransactionContextProvider>
<ModalFlowContext.Provider value={contextValue}>
<SupportWrapper>{children}</SupportWrapper>
Expand Down
10 changes: 9 additions & 1 deletion dapp/src/contexts/ModalFlowContext.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,20 @@ export type ModalStep = {

export type ModalFlowContextValue = {
activeStep?: number
isPaused?: boolean
onClose: () => void
onResume: () => void
goNext: () => void
startTransactionProcess: () => void
endTransactionProcess: () => void
}

export const ModalFlowContext = createContext<ModalFlowContextValue>({
activeStep: undefined,
goNext: () => {},
isPaused: false,
onClose: () => {},
onResume: () => {},
goNext: () => {},
startTransactionProcess: () => {},
endTransactionProcess: () => {},
})
11 changes: 10 additions & 1 deletion dapp/src/theme/Spinner.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,4 +8,13 @@ const baseStyle = defineStyle({
borderLeftColor: "gold.400",
})

export const spinnerTheme = defineStyleConfig({ baseStyle })
const sizeXl = defineStyle({
width: 16,
height: 16,
})

const sizes = {
xl: sizeXl,
}

export const spinnerTheme = defineStyleConfig({ baseStyle, sizes })
Loading