diff --git a/app/src/main/java/to/bitkit/ui/screens/transfer/SpendingAdvancedScreen.kt b/app/src/main/java/to/bitkit/ui/screens/transfer/SpendingAdvancedScreen.kt index ba779be63..06a48a341 100644 --- a/app/src/main/java/to/bitkit/ui/screens/transfer/SpendingAdvancedScreen.kt +++ b/app/src/main/java/to/bitkit/ui/screens/transfer/SpendingAdvancedScreen.kt @@ -75,6 +75,7 @@ fun SpendingAdvancedScreen( val transferValues by viewModel.transferValues.collectAsStateWithLifecycle() val currentMaxLspBalance by rememberUpdatedState(transferValues.maxLspBalance) + val currentCurrencies by rememberUpdatedState(currencies) LaunchedEffect(order.clientBalanceSat) { viewModel.updateTransferValues(order.clientBalanceSat) @@ -112,13 +113,16 @@ fun SpendingAdvancedScreen( LaunchedEffect(Unit) { amountInputViewModel.effect.collect { when (it) { - AmountInputEffect.MaxExceeded -> app.toast( - type = Toast.ToastType.WARNING, - title = context.getString(R.string.lightning__spending_advanced__error_max__title), - description = context.getString(R.string.lightning__spending_advanced__error_max__description) - .replace("{amount}", currentMaxLspBalance.formatToModernDisplay()), - visibilityTime = Toast.VISIBILITY_TIME_SHORT, - ) + AmountInputEffect.MaxExceeded -> { + amountInputViewModel.setSats(currentMaxLspBalance.toLong(), currentCurrencies) + app.toast( + type = Toast.ToastType.WARNING, + title = context.getString(R.string.lightning__spending_advanced__error_max__title), + description = context.getString(R.string.lightning__spending_advanced__error_max__description) + .replace("{amount}", currentMaxLspBalance.formatToModernDisplay()), + visibilityTime = Toast.VISIBILITY_TIME_SHORT, + ) + } } } } diff --git a/app/src/main/java/to/bitkit/ui/screens/transfer/SpendingAmountScreen.kt b/app/src/main/java/to/bitkit/ui/screens/transfer/SpendingAmountScreen.kt index 7a9fe15e9..36ea358a0 100644 --- a/app/src/main/java/to/bitkit/ui/screens/transfer/SpendingAmountScreen.kt +++ b/app/src/main/java/to/bitkit/ui/screens/transfer/SpendingAmountScreen.kt @@ -55,7 +55,6 @@ import to.bitkit.viewmodels.TransferEffect import to.bitkit.viewmodels.TransferToSpendingUiState import to.bitkit.viewmodels.TransferViewModel import to.bitkit.viewmodels.previewAmountInputViewModel -import kotlin.math.min @Suppress("ViewModelForwarding") @Composable @@ -74,6 +73,7 @@ fun SpendingAmountScreen( val amountUiState by amountInputViewModel.uiState.collectAsStateWithLifecycle() val context = LocalContext.current val currentMaxAllowedToSend by rememberUpdatedState(uiState.maxAllowedToSend) + val currentCurrencies by rememberUpdatedState(currencies) LaunchedEffect(isOffline) { viewModel.updateLimits() @@ -92,11 +92,14 @@ fun SpendingAmountScreen( LaunchedEffect(Unit) { amountInputViewModel.effect.collect { when (it) { - AmountInputEffect.MaxExceeded -> toast( - context.getString(R.string.lightning__spending_amount__error_max__title), - context.getString(R.string.lightning__spending_amount__error_max__description) - .replace("{amount}", currentMaxAllowedToSend.formatToModernDisplay()), - ) + AmountInputEffect.MaxExceeded -> { + amountInputViewModel.setSats(currentMaxAllowedToSend, currentCurrencies) + toast( + context.getString(R.string.lightning__spending_amount__error_max__title), + context.getString(R.string.lightning__spending_amount__error_max__description) + .replace("{amount}", currentMaxAllowedToSend.formatToModernDisplay()), + ) + } } } } @@ -109,23 +112,10 @@ fun SpendingAmountScreen( currencies = currencies, onBackClick = onBackClick, onClickQuarter = { - val quarter = uiState.balanceAfterFeeQuarter() - val max = uiState.maxAllowedToSend - if (quarter > max) { - toast( - context.getString(R.string.lightning__spending_amount__error_max__title), - context.getString(R.string.lightning__spending_amount__error_max__description) - .replace("{amount}", max.formatToModernDisplay()), - ) - } - val cappedQuarter = min(quarter, max) - viewModel.updateLimits(cappedQuarter) - amountInputViewModel.setSats(cappedQuarter, currencies) + amountInputViewModel.setSats(uiState.quarterAmount, currencies) }, onClickMaxAmount = { - val newAmountSats = uiState.maxAllowedToSend - viewModel.updateLimits(newAmountSats) - amountInputViewModel.setSats(newAmountSats, currencies) + amountInputViewModel.setSats(uiState.maxAllowedToSend, currencies) }, onConfirmAmount = { viewModel.onConfirmAmount(amountUiState.sats) }, ) diff --git a/app/src/main/java/to/bitkit/viewmodels/TransferViewModel.kt b/app/src/main/java/to/bitkit/viewmodels/TransferViewModel.kt index 6e03c7514..202ac4ee9 100644 --- a/app/src/main/java/to/bitkit/viewmodels/TransferViewModel.kt +++ b/app/src/main/java/to/bitkit/viewmodels/TransferViewModel.kt @@ -405,12 +405,14 @@ class TransferViewModel @Inject constructor( liquidity.maxClientBalanceSat.toLong(), maxClientBalance.toLong() ) + val quarterAmount = min((maxSend.toDouble() * 0.25).roundToLong(), maxSend) _spendingUiState.update { it.copy( maxAllowedToSend = maxSend, isLoading = false, balanceAfterFee = maxSend, + quarterAmount = quarterAmount, ) } }.onFailure { @@ -650,12 +652,11 @@ data class TransferToSpendingUiState( val isAdvanced: Boolean = false, val maxAllowedToSend: Long = 0, val balanceAfterFee: Long = 0, + val quarterAmount: Long = 0, val isLoading: Boolean = false, val receivingAmount: Long = 0, val feeEstimate: Long? = null, -) { - fun balanceAfterFeeQuarter() = (balanceAfterFee.toDouble() * 0.25).roundToLong() -} +) data class TransferValues( val defaultLspBalance: ULong = 0u, diff --git a/app/src/test/java/to/bitkit/viewmodels/TransferViewModelTest.kt b/app/src/test/java/to/bitkit/viewmodels/TransferViewModelTest.kt index 2f45eefa3..e4472bdab 100644 --- a/app/src/test/java/to/bitkit/viewmodels/TransferViewModelTest.kt +++ b/app/src/test/java/to/bitkit/viewmodels/TransferViewModelTest.kt @@ -27,6 +27,7 @@ import to.bitkit.repositories.LightningState import to.bitkit.repositories.TransferRepo import to.bitkit.repositories.WalletRepo import to.bitkit.test.BaseUnitTest +import kotlin.math.roundToLong import kotlin.test.assertEquals import kotlin.time.Clock import kotlin.time.ExperimentalTime @@ -89,6 +90,7 @@ class TransferViewModelTest : BaseUnitTest() { val state = sut.spendingUiState.value assertEquals(OPTION_MAX_CLIENT_BALANCE.toLong(), state.maxAllowedToSend) assertEquals(OPTION_MAX_CLIENT_BALANCE.toLong(), state.balanceAfterFee) + assertEquals((OPTION_MAX_CLIENT_BALANCE.toDouble() * 0.25).roundToLong(), state.quarterAmount) // The order fee must be estimated against the clamped client balance, not the full balance. verify(blocktankRepo).estimateOrderFee(eq(LSP_MAX_CLIENT_BALANCE), any(), any()) diff --git a/changelog.d/next/1013.fixed.md b/changelog.d/next/1013.fixed.md new file mode 100644 index 000000000..a18e5fbe3 --- /dev/null +++ b/changelog.d/next/1013.fixed.md @@ -0,0 +1 @@ +Transfer to Spending now fills in the maximum transferable amount when you enter a value above the limit, instead of only showing an error.