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

feat(TokenEnterAmount): add new flow to EnterAmount.tsx #6245

Merged
merged 77 commits into from
Dec 2, 2024
Merged
Show file tree
Hide file tree
Changes from 56 commits
Commits
Show all changes
77 commits
Select commit Hold shift + click to select a range
e5ab0a5
add new TokenEnterAmount component
sviderock Nov 18, 2024
2fbc1b2
fix exports
sviderock Nov 18, 2024
b12d50f
Merge branch 'main' into slava/add-new-enter-amount-component
sviderock Nov 18, 2024
8af7b8d
Add reusable useEnterAmount hook
sviderock Nov 18, 2024
44c0aab
remove unused code
sviderock Nov 18, 2024
1aa17d6
change flow on send
sviderock Nov 19, 2024
4ed89fc
fix tests
sviderock Nov 19, 2024
d0c7099
fix jumpstart
sviderock Nov 19, 2024
b7e5107
remove unnecessary changes
sviderock Nov 19, 2024
6ca6f92
Merge branch 'main' into slava/add-new-enter-amount-component
sviderock Nov 19, 2024
f2185bc
Merge branch 'slava/add-new-enter-amount-component' into slava/add-en…
sviderock Nov 19, 2024
8762401
Merge branch 'slava/add-enter-amount-hook' into slava/change-send-flow
sviderock Nov 19, 2024
98938bc
fix knip
sviderock Nov 19, 2024
5a3f776
uncomment some tests
sviderock Nov 19, 2024
9360626
fixes
sviderock Nov 19, 2024
b3f3c67
add tests
sviderock Nov 20, 2024
8ce68a4
clear up console logs
sviderock Nov 20, 2024
c2773fa
Merge branch 'slava/add-new-enter-amount-component' into slava/add-en…
sviderock Nov 20, 2024
37455cb
WIP: tests for the hook
sviderock Nov 20, 2024
8357b18
reformat groupNumber, finish number formatting tests
sviderock Nov 21, 2024
f5db952
add useEnterAmount initial tests
sviderock Nov 21, 2024
130b620
finish tests
sviderock Nov 21, 2024
10fb5bd
revert unnecessary change
sviderock Nov 21, 2024
112e5f9
Merge branch 'main' into slava/add-new-enter-amount-component
sviderock Nov 21, 2024
bce9c2b
Merge branch 'slava/add-new-enter-amount-component' into slava/add-en…
sviderock Nov 21, 2024
7048f8e
Merge branch 'slava/add-enter-amount-hook' into slava/change-send-flow
sviderock Nov 21, 2024
a08f3a9
format input values
sviderock Nov 22, 2024
22f4a44
fix tests
sviderock Nov 22, 2024
78218f6
fix zero values for readable amounts
sviderock Nov 22, 2024
cea53aa
add comments
sviderock Nov 22, 2024
060a81a
Merge branch 'slava/add-enter-amount-hook' into slava/change-send-flow
sviderock Nov 22, 2024
8d80b3d
add comment
sviderock Nov 22, 2024
f9b5e31
unskip test that checks logic when fiat prices unavailable
sviderock Nov 22, 2024
0d64a5b
fix as per the review
sviderock Nov 22, 2024
2031bbc
fix as per the review comments
sviderock Nov 25, 2024
d7b5f0a
Merge branch 'main' into slava/add-new-enter-amount-component
sviderock Nov 25, 2024
6d738e4
Merge branch 'slava/add-new-enter-amount-component' into slava/add-en…
sviderock Nov 25, 2024
4c9ed39
remove refs and their handlers outside of the component
sviderock Nov 25, 2024
e1dbbec
refactor tests related to amount formatting
sviderock Nov 25, 2024
e9fc844
rename readabale to display
sviderock Nov 25, 2024
ec1f0a8
change variables names
sviderock Nov 25, 2024
96bc9b3
Merge branch 'slava/add-enter-amount-hook' into slava/change-send-flow
sviderock Nov 25, 2024
2c6f88b
fix tests after changes to hook
sviderock Nov 26, 2024
1a0c2bc
Merge branch 'main' into slava/add-new-enter-amount-component
sviderock Nov 26, 2024
6921dc5
Merge branch 'slava/add-new-enter-amount-component' into slava/add-en…
sviderock Nov 26, 2024
bcb4c6f
Merge branch 'slava/add-enter-amount-hook' into slava/change-send-flow
sviderock Nov 26, 2024
5d85bbd
remove unused callback
sviderock Nov 26, 2024
da1652b
change derived to processedAmounts
sviderock Nov 26, 2024
f57fac6
rename readable to displayAmount
sviderock Nov 26, 2024
39c6766
remove unnecessary hooks and mocks
sviderock Nov 26, 2024
cdd8396
fix tests as per review
sviderock Nov 26, 2024
6bb7c89
fix tests
sviderock Nov 26, 2024
1f40e7c
fix test
sviderock Nov 26, 2024
5cec1fb
Merge branch 'slava/add-enter-amount-hook' into slava/change-send-flow
sviderock Nov 26, 2024
b9f21de
fix as per the comments, adjust to "max" button
sviderock Nov 26, 2024
3858035
Merge branch 'main' into slava/change-send-flow
sviderock Nov 26, 2024
4eb45ba
unskip "max" tests
sviderock Nov 26, 2024
639e612
replace props.children check with .toHaveTextContent() in tests
sviderock Nov 26, 2024
080de6d
fix lint
sviderock Nov 27, 2024
e0de08b
add spacing for title
sviderock Nov 27, 2024
8001e05
fix percentages
sviderock Nov 28, 2024
ae82212
rename handler for better clarity
sviderock Nov 28, 2024
7714b4d
clear percentage on token select
sviderock Nov 28, 2024
b91f09d
change as per the review
sviderock Nov 29, 2024
fbcd741
Merge branch 'main' into slava/change-send-flow
sviderock Nov 29, 2024
757a759
revert some changes
sviderock Nov 29, 2024
8aed766
remove unused ref
sviderock Nov 29, 2024
ac325bd
fix 2e2
sviderock Nov 29, 2024
c5bc604
fix assets e2e
sviderock Nov 29, 2024
c0b5ab2
try to fix assets again
sviderock Nov 29, 2024
81991b5
ignore currency symbols for unformat function, cover new functions wi…
sviderock Nov 29, 2024
7c746d6
revert changes with removing symbols
sviderock Nov 29, 2024
12b4e47
fix: fee amount formatting on android
kathaypacific Dec 2, 2024
6d6ae26
fix: avoid showing fees when no amount
kathaypacific Dec 2, 2024
e54e741
fix: more than max amount set when max amount selected
kathaypacific Dec 2, 2024
1aa565d
fix: ensure token symbol displayed in secondary amount
kathaypacific Dec 2, 2024
5e2dbee
chore: increase switch icon touch area
kathaypacific Dec 2, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion ios/Podfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -1339,4 +1339,4 @@ SPEC CHECKSUMS:

PODFILE CHECKSUM: e49ec411923f9bb1906dff8d0e27d0aa410bf3ad

COCOAPODS: 1.15.2
COCOAPODS: 1.16.2
1 change: 1 addition & 0 deletions locales/base/translation.json
Original file line number Diff line number Diff line change
Expand Up @@ -2208,6 +2208,7 @@
"title": "Enter Amount",
"selectToken": "Select a Token",
"networkFee": "{{networkName}} Network Fee",
"networkFeeV1_97": "Network Fee",
"lowerAmount": "Enter a lower amount",
"maxAmountWarning": {
"title": "Sending the maximum amount",
Expand Down
3 changes: 2 additions & 1 deletion src/components/TokenDisplay.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import * as React from 'react'
import 'react-native'
import { Provider } from 'react-redux'
import TokenDisplay, { formatValueToDisplay } from 'src/components/TokenDisplay'
import { APPROX_SYMBOL } from 'src/components/TokenEnterAmount'
import { LocalCurrencyCode } from 'src/localCurrency/consts'
import { RootState } from 'src/redux/reducers'
import { NetworkId } from 'src/transactions/types'
Expand Down Expand Up @@ -253,7 +254,7 @@ describe('TokenDisplay', () => {
/>
</Provider>
)
expect(getElementText(getByTestId('test'))).toEqual(`~10.00 cUSD`)
expect(getElementText(getByTestId('test'))).toEqual(`${APPROX_SYMBOL} 10.00 cUSD`)
})
})
})
Expand Down
3 changes: 2 additions & 1 deletion src/components/TokenDisplay.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import BigNumber from 'bignumber.js'
import * as React from 'react'
import { StyleProp, Text, TextStyle } from 'react-native'
import { APPROX_SYMBOL } from 'src/components/TokenEnterAmount'
import { LocalCurrencyCode, LocalCurrencySymbol } from 'src/localCurrency/consts'
import { getLocalCurrencySymbol, usdToLocalCurrencyRateSelector } from 'src/localCurrency/selectors'
import { useSelector } from 'src/redux/hooks'
Expand Down Expand Up @@ -81,7 +82,7 @@ function TokenDisplay({
errorFallback
) : (
<>
{showApprox && '~'}
{showApprox && `${APPROX_SYMBOL} `}
{sign}
{showLocalAmount && fiatSymbol}
{amountToShow.isNaN()
Expand Down
4 changes: 4 additions & 0 deletions src/components/TokenEnterAmount.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -163,6 +163,7 @@ describe('TokenEnterAmount', () => {
decimals: 6,
tokenId: mockUSDCTokenId,
priceUsd: new BigNumber(1.001),
balance: new BigNumber(1500.76),
} as TokenBalance,
})

Expand All @@ -181,6 +182,7 @@ describe('TokenEnterAmount', () => {
amount: '1235.91',
bignum: new BigNumber('1235.912678'),
displayAmount: '$1,235.91',
balance: new BigNumber('1502.26076'),
},
})
})
Expand All @@ -193,6 +195,7 @@ describe('TokenEnterAmount', () => {
decimals: 6,
tokenId: mockUSDCTokenId,
priceUsd: new BigNumber(1.001),
balance: new BigNumber(1500.76),
} as TokenBalance,
})

Expand All @@ -206,6 +209,7 @@ describe('TokenEnterAmount', () => {
amount: '1234.67',
bignum: new BigNumber('1234.67'),
displayAmount: '$1,234.67',
balance: new BigNumber('1502.26076'),
},
token: {
amount: '1233.436563',
Expand Down
30 changes: 24 additions & 6 deletions src/components/TokenEnterAmount.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ import { parseInputAmount } from 'src/utils/parsing'
export const APPROX_SYMBOL = '≈'

const BORDER_RADIUS = 12
export const FETCH_UPDATED_TRANSACTIONS_DEBOUNCE_TIME_MS = 250

/**
* This function formats numbers in a "1234.5678" format into the correct format according to the
Expand Down Expand Up @@ -95,6 +96,7 @@ export function getDisplayLocalAmount(
export function useEnterAmount(props: {
token: TokenBalance
inputRef: React.RefObject<RNTextInput>
onAmountChange?(value: string): void
}) {
const { decimalSeparator, groupingSeparator } = getNumberFormatSettings()
const [amount, setAmount] = useState('')
Expand All @@ -120,17 +122,28 @@ export function useEnterAmount(props: {
* This field consists of two values: token and local. Both values represent calculated values for the
* corresponding amount type. Whenever we change token amount - we need to recalculate both token and
* local amounts. Each object consists of:
* - "amount" - this is the actual value, formatted to the unified format without any groupings
* - `amount` - this is the actual value, formatted to the unified format without any groupings
* and with a point as a decimal separator, format example: "1234.5678" (as per "amountRaw" value above)
* - "bignum" - this is a BigNumber representation of the "amount" field. Necessary for easier
* - `bignum` - this is a BigNumber representation of the "amount" field. Necessary for easier
* condition checks and various processing things.
* - "displayAmount" - this is a read-only component-friendly value that contains all of the necessary
* - `displayAmount` - this is a read-only component-friendly value that contains all of the necessary
* formatting, including: grouping, decimals, token symbol/fiat sign, small amounts format. This
* value is only necessary to be passed to TokenEnterAmount component fields as:
* - token.displayAmount -> tokenAmount
* - local.displayAmount -> localAmount
* - `token.displayAmount` -> `tokenDisplayAmount`
* - `local.displayAmount` -> `localDisplayAmount`
*
* `local` also includes the following fields:
* - `balance` - this is a field representing fiat balance of the token. We don't duplicate the same
* field to `token` as we can already get it from `props.token` and don't want to have multiple
* sources of truth for the token balance. This field is used whenever `max` option is used.
*/
const processedAmounts = useMemo(() => {
const localBalance = convertTokenToLocalAmount({
tokenAmount: props.token.balance,
tokenInfo: props.token,
usdToLocalRate,
})

if (amountType === 'token') {
const parsedTokenAmount = amountRaw === '' ? null : parseInputAmount(amountRaw)

Expand All @@ -153,6 +166,7 @@ export function useEnterAmount(props: {
amount: convertedTokenToLocal,
bignum: tokenToLocal,
displayAmount: getDisplayLocalAmount(tokenToLocal, localCurrencySymbol),
balance: localBalance,
},
}
}
Expand Down Expand Up @@ -188,6 +202,7 @@ export function useEnterAmount(props: {
amount: parsedLocalAmount?.toFixed(2) ?? '',
bignum: parsedLocalAmount,
displayAmount: getDisplayLocalAmount(parsedLocalAmount, localCurrencySymbol),
balance: localBalance,
},
}
}, [amountRaw, amountType, localCurrencySymbol])
Expand All @@ -205,6 +220,7 @@ export function useEnterAmount(props: {

if (!value) {
setAmount('')
props.onAmountChange?.('')
return
}

Expand All @@ -227,6 +243,7 @@ export function useEnterAmount(props: {
(amountType === 'local' && value.match(localAmountRegex))
) {
setAmount(value)
props.onAmountChange?.(value)
return
}
}
Expand All @@ -235,6 +252,7 @@ export function useEnterAmount(props: {
amount: amountRaw,
amountType,
processedAmounts,
setAmount,
handleToggleAmountType,
handleAmountInputChange,
}
Expand Down Expand Up @@ -406,7 +424,7 @@ export default function TokenEnterAmount({

<Text
numberOfLines={1}
style={[styles.secondaryAmountText, { maxWidth: '35%' }]}
style={[styles.secondaryAmountText, { flexShrink: 0, maxWidth: '45%' }]}
testID={`${testID}/ExchangeAmount`}
>
{amountType === 'token'
Expand Down
9 changes: 7 additions & 2 deletions src/components/TokenTotalLineItem.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import BigNumber from 'bignumber.js'
import * as React from 'react'
import 'react-native'
import { Provider } from 'react-redux'
import { APPROX_SYMBOL } from 'src/components/TokenEnterAmount'
import TokenTotalLineItem from 'src/components/TokenTotalLineItem'
import { LocalCurrencyCode } from 'src/localCurrency/consts'
import { LocalAmount, NetworkId } from 'src/transactions/types'
Expand Down Expand Up @@ -173,7 +174,9 @@ describe('TokenTotalLineItem', () => {
showLocalAmountForTotal: false,
newSendScreen: true,
})
expect(getElementText(getByTestId('TotalLineItem/Total'))).toEqual('~10.50 cUSD')
expect(getElementText(getByTestId('TotalLineItem/Total'))).toEqual(
`${APPROX_SYMBOL} 10.50 cUSD`
)
expect(getElementText(getByTestId('TotalLineItem/ExchangeRate'))).toEqual(
'tokenExchangeRateApprox, {"symbol":"cUSD"}R$1.50'
)
Expand All @@ -184,7 +187,9 @@ describe('TokenTotalLineItem', () => {
showLocalAmountForTotal: false,
newSendScreen: true,
})
expect(getElementText(getByTestId('TotalLineItem/Total'))).toEqual('~10.00 cUSD')
expect(getElementText(getByTestId('TotalLineItem/Total'))).toEqual(
`${APPROX_SYMBOL} 10.00 cUSD`
)
expect(getElementText(getByTestId('TotalLineItem/ExchangeRate'))).toEqual(
'tokenExchangeRateApprox, {"symbol":"cUSD"}R$1.50'
)
Expand Down
11 changes: 6 additions & 5 deletions src/components/__snapshots__/PhoneNumberInput.test.tsx.snap
Original file line number Diff line number Diff line change
Expand Up @@ -129,15 +129,16 @@ exports[`PhoneNumberInput renders and behaves correctly 1`] = `
>
<svg
fill="none"
height={32}
height={38}
strokeWidth={1}
style={{}}
testID="downArrowIcon"
viewBox="0 0 16 16"
width={32}
viewBox="0 0 24 24"
width={38}
>
<path
d="M3 6l5 5 5-5"
d="m16.59 8.707.703.703L12 14.703 6.707 9.41l.703-.703 4.237 4.227.353.352.353-.352 4.237-4.227Z"
fill="#757575"
stroke="#757575"
/>
</svg>
Expand Down Expand Up @@ -210,4 +211,4 @@ exports[`PhoneNumberInput renders and behaves correctly 1`] = `
</View>
</View>
</View>
`;
`;
2 changes: 1 addition & 1 deletion src/earn/EarnEnterAmount.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -660,7 +660,7 @@
},
})

it('selecting max token amount applies correct decimal separator', async () => {
it.skip('selecting max token amount applies correct decimal separator', async () => {

Check failure on line 663 in src/earn/EarnEnterAmount.test.tsx

View workflow job for this annotation

GitHub Actions / Lint

Skipped test
Copy link
Collaborator

Choose a reason for hiding this comment

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

maybe add a TODO to unskip?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@kathaypacific I think this is also outdated!

const { getByTestId } = render(
<Provider store={mockStore}>
<MockedNavigator component={EarnEnterAmount} params={params} />
Expand Down
87 changes: 85 additions & 2 deletions src/earn/EarnEnterAmount.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,16 @@ import { NativeStackScreenProps } from '@react-navigation/native-stack'
import BigNumber from 'bignumber.js'
import React, { useEffect, useMemo, useRef, useState } from 'react'
import { useTranslation } from 'react-i18next'
import { Keyboard, TextInput as RNTextInput, StyleSheet, Text, View } from 'react-native'
import {
Keyboard,
Platform,
TextInput as RNTextInput,
StyleProp,
StyleSheet,
Text,
TextStyle,
View,
} from 'react-native'
import { getNumberFormatSettings } from 'react-native-localize'
import { SafeAreaView, useSafeAreaInsets } from 'react-native-safe-area-context'
import AppAnalytics from 'src/analytics/AppAnalytics'
Expand All @@ -14,6 +23,7 @@ import InLineNotification, { NotificationVariant } from 'src/components/InLineNo
import KeyboardAwareScrollView from 'src/components/KeyboardAwareScrollView'
import { LabelWithInfo } from 'src/components/LabelWithInfo'
import RowDivider from 'src/components/RowDivider'
import TextInput from 'src/components/TextInput'
import TokenBottomSheet, { TokenPickerOrigin } from 'src/components/TokenBottomSheet'
import TokenDisplay from 'src/components/TokenDisplay'
import TokenIcon, { IconSize } from 'src/components/TokenIcon'
Expand All @@ -33,7 +43,6 @@ import { StackParamList } from 'src/navigator/types'
import { hooksApiUrlSelector, positionsWithBalanceSelector } from 'src/positions/selectors'
import { EarnPosition, Position } from 'src/positions/types'
import { useSelector } from 'src/redux/hooks'
import { AmountInput } from 'src/send/EnterAmount'
import EnterAmountOptions from 'src/send/EnterAmountOptions'
import { AmountEnteredIn } from 'src/send/types'
import { NETWORK_NAMES } from 'src/shared/conts'
Expand Down Expand Up @@ -1170,6 +1179,80 @@ const styles = StyleSheet.create({
...typeScale.bodySmall,
color: Colors.black,
},
input: {
flex: 1,
marginRight: Spacing.Smallest8,
},
})

function AmountInput({
inputValue,
onInputChange,
inputRef,
inputStyle,
autoFocus,
placeholder = '0',
testID = 'AmountInput',
editable = true,
}: {
inputValue: string
onInputChange(value: string): void
inputRef: React.MutableRefObject<RNTextInput | null>
inputStyle?: StyleProp<TextStyle>
autoFocus?: boolean
placeholder?: string
testID?: string
editable?: boolean
}) {
// the startPosition and inputRef variables exist to ensure TextInput
// displays the start of the value for long values on Android
// https://github.com/facebook/react-native/issues/14845
const [startPosition, setStartPosition] = useState<number | undefined>(0)

const handleSetStartPosition = (value?: number) => {
if (Platform.OS === 'android') {
setStartPosition(value)
}
}

return (
<View style={styles.input}>
<TextInput
forwardedRef={inputRef}
onChangeText={(value) => {
handleSetStartPosition(undefined)
onInputChange(value)
}}
editable={editable}
value={inputValue || undefined}
placeholder={placeholder}
keyboardType="decimal-pad"
// Work around for RN issue with Samsung keyboards
// https://github.com/facebook/react-native/issues/22005
autoCapitalize="words"
autoFocus={autoFocus}
// unset lineHeight to allow ellipsis on long inputs on iOS. For
// android, ellipses doesn't work and unsetting line height causes
// height changes when amount is entered
inputStyle={[inputStyle, Platform.select({ ios: { lineHeight: undefined } })]}
testID={testID}
onBlur={() => {
handleSetStartPosition(0)
}}
onFocus={() => {
handleSetStartPosition(inputValue?.length ?? 0)
}}
onSelectionChange={() => {
handleSetStartPosition(undefined)
}}
selection={
Platform.OS === 'android' && typeof startPosition === 'number'
? { start: startPosition }
: undefined
}
/>
</View>
)
}

export default EarnEnterAmount
12 changes: 8 additions & 4 deletions src/icons/DownArrowIcon.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,15 +19,19 @@ export default function DownArrowIcon({
}: Props) {
return (
<Svg
width={getSizing(height)}
height={getSizing(height)}
width={getSizing(height, 24)}
height={getSizing(height, 24)}
strokeWidth={strokeWidth}
viewBox="0 0 16 16"
viewBox="0 0 24 24"
fill="none"
testID="downArrowIcon"
style={style}
>
<Path d="M3 6l5 5 5-5" stroke={color} />
<Path
fill={color}
stroke={color}
d="m16.59 8.707.703.703L12 14.703 6.707 9.41l.703-.703 4.237 4.227.353.352.353-.352 4.237-4.227Z"
/>
</Svg>
)
}
1 change: 1 addition & 0 deletions src/jumpstart/JumpstartEnterAmount.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -180,6 +180,7 @@ function JumpstartEnterAmount() {
<EnterAmount
tokens={tokens}
prepareTransactionsResult={prepareJumpstartTransactions.result}
prepareTransactionsLoading={prepareJumpstartTransactions.loading}
onClearPreparedTransactions={prepareJumpstartTransactions.reset}
onRefreshPreparedTransactions={handleRefreshPreparedTransactions}
prepareTransactionError={prepareJumpstartTransactions.error}
Expand Down
Loading
Loading