commit 552c95a8d6f561e0d87b0b4d9edd1d913d3956d7
parent 2ee27388aa2520c1625df3f20e2aecc0bad680b4
Author: Iván Ávalos <avalos@disroot.org>
Date: Fri, 31 Jul 2026 15:28:25 +0200
[wallet] fix #11696 and #11695
Diffstat:
5 files changed, 80 insertions(+), 45 deletions(-)
diff --git a/wallet/src/main/java/net/taler/wallet/deposit/TransactionDepositComposable.kt b/wallet/src/main/java/net/taler/wallet/deposit/TransactionDepositComposable.kt
@@ -17,7 +17,9 @@
package net.taler.wallet.deposit
import androidx.compose.foundation.layout.Column
+import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxWidth
+import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.verticalScroll
@@ -25,6 +27,11 @@ import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Surface
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
+import androidx.compose.runtime.LaunchedEffect
+import androidx.compose.runtime.getValue
+import androidx.compose.runtime.mutableIntStateOf
+import androidx.compose.runtime.remember
+import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.LocalContext
@@ -50,17 +57,22 @@ import net.taler.wallet.transactions.TransactionAction.Suspend
import net.taler.wallet.transactions.TransactionAmountComposable
import net.taler.wallet.transactions.TransactionDeposit
import net.taler.wallet.transactions.TransactionMajorState.Pending
+import net.taler.wallet.transactions.TransactionMinorState
import net.taler.wallet.transactions.TransactionState
import net.taler.wallet.transactions.TransactionStateComposable
+import net.taler.wallet.transactions.TransferOption
import net.taler.wallet.transactions.TransitionsComposable
+import net.taler.wallet.withdraw.TransferOptionChooser
@Composable
fun TransactionDepositComposable(
t: TransactionDeposit,
devMode: Boolean,
spec: CurrencySpecification?,
+ onSelectOption: (option: TransferOption?) -> Unit,
onWireTransfer: () -> Unit,
onShowQrCodes: () -> Unit,
+ onConfirmKyc: (url: String) -> Unit,
onTransition: (t: TransactionAction) -> Unit,
modifier: Modifier = Modifier,
) {
@@ -71,6 +83,27 @@ fun TransactionDepositComposable(
.verticalScroll(scrollState),
horizontalAlignment = Alignment.CenterHorizontally,
) {
+ val defaultOptionIndex = 0
+ var selectedOptionIndex by remember { mutableIntStateOf(defaultOptionIndex) }
+ val selectedOption = t.kycAuthTransferInfo?.transferOptions[selectedOptionIndex]
+
+ LaunchedEffect(selectedOption) {
+ selectedOption?.let { onSelectOption(it) }
+ }
+
+ val showOptionChooser = t.kycAuthTransferInfo != null
+ && t.kycAuthTransferInfo.transferOptions.size > 1
+ && t.txState.minor == TransactionMinorState.KycAuthRequired
+
+ if (showOptionChooser) {
+ TransferOptionChooser(
+ options = t.kycAuthTransferInfo.transferOptions,
+ selectedIndex = selectedOptionIndex,
+ onSelectOption = { selectedOptionIndex = it },
+ )
+ Spacer(Modifier.height(16.dp))
+ }
+
TransactionStateComposable(state = t.txState)
Text(
@@ -79,12 +112,12 @@ fun TransactionDepositComposable(
style = MaterialTheme.typography.bodyLarge,
)
- val qrCodes = t.kycAuthTransferInfo?.transferOptions
- ?.firstOrNull()?.qrCodes ?: emptyList()
+ val qrCodes = selectedOption?.qrCodes ?: emptyList()
DepositActions(t,
qrCodes = qrCodes,
onWireTransfer = onWireTransfer,
- onShowQrCodes = onShowQrCodes)
+ onShowQrCodes = onShowQrCodes,
+ onConfirmKyc = onConfirmKyc)
TransactionAmountComposable(
label = stringResource(id = R.string.amount_chosen),
@@ -121,7 +154,7 @@ fun TransactionDepositComposable(
fun TransactionDepositComposablePreview() {
val t = TransactionDeposit(
transactionId = "transactionId",
- timestamp = Timestamp.fromMillis(System.currentTimeMillis() - 360 * 60 * 1000),
+ timestamp = Timestamp.fromMillis(System.currentTimeMillis() - 360 * 60 * 1000),
txState = TransactionState(Pending),
txActions = listOf(Retry, Suspend, Abort),
depositGroupId = "fooBar",
@@ -139,6 +172,8 @@ fun TransactionDepositComposablePreview() {
t = t,
devMode = true,
spec = null,
+ onSelectOption = {},
+ onConfirmKyc = {},
onWireTransfer = {},
onShowQrCodes = {},
onTransition = {},
diff --git a/wallet/src/main/java/net/taler/wallet/transactions/TransactionActionsComposable.kt b/wallet/src/main/java/net/taler/wallet/transactions/TransactionActionsComposable.kt
@@ -108,23 +108,34 @@ fun ColumnScope.DepositActions(
qrCodes: List<QrCodeSpec>,
onWireTransfer: () -> Unit,
onShowQrCodes: () -> Unit,
+ onConfirmKyc: (url: String) -> Unit,
) {
- if (tx.txState.minor == KycAuthRequired) {
- WireTransferStepsButton(onWireTransfer)
- if (qrCodes.size == 1) {
- Text(
- text = stringResource(R.string.withdraw_manual_instruction_qr),
- modifier = Modifier.padding(16.dp),
- textAlign = TextAlign.Center,
- style = MaterialTheme.typography.bodyLarge,
- )
- PaytoQrCode(
- modifier = Modifier.padding(horizontal = 16.dp),
- qrCode = qrCodes[0],
- )
- } else if (qrCodes.size > 1) {
- ShowQrCodesButton(onShowQrCodes)
+ when (tx.txState.minor) {
+ KycAuthRequired -> {
+ WireTransferStepsButton(onWireTransfer)
+ if (qrCodes.size == 1) {
+ Text(
+ text = stringResource(R.string.withdraw_manual_instruction_qr),
+ modifier = Modifier.padding(16.dp),
+ textAlign = TextAlign.Center,
+ style = MaterialTheme.typography.bodyLarge,
+ )
+ PaytoQrCode(
+ modifier = Modifier.padding(horizontal = 16.dp),
+ qrCode = qrCodes[0],
+ )
+ } else if (qrCodes.size > 1) {
+ ShowQrCodesButton(onShowQrCodes)
+ }
}
+
+ KycRequired -> if (tx.kycUrl != null) {
+ ConfirmKycButton {
+ onConfirmKyc(tx.kycUrl)
+ }
+ }
+
+ else -> {}
}
}
diff --git a/wallet/src/main/java/net/taler/wallet/transactions/TransactionDetailScreen.kt b/wallet/src/main/java/net/taler/wallet/transactions/TransactionDetailScreen.kt
@@ -210,6 +210,10 @@ fun TransactionDetailScreen(
t = tx,
devMode = devMode,
spec = exchangeManager.getSpecForCurrency(tx.amountRaw.currency, tx.scopes),
+ onSelectOption = { it?.let { transactionManager.selectTransferOption(it) } },
+ onConfirmKyc = { url ->
+ launchInAppBrowser(context, url)
+ },
onWireTransfer = {
keepSelectedTx = true
onNavigate(
diff --git a/wallet/src/main/java/net/taler/wallet/transactions/Transactions.kt b/wallet/src/main/java/net/taler/wallet/transactions/Transactions.kt
@@ -553,7 +553,7 @@ class TransactionDeposit(
override val amountType = AmountType.Negative
@Composable
override fun getTitle(): String {
- val uri = Uri.parse(targetPaytoUri)
+ val uri = targetPaytoUri.toUri()
return uri.getQueryParameter("receiver-name")?.let { receiverName ->
stringResource(R.string.transaction_deposit_to, receiverName)
} ?: stringResource(R.string.transaction_deposit)
diff --git a/wallet/src/main/java/net/taler/wallet/transfer/WireTransferDetailsScreen.kt b/wallet/src/main/java/net/taler/wallet/transfer/WireTransferDetailsScreen.kt
@@ -82,16 +82,16 @@ fun WireTransferDetailsScreen(
context.shareText(text = transfer.withdrawalAccount.paytoUri)
}
+ val option = selectedOption
+ val paytoUri = when (option) {
+ is TransferOption.Payto -> option.paytoUri
+ is TransferOption.SwissQrBill -> option.paytoUri
+ else -> null
+ }
+ if (paytoUri == null || option == null) return@GlobalScaffold
+
when (tx) {
is TransactionWithdrawal -> {
- val option = selectedOption
- val paytoUri = when (option) {
- is TransferOption.Payto -> option.paytoUri
- is TransferOption.SwissQrBill -> option.paytoUri
- else -> null
- }
- if (paytoUri == null || option == null) return@GlobalScaffold
-
val transferData = remember(option, tx) {
WithdrawalExchangeAccountDetails(
paytoUri = paytoUri,
@@ -120,29 +120,14 @@ fun WireTransferDetailsScreen(
}
is TransactionDeposit -> {
- val opt = tx.kycAuthTransferInfo?.transferOptions?.firstOrNull()
- if (opt == null) {
- EmptyComposable(modifier = Modifier.padding(paddingValues))
- return@GlobalScaffold
- }
-
- val paytoUri = when (opt) {
- is TransferOption.Payto -> opt.paytoUri
- is TransferOption.SwissQrBill -> opt.paytoUri
- is TransferOption.Uri -> {
- EmptyComposable(modifier = Modifier.padding(paddingValues))
- return@GlobalScaffold
- }
- }
-
- val transferData = remember(opt, tx) {
+ val transferData = remember(option, tx) {
WithdrawalExchangeAccountDetails(
paytoUri = paytoUri,
status = WithdrawalExchangeAccountDetails.Status.Ok,
).getTransferDetails(
amountRaw = tx.amountRaw,
amountEffective = tx.amountEffective,
- transferOption = opt,
+ transferOption = option,
)
}