diff --git a/CHANGELOG.md b/CHANGELOG.md
index 0e515565c1b..c16d4130ff7 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -4,6 +4,8 @@
- added: Added Infinite ramp plugin.
- fixed: Append chain name for L2-native assets in `RampCreateScene`
+- changed: `SwapCreateScene` shows a "Cancel" and "Next" button when editing
+ amounts
## 4.39.0 (staging)
diff --git a/package.json b/package.json
index e9dfa668424..e5abcc64f0d 100644
--- a/package.json
+++ b/package.json
@@ -145,7 +145,6 @@
"react-native-image-colors": "^2.4.0",
"react-native-image-picker": "^8.2.1",
"react-native-in-app-review": "^4.3.5",
- "react-native-keyboard-accessory": "^0.1.16",
"react-native-keyboard-aware-scroll-view": "^0.9.5",
"react-native-keyboard-controller": "^1.19.0",
"react-native-linear-gradient": "^2.8.3",
diff --git a/src/__tests__/scenes/__snapshots__/SwapCreateScene.test.tsx.snap b/src/__tests__/scenes/__snapshots__/SwapCreateScene.test.tsx.snap
index 04463a97755..b341e21470f 100644
--- a/src/__tests__/scenes/__snapshots__/SwapCreateScene.test.tsx.snap
+++ b/src/__tests__/scenes/__snapshots__/SwapCreateScene.test.tsx.snap
@@ -237,7 +237,7 @@ exports[`SwapCreateScene should render with loading props 1`] = `
"width": 750,
},
{
- "padding": 11,
+ "padding": 0,
},
]
}
@@ -265,572 +265,589 @@ exports[`SwapCreateScene should render with loading props 1`] = `
"maxHeight": 1334,
},
{
- "padding": 11,
+ "padding": 0,
},
]
}
>
-
+
-
-
-
+
+
- Select Source Wallet
-
+ ]
+ }
+ >
+ Select Source Wallet
+
+
-
-
-
+
+
-
-
-
-
-
+
+
+
+
+ />
+
-
-
-
+
-
-
-
+
+
- Select Receiving Wallet
-
+ ]
+ }
+ >
+ Select Receiving Wallet
+
+
-
-
-
+
+ nativeID="5"
+ />
+
,
= props => {
+ const { primary, tertiary } = props
+ const theme = useTheme()
+ const styles = getStyles(theme)
+
+ const handlePrimaryPress = useHandler(() => {
+ const res = primary.onPress?.()
+ Promise.resolve(res).catch(() => {})
+ })
+ const handleTertiaryPress = useHandler(() => {
+ const res = tertiary?.onPress?.()
+ Promise.resolve(res).catch(() => {})
+ })
+
+ if (tertiary == null) {
+ return (
+
+ )
+ }
+
+ return (
+
+
+
+
+
+ )
+}
+
+const getStyles = cacheStyles((theme: Theme) => ({
+ container: {
+ position: 'relative',
+ flexDirection: 'row',
+ justifyContent: 'space-between',
+ alignItems: 'center',
+ padding: theme.rem(0.5)
+ },
+ tertiary: {
+ marginTop: theme.rem(0.25)
+ }
+}))
diff --git a/src/components/common/SceneWrapper.tsx b/src/components/common/SceneWrapper.tsx
index 99b4a4bd1e8..b8b41b68695 100644
--- a/src/components/common/SceneWrapper.tsx
+++ b/src/components/common/SceneWrapper.tsx
@@ -6,14 +6,21 @@ import {
} from '@react-navigation/native'
import * as React from 'react'
import { useEffect, useMemo, useState } from 'react'
-import { Keyboard, StyleSheet, View, type ViewStyle } from 'react-native'
+import {
+ Keyboard,
+ Platform,
+ StyleSheet,
+ View,
+ type ViewStyle
+} from 'react-native'
import {
useKeyboardHandler,
useReanimatedKeyboardAnimation
} from 'react-native-keyboard-controller'
import Reanimated, {
useAnimatedReaction,
- useAnimatedStyle
+ useAnimatedStyle,
+ useSharedValue
} from 'react-native-reanimated'
import {
type EdgeInsets,
@@ -118,6 +125,14 @@ interface SceneWrapperProps {
// True to make the scene scrolling (if avoidKeyboard is false):
scroll?: boolean
+
+ // Optional "dock" view rendered at the bottom of the scene, attached to the
+ // keyboard, tabs, footer, etc, whatever is highest:
+ dockProps?: {
+ children: React.ReactNode
+ keyboardVisibleOnly?: boolean
+ contentContainerStyle?: ViewStyle
+ }
}
/**
@@ -147,12 +162,14 @@ function SceneWrapperComponent(props: SceneWrapperProps): React.ReactElement {
hasTabs = false,
padding = 0,
renderFooter,
- scroll = false
+ scroll = false,
+ dockProps
} = props
const notificationHeight = useSelector(state => state.ui.notificationHeight)
const navigation = useNavigation()
+ const isIos = Platform.OS === 'ios'
// We need to track this state in the JS thread because insets are not shared values
const [isKeyboardOpen, setIsKeyboardOpen] = useState(false)
@@ -163,6 +180,33 @@ function SceneWrapperComponent(props: SceneWrapperProps): React.ReactElement {
}
})
+ // Local keyboard opening/closing start/end state for dock parity between iOS
+ // and Android. `keyboardWillShow`/`keyboardDidShow` mean different things on
+ // each platform:
+ const [isKeyboardVisibleDock, setKeyboardVisibleDock] = useState(false)
+ // Track closing/opening state explicitly for animation direction:
+ const isClosingSv = useSharedValue(false)
+ useEffect(() => {
+ const showEvent = isIos ? 'keyboardWillShow' : 'keyboardDidShow'
+ const hideEvent = isIos ? 'keyboardWillHide' : 'keyboardDidHide'
+ const onShow = (): void => {
+ setKeyboardVisibleDock(true)
+ isClosingSv.value = false
+ }
+ const onHide = (): void => {
+ setKeyboardVisibleDock(false)
+ isClosingSv.value = true
+ }
+ const showListener = Keyboard.addListener(showEvent, onShow)
+ const hideListener = Keyboard.addListener(hideEvent, onHide)
+ return () => {
+ showListener.remove()
+ hideListener.remove()
+ }
+ // No need to depend on `isClosingSv` since it's a shared value
+ // eslint-disable-next-line react-hooks/exhaustive-deps
+ }, [isIos])
+
// Reset the footer ratio when focused
// We can do this because multiple calls to resetFooterRatio isn't costly
// because it just sets snapTo SharedValue to `1`
@@ -233,6 +277,22 @@ function SceneWrapperComponent(props: SceneWrapperProps): React.ReactElement {
[insets.top, insets.right, insets.bottom, insets.left]
)
+ // Collapsed bottom inset that ignores keyboard-open state (used to clamp during close):
+ const collapsedInsetBottom = useMemo(
+ () =>
+ safeAreaInsets.bottom +
+ (hasNotifications ? notificationHeight : 0) +
+ (hasTabs ? MAX_TAB_BAR_HEIGHT : 0) +
+ footerHeight,
+ [
+ footerHeight,
+ hasNotifications,
+ hasTabs,
+ notificationHeight,
+ safeAreaInsets.bottom
+ ]
+ )
+
// This is a convenient styles object which may be applied to scene container
// components to offset the inset styles applied to the SceneWrapper.
const undoInsetStyle: UndoInsetStyle = useMemo(
@@ -267,6 +327,58 @@ function SceneWrapperComponent(props: SceneWrapperProps): React.ReactElement {
return children
}, [children, sceneWrapperInfo])
+ // Build Dock View element
+ const keyboardVisibleOnlyDoc = dockProps?.keyboardVisibleOnly ?? true
+ const dockBaseStyle = useMemo(
+ () => ({
+ position: 'absolute' as const,
+ left: 0,
+ right: 0,
+ bottom: 0,
+ backgroundColor: 'transparent'
+ }),
+ []
+ )
+ const insetBottomSv = useSharedValue(insets.bottom)
+ const collapsedInsetSv = useSharedValue(collapsedInsetBottom)
+ useEffect(() => {
+ insetBottomSv.value = insets.bottom
+ collapsedInsetSv.value = collapsedInsetBottom
+ }, [collapsedInsetBottom, insets.bottom, collapsedInsetSv, insetBottomSv])
+ const dockAnimatedStyle = useAnimatedStyle(() => {
+ // keyboardHeightDiff.value is negative when open; invert to get height
+ const keyboardHeight =
+ keyboardHeightDiff.value < 0 ? -keyboardHeightDiff.value : 0
+ const isClosing = isClosingSv.value
+
+ let bottom: number
+ if (keyboardHeight > 0) {
+ // While opening, ignore insets to hug keyboard.
+ // While closing, never dip below the insets (avoid flicker under tab bar).
+ bottom = isClosing
+ ? Math.max(keyboardHeight, collapsedInsetSv.value)
+ : keyboardHeight
+ } else {
+ // Settled closed: rest above insets.
+ bottom = collapsedInsetSv.value
+ }
+
+ return { bottom }
+ })
+ const shouldShowDock =
+ dockProps != null && (!keyboardVisibleOnlyDoc || isKeyboardVisibleDock)
+ const dockElement = !shouldShowDock ? null : (
+
+ {dockProps?.children}
+
+ )
+
if (scroll) {
return (
<>
@@ -300,6 +412,7 @@ function SceneWrapperComponent(props: SceneWrapperProps): React.ReactElement {
navigation={navigation}
/>
) : null}
+ {dockElement}
>
)
@@ -342,6 +455,7 @@ function SceneWrapperComponent(props: SceneWrapperProps): React.ReactElement {
navigation={navigation}
/>
) : null}
+ {dockElement}
>
)
@@ -377,6 +491,7 @@ function SceneWrapperComponent(props: SceneWrapperProps): React.ReactElement {
navigation={navigation}
/>
) : null}
+ {dockElement}
>
)
diff --git a/src/components/keyboard/KavButton.tsx b/src/components/keyboard/KavButton.tsx
deleted file mode 100644
index 08705a43147..00000000000
--- a/src/components/keyboard/KavButton.tsx
+++ /dev/null
@@ -1,114 +0,0 @@
-import * as React from 'react'
-import { Keyboard, Platform } from 'react-native'
-import { KeyboardAccessoryView } from 'react-native-keyboard-accessory'
-import { useSafeAreaInsets } from 'react-native-safe-area-context'
-
-import { useSelector } from '../../types/reactRedux'
-import { EdgeButton } from '../buttons/EdgeButton'
-import { MAX_TAB_BAR_HEIGHT } from '../themed/MenuTabs'
-
-interface KavButtonProps {
- children?: React.ReactNode
- disabled?: boolean
- hasNotifications?: boolean
- hasTabs?: boolean
- label?: string
- spinner?: boolean
- testID?: string
- visible?: boolean
- onPress?: () => void | Promise
-}
-
-/**
- * A keyboard accessory button that spans most of the width of the screen,
- * positioned above the keyboard.
- *
- * Collapsing the keyboard will animate the button to the bottom of the scene,
- * taking into account any insets from tabs, notification cards, etc.
- *
- * IMPORTANT: This component MUST be placed as a direct sibling of SceneWrapper
- * for proper keyboard positioning.
- *
- * TODO: Consider moving this to SceneWrapper since there is a lot of duplicate
- * inset logic
- */
-export const KavButton = (props: KavButtonProps) => {
- const {
- children,
- disabled = false,
- label,
- onPress,
- spinner = false,
- visible = true,
- testID,
- hasTabs = false,
- hasNotifications = false
- } = props
- const isIos = Platform.OS === 'ios'
-
- const safeAreaInsets = useSafeAreaInsets()
- const notificationHeight = useSelector(state => state.ui.notificationHeight)
-
- const [isKeyboardVisible, setKeyboardVisible] = React.useState(false)
-
- React.useEffect(() => {
- // Listening event is different between iOS and Android, but actually mean
- // the same thing: when the keyboard begins its movement
- const keyboardDidShowListener = Keyboard.addListener(
- isIos ? 'keyboardWillShow' : 'keyboardDidShow',
- () => {
- setKeyboardVisible(true)
- }
- )
- const keyboardDidHideListener = Keyboard.addListener(
- isIos ? 'keyboardWillHide' : 'keyboardDidHide',
- () => {
- setKeyboardVisible(false)
- }
- )
-
- return () => {
- keyboardDidShowListener.remove()
- keyboardDidHideListener.remove()
- }
- }, [isIos])
-
- const maybeTabBarHeight = hasTabs ? MAX_TAB_BAR_HEIGHT : 0
- const maybeNotificationHeight = hasNotifications ? notificationHeight : 0
-
- const keyboardAccessoryStyle = React.useMemo(
- () => ({
- backgroundColor: 'transparent',
- marginBottom: isKeyboardVisible
- ? 0
- : safeAreaInsets.bottom + maybeTabBarHeight + maybeNotificationHeight
- }),
- [
- isKeyboardVisible,
- safeAreaInsets.bottom,
- maybeTabBarHeight,
- maybeNotificationHeight
- ]
- )
-
- return !visible ? null : (
-
-
- {children}
-
-
- )
-}
diff --git a/src/components/scenes/RampCreateScene.tsx b/src/components/scenes/RampCreateScene.tsx
index 2919d6aa49a..357c83d156c 100644
--- a/src/components/scenes/RampCreateScene.tsx
+++ b/src/components/scenes/RampCreateScene.tsx
@@ -57,6 +57,7 @@ import {
} from '../../util/utils'
import { DropdownInputButton } from '../buttons/DropdownInputButton'
import { EdgeButton } from '../buttons/EdgeButton'
+import { KavButtons } from '../buttons/KavButtons'
import { PillButton } from '../buttons/PillButton'
import { AlertCardUi4 } from '../cards/AlertCard'
import { ErrorCard, I18nError } from '../cards/ErrorCard'
@@ -64,7 +65,6 @@ import { EdgeTouchableOpacity } from '../common/EdgeTouchableOpacity'
import { SceneWrapper } from '../common/SceneWrapper'
import { CryptoIcon } from '../icons/CryptoIcon'
import { FiatIcon } from '../icons/FiatIcon'
-import { KavButton } from '../keyboard/KavButton'
import { SceneContainer } from '../layout/SceneContainer'
import { FiatListModal } from '../modals/FiatListModal'
import {
@@ -799,210 +799,210 @@ export const RampCreateScene: React.FC = (props: Props) => {
// Render trade form view
return (
- <>
-
-
- flagUri != null ? (
-
- ) : null
- }
- label={getRegionText()}
- onPress={handleRegionSelect}
- />
- }
- >
- {/* Amount Inputs */}
- {/* Top Input (Fiat) */}
-
-
- {selectedFiatFlagUri !== '' ? (
-
-
-
- ) : (
- // Shouldn't be possible to reach this case, but just in case:
- // show the fiat currency code as the placeholder
-
+ )
+ }}
+ >
+
+ flagUri != null ? (
+
- )}
-
-
-
-
-
- {/* Bottom Input (Crypto by design) */}
-
- {selectedCryptoCurrencyCode == null &&
- !isLoadingPersistedCryptoSelection ? (
-
- ) : (
- <>
-
- {isLoadingPersistedCryptoSelection ? (
-
- ) : selectedCrypto == null ||
- selectedWallet == null ? null : (
-
- )}
-
-
-
+ }
+ >
+ {/* Amount Inputs */}
+ {/* Top Input (Fiat) */}
+
+
+ {selectedFiatFlagUri !== '' ? (
+
+
- >
+
+ ) : (
+ // Shouldn't be possible to reach this case, but just in case:
+ // show the fiat currency code as the placeholder
+
)}
-
-
- {/* Wallet Name and MAX Button Row */}
- {selectedWallet == null ? null : (
-
- {selectedWallet?.name != null ? (
-
- {selectedWallet.name}
-
- ) : null}
-
-
- {lstrings.trade_create_max}
-
-
-
- )}
-
- {/* Exchange Rate */}
- {selectedCrypto == null ||
- selectedWallet == null ||
- denomination == null ||
- 'empty' in amountQuery ||
- lastUsedInput == null ||
- (!isLoadingQuotes &&
- !isFetchingQuotes &&
- allQuotes.length === 0) ? null : (
+
+
+
+
+
+ {/* Bottom Input (Crypto by design) */}
+
+ {selectedCryptoCurrencyCode == null &&
+ !isLoadingPersistedCryptoSelection ? (
+
+ ) : (
<>
-
- {lstrings.trade_create_exchange_rate}
-
- {bestQuote != null ? (
-
- {exchangeRateText}
-
- ) : null}
-
+ {isLoadingPersistedCryptoSelection ? (
+
+ ) : selectedCrypto == null || selectedWallet == null ? null : (
+
+ )}
+
+
+
>
)}
-
- {/* Alert for no supported plugins */}
- {
- // Nothing is loading
- !isResultLoading &&
- // Nothing was returned
- allQuotes.length === 0 &&
- quoteErrors.length === 0 &&
- // No other error to show (e.g., insufficient funds)
- errorForDisplay == null &&
- // User has queried
- !('empty' in amountQuery) &&
- lastUsedInput != null &&
- selectedWallet != null &&
- selectedCryptoCurrencyCode != null ? (
-
- ) : null
- }
-
- {errorForDisplay != null ? (
-
- ) : null}
-
-
- {/* Next Button - Must be sibling of SceneWrapper for proper keyboard positioning */}
-
+
+ {/* Wallet Name and MAX Button Row */}
+ {selectedWallet == null ? null : (
+
+ {selectedWallet?.name != null ? (
+
+ {selectedWallet.name}
+
+ ) : null}
+
+
+ {lstrings.trade_create_max}
+
+
+
+ )}
+
+ {/* Exchange Rate */}
+ {selectedCrypto == null ||
+ selectedWallet == null ||
+ denomination == null ||
+ 'empty' in amountQuery ||
+ lastUsedInput == null ||
+ (!isLoadingQuotes &&
+ !isFetchingQuotes &&
+ allQuotes.length === 0) ? null : (
+ <>
+
+ {lstrings.trade_create_exchange_rate}
+
+ {bestQuote != null ? (
+
+ {exchangeRateText}
+
+ ) : null}
+
+ >
+ )}
+
+ {/* Alert for no supported plugins */}
+ {
+ // Nothing is loading
+ !isResultLoading &&
+ // Nothing was returned
+ allQuotes.length === 0 &&
+ quoteErrors.length === 0 &&
+ // No other error to show (e.g., insufficient funds)
+ errorForDisplay == null &&
+ // User has queried
+ !('empty' in amountQuery) &&
+ lastUsedInput != null &&
+ selectedWallet != null &&
+ selectedCryptoCurrencyCode != null ? (
+
+ ) : null
}
- />
- >
+
+ {errorForDisplay != null ? : null}
+
+
)
}
diff --git a/src/components/scenes/RampKycFormScene.tsx b/src/components/scenes/RampKycFormScene.tsx
index b4b7ffec87e..d952fb04389 100644
--- a/src/components/scenes/RampKycFormScene.tsx
+++ b/src/components/scenes/RampKycFormScene.tsx
@@ -6,9 +6,9 @@ import { lstrings } from '../../locales/strings'
import { GuiFormField } from '../../plugins/gui/components/GuiFormField'
import { GuiFormRow } from '../../plugins/gui/components/GuiFormRow'
import type { BuySellTabSceneProps } from '../../types/routerTypes'
+import { KavButtons } from '../buttons/KavButtons'
import { ErrorCard } from '../cards/ErrorCard'
import { SceneWrapper } from '../common/SceneWrapper'
-import { KavButton } from '../keyboard/KavButton'
import { SceneContainer } from '../layout/SceneContainer'
import { showError } from '../services/AirshipInstance'
import type { FilledTextInputRef } from '../themed/FilledTextInput'
@@ -189,103 +189,111 @@ export const RampKycFormScene = React.memo((props: Props) => {
postalCode.trim() !== ''
return (
- <>
-
-
-
-
-
-
-
-
-
-
-
-
-
+ )
+ }}
+ >
+
+
-
- {
- handleSubmit().catch(showError)
- }}
- returnKeyType="done"
- fieldRef={postalCodeRef}
+ fieldRef={lastNameRef}
/>
-
- {error == null ? null : }
-
-
-
- >
+
+
+
+
+
+
+
+
+
+
+
+ {
+ handleSubmit().catch(showError)
+ }}
+ returnKeyType="done"
+ fieldRef={postalCodeRef}
+ />
+
+ {error == null ? null : }
+
+
)
})
diff --git a/src/components/scenes/SwapCreateScene.tsx b/src/components/scenes/SwapCreateScene.tsx
index 4ec1c7391d5..13130513eeb 100644
--- a/src/components/scenes/SwapCreateScene.tsx
+++ b/src/components/scenes/SwapCreateScene.tsx
@@ -26,8 +26,9 @@ import type { NavigationBase, SwapTabSceneProps } from '../../types/routerTypes'
import { getCurrencyCode } from '../../util/CurrencyInfoHelpers'
import { getWalletName } from '../../util/CurrencyWalletHelpers'
import { zeroString } from '../../util/utils'
-import { ButtonsView } from '../buttons/ButtonsView'
import { EdgeButton } from '../buttons/EdgeButton'
+import { KavButtons } from '../buttons/KavButtons'
+import { SceneButtons } from '../buttons/SceneButtons'
import { AlertCardUi4 } from '../cards/AlertCard'
import {
EdgeAnim,
@@ -40,6 +41,7 @@ import { EdgeTouchableOpacity } from '../common/EdgeTouchableOpacity'
import { SceneWrapper } from '../common/SceneWrapper'
import { styled } from '../hoc/styled'
import { SwapVerticalIcon } from '../icons/ThemedIcons'
+import { SceneContainer } from '../layout/SceneContainer'
import {
WalletListModal,
type WalletListResult
@@ -435,7 +437,7 @@ export const SwapCreateScene: React.FC = props => {
await showWalletListModal('to')
})
- const handleReturnKeyPress = useHandler(() => {
+ const handleCancelKeyPress = useHandler(() => {
Keyboard.dismiss()
})
@@ -515,92 +517,109 @@ export const SwapCreateScene: React.FC = props => {
hasNotifications
scroll
keyboardShouldPersistTaps="handled"
- padding={theme.rem(0.5)}
- >
-
- {fromWallet == null ? (
-
- ) : (
-
- )}
-
-
-
-
-
-
- {hasMaxSpend ? (
-
-
- {lstrings.string_max_cap}
-
-
- ) : null}
-
-
-
- {toWallet == null ? (
-
- ) : (
-
- )}
-
- {renderAlert()}
-
- {isNextHidden ? null : (
-
- )}
-
+ )
+ }}
+ >
+ {({ isKeyboardOpen }) => (
+
+
+ {fromWallet == null ? (
+
+ ) : (
+
+ )}
+
+
+
+
+
+
+ {hasMaxSpend ? (
+
+
+ {lstrings.string_max_cap}
+
+
+ ) : null}
+
+
+
+ {toWallet == null ? (
+
+ ) : (
+
+ )}
+
+ {renderAlert()}
+
+ {isNextHidden || isKeyboardOpen ? null : (
+
+ )}
+
+
+ )}
)
}
diff --git a/src/components/themed/SwapInput.tsx b/src/components/themed/SwapInput.tsx
index dcefd4c4eca..e746b5877ad 100644
--- a/src/components/themed/SwapInput.tsx
+++ b/src/components/themed/SwapInput.tsx
@@ -1,7 +1,7 @@
import { div, log10, mul, round } from 'biggystring'
import type { EdgeCurrencyWallet, EdgeTokenId } from 'edge-core-js'
import React, { useMemo } from 'react'
-import { type ReturnKeyType, View } from 'react-native'
+import { View } from 'react-native'
import { useHandler } from '../../hooks/useHandler'
import {
@@ -52,7 +52,6 @@ export interface Props {
forceField?: 'fiat' | 'crypto'
keyboardVisible?: boolean
placeholders?: [string, string]
- returnKeyType?: ReturnKeyType
startNativeAmount?: string
tokenId: EdgeTokenId
wallet: EdgeCurrencyWallet
@@ -62,7 +61,6 @@ export interface Props {
onBlur?: () => void
onFocus?: () => void
onNext?: () => void
- onReturnKeyPress?: () => void
onSelectWallet: () => Promise
}
@@ -80,7 +78,6 @@ const SwapInputComponent = React.forwardRef(
keyboardVisible = true,
placeholders,
startNativeAmount,
- returnKeyType,
tokenId,
wallet,
walletPlaceholderText,
@@ -89,8 +86,7 @@ const SwapInputComponent = React.forwardRef(
onSelectWallet,
onBlur,
onFocus,
- onNext,
- onReturnKeyPress
+ onNext
} = props
const exchangeRates = useSelector(state => state.exchangeRates)
@@ -353,12 +349,11 @@ const SwapInputComponent = React.forwardRef(
ref={flipInputRef}
renderFooter={renderFooter}
renderHeader={renderHeader}
- returnKeyType={returnKeyType}
startAmounts={[initialDisplayAmount, initialFiatAmount]}
// Events:
onBlur={onBlur}
onFocus={onFocus}
- onNext={onReturnKeyPress ?? onNext}
+ onNext={onNext}
/>
>
)
diff --git a/src/plugins/gui/scenes/FiatPluginEnterAmountScene.tsx b/src/plugins/gui/scenes/FiatPluginEnterAmountScene.tsx
index e7446ed003c..73342eeb5b2 100644
--- a/src/plugins/gui/scenes/FiatPluginEnterAmountScene.tsx
+++ b/src/plugins/gui/scenes/FiatPluginEnterAmountScene.tsx
@@ -4,6 +4,7 @@ import { useEffect } from 'react'
import { Image, type TextStyle, View } from 'react-native'
import { ButtonsView } from '../../../components/buttons/ButtonsView'
+import { KavButtons } from '../../../components/buttons/KavButtons'
import { PoweredByCard } from '../../../components/cards/PoweredByCard'
import {
EdgeAnim,
@@ -13,7 +14,6 @@ import {
fadeInUp60
} from '../../../components/common/EdgeAnim'
import { SceneWrapper } from '../../../components/common/SceneWrapper'
-import { KavButton } from '../../../components/keyboard/KavButton'
import { SceneContainer } from '../../../components/layout/SceneContainer'
import { showError } from '../../../components/services/AirshipInstance'
import {
@@ -236,144 +236,147 @@ export const FiatPluginEnterAmountScene = React.memo((props: Props) => {
poweredBy != null ? getPartnerIconUri(poweredBy.poweredByIcon) : undefined
return (
- <>
-
+ )
+ }}
+ >
+
-
-
- {swapInputLocations ? (
-
-
-
-
-
-
-
- {onMax != null ? (
-
-
-
- ) : null}
-
- ) : (
-
-
-
-
-
-
+ {swapInputLocations ? (
+
+
+
+
+
+
+
+ {onMax != null ? (
+
+
-
- {onMax != null ? (
-
-
-
- ) : null}
-
- )}
- <>
-
-
- {statusText.content}
-
+
+ ) : null}
+
+ ) : (
+
+
+
-
-
+
- >
-
-
-
-
- >
+ {onMax != null ? (
+
+
+
+ ) : null}
+
+ )}
+ <>
+
+
+ {statusText.content}
+
+
+
+
+
+ >
+
+
+
)
})
diff --git a/yarn.lock b/yarn.lock
index 7d946df2c5a..95543d581c0 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -15983,11 +15983,6 @@ react-native-is-edge-to-edge@^1.1.7, react-native-is-edge-to-edge@^1.2.1:
resolved "https://registry.yarnpkg.com/react-native-is-edge-to-edge/-/react-native-is-edge-to-edge-1.2.1.tgz#64e10851abd9d176cbf2b40562f751622bde3358"
integrity sha512-FLbPWl/MyYQWz+KwqOZsSyj2JmLKglHatd3xLZWskXOpRaio4LfEDEz8E/A6uD8QoTHW6Aobw1jbEwK7KMgR7Q==
-react-native-keyboard-accessory@^0.1.16:
- version "0.1.16"
- resolved "https://registry.yarnpkg.com/react-native-keyboard-accessory/-/react-native-keyboard-accessory-0.1.16.tgz#f0babba9e6568c0c2c8f3fd774fcb2b90b8274ba"
- integrity sha512-zpdaduoGjp/spLtM0XxxyxFpCqFQu3fospy/HeYpaIfsXTqGdT1MIajS8tahDxeG6fHLDrWvEIYA6zWM5jni0w==
-
react-native-keyboard-aware-scroll-view@^0.9.5:
version "0.9.5"
resolved "https://registry.yarnpkg.com/react-native-keyboard-aware-scroll-view/-/react-native-keyboard-aware-scroll-view-0.9.5.tgz#e2e9665d320c188e6b1f22f151b94eb358bf9b71"