-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Set up an action sheet for the deposit flow from the homepage; set up…
… Redux for managing its state (#11) * Set up Redux * Add ListItem/ConditionalWrap components * Create stub AssetIcon component * Fix radii * Create ListItems component * Set up action sheet lib * Modify store to be used for deposit flow * Install expo-clipboard * Allow buttons to be disabled * Create ActionSheet component * Add step to deposit flow state * Create deposit flow * Add help step * Add docblock * Remove unnecessary comments * Tweak comment * Set up i18n using Lingui (#12) * Set up i18n using Lingui * Require compilation * Add more docs to ActionSheet * Add property docs * Add docs re: typed hooks * Switch to enum; fix import
- Loading branch information
1 parent
3164cdd
commit cedf501
Showing
29 changed files
with
1,544 additions
and
108 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
module.exports = function (api) { | ||
api.cache(true); | ||
return { | ||
presets: ['babel-preset-expo'], | ||
plugins: ['@lingui/babel-plugin-lingui-macro'], | ||
}; | ||
}; |
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,54 @@ | ||
import { Sx, View } from 'dripsy'; | ||
import { ReactNode, useEffect, useRef } from 'react'; | ||
import RNASActionSheet, { ActionSheetRef } from 'react-native-actions-sheet'; | ||
import { useSafeAreaInsets } from 'react-native-safe-area-context'; | ||
|
||
export interface ActionSheetProps { | ||
children: ReactNode; | ||
isOpen?: boolean; | ||
onClose?: () => void; | ||
} | ||
|
||
/** | ||
* Renders an action sheet that slides up from the bottom of the screen for UI | ||
* flows that don't require an entire route/screen. | ||
* | ||
* Pass it `isOpen` and `onClose` to control its state with, e.g., Redux. | ||
* | ||
* ```tsx | ||
* <ActionSheet isOpen={isOpen} onClose={onClose}> | ||
* <View> | ||
* <Text>ActionSheet content here.</Text> | ||
* </View> | ||
* </ActionSheet> | ||
* ``` | ||
* | ||
* For now, `<ActionSheet />` is implemented as a simple wrapper around | ||
* `react-native-actions-sheet` that allows declarative control of the action | ||
* sheet via `isOpen` and `onClose` props, rather than needing a `ref` to | ||
* control the action sheet imperatively. | ||
* | ||
* Eventually, this will also apply Prax Wallet's proper styling to the action | ||
* sheet, at which point this comment should be deleted/updated. | ||
*/ | ||
export default function ActionSheet({ children, isOpen, onClose }: ActionSheetProps) { | ||
const ref = useRef<ActionSheetRef>(null); | ||
const insets = useSafeAreaInsets(); | ||
|
||
useEffect(() => { | ||
if (isOpen) ref.current?.show(); | ||
else ref.current?.hide(); | ||
}, [isOpen]); | ||
|
||
return ( | ||
<RNASActionSheet ref={ref} onClose={onClose} gestureEnabled safeAreaInsets={insets}> | ||
<View sx={sx.root}>{children}</View> | ||
</RNASActionSheet> | ||
); | ||
} | ||
|
||
const sx = { | ||
root: { | ||
px: '$4', | ||
}, | ||
} satisfies Record<string, Sx>; |
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,12 @@ | ||
import { Meta, StoryObj } from '@storybook/react'; | ||
|
||
import AssetIcon from '.'; | ||
|
||
const meta: Meta<typeof AssetIcon> = { | ||
component: AssetIcon, | ||
tags: ['autodocs'], | ||
}; | ||
|
||
export default meta; | ||
|
||
export const Basic: StoryObj<typeof AssetIcon> = {}; |
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,17 @@ | ||
import { Sx, View } from 'dripsy'; | ||
|
||
/** | ||
* A dummy component that, once populated with data, will render an icon for a | ||
* specific asset. | ||
*/ | ||
export default function AssetIcon() { | ||
return <View sx={sx.root} />; | ||
} | ||
|
||
const sx = { | ||
root: { | ||
backgroundColor: 'neutralLight', | ||
size: 40, | ||
borderRadius: 20, | ||
}, | ||
} satisfies Record<string, Sx>; |
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,58 @@ | ||
import { ReactNode } from 'react'; | ||
|
||
export interface ConditionalWrapProps { | ||
if: boolean; | ||
then: (children: ReactNode) => ReactNode; | ||
else?: (children: ReactNode) => ReactNode; | ||
children: ReactNode; | ||
} | ||
|
||
/** | ||
* Utility component to optionally wrap a React component with another React | ||
* component, depending on a condition. | ||
* | ||
* @example | ||
* ```tsx | ||
* <ConditionalWrap | ||
* if={shouldUseTooltip} | ||
* then={(children) => ( | ||
* <Tooltip> | ||
* <TooltipTrigger>{children}</TooltipTrigger> | ||
* <TooltipContent>Here is the tooltip text.</TooltipContent> | ||
* </Tooltip> | ||
* )} | ||
* > | ||
* Here is the content that may or may not need a tooltip. | ||
* </ConditionalWrap> | ||
* ``` | ||
* | ||
* You can also pass an `else` prop to wrap the `children` if the condition is | ||
* _not_ met. | ||
* | ||
* @example | ||
* ```tsx | ||
* <ConditionalWrap | ||
* if={shouldUseTooltip} | ||
* then={(children) => ( | ||
* <Tooltip> | ||
* <TooltipTrigger>{children}</TooltipTrigger> | ||
* <TooltipContent>Here is the tooltip text.</TooltipContent> | ||
* </Tooltip> | ||
* )} | ||
* else={(children) => ( | ||
* <NonTooltipWrapper>{children}</NonTooltipWrapper> | ||
* )} | ||
* > | ||
* Here is the content that may or may not need a tooltip. | ||
* </ConditionalWrap> | ||
* ``` | ||
* | ||
* @see https://stackoverflow.com/a/56870316/974981 | ||
*/ | ||
export const ConditionalWrap = ({ | ||
children, | ||
if: condition, | ||
then: thenWrapper, | ||
else: elseWrapper, | ||
}: ConditionalWrapProps) => | ||
condition ? thenWrapper(children) : elseWrapper ? elseWrapper(children) : children; |
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,87 @@ | ||
import Button from '../Button'; | ||
import * as Clipboard from 'expo-clipboard'; | ||
import Icon from '../Icon'; | ||
import { Info } from 'lucide-react-native'; | ||
import { Pressable, Sx, Text, View } from 'dripsy'; | ||
import { setStep } from '@/store/depositFlow'; | ||
import { useAppDispatch } from '@/store/hooks'; | ||
import { useState } from 'react'; | ||
import { Trans, useLingui } from '@lingui/react/macro'; | ||
|
||
const MOCK_PENUMBRA_ADDRESS = | ||
'penumbra147mfall0zr6am5r45qkwht7xqqrdsp50czde7empv7yq2nk3z8yyfh9k9520ddgswkmzar22vhz9dwtuem7uxw0qytfpv7lk3q9dp8ccaw2fn5c838rfackazmgf3ahh09cxmz'; | ||
|
||
export default function Address() { | ||
const { t } = useLingui(); | ||
|
||
const BUTTON_PROPS_DEFAULT = { | ||
children: t`Copy IBC address`, | ||
disabled: false, | ||
}; | ||
|
||
const BUTTON_PROPS_COPIED = { | ||
children: t`Copied!`, | ||
disabled: true, | ||
}; | ||
|
||
const [buttonProps, setButtonProps] = useState(BUTTON_PROPS_DEFAULT); | ||
const dispatch = useAppDispatch(); | ||
|
||
const copyToClipboard = async () => { | ||
await Clipboard.setStringAsync(MOCK_PENUMBRA_ADDRESS); | ||
|
||
setButtonProps(BUTTON_PROPS_COPIED); | ||
setTimeout(() => setButtonProps(BUTTON_PROPS_DEFAULT), 2_000); | ||
}; | ||
|
||
return ( | ||
<View sx={sx.root}> | ||
<Text variant='large'> | ||
<Trans>Shielded IBC deposit</Trans> | ||
</Text> | ||
|
||
<Text variant='small'> | ||
<Trans> | ||
This address rotates for each deposit to ensure privacy in Penumbra's shielded pool. | ||
</Trans> | ||
</Text> | ||
|
||
<View sx={sx.addressWrapper}> | ||
<Text variant='small'>{MOCK_PENUMBRA_ADDRESS}</Text> | ||
</View> | ||
|
||
<Pressable sx={sx.helpButton} onPress={() => dispatch(setStep('help'))}> | ||
<Text variant='small'> | ||
<Trans>What is a shielded IBC deposit?</Trans> | ||
</Text> | ||
|
||
<Icon IconComponent={Info} size='sm' /> | ||
</Pressable> | ||
|
||
<Button actionType='accent' onPress={copyToClipboard} {...buttonProps} /> | ||
</View> | ||
); | ||
} | ||
|
||
const sx = { | ||
addressWrapper: { | ||
borderRadius: 'lg', | ||
borderColor: 'actionNeutralFocusOutline', | ||
borderWidth: 1, | ||
|
||
px: '$4', | ||
py: '$2', | ||
}, | ||
|
||
helpButton: { | ||
flexDirection: 'row', | ||
alignItems: 'center', | ||
justifyContent: 'center', | ||
gap: '$2', | ||
}, | ||
|
||
root: { | ||
flexDirection: 'column', | ||
gap: '$4', | ||
}, | ||
} satisfies Record<string, Sx>; |
37 changes: 37 additions & 0 deletions
37
react-native-expo/components/DepositFlow/DepositMethod.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,37 @@ | ||
import { Text } from 'dripsy'; | ||
import ListItems from '../ListItems'; | ||
import ListItem from '../ListItem'; | ||
import AssetIcon from '../AssetIcon'; | ||
import Icon from '../Icon'; | ||
import { ChevronRight } from 'lucide-react-native'; | ||
import { setStep } from '@/store/depositFlow'; | ||
import { useAppDispatch } from '@/store/hooks'; | ||
import { Trans, useLingui } from '@lingui/react/macro'; | ||
|
||
export default function DepositMethod() { | ||
const dispatch = useAppDispatch(); | ||
const { t } = useLingui(); | ||
|
||
return ( | ||
<> | ||
<Text variant='large'> | ||
<Trans>Select deposit method</Trans> | ||
</Text> | ||
|
||
<ListItems> | ||
<ListItem | ||
avatar={<AssetIcon />} | ||
primaryText={t`Shielded IBC deposit`} | ||
suffix={<Icon IconComponent={ChevronRight} size='md' color='neutralLight' />} | ||
onPress={() => dispatch(setStep('address'))} | ||
/> | ||
|
||
<ListItem | ||
avatar={<AssetIcon />} | ||
primaryText={t`Noble USDC deposit`} | ||
secondaryText={t`Coming soon`} | ||
/> | ||
</ListItems> | ||
</> | ||
); | ||
} |
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,36 @@ | ||
import Button from '../Button'; | ||
import { setStep } from '@/store/depositFlow'; | ||
import { Sx, Text, View } from 'dripsy'; | ||
import { useAppDispatch } from '@/store/hooks'; | ||
import { Trans } from '@lingui/react/macro'; | ||
|
||
export default function Help() { | ||
const dispatch = useAppDispatch(); | ||
|
||
return ( | ||
<View sx={sx.root}> | ||
<Text variant='large'> | ||
<Trans>Shielded IBC deposit</Trans> | ||
</Text> | ||
|
||
<Text> | ||
<Trans> | ||
A Shielded IBC Deposit allows you to transfer assets (e.g., ATOM, OSMO) from Cosmos-based | ||
networks into Penumbra's shielded pool. Once deposited, your assets become private and | ||
anonymous, ensuring maximum confidentiality when used within Penumbra. | ||
</Trans> | ||
</Text> | ||
|
||
<Button actionType='accent' onPress={() => dispatch(setStep('address'))}> | ||
<Trans>OK</Trans> | ||
</Button> | ||
</View> | ||
); | ||
} | ||
|
||
const sx = { | ||
root: { | ||
flexDirection: 'column', | ||
gap: '$4', | ||
}, | ||
} satisfies Record<string, Sx>; |
Oops, something went wrong.