-
Notifications
You must be signed in to change notification settings - Fork 195
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: mobile wallet new flow (#8689)
* add wallet switch * add active state * Update MobileWalletDialog.tsx * Update MobileWalletDialog.tsx * move button * add routes for wallet actions * add delete flow * Update SavedWallets.tsx * fix routing of delete * add missing translations * Update WalletList.tsx * comments * check for vault outside of confirm * Update DeleteWallet.tsx * fix: mergefix * fix: finish * fix: disable same button click * fix: try things * fix: review feedbacks * fix: a few more bugs --------- Co-authored-by: reallybeard <[email protected]>
- Loading branch information
1 parent
8489655
commit 7a87bf4
Showing
21 changed files
with
1,116 additions
and
349 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,40 @@ | ||
import { AnimatePresence } from 'framer-motion' | ||
import { MemoryRouter, Redirect, Route, Switch } from 'react-router' | ||
import { Dialog } from 'components/Modal/components/Dialog' | ||
|
||
import { DeleteWallet } from './routes/DeleteWallet/DeleteWallet' | ||
import { RenameWallet } from './routes/RenameWallet' | ||
import { SavedWallets } from './routes/SavedWallets' | ||
import { MobileWalletDialogRoutes } from './types' | ||
|
||
type MobileWalletDialogProps = { | ||
isOpen: boolean | ||
onClose: () => void | ||
} | ||
|
||
export const MobileWalletDialog: React.FC<MobileWalletDialogProps> = ({ isOpen, onClose }) => { | ||
return ( | ||
<Dialog isOpen={isOpen} onClose={onClose} height='auto' isDisablingPropagation={false}> | ||
<MemoryRouter> | ||
<Route> | ||
{({ location }) => ( | ||
<AnimatePresence mode='wait' initial={false}> | ||
<Switch key={location.key} location={location}> | ||
<Route path={MobileWalletDialogRoutes.Saved}> | ||
<SavedWallets onClose={onClose} /> | ||
</Route> | ||
<Route path={MobileWalletDialogRoutes.Rename}> | ||
<RenameWallet /> | ||
</Route> | ||
<Route path={MobileWalletDialogRoutes.Delete}> | ||
<DeleteWallet /> | ||
</Route> | ||
<Redirect exact from='/' to={MobileWalletDialogRoutes.Saved} /> | ||
</Switch> | ||
</AnimatePresence> | ||
)} | ||
</Route> | ||
</MemoryRouter> | ||
</Dialog> | ||
) | ||
} |
60 changes: 60 additions & 0 deletions
60
src/components/MobileWalletDialog/routes/DeleteWallet/Backup.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,60 @@ | ||
import { Button, Heading, Stack } from '@chakra-ui/react' | ||
import React, { useCallback } from 'react' | ||
import { useTranslate } from 'react-polyglot' | ||
import { useHistory } from 'react-router' | ||
import { MobileWalletDialogRoutes } from 'components/MobileWalletDialog/types' | ||
import { DialogBackButton } from 'components/Modal/components/DialogBackButton' | ||
import { DialogBody } from 'components/Modal/components/DialogBody' | ||
import { DialogFooter } from 'components/Modal/components/DialogFooter' | ||
import { DialogHeader, DialogHeaderLeft } from 'components/Modal/components/DialogHeader' | ||
import { SlideTransition } from 'components/SlideTransition' | ||
import { RawText } from 'components/Text' | ||
import { useModal } from 'hooks/useModal/useModal' | ||
|
||
// TODO: This is placeholder content follow up PR will implement this correctly | ||
|
||
type BackupProps = { | ||
onBack: () => void | ||
} | ||
|
||
export const Backup: React.FC<BackupProps> = ({ onBack }) => { | ||
const translate = useTranslate() | ||
const history = useHistory() | ||
const backupModal = useModal('backupNativePassphrase') | ||
|
||
const handleContinue = useCallback(() => { | ||
history.push(MobileWalletDialogRoutes.ConfirmDelete) | ||
}, [history]) | ||
|
||
const handleBackup = useCallback(() => { | ||
backupModal.open({}) | ||
}, [backupModal]) | ||
|
||
return ( | ||
<SlideTransition> | ||
<DialogHeader> | ||
<DialogHeaderLeft> | ||
<DialogBackButton onClick={onBack} /> | ||
</DialogHeaderLeft> | ||
</DialogHeader> | ||
<DialogBody pb={8}> | ||
<Stack> | ||
<Heading size='md' textAlign='center' maxWidth='250px' mx='auto'> | ||
{translate('modals.shapeShift.backupPassphrase.confirm.title')} | ||
</Heading> | ||
<RawText textAlign='center' maxWidth='300px' mx='auto' mb={6} color='text.subtle'> | ||
{translate('modals.shapeShift.backupPassphrase.confirm.body')} | ||
</RawText> | ||
</Stack> | ||
</DialogBody> | ||
<DialogFooter flexDir='column' gap={2}> | ||
<Button colorScheme='blue' size='lg' width='full' onClick={handleBackup}> | ||
{translate('modals.shapeShift.backupPassphrase.confirm.backupNow')} | ||
</Button> | ||
<Button colorScheme='gray' size='lg' width='full' onClick={handleContinue}> | ||
{translate('common.noThanks')} | ||
</Button> | ||
</DialogFooter> | ||
</SlideTransition> | ||
) | ||
} |
72 changes: 72 additions & 0 deletions
72
src/components/MobileWalletDialog/routes/DeleteWallet/Confirm.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,72 @@ | ||
import { WarningIcon } from '@chakra-ui/icons' | ||
import { Alert, AlertDescription, Button, Heading, Stack, Text } from '@chakra-ui/react' | ||
import { useCallback, useState } from 'react' | ||
import { useTranslate } from 'react-polyglot' | ||
import { DialogBackButton } from 'components/Modal/components/DialogBackButton' | ||
import { DialogBody } from 'components/Modal/components/DialogBody' | ||
import { DialogFooter } from 'components/Modal/components/DialogFooter' | ||
import { DialogHeader, DialogHeaderLeft } from 'components/Modal/components/DialogHeader' | ||
import { SlideTransition } from 'components/SlideTransition' | ||
import { deleteWallet } from 'context/WalletProvider/MobileWallet/mobileMessageHandlers' | ||
import type { RevocableWallet } from 'context/WalletProvider/MobileWallet/RevocableWallet' | ||
import { useWallet } from 'hooks/useWallet/useWallet' | ||
import { WalletCard } from 'pages/ConnectWallet/components/WalletCard' | ||
|
||
type ConfirmDeleteProps = { | ||
vault: RevocableWallet | ||
onBack: () => void | ||
} | ||
|
||
export const ConfirmDelete: React.FC<ConfirmDeleteProps> = ({ vault, onBack }) => { | ||
const [error, setError] = useState<string | null>(null) | ||
const translate = useTranslate() | ||
const { disconnect, state } = useWallet() | ||
|
||
const handleDelete = useCallback(async () => { | ||
if (vault?.id) { | ||
try { | ||
await deleteWallet(vault.id) | ||
|
||
if (state.walletInfo?.deviceId === vault.id) { | ||
disconnect() | ||
} | ||
onBack() | ||
} catch (e) { | ||
console.log(e) | ||
setError('walletProvider.shapeShift.load.error.delete') | ||
} | ||
} | ||
}, [onBack, vault?.id, disconnect, state.walletInfo?.deviceId]) | ||
|
||
return ( | ||
<SlideTransition> | ||
<DialogHeader> | ||
<DialogHeaderLeft> | ||
<DialogBackButton onClick={onBack} /> | ||
</DialogHeaderLeft> | ||
</DialogHeader> | ||
<DialogBody> | ||
<Stack mb={4}> | ||
<WarningIcon color='text.error' boxSize='48px' mx='auto' /> | ||
<Heading size='md' textAlign='center' maxWidth='250px' mx='auto'> | ||
{translate('walletProvider.shapeShift.load.confirmForget', { wallet: vault?.label })} | ||
</Heading> | ||
<Text textAlign='center' maxWidth='300px' mx='auto' mb={6} color='text.subtle'> | ||
{translate('walletProvider.shapeShift.load.confirmForgetBody')} | ||
</Text> | ||
<WalletCard wallet={vault} id={vault.id} /> | ||
</Stack> | ||
</DialogBody> | ||
<DialogFooter flexDir='column' gap={2}> | ||
{error && ( | ||
<Alert status='error'> | ||
<AlertDescription>{error}</AlertDescription> | ||
</Alert> | ||
)} | ||
<Button size='lg' colorScheme='red' width='full' onClick={handleDelete}> | ||
{translate('walletProvider.shapeShift.load.forgetWallet')} | ||
</Button> | ||
</DialogFooter> | ||
</SlideTransition> | ||
) | ||
} |
61 changes: 61 additions & 0 deletions
61
src/components/MobileWalletDialog/routes/DeleteWallet/DeleteWallet.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,61 @@ | ||
import { Button, Heading } from '@chakra-ui/react' | ||
import { AnimatePresence } from 'framer-motion' | ||
import { useCallback } from 'react' | ||
import { useTranslate } from 'react-polyglot' | ||
import { MemoryRouter, Redirect, Route, Switch, useHistory, useLocation } from 'react-router' | ||
import { MobileWalletDialogRoutes } from 'components/MobileWalletDialog/types' | ||
import { DialogBody } from 'components/Modal/components/DialogBody' | ||
import { SlideTransition } from 'components/SlideTransition' | ||
import type { MobileLocationState } from 'context/WalletProvider/MobileWallet/types' | ||
|
||
import { Backup } from './Backup' | ||
import { ConfirmDelete } from './Confirm' | ||
|
||
export const DeleteWallet = () => { | ||
const { | ||
state: { vault }, | ||
} = useLocation<MobileLocationState>() | ||
const history = useHistory() | ||
const translate = useTranslate() | ||
|
||
const handleBack = useCallback(() => { | ||
history.push(MobileWalletDialogRoutes.Saved) | ||
}, [history]) | ||
|
||
if (!vault) | ||
return ( | ||
<SlideTransition> | ||
<DialogBody> | ||
<Heading size='md' textAlign='center' maxWidth='250px' mx='auto'> | ||
{translate('common.somethingWentWrong')} | ||
</Heading> | ||
<Button onClick={handleBack} mx='auto'> | ||
{translate('common.goBack')} | ||
</Button> | ||
</DialogBody> | ||
</SlideTransition> | ||
) | ||
|
||
return ( | ||
<SlideTransition> | ||
<MemoryRouter> | ||
<Route> | ||
{({ location }) => ( | ||
<AnimatePresence mode='wait' initial={false}> | ||
<Switch key={location.key} location={location}> | ||
<Route path={MobileWalletDialogRoutes.Backup}> | ||
<Backup onBack={handleBack} /> | ||
</Route> | ||
<Route path={MobileWalletDialogRoutes.ConfirmDelete}> | ||
<ConfirmDelete vault={vault} onBack={handleBack} /> | ||
</Route> | ||
{/* TODO: This will change to backup in a follow up PR */} | ||
<Redirect from='/' to={MobileWalletDialogRoutes.ConfirmDelete} /> | ||
</Switch> | ||
</AnimatePresence> | ||
)} | ||
</Route> | ||
</MemoryRouter> | ||
</SlideTransition> | ||
) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,99 @@ | ||
import { Button, FormControl, FormErrorMessage, Input } from '@chakra-ui/react' | ||
import { useCallback } from 'react' | ||
import { useForm } from 'react-hook-form' | ||
import { useTranslate } from 'react-polyglot' | ||
import { useHistory, useLocation } from 'react-router' | ||
import { DialogBackButton } from 'components/Modal/components/DialogBackButton' | ||
import { DialogBody } from 'components/Modal/components/DialogBody' | ||
import { DialogFooter } from 'components/Modal/components/DialogFooter' | ||
import { | ||
DialogHeader, | ||
DialogHeaderLeft, | ||
DialogHeaderMiddle, | ||
} from 'components/Modal/components/DialogHeader' | ||
import { DialogTitle } from 'components/Modal/components/DialogTitle' | ||
import { SlideTransition } from 'components/SlideTransition' | ||
import { Text } from 'components/Text' | ||
import { updateWallet } from 'context/WalletProvider/MobileWallet/mobileMessageHandlers' | ||
import type { MobileLocationState } from 'context/WalletProvider/MobileWallet/types' | ||
|
||
import { MobileWalletDialogRoutes } from '../types' | ||
|
||
type FormValues = { | ||
label: string | ||
} | ||
|
||
export const RenameWallet = () => { | ||
const location = useLocation<MobileLocationState>() | ||
const history = useHistory() | ||
const translate = useTranslate() | ||
const { | ||
handleSubmit, | ||
register, | ||
formState: { errors, isSubmitting, isValid }, | ||
} = useForm<FormValues>({ | ||
mode: 'onChange', | ||
defaultValues: { label: location.state.vault?.label }, | ||
}) | ||
|
||
const onSubmit = useCallback( | ||
async (values: FormValues) => { | ||
if (!location.state.vault?.id) return | ||
try { | ||
await updateWallet(location.state.vault.id, { label: values.label }) | ||
history.goBack() | ||
} catch (e) { | ||
console.log(e) | ||
} | ||
}, | ||
[history, location.state.vault?.id], | ||
) | ||
|
||
const handleBack = useCallback(() => history.push(MobileWalletDialogRoutes.Saved), [history]) | ||
|
||
return ( | ||
<SlideTransition> | ||
<DialogHeader> | ||
<DialogHeaderLeft> | ||
<DialogBackButton onClick={handleBack} /> | ||
</DialogHeaderLeft> | ||
<DialogHeaderMiddle> | ||
<DialogTitle>{translate('walletProvider.shapeShift.rename.header')}</DialogTitle> | ||
</DialogHeaderMiddle> | ||
</DialogHeader> | ||
<form onSubmit={handleSubmit(onSubmit)}> | ||
<DialogBody> | ||
<Text mb={6} color='text.subtle' translation={'walletProvider.shapeShift.rename.body'} /> | ||
<FormControl mb={6} isInvalid={!!errors.label}> | ||
<Input | ||
size='lg' | ||
variant='filled' | ||
id='name' | ||
placeholder={translate('walletProvider.shapeShift.rename.walletName')} | ||
{...register('label', { | ||
required: true, | ||
maxLength: { | ||
value: 64, | ||
message: translate('modals.shapeShift.password.error.maxLength', { length: 64 }), | ||
}, | ||
})} | ||
/> | ||
<FormErrorMessage>{errors.label && errors.label.message}</FormErrorMessage> | ||
</FormControl> | ||
</DialogBody> | ||
<DialogFooter pt={4}> | ||
<Button | ||
colorScheme='blue' | ||
size='lg' | ||
width='full' | ||
isLoading={isSubmitting} | ||
type='submit' | ||
isDisabled={!isValid} | ||
> | ||
<Text translation={'walletProvider.shapeShift.rename.button'} /> | ||
</Button> | ||
</DialogFooter> | ||
</form> | ||
</SlideTransition> | ||
) | ||
} |
Oops, something went wrong.