commit 6e7c17b810543725d5982228cb597c6b3ad06aa9
parent ec34c9ab65358840cad4e959dca9e6e2aa2b6352
Author: Iván Ávalos <avalos@disroot.org>
Date: Wed, 14 Jan 2026 22:31:18 +0100
[wallet] fix withdrawal crash on empty wallet
Diffstat:
2 files changed, 29 insertions(+), 14 deletions(-)
diff --git a/wallet/src/main/java/net/taler/wallet/withdraw/PromptWithdrawFragment.kt b/wallet/src/main/java/net/taler/wallet/withdraw/PromptWithdrawFragment.kt
@@ -24,12 +24,14 @@ import androidx.appcompat.app.AppCompatActivity
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.getValue
import androidx.compose.runtime.livedata.observeAsState
+import androidx.compose.runtime.remember
import androidx.compose.ui.platform.ComposeView
import androidx.core.os.bundleOf
import androidx.fragment.app.Fragment
import androidx.fragment.app.activityViewModels
import androidx.lifecycle.Lifecycle
import androidx.lifecycle.lifecycleScope
+import androidx.lifecycle.map
import androidx.lifecycle.repeatOnLifecycle
import androidx.navigation.fragment.findNavController
import com.google.android.material.snackbar.Snackbar
@@ -40,10 +42,7 @@ import net.taler.common.EventObserver
import net.taler.wallet.MainViewModel
import net.taler.wallet.R
import net.taler.wallet.main.ViewMode
-import net.taler.wallet.backend.BackendManager
-import net.taler.wallet.balances.ScopeInfo
import net.taler.wallet.compose.AmountScope
-import net.taler.wallet.compose.EmptyComposable
import net.taler.wallet.compose.LoadingScreen
import net.taler.wallet.compose.TalerSurface
import net.taler.wallet.compose.collectAsStateLifecycleAware
@@ -81,19 +80,30 @@ class PromptWithdrawFragment: Fragment() {
val withdrawExchangeUri = arguments?.getString("withdrawExchangeUri")
val exchangeBaseUrl = arguments?.getString("exchangeBaseUrl")
val amount = arguments?.getString("amount")?.let { Amount.fromJSONString(it) }
- val scope: ScopeInfo? = arguments?.getString("scopeInfo")?.let {
- BackendManager.json.decodeFromString(it)
- } ?: (model.viewMode.value as? ViewMode.Transactions)?.selectedScope
editableCurrency = arguments?.getBoolean("editableCurrency") ?: true
- val scopes = balanceManager.getScopes()
setContent {
val status by withdrawManager.withdrawStatus.collectAsStateLifecycleAware()
+ val viewMode by model.viewMode.collectAsStateLifecycleAware()
val devMode by model.devMode.observeAsState()
+ val selectedScope = remember (viewMode) {
+ (viewMode as? ViewMode.Transactions)?.selectedScope
+ }
+
+ val scopes by balanceManager.balances
+ .map { bl -> bl.map { it.scopeInfo } }
+ .map { bl ->
+ val scope = status.amountInfo?.scopeInfo
+ if (scope != null && !bl.contains(scope)) { bl + scope } else bl
+ }.observeAsState(emptyList())
+
+ val initialAmount = status.selectedAmount
+ ?: selectedScope?.let { Amount.zero(it.currency) }
+ ?: scopes.firstOrNull()?.let { Amount.zero(it.currency) }
- if (scopes.isEmpty()) EmptyComposable()
- val initialScope = status.selectedScope ?: scope ?: scopes.first()
- val initialAmount = status.selectedAmount ?: Amount.zero(initialScope.currency)
+ val initialScope = status.selectedScope
+ ?: selectedScope
+ ?: scopes.firstOrNull()
LaunchedEffect(status.status) {
if (status.status == None) {
@@ -105,7 +115,7 @@ class PromptWithdrawFragment: Fragment() {
withdrawManager.prepareManualWithdrawal(withdrawExchangeUri)
} else if (exchangeBaseUrl != null) {
withdrawManager.getWithdrawalDetailsForExchange(exchangeBaseUrl, loading = true)
- } else {
+ } else if (initialAmount != null) {
withdrawManager.getWithdrawalDetailsForAmount(
amount = initialAmount,
scopeInfo = initialScope,
@@ -133,8 +143,8 @@ class PromptWithdrawFragment: Fragment() {
WithdrawalShowInfo(
status = s,
devMode = devMode ?: false,
- initialAmountScope = status.selectedAmount?.let { amount ->
- status.selectedScope?.let { scope ->
+ initialAmountScope = initialAmount?.let { amount ->
+ initialScope?.let { scope ->
AmountScope(amount, scope)
}
},
diff --git a/wallet/src/main/java/net/taler/wallet/withdraw/WithdrawalShowInfo.kt b/wallet/src/main/java/net/taler/wallet/withdraw/WithdrawalShowInfo.kt
@@ -92,6 +92,11 @@ fun WithdrawalShowInfo(
val possibleExchanges = status.uriInfo?.possibleExchanges ?: emptyList()
val ageRestrictionOptions = status.amountInfo?.ageRestrictionOptions ?: emptyList()
+ if (scopes.isEmpty()) {
+ LoadingScreen()
+ return
+ }
+
val keyboardController = LocalSoftwareKeyboardController.current
var selectedAmount by remember(initialAmountScope != null) {
mutableStateOf(initialAmountScope
@@ -330,7 +335,7 @@ fun WithdrawalShowInfo(
enabled = status.status != Updating
&& (status.isCashAcceptor
|| status.status == TosReviewRequired
- || !selectedAmount.amount.isZero()),
+ || status.selectedAmount?.isZero() == false),
onClick = {
keyboardController?.hide()
if (status.status == TosReviewRequired) {