commit de360e89efc45a4e0686cd8fc83173ccab134a4d
parent 957162b26597a6d1224f53b1755e1111e051a188
Author: Iván Ávalos <avalos@disroot.org>
Date: Tue, 3 Feb 2026 19:59:24 +0100
[wallet] show QR codes on withdrawal details
Diffstat:
4 files changed, 88 insertions(+), 12 deletions(-)
diff --git a/wallet/src/main/java/net/taler/wallet/compose/QrCodeUriComposable.kt b/wallet/src/main/java/net/taler/wallet/compose/QrCodeUriComposable.kt
@@ -125,6 +125,7 @@ fun ColumnScope.QrCodeUriComposable(
}
ShareButton(
+ modifier = if (shareAsQrCode) Modifier.weight(1f) else Modifier,
content = talerUri,
shareAsQrCode = shareAsQrCode,
colors = ButtonDefaults.buttonColors(
diff --git a/wallet/src/main/java/net/taler/wallet/transactions/ActionButtonComposable.kt b/wallet/src/main/java/net/taler/wallet/transactions/ActionButtonComposable.kt
@@ -135,17 +135,24 @@ private fun ConfirmManualButton(
Text(stringResource(R.string.withdraw_manual_ready_details_intro))
}
- Button(
- onClick = { listener.onActionButtonClicked(tx, ActionListener.Type.SHOW_WIRE_QR) },
- modifier = modifier,
- ) {
- Icon(
- Icons.Default.QrCode,
- contentDescription = null,
- modifier = Modifier.size(ButtonDefaults.IconSize)
- )
- Spacer(Modifier.size(ButtonDefaults.IconSpacing))
- Text(stringResource(R.string.withdraw_manual_ready_details_qr))
+ // only show in separate view when there's more than one transfer account
+ // otherwise it will be shown on withdrawal details directly
+ if (tx is TransactionWithdrawal
+ && tx.withdrawalDetails is WithdrawalDetails.ManualTransfer
+ && tx.withdrawalDetails.exchangeCreditAccountDetails != null
+ && tx.withdrawalDetails.exchangeCreditAccountDetails.size > 1) {
+ Button(
+ onClick = { listener.onActionButtonClicked(tx, ActionListener.Type.SHOW_WIRE_QR) },
+ modifier = modifier,
+ ) {
+ Icon(
+ Icons.Default.QrCode,
+ contentDescription = null,
+ modifier = Modifier.size(ButtonDefaults.IconSize)
+ )
+ Spacer(Modifier.size(ButtonDefaults.IconSpacing))
+ Text(stringResource(R.string.withdraw_manual_ready_details_qr))
+ }
}
}
}
diff --git a/wallet/src/main/java/net/taler/wallet/transactions/TransactionWithdrawalFragment.kt b/wallet/src/main/java/net/taler/wallet/transactions/TransactionWithdrawalFragment.kt
@@ -20,10 +20,15 @@ import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
+import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.getValue
+import androidx.compose.runtime.mutableStateOf
+import androidx.compose.runtime.remember
+import androidx.compose.runtime.setValue
import androidx.compose.ui.platform.ComposeView
import net.taler.wallet.compose.TalerSurface
import net.taler.wallet.compose.collectAsStateLifecycleAware
+import net.taler.wallet.withdraw.QrCodeSpec
import net.taler.wallet.withdraw.TransactionWithdrawalComposable
class TransactionWithdrawalFragment : TransactionDetailFragment(), ActionListener {
@@ -36,9 +41,22 @@ class TransactionWithdrawalFragment : TransactionDetailFragment(), ActionListene
setContent {
TalerSurface {
val t by transactionManager.selectedTransaction.collectAsStateLifecycleAware()
+ var qrCodes by remember { mutableStateOf<List<QrCodeSpec>>(emptyList()) }
+
(t as? TransactionWithdrawal)?.let { tx ->
+ LaunchedEffect(Unit) {
+ if (tx.withdrawalDetails is WithdrawalDetails.ManualTransfer
+ && tx.txState.minor == TransactionMinorState.ExchangeWaitReserve) {
+ if (tx.withdrawalDetails.exchangeCreditAccountDetails?.size == 1) {
+ val transfer = tx.withdrawalDetails.exchangeCreditAccountDetails[0]
+ qrCodes = withdrawManager.getQrCodesForPayto(transfer.paytoUri)
+ }
+ }
+ }
+
TransactionWithdrawalComposable(
t = tx,
+ qrCodes = qrCodes,
devMode = devMode,
spec = exchangeManager.getSpecForCurrency(tx.amountRaw.currency, tx.scopes),
actionListener = this@TransactionWithdrawalFragment,
diff --git a/wallet/src/main/java/net/taler/wallet/withdraw/TransactionWithdrawalComposable.kt b/wallet/src/main/java/net/taler/wallet/withdraw/TransactionWithdrawalComposable.kt
@@ -25,6 +25,8 @@ import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Surface
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
+import androidx.compose.runtime.mutableStateMapOf
+import androidx.compose.runtime.remember
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.LocalContext
@@ -60,10 +62,12 @@ import net.taler.wallet.transactions.TransactionWithdrawal
import net.taler.wallet.transactions.TransitionsComposable
import net.taler.wallet.transactions.WithdrawalDetails.ManualTransfer
import net.taler.wallet.transactions.WithdrawalExchangeAccountDetails
+import net.taler.wallet.transfer.PaytoQrCard
@Composable
fun TransactionWithdrawalComposable(
t: TransactionWithdrawal,
+ qrCodes: List<QrCodeSpec> = emptyList(),
devMode: Boolean,
spec: CurrencySpecification?,
actionListener: ActionListener,
@@ -77,6 +81,13 @@ fun TransactionWithdrawalComposable(
horizontalAlignment = Alignment.CenterHorizontally,
) {
val context = LocalContext.current
+ val qrExpandedStates = remember(qrCodes) {
+ val map = mutableStateMapOf<QrCodeSpec, Boolean>()
+ qrCodes.forEach {
+ map[it] = qrCodes.size == 1
+ }
+ map
+ }
TransactionStateComposable(state = t.txState, tx = t)
@@ -88,6 +99,34 @@ fun TransactionWithdrawalComposable(
ActionButton(tx = t, listener = actionListener)
+ if (qrCodes.isNotEmpty()) {
+ Text(
+ text = stringResource(R.string.withdraw_manual_qr_intro),
+ style = MaterialTheme.typography.bodyLarge,
+ modifier = Modifier
+ .padding(
+ vertical = 8.dp,
+ horizontal = 16.dp,
+ )
+ )
+
+ qrCodes.forEach { spec ->
+ PaytoQrCard(
+ expanded = qrExpandedStates[spec]!!,
+ setExpanded = { expanded ->
+ if (expanded) { // un-expand all others
+ qrExpandedStates.forEach { (k, _) ->
+ qrExpandedStates[k] = false
+ }
+ }
+ // expand only toggled one
+ qrExpandedStates[spec] = expanded
+ },
+ qrCode = spec,
+ )
+ }
+ }
+
if (t.amountRaw != t.amountEffective) {
TransactionAmountComposable(
label = stringResource(R.string.amount_chosen),
@@ -162,12 +201,23 @@ fun TransactionWithdrawalComposablePreview() {
url = "exchange.test.taler.net",
))
)
+
+ val qrCodes = listOf(
+ QrCodeSpec(
+ type = QrCodeSpec.Type.SPC,
+ qrContent = "something",
+ ),
+// QrCodeSpec(
+// type = QrCodeSpec.Type.EpcQr,
+// qrContent = "something",
+// ),
+ )
val listener = object : ActionListener {
override fun onActionButtonClicked(tx: Transaction, type: ActionListener.Type) {}
}
Surface {
- TransactionWithdrawalComposable(t, true, null, listener) {}
+ TransactionWithdrawalComposable(t, qrCodes, true, null, listener) {}
}
}