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

refactor(wallet-mobile): Receive funnel fixes and refactor #3092

Merged
merged 4 commits into from
Feb 27, 2024

Conversation

stackchain
Copy link
Member

@stackchain stackchain commented Feb 26, 2024

  • query fixes missing wallet.id
  • collocated code
  • renamed the screens to reflect the use cases
  • bug fixes
  • major bug on transfer (not resetting state properly)
  • dropped unnecessary code
  • refactored the hooks

@stackchain stackchain added this to the 4.26.0 milestone Feb 26, 2024
@@ -971,4 +971,4 @@ SPEC CHECKSUMS:

PODFILE CHECKSUM: 4045625f1556b4d232075df8dbd22524a7010c3f

COCOAPODS: 1.14.3
COCOAPODS: 1.15.2
Copy link
Member Author

@stackchain stackchain Feb 26, 2024

Choose a reason for hiding this comment

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

all bump your Xcodes / cocoa pods


const ACTION_PROPS = {
size: 24,
color: String(colors.actionColor),
Copy link
Member Author

Choose a reason for hiding this comment

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

dropped unnecessary String

const wallet = useSelectedWallet()

const {isSingle, addressDerivation} = useAddressDerivationManager()
const {next: nextReceiveAddress} = useReceiveAddressesStatus(addressDerivation)
Copy link
Member Author

Choose a reason for hiding this comment

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

on ActionsBanner, there is no receive address selected, only the next that depends on wallet state, the context is only for the details, since we avoid params.

@stackchain stackchain force-pushed the refactor/receive-funnel branch from 1fc7ecd to 32e87a1 Compare February 26, 2024 23:25
const stakingKey = useStakingKey(wallet)
const swapManager = React.useMemo(() => {
const aggregatorTokenId = isMainnetNetworkId(wallet.networkId) ? milkTokenId.mainnet : milkTokenId.preprod
Copy link
Member Author

Choose a reason for hiding this comment

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

moved inside memo

@@ -75,19 +75,15 @@ export const TxHistoryNavigator = () => {
const storage = useAsyncStorage()
const {theme} = useTheme()

// receive
const receiveAddresses = useReceiveAddresses(wallet)
Copy link
Member Author

Choose a reason for hiding this comment

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

dropped

@@ -126,7 +122,7 @@ export const TxHistoryNavigator = () => {
const headerRightHistory = React.useCallback(() => <HeaderRightHistory />, [])

return (
<ReceiveProvider key={wallet.id} initialCurrentAddress={currentAddress}>
<ReceiveProvider key={wallet.id}>
Copy link
Member Author

Choose a reason for hiding this comment

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

initial state is mainly for testing / stories.

<ReceiveProvider>
<AddressDetailCard address={mocks.address} title="Test Title" />
</ReceiveProvider>
.addDecorator((story) => (
Copy link
Member Author

Choose a reason for hiding this comment

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

moved the provider as decorator.

import {useKeyHashes} from '../../../../yoroi-wallets/hooks'
import {useReceive} from '../ReceiveProvider'
import {ShareDetailsCard} from '../ShareDetailsCard/ShareDetailsCard'
import {ShareQRCodeCard} from '../ShareQRCodeCard/ShareQRCodeCard'

type ShareProps = {
address: string
type AddressDetailCardProps = {
Copy link
Member Author

Choose a reason for hiding this comment

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

consistency

if (selectedAddress === undefined) {
return
const index = Math.floor(offset / (itemsPerPage * screenWidth - minToSwitchPage))
setScrollPosition(Math.max(index, 0))
Copy link
Member Author

Choose a reason for hiding this comment

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

otherwise when swiping left at first page will cause no index be off while holding the first page, causing the indicator to be wrong until the page is released.

title,
},
] as const

const screenWidth = useWindowDimensions().width
Copy link
Member Author

Choose a reason for hiding this comment

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

no need for caps.

const totalPages = Math.ceil(cards.length / itemsPerPage)
const circleIndex = Array.from({length: totalPages}, (_, index) => index + 1)
const cardIndicators = Array.from({length: totalPages}, (_, index) => index)
Copy link
Member Author

Choose a reason for hiding this comment

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

declarative

} & (
| {
cardType: 'QRCode'
}
| ({cardType: 'Details'} & AddressDetailsProps)
)

export const AddressDetailCard = ({title}: ShareProps) => {
const [scrollPosition, setScrollPosition] = useState(0)
const [isSecondPage, setIsSecondPage] = useState(false)
Copy link
Member Author

Choose a reason for hiding this comment

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

dropped unnecessary state

onLongPress={() => copy(item.address)}
isCopying={isCopying}
/>
)
case 'Details':
if (Boolean(item.address) && Boolean(item.stakingHash) && Boolean(item.spendingHash) && Boolean(item.title)) {
setIsSecondPage(true)
Copy link
Member Author

Choose a reason for hiding this comment

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

unnecessary state

<ShareDetailsCard address={item.address} stakingHash={item.stakingHash} spendingHash={item.spendingHash} />
)
default:
return null
Copy link
Member Author

Choose a reason for hiding this comment

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

only to satisfy TS.

@@ -116,21 +104,19 @@ export const AddressDetailCard = ({title}: ShareProps) => {

<Spacer height={12} />

{isSecondPage && (
Copy link
Member Author

Choose a reason for hiding this comment

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

unnecessary

@@ -156,8 +142,8 @@ const useStyles = () => {
})

const colors = {
indexActive: theme.color.primary[600],
Copy link
Member Author

Choose a reason for hiding this comment

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

leaky

@@ -8,26 +8,14 @@ import {Spacer, Text} from '../../../../components'
import {YoroiLogoIllustration} from '../../illustrations/YoroiLogo'

type ShareProps = {
address?: string
title?: string
Copy link
Member Author

Choose a reason for hiding this comment

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

a lot of unused props

}

type AddressDetailsProps = {
address: string
Copy link
Member Author

Choose a reason for hiding this comment

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

ibid idem

const {styles, colors} = useStyles()

return (
<View style={[styles.touchableCard]}>
Copy link
Member Author

Choose a reason for hiding this comment

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

?

@@ -37,23 +25,23 @@ export const CaptureShareQRCodeCard = ({address}: ShareProps) => {

<Spacer height={16} />

<YoroiLogoIllustration height={logoHeight} width={logoWidth} />
<YoroiLogoIllustration height={37} width={35} />
Copy link
Member Author

Choose a reason for hiding this comment

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

no need for constant, is not a magic number, the api is very declarative

}: {
children: React.ReactNode
initialState?: Partial<ReceiveState>
initialCurrentAddress?: string
Copy link
Member Author

Choose a reason for hiding this comment

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

dropped part of the state already

}) => {
const [state, dispatch] = React.useReducer(receiveReducer, {
...defaultState,
...initialState,
})

const actions = React.useRef<ReceiveActions>({
currentAddressChanged: (address: string) => dispatch({type: ReceiveActionType.CurrentAddressChanged, address}),
selectedAddressChanged: (address: string) => dispatch({type: ReceiveActionType.SelectedAddressChanged, address}),
Copy link
Member Author

Choose a reason for hiding this comment

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

consistency

}

const defaultState: ReceiveState = Object.freeze({
selectedAddress: null,
defaultAddress: null,
selectedAddress: '',
Copy link
Member Author

Choose a reason for hiding this comment

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

receive address can't never be null, since is created on wallet basis

stakingHash={mocks.stakinghash}
title="Test Title"
/>
<ShareDetailsCard address={mocks.address} spendingHash={mocks.spendinghash} stakingHash={mocks.stakinghash} />
Copy link
Member Author

Choose a reason for hiding this comment

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

unused prop

@@ -7,7 +8,9 @@ import {ShareQRCodeCard} from './ShareQRCodeCard'

storiesOf('Receive ShareQRCodeCard', module)
.addDecorator((story) => <View style={styles.container}>{story()}</View>)
.add('default', () => <ShareQRCodeCard address={mocks.address} />)
.add('with content', () => (
<ShareQRCodeCard content={mocks.address} onLongPress={action('onLongPress')} title="Title" />
Copy link
Member Author

Choose a reason for hiding this comment

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

most components in common are actually useCases of just one screen, it needs a second refactor later


const query = useQuery({
suspense: true,
queryKey: [wallet.id, isShowingMultipleAddressInfoKey],
Copy link
Member Author

Choose a reason for hiding this comment

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

ibid idem


const parsed = parseSafe(storedStorage)
// old wallets wont have this key, so we default to true
return isBoolean(parsed) ? parsed : true
Copy link
Member Author

Choose a reason for hiding this comment

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

marking to display by default (empty storage), it affects only multiple funnel so needs to be configured, looks right needs confirmation cc: @SorinC6

@@ -7,7 +7,7 @@ export const useNavigateTo = () => {
const navigation = useNavigation<TxHistoryRouteNavigation>()

return useRef({
receiceDetails: () => navigation.navigate('receive-single'),
receiveDetails: () => navigation.navigate('receive-single'),
Copy link
Member Author

Choose a reason for hiding this comment

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

typo

Copy link
Member Author

Choose a reason for hiding this comment

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

also part of package candidate

{used: [], unused: []} as Omit<ReceiveAddressesStatus, 'next'>,
)
const multipleAddress = addressesStatus.unused[0] ?? addressesStatus.used[0]
const nextAddress = isSingle ? singleAddress : multipleAddress
Copy link
Member Author

Choose a reason for hiding this comment

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

next can only be calculated after the unused are discovered for multiple addresses, (first unused), if single always path index 0

@@ -57,18 +38,16 @@ export const SingleAddressScreen = () => {
textStyles={{
color: colors.buttonBackgroundBlue,
}}
onPress={() => navigate.specificAmount()}
disabled={currentAddress === null}
onPress={navigate.specificAmount}
Copy link
Member Author

Choose a reason for hiding this comment

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

clean ups

address: string
}

export const MultipleAddressesScreen = () => {
export const ListMultipleAddressesScreen = () => {
Copy link
Member Author

Choose a reason for hiding this comment

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

declarative use case

}}
// date={mocks.usedAddressDate} // TODO don't have the date??
// date={} // TODO define with project
Copy link
Member Author

@stackchain stackchain Feb 26, 2024

Choose a reason for hiding this comment

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

needs checking, it should be dropped for the 1st iteration, it will require to scrap all txs. cc: @SorinC6

)

return (
<SafeAreaView style={styles.root} edges={['left', 'right', 'bottom']}>
{mappedAddresses.length >= BIP32_HD_GAP_LIMIT && (
{hasReachedGapLimit && (
Copy link
Member Author

Choose a reason for hiding this comment

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

clean ups less overhead, declarative

@@ -159,7 +160,7 @@ const useStyles = () => {
return {styles, colors} as const
}

const mapAddresses = (addresses: {unused: string[]; used: string[]}): AddressInfo[] => {
const toAddressInfos = (addresses: {unused: string[]; used: string[]}): AddressInfo[] => {
Copy link
Member Author

Choose a reason for hiding this comment

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

transformer, was leaking impl

import {useStrings} from '../common/useStrings'

export const EnterAmountScreen = () => {
export const RequestSpecificAmountScreen = () => {
Copy link
Member Author

Choose a reason for hiding this comment

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

use case


const screenHeight = useWindowDimensions().height
Copy link
Member Author

Choose a reason for hiding this comment

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

collocated

@@ -83,13 +79,11 @@ export const EnterAmountScreen = () => {
)
}

const Modal = ({amount, address}: {amount: string; address?: string}) => {
const Modal = ({amount, address}: {amount: string; address: string}) => {
Copy link
Member Author

Choose a reason for hiding this comment

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

not optional

const {setMultipleAddressesOn, setMultipleAddressesOff, isToggleReceiveTypeLoading} = useMultipleAddresses()
const [isLocalMultipleAddressOff, setIsLocalMultipleAddressesOff] = React.useState(isMultipleAddressesOff)
const AddresseDerivationSwitcher = (props: {isSingle: boolean}) => {
const addressDerivation = useAddressDerivationManager()
Copy link
Member Author

Choose a reason for hiding this comment

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

refactor mainly for the new hooks

@@ -33,6 +33,8 @@ const transferReducer = (state: TransferState, action: TransferAction) => {
draft.selectedTokenId = defaultTransferState.selectedTokenId
draft.memo = defaultTransferState.memo
draft.unsignedTx = castDraft(defaultTransferState.unsignedTx)
draft.selectedTargetIndex = defaultTransferState.selectedTargetIndex
Copy link
Member Author

Choose a reason for hiding this comment

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

bug when resetting state, was not setting back some properties cc: @banklesss (maybe there is a better way of settings the entire draft as initialState)

Copy link
Contributor

Choose a reason for hiding this comment

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

need to have a look

Copy link
Contributor

Choose a reason for hiding this comment

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

amazing catch

entry: {
address: '',
amounts: {},
export const defaultTransferState: TransferState = freeze(
Copy link
Member Author

Choose a reason for hiding this comment

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

as const is shallow

@stackchain stackchain marked this pull request as ready for review February 27, 2024 00:07
Comment on lines 87 to 88
singleMode: () => setAddressDerivationMode('single'),
multipleMode: () => setAddressDerivationMode('multiple'),
Copy link
Collaborator

Choose a reason for hiding this comment

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

I'd suggest enableSingleMode and enableMultipleMode

@banklesss
Copy link
Contributor

share functionality will be refactored here https://emurgo.atlassian.net/browse/YOMO-1201

@stackchain stackchain merged commit 6ce1921 into develop Feb 27, 2024
2 checks passed
@stackchain stackchain deleted the refactor/receive-funnel branch February 27, 2024 09:45
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants