diff --git a/app/src/main/java/to/bitkit/ui/screens/wallets/send/SendAmountScreen.kt b/app/src/main/java/to/bitkit/ui/screens/wallets/send/SendAmountScreen.kt index 45eabb6bb7..9ef94cae3a 100644 --- a/app/src/main/java/to/bitkit/ui/screens/wallets/send/SendAmountScreen.kt +++ b/app/src/main/java/to/bitkit/ui/screens/wallets/send/SendAmountScreen.kt @@ -10,11 +10,14 @@ import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.height +import androidx.compose.foundation.layout.heightIn import androidx.compose.foundation.layout.navigationBarsPadding import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.size import androidx.compose.foundation.layout.width +import androidx.compose.foundation.rememberScrollState import androidx.compose.foundation.shape.RoundedCornerShape +import androidx.compose.foundation.verticalScroll import androidx.compose.material3.DropdownMenu import androidx.compose.material3.HorizontalDivider import androidx.compose.material3.Icon @@ -300,7 +303,15 @@ private fun SendAmountNodeRunning( } Column( - modifier = Modifier.padding(horizontal = 16.dp) + modifier = Modifier + .padding(horizontal = 16.dp) + .then( + if (uiState.paykitUsesUsdt) { + Modifier.verticalScroll(rememberScrollState()).heightIn(min = maxHeight) + } else { + Modifier + } + ) ) { VerticalSpacer(16.dp) @@ -318,7 +329,7 @@ private fun SendAmountNodeRunning( ) } - if (uiState.paykitUsesUsdt) VerticalSpacer(32.dp) else FillHeight(min = 12.dp) + FillHeight(min = 12.dp) if (uiState.paykitRateUnavailable) { BodyS( stringResource(R.string.wallet__payment_request_rate_unavailable), @@ -413,28 +424,23 @@ private fun SendAmountNodeRunning( HorizontalDivider(modifier = Modifier.padding(top = if (uiState.paykitUsesUsdt) 16.dp else 12.dp)) if (uiState.paykitUsesUsdt) { - BoxWithConstraints( - contentAlignment = Alignment.Center, - modifier = Modifier.weight(1f).fillMaxWidth() - ) { - NumberPad( - type = NumberPadType.DECIMAL, - decimalSeparator = DecimalFormatSymbols.getInstance().decimalSeparator.toString(), - availableHeight = this.maxHeight, - enabled = uiState.isAmountEditable, - onPress = { - app?.onUsdtAmountChange( - NumberPadInputHandler.handleInput( - it, - uiState.paykitAmount, - maxLength = 21, - maxDecimals = 6 - ) + NumberPad( + type = NumberPadType.DECIMAL, + decimalSeparator = DecimalFormatSymbols.getInstance().decimalSeparator.toString(), + availableHeight = maxHeight, + enabled = uiState.isAmountEditable, + onPress = { + app?.onUsdtAmountChange( + NumberPadInputHandler.handleInput( + it, + uiState.paykitAmount, + maxLength = 21, + maxDecimals = 6 ) - }, - onDeleteLongPress = { app?.onUsdtAmountChange("") } - ) - } + ) + }, + onDeleteLongPress = { app?.onUsdtAmountChange("") }, + ) } else { NumberPad( enabled = uiState.isAmountEditable, @@ -446,7 +452,6 @@ private fun SendAmountNodeRunning( ) } - if (uiState.paykitUsesUsdt) VerticalSpacer(16.dp) PrimaryButton( text = stringResource(R.string.common__continue), enabled = uiState.isAmountInputValid && !uiState.isFundingSourceLoading, diff --git a/app/src/main/java/to/bitkit/ui/screens/wallets/usdt/UsdtSendContent.kt b/app/src/main/java/to/bitkit/ui/screens/wallets/usdt/UsdtSendContent.kt index ed5c1a4bfb..5a70c1ef00 100644 --- a/app/src/main/java/to/bitkit/ui/screens/wallets/usdt/UsdtSendContent.kt +++ b/app/src/main/java/to/bitkit/ui/screens/wallets/usdt/UsdtSendContent.kt @@ -437,76 +437,77 @@ private fun UsdtAmountContent( onNetworkClick: (() -> Unit)?, destinations: ImmutableList, ) { - Column(modifier = Modifier.fillMaxSize()) { - UsdtAmountHeader(amount.ifEmpty { "0" }, modifier = Modifier.testTag("UsdtAmount")) - VerticalSpacer(32.dp) - state.error?.let { - BodyS( - state.errorMessage(it), - color = Colors.Brand, - modifier = Modifier.testTag("UsdtError") - ) - VerticalSpacer(16.dp) - } - FlowRow( - horizontalArrangement = Arrangement.SpaceBetween, - verticalArrangement = Arrangement.spacedBy(8.dp), - modifier = Modifier.fillMaxWidth(), - ) { - Column(modifier = Modifier.padding(end = 8.dp).align(Alignment.CenterVertically)) { - Caption13Up( - stringResource(R.string.wallet__send_available), - color = Colors.White64, - style = AppTextStyles.CaptionM.copy(letterSpacing = 1.sp), + BoxWithConstraints(modifier = Modifier.fillMaxSize()) { + val maxHeight = this.maxHeight + Column(modifier = Modifier.fillMaxWidth().verticalScroll(rememberScrollState()).heightIn(min = maxHeight)) { + UsdtAmountHeader(amount.ifEmpty { "0" }, modifier = Modifier.testTag("UsdtAmount")) + FillHeight(min = 12.dp) + state.error?.let { + BodyS( + state.errorMessage(it), + color = Colors.Brand, + modifier = Modifier.testTag("UsdtError") ) - VerticalSpacer(4.dp) - Row(horizontalArrangement = Arrangement.spacedBy(4.dp)) { - if (!hideBalance && wallet.balance != null) BodySSB("$", color = Colors.White64) - BodySSB( - text = if (hideBalance) { - UiConstants.HIDE_BALANCE_SHORT - } else { - wallet.balance?.let { usdtOverviewAmount(it) } ?: "—" - }, - style = AppTextStyles.BodySSB.copy(letterSpacing = 0.sp), - ) - } + VerticalSpacer(16.dp) } - Row( - horizontalArrangement = Arrangement.spacedBy(8.dp), - verticalAlignment = Alignment.CenterVertically, - modifier = Modifier.align(Alignment.CenterVertically), + FlowRow( + horizontalArrangement = Arrangement.SpaceBetween, + verticalArrangement = Arrangement.spacedBy(8.dp), + modifier = Modifier.fillMaxWidth(), ) { - NumberPadActionButton( - text = "USDT", - color = Colors.Usdt, - enabled = false, - textStyle = AppTextStyles.CaptionM.copy(letterSpacing = 1.sp), - onClick = {}, - ) - if (onMaximum != null && amountEditable) { + Column(modifier = Modifier.padding(end = 8.dp).align(Alignment.CenterVertically)) { + Caption13Up( + stringResource(R.string.wallet__send_available), + color = Colors.White64, + style = AppTextStyles.CaptionM.copy(letterSpacing = 1.sp), + ) + VerticalSpacer(4.dp) + Row(horizontalArrangement = Arrangement.spacedBy(4.dp)) { + if (!hideBalance && wallet.balance != null) BodySSB("$", color = Colors.White64) + BodySSB( + text = if (hideBalance) { + UiConstants.HIDE_BALANCE_SHORT + } else { + wallet.balance?.let { usdtOverviewAmount(it) } ?: "—" + }, + style = AppTextStyles.BodySSB.copy(letterSpacing = 0.sp), + ) + } + } + Row( + horizontalArrangement = Arrangement.spacedBy(8.dp), + verticalAlignment = Alignment.CenterVertically, + modifier = Modifier.align(Alignment.CenterVertically), + ) { NumberPadActionButton( - text = stringResource(R.string.common__max), + text = "USDT", color = Colors.Usdt, - onClick = onMaximum, - enabled = !state.busy, - isLoading = state.preparingMaximum, + enabled = false, textStyle = AppTextStyles.CaptionM.copy(letterSpacing = 1.sp), - modifier = Modifier.testTag("UsdtMax") - ) - } - if (onNetworkClick != null) { - UsdtNetworkButton( - destination, - onNetworkClick.takeUnless { state.busy }, - destinations, + onClick = {}, ) + if (onMaximum != null && amountEditable) { + NumberPadActionButton( + text = stringResource(R.string.common__max), + color = Colors.Usdt, + onClick = onMaximum, + enabled = !state.busy, + isLoading = state.preparingMaximum, + textStyle = AppTextStyles.CaptionM.copy(letterSpacing = 1.sp), + modifier = Modifier.testTag("UsdtMax") + ) + } + if (onNetworkClick != null) { + UsdtNetworkButton( + destination, + onNetworkClick.takeUnless { state.busy }, + destinations, + ) + } } } - } - VerticalSpacer(16.dp) - HorizontalDivider(color = Colors.White10) - BoxWithConstraints(contentAlignment = Alignment.Center, modifier = Modifier.weight(1f).fillMaxWidth()) { + VerticalSpacer(16.dp) + HorizontalDivider(color = Colors.White10) NumberPad( type = NumberPadType.DECIMAL, decimalSeparator = DecimalFormatSymbols.getInstance().decimalSeparator.toString(), @@ -517,16 +518,15 @@ private fun UsdtAmountContent( onAmountChange(NumberPadInputHandler.handleInput(key, amount, maxLength = 21, maxDecimals = 6)) }, ) + PrimaryButton( + text = stringResource(R.string.common__continue), + onClick = onReview, + enabled = amount.isNotEmpty() && !state.busy, + isLoading = state.busy && !state.preparingMaximum, + textStyle = AppTextStyles.BodySSB.copy(letterSpacing = 0.sp), + modifier = Modifier.testTag("UsdtReview") + ) } - VerticalSpacer(16.dp) - PrimaryButton( - text = stringResource(R.string.common__continue), - onClick = onReview, - enabled = amount.isNotEmpty() && !state.busy, - isLoading = state.busy && !state.preparingMaximum, - textStyle = AppTextStyles.BodySSB.copy(letterSpacing = 0.sp), - modifier = Modifier.testTag("UsdtReview") - ) } } diff --git a/changelog.d/next/1627.fixed.md b/changelog.d/next/1627.fixed.md new file mode 100644 index 0000000000..6548a033fd --- /dev/null +++ b/changelog.d/next/1627.fixed.md @@ -0,0 +1 @@ +The USDT amount keypad now sits right above Continue, as on the Bitcoin amount screen. diff --git a/journeys/usdt-send-review-and-details.xml b/journeys/usdt-send-review-and-details.xml index 64186accf5..71766d93e6 100644 --- a/journeys/usdt-send-review-and-details.xml +++ b/journeys/usdt-send-review-and-details.xml @@ -2,7 +2,7 @@ Use an onboarded wallet with USDT, a fresh BTC/USD rate, an owned recipient and existing sent/received activity. Quotes require the service with MAX support. No payment is submitted. Enable USDT in the introductory sheet or Settings, General, Payments before starting this flow. - Open USDT Send and enter the owned recipient. On Amount, verify the BTC equivalent above the dollar amount, 32-point gap before Available balance, USDT badge, MAX and network pill. Enter a six-decimal amount and verify no precision is lost. With a large available balance and BNB Smart Chain selected, verify both values remain fully readable; the controls may wrap onto a second row. + Open USDT Send and enter the owned recipient. On Amount, verify the BTC equivalent above the dollar amount at the top, then the free space, then Available balance, USDT badge, MAX and network pill right above the keypad, and Continue right below the keypad, laid out as on the Bitcoin Amount screen. Enter a six-decimal amount and verify no precision is lost. With a large available balance and BNB Smart Chain selected, verify both values remain fully readable; the controls may wrap onto a second row. Open the network pill and verify the full USDT Network picker, Tether rows and selected teal check. Select another EVM network. Verify the amount and valid recipient remain. Change to Solana with an EVM recipient and verify recipient entry is required. Enter an owned plain Solana address and verify the previous amount remains. Return to Arbitrum, enter the owned EVM address and verify the amount still remains. From recipient entry with another network selected, paste an explicit Arbitrum USDT URI. Verify the selected network becomes Arbitrum and the link amount is retained. A plain 0x address preserves the selected network. Tap MAX. Verify it fills a positive amount below the balance and remains on Amount. Continue and verify the payment plus maximum fee fits within the balance. Back out without swiping.