taler-android

Android apps for GNU Taler (wallet, PoS, cashier)
Log | Files | Refs | README | LICENSE

commit 24258708e389e9452f88e9dd34bd79f8655acefa
parent 96a50fc17a869540bec4c15d5afe382e3bc2ea80
Author: Iván Ávalos <avalos@disroot.org>
Date:   Tue, 17 Mar 2026 10:20:03 +0100

[wallet] refactor tx action buttons

Diffstat:
Mwallet/src/main/java/net/taler/wallet/deposit/TransactionDepositComposable.kt | 15+++++++--------
Mwallet/src/main/java/net/taler/wallet/peer/TransactionPeerPullCredit.kt | 12++++--------
Mwallet/src/main/java/net/taler/wallet/peer/TransactionPeerPullDebit.kt | 6+-----
Mwallet/src/main/java/net/taler/wallet/peer/TransactionPeerPushCredit.kt | 15++++++---------
Mwallet/src/main/java/net/taler/wallet/peer/TransactionPeerPushDebit.kt | 6+-----
Dwallet/src/main/java/net/taler/wallet/transactions/ActionButtonComposable.kt | 150-------------------------------------------------------------------------------
Awallet/src/main/java/net/taler/wallet/transactions/TransactionActionsComposable.kt | 176+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Mwallet/src/main/java/net/taler/wallet/transactions/TransactionDepositFragment.kt | 20++++++++++++++++++--
Mwallet/src/main/java/net/taler/wallet/transactions/TransactionDetailFragment.kt | 57++-------------------------------------------------------
Mwallet/src/main/java/net/taler/wallet/transactions/TransactionPeerFragment.kt | 15++++++++++-----
Mwallet/src/main/java/net/taler/wallet/transactions/TransactionWithdrawalFragment.kt | 36++++++++++++++++++++++++++++++++----
Mwallet/src/main/java/net/taler/wallet/withdraw/TransactionWithdrawalComposable.kt | 77+++++++++++------------------------------------------------------------------
12 files changed, 268 insertions(+), 317 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 @@ -40,11 +40,9 @@ import net.taler.wallet.R import net.taler.wallet.backend.TalerErrorCode.EXCHANGE_GENERIC_KYC_REQUIRED import net.taler.wallet.backend.TalerErrorInfo import net.taler.wallet.balances.ScopeInfo -import net.taler.wallet.transactions.ActionButton -import net.taler.wallet.transactions.ActionListener import net.taler.wallet.transactions.AmountType +import net.taler.wallet.transactions.DepositActions import net.taler.wallet.transactions.ErrorTransactionButton -import net.taler.wallet.transactions.Transaction import net.taler.wallet.transactions.TransactionAction import net.taler.wallet.transactions.TransactionAction.Abort import net.taler.wallet.transactions.TransactionAction.Retry @@ -61,7 +59,8 @@ fun TransactionDepositComposable( t: TransactionDeposit, devMode: Boolean, spec: CurrencySpecification?, - actionListener: ActionListener, + onWireTransfer: () -> Unit, + onShowQrCodes: () -> Unit, onTransition: (t: TransactionAction) -> Unit, ) { val scrollState = rememberScrollState() @@ -81,7 +80,9 @@ fun TransactionDepositComposable( style = MaterialTheme.typography.bodyLarge, ) - ActionButton(tx = t, listener = actionListener) + DepositActions(t, + onWireTransfer = onWireTransfer, + onShowQrCodes = onShowQrCodes) TransactionAmountComposable( label = stringResource(id = R.string.amount_chosen), @@ -132,8 +133,6 @@ fun TransactionDepositComposablePreview() { )) ) Surface { - TransactionDepositComposable(t, true, null, object : ActionListener { - override fun onActionButtonClicked(tx: Transaction, type: ActionListener.Type) {} - }) {} + TransactionDepositComposable(t, true, null, {}, {}) {} } } diff --git a/wallet/src/main/java/net/taler/wallet/peer/TransactionPeerPullCredit.kt b/wallet/src/main/java/net/taler/wallet/peer/TransactionPeerPullCredit.kt @@ -28,11 +28,9 @@ import net.taler.wallet.R import net.taler.wallet.backend.TalerErrorCode.EXCHANGE_GENERIC_KYC_REQUIRED import net.taler.wallet.backend.TalerErrorInfo import net.taler.wallet.balances.ScopeInfo -import net.taler.wallet.transactions.ActionButton -import net.taler.wallet.transactions.ActionListener import net.taler.wallet.transactions.AmountType +import net.taler.wallet.transactions.PeerActions import net.taler.wallet.transactions.PeerInfoShort -import net.taler.wallet.transactions.Transaction import net.taler.wallet.transactions.TransactionAction.Abort import net.taler.wallet.transactions.TransactionAction.Retry import net.taler.wallet.transactions.TransactionAction.Suspend @@ -50,9 +48,9 @@ import net.taler.wallet.transactions.TransactionState fun ColumnScope.TransactionPeerPullCreditComposable( t: TransactionPeerPullCredit, spec: CurrencySpecification?, - actionListener: ActionListener, + onConfirmKyc: (url: String) -> Unit, ) { - ActionButton(tx = t, listener = actionListener) + PeerActions(t, onConfirmKyc) if (t.error == null) PeerQrCode( state = t.txState, @@ -115,9 +113,7 @@ fun TransactionPeerPullCreditPreview(loading: Boolean = false) { )) ) Surface { - TransactionPeerComposable(t, true, null, object: ActionListener { - override fun onActionButtonClicked(tx: Transaction, type: ActionListener.Type) {} - }) {} + TransactionPeerComposable(t, true, null, {}) {} } } diff --git a/wallet/src/main/java/net/taler/wallet/peer/TransactionPeerPullDebit.kt b/wallet/src/main/java/net/taler/wallet/peer/TransactionPeerPullDebit.kt @@ -27,10 +27,8 @@ import net.taler.wallet.R import net.taler.wallet.backend.TalerErrorCode.EXCHANGE_GENERIC_KYC_REQUIRED import net.taler.wallet.backend.TalerErrorInfo import net.taler.wallet.balances.ScopeInfo -import net.taler.wallet.transactions.ActionListener import net.taler.wallet.transactions.AmountType import net.taler.wallet.transactions.PeerInfoShort -import net.taler.wallet.transactions.Transaction import net.taler.wallet.transactions.TransactionAction.Abort import net.taler.wallet.transactions.TransactionAction.Retry import net.taler.wallet.transactions.TransactionAction.Suspend @@ -92,8 +90,6 @@ fun TransactionPeerPullDebitPreview() { )) ) Surface { - TransactionPeerComposable(t, true, null, object: ActionListener { - override fun onActionButtonClicked(tx: Transaction, type: ActionListener.Type) {} - }) {} + TransactionPeerComposable(t, true, null, {}) {} } } diff --git a/wallet/src/main/java/net/taler/wallet/peer/TransactionPeerPushCredit.kt b/wallet/src/main/java/net/taler/wallet/peer/TransactionPeerPushCredit.kt @@ -16,6 +16,7 @@ package net.taler.wallet.peer +import androidx.compose.foundation.layout.ColumnScope import androidx.compose.material3.Surface import androidx.compose.runtime.Composable import androidx.compose.ui.res.stringResource @@ -27,11 +28,9 @@ import net.taler.wallet.R import net.taler.wallet.backend.TalerErrorCode.EXCHANGE_GENERIC_KYC_REQUIRED import net.taler.wallet.backend.TalerErrorInfo import net.taler.wallet.balances.ScopeInfo -import net.taler.wallet.transactions.ActionButton -import net.taler.wallet.transactions.ActionListener import net.taler.wallet.transactions.AmountType +import net.taler.wallet.transactions.PeerActions import net.taler.wallet.transactions.PeerInfoShort -import net.taler.wallet.transactions.Transaction import net.taler.wallet.transactions.TransactionAction.Abort import net.taler.wallet.transactions.TransactionAction.Retry import net.taler.wallet.transactions.TransactionAction.Suspend @@ -43,12 +42,12 @@ import net.taler.wallet.transactions.TransactionPeerPushCredit import net.taler.wallet.transactions.TransactionState @Composable -fun TransactionPeerPushCreditComposable( +fun ColumnScope.TransactionPeerPushCreditComposable( t: TransactionPeerPushCredit, spec: CurrencySpecification?, - actionListener: ActionListener, + onConfirmKyc: (url: String) -> Unit, ) { - ActionButton(tx = t, listener = actionListener) + PeerActions(t, onConfirmKyc) TransactionAmountComposable( label = stringResource(id = R.string.amount_sent), @@ -99,8 +98,6 @@ fun TransactionPeerPushCreditPreview() { )) ) Surface { - TransactionPeerComposable(t, true, null, object : ActionListener { - override fun onActionButtonClicked(tx: Transaction, type: ActionListener.Type) {} - }) {} + TransactionPeerComposable(t, true, null, {}) {} } } diff --git a/wallet/src/main/java/net/taler/wallet/peer/TransactionPeerPushDebit.kt b/wallet/src/main/java/net/taler/wallet/peer/TransactionPeerPushDebit.kt @@ -42,10 +42,8 @@ import net.taler.wallet.R import net.taler.wallet.balances.ScopeInfo import net.taler.wallet.compose.QrCodeUriComposable import net.taler.wallet.compose.TalerSurface -import net.taler.wallet.transactions.ActionListener import net.taler.wallet.transactions.AmountType import net.taler.wallet.transactions.PeerInfoShort -import net.taler.wallet.transactions.Transaction import net.taler.wallet.transactions.TransactionAction.Abort import net.taler.wallet.transactions.TransactionAction.Retry import net.taler.wallet.transactions.TransactionAction.Suspend @@ -169,9 +167,7 @@ fun TransactionPeerPushDebitPreview(loading: Boolean = false) { ) TalerSurface { - TransactionPeerComposable(t, true, null, object: ActionListener { - override fun onActionButtonClicked(tx: Transaction, type: ActionListener.Type) {} - }) {} + TransactionPeerComposable(t, true, null, {}) {} } } diff --git a/wallet/src/main/java/net/taler/wallet/transactions/ActionButtonComposable.kt b/wallet/src/main/java/net/taler/wallet/transactions/ActionButtonComposable.kt @@ -1,150 +0,0 @@ -/* - * This file is part of GNU Taler - * (C) 2023 Taler Systems S.A. - * - * GNU Taler is free software; you can redistribute it and/or modify it under the - * terms of the GNU General Public License as published by the Free Software - * Foundation; either version 3, or (at your option) any later version. - * - * GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY - * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR - * A PARTICULAR PURPOSE. See the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along with - * GNU Taler; see the file COPYING. If not, see <http://www.gnu.org/licenses/> - */ - -package net.taler.wallet.transactions - -import androidx.compose.foundation.layout.Column -import androidx.compose.foundation.layout.Spacer -import androidx.compose.foundation.layout.size -import androidx.compose.material.icons.Icons -import androidx.compose.material.icons.filled.AccountBalance -import androidx.compose.material.icons.filled.Link -import androidx.compose.material.icons.filled.QrCode -import androidx.compose.material3.Button -import androidx.compose.material3.ButtonDefaults -import androidx.compose.material3.Icon -import androidx.compose.material3.Text -import androidx.compose.runtime.Composable -import androidx.compose.ui.Alignment -import androidx.compose.ui.Modifier -import androidx.compose.ui.res.stringResource -import net.taler.wallet.R -import net.taler.wallet.transactions.TransactionMajorState.Pending -import net.taler.wallet.transactions.TransactionMinorState.BalanceKycRequired -import net.taler.wallet.transactions.TransactionMinorState.BankConfirmTransfer -import net.taler.wallet.transactions.TransactionMinorState.ExchangeWaitReserve -import net.taler.wallet.transactions.TransactionMinorState.KycAuthRequired -import net.taler.wallet.transactions.TransactionMinorState.KycRequired - -interface ActionListener { - enum class Type { - COMPLETE_KYC, - CONFIRM_WITH_BANK, - CONFIRM_MANUAL, - SHOW_WIRE_QR, - } - - fun onActionButtonClicked(tx: Transaction, type: Type) -} - -@Composable -fun ActionButton( - modifier: Modifier = Modifier, - tx: Transaction, - listener: ActionListener, -) { - if (tx.txState.major == Pending) { - when (tx.txState.minor) { - KycRequired, BalanceKycRequired -> KycButton(modifier, tx, listener) - BankConfirmTransfer -> ConfirmBankButton(modifier, tx, listener) - ExchangeWaitReserve, KycAuthRequired -> ConfirmManualButton(modifier, tx, listener) - else -> {} - } - } -} - -@Composable -private fun KycButton( - modifier: Modifier = Modifier, - tx: Transaction, - listener: ActionListener, -) { - Button( - onClick = { listener.onActionButtonClicked(tx, ActionListener.Type.COMPLETE_KYC) }, - modifier = modifier, - ) { - Icon( - Icons.Default.Link, - contentDescription = null, - modifier = Modifier.size(ButtonDefaults.IconSize) - ) - Spacer(Modifier.size(ButtonDefaults.IconSpacing)) - Text(stringResource(R.string.transaction_action_kyc)) - } -} - -@Composable -private fun ConfirmBankButton( - modifier: Modifier = Modifier, - tx: Transaction, - listener: ActionListener, -) { - // TODO: should check go here? - if (tx is TransactionWithdrawal - && tx.withdrawalDetails is WithdrawalDetails.TalerBankIntegrationApi - && tx.withdrawalDetails.bankConfirmationUrl == null) return - - Button( - onClick = { listener.onActionButtonClicked(tx, ActionListener.Type.CONFIRM_WITH_BANK) }, - modifier = modifier, - ) { - val label = stringResource(R.string.withdraw_button_confirm_bank) - Icon( - Icons.Default.Link, - label, - modifier = Modifier.size(ButtonDefaults.IconSize) - ) - Spacer(Modifier.size(ButtonDefaults.IconSpacing)) - Text(label) - } -} - -@Composable -private fun ConfirmManualButton( - modifier: Modifier = Modifier, - tx: Transaction, - listener: ActionListener, -) { - Column( - horizontalAlignment = Alignment.CenterHorizontally, - ) { - Button( - onClick = { listener.onActionButtonClicked(tx, ActionListener.Type.CONFIRM_MANUAL) }, - modifier = modifier, - ) { - Icon( - Icons.Default.AccountBalance, - contentDescription = null, - modifier = Modifier.size(ButtonDefaults.IconSize) - ) - Spacer(Modifier.size(ButtonDefaults.IconSpacing)) - 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)) - } - } -} diff --git a/wallet/src/main/java/net/taler/wallet/transactions/TransactionActionsComposable.kt b/wallet/src/main/java/net/taler/wallet/transactions/TransactionActionsComposable.kt @@ -0,0 +1,175 @@ +/* + * This file is part of GNU Taler + * (C) 2023 Taler Systems S.A. + * + * GNU Taler is free software; you can redistribute it and/or modify it under the + * terms of the GNU General Public License as published by the Free Software + * Foundation; either version 3, or (at your option) any later version. + * + * GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + * A PARTICULAR PURPOSE. See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along with + * GNU Taler; see the file COPYING. If not, see <http://www.gnu.org/licenses/> + */ + +package net.taler.wallet.transactions + +import androidx.compose.foundation.layout.ColumnScope +import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.size +import androidx.compose.material.icons.Icons +import androidx.compose.material.icons.filled.AccountBalance +import androidx.compose.material.icons.filled.Link +import androidx.compose.material.icons.filled.QrCode +import androidx.compose.material3.Button +import androidx.compose.material3.ButtonDefaults +import androidx.compose.material3.Icon +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import androidx.compose.ui.res.stringResource +import androidx.compose.ui.text.style.TextAlign +import androidx.compose.ui.unit.dp +import net.taler.wallet.R +import net.taler.wallet.transactions.TransactionMinorState.BankConfirmTransfer +import net.taler.wallet.transactions.TransactionMinorState.ExchangeWaitReserve +import net.taler.wallet.transactions.TransactionMinorState.KycAuthRequired +import net.taler.wallet.transactions.TransactionMinorState.KycRequired +import net.taler.wallet.transfer.PaytoQrCode +import net.taler.wallet.withdraw.QrCodeSpec + +@Composable +fun ColumnScope.WithdrawalActions( + tx: TransactionWithdrawal, + mainQrCode: QrCodeSpec? = null, + onConfirmBank: () -> Unit, + onConfirmKyc: (url: String) -> Unit, + onConfirmManual: () -> Unit, + onShowQrCodes: () -> Unit, +) { + when (tx.txState.minor) { + BankConfirmTransfer -> { + ConfirmBankButton(onConfirmBank) + } + + KycRequired -> if (tx.kycUrl != null) { + ConfirmKycButton { + onConfirmKyc(tx.kycUrl) + } + } + + ExchangeWaitReserve -> { + Text( + text = stringResource(R.string.withdraw_manual_instruction_manual), + modifier = Modifier.padding(16.dp), + textAlign = TextAlign.Center, + style = MaterialTheme.typography.bodyLarge, + ) + + WireTransferStepsButton(onConfirmManual) + + if (mainQrCode != null) { + 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 = mainQrCode, + ) + } else { + ShowQrCodesButton(onShowQrCodes) + } + } + + else -> {} + } +} + +@Composable +fun ColumnScope.DepositActions( + tx: TransactionDeposit, + onWireTransfer: () -> Unit, + onShowQrCodes: () -> Unit, +) { + if (tx.txState.minor == KycAuthRequired) { + WireTransferStepsButton(onWireTransfer) + ShowQrCodesButton(onShowQrCodes) + } +} + +@Composable +fun ColumnScope.PeerActions( + tx: Transaction, + onConfirmKyc: (url: String) -> Unit, +) { + val kycUrl = when(tx) { + is TransactionPeerPushCredit -> tx.kycUrl + is TransactionPeerPullCredit -> tx.kycUrl + else -> null + } ?: return + + if (tx.txState.minor == KycRequired) { + ConfirmKycButton { onConfirmKyc(kycUrl) } + } +} + +@Composable +private fun ConfirmBankButton(onClick: () -> Unit) { + Button(onClick) { + val label = stringResource(R.string.withdraw_button_confirm_bank) + Icon( + Icons.Default.Link, + label, + modifier = Modifier.size(ButtonDefaults.IconSize) + ) + Spacer(Modifier.size(ButtonDefaults.IconSpacing)) + Text(label) + } +} + +@Composable +private fun WireTransferStepsButton(onClick: () -> Unit) { + Button(onClick) { + Icon( + Icons.Default.AccountBalance, + contentDescription = null, + modifier = Modifier.size(ButtonDefaults.IconSize) + ) + Spacer(Modifier.size(ButtonDefaults.IconSpacing)) + Text(stringResource(R.string.withdraw_manual_ready_details_intro)) + } +} + +@Composable +private fun ShowQrCodesButton(onClick: () -> Unit) { + Button(onClick) { + 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)) + } +} + +@Composable +private fun ConfirmKycButton(onClick: () -> Unit) { + Button(onClick) { + Icon( + Icons.Default.Link, + contentDescription = null, + modifier = Modifier.size(ButtonDefaults.IconSize) + ) + Spacer(Modifier.size(ButtonDefaults.IconSpacing)) + Text(stringResource(R.string.transaction_action_kyc)) + } +} +\ No newline at end of file diff --git a/wallet/src/main/java/net/taler/wallet/transactions/TransactionDepositFragment.kt b/wallet/src/main/java/net/taler/wallet/transactions/TransactionDepositFragment.kt @@ -23,6 +23,9 @@ import android.view.ViewGroup import androidx.compose.runtime.getValue import androidx.compose.runtime.remember import androidx.compose.ui.platform.ComposeView +import androidx.core.os.bundleOf +import androidx.navigation.fragment.findNavController +import net.taler.wallet.R import net.taler.wallet.compose.TalerSurface import net.taler.wallet.compose.collectAsStateLifecycleAware import net.taler.wallet.deposit.TransactionDepositComposable @@ -42,11 +45,23 @@ class TransactionDepositFragment : TransactionDetailFragment() { t = tx, devMode = devMode, spec = exchangeManager.getSpecForCurrency(tx.amountRaw.currency, tx.scopes), - actionListener = this@TransactionDepositFragment, + onWireTransfer = { onConfirmManual() }, + onShowQrCodes = { onShowQrCodes() }, ) { onTransitionButtonClicked(tx, it) } } } } -} + + fun onConfirmManual(showQrCodes: Boolean = false) { + findNavController().navigate( + R.id.nav_wire_transfer_details, + bundleOf("showQrCodes" to showQrCodes) + ) + } + + fun onShowQrCodes() { + onConfirmManual(showQrCodes = true) + } +} +\ No newline at end of file diff --git a/wallet/src/main/java/net/taler/wallet/transactions/TransactionDetailFragment.kt b/wallet/src/main/java/net/taler/wallet/transactions/TransactionDetailFragment.kt @@ -19,7 +19,6 @@ package net.taler.wallet.transactions import android.os.Bundle import android.util.Log import android.view.View -import androidx.core.os.bundleOf import androidx.fragment.app.Fragment import androidx.fragment.app.activityViewModels import androidx.lifecycle.Lifecycle @@ -29,10 +28,9 @@ import androidx.navigation.fragment.findNavController import com.google.android.material.dialog.MaterialAlertDialogBuilder import kotlinx.coroutines.launch import net.taler.common.showError -import net.taler.wallet.main.MainViewModel import net.taler.wallet.R +import net.taler.wallet.main.MainViewModel import net.taler.wallet.main.TAG -import net.taler.wallet.launchInAppBrowser import net.taler.wallet.showError import net.taler.wallet.transactions.TransactionAction.Abort import net.taler.wallet.transactions.TransactionAction.Delete @@ -40,10 +38,8 @@ import net.taler.wallet.transactions.TransactionAction.Fail import net.taler.wallet.transactions.TransactionAction.Resume import net.taler.wallet.transactions.TransactionAction.Retry import net.taler.wallet.transactions.TransactionAction.Suspend -import net.taler.wallet.transactions.WithdrawalDetails.ManualTransfer -import net.taler.wallet.transactions.WithdrawalDetails.TalerBankIntegrationApi -abstract class TransactionDetailFragment : Fragment(), ActionListener { +abstract class TransactionDetailFragment : Fragment() { private val model: MainViewModel by activityViewModels() protected val transactionManager by lazy { model.transactionManager } @@ -102,55 +98,6 @@ abstract class TransactionDetailFragment : Fragment(), ActionListener { Resume -> resumeTransaction(t) } - override fun onActionButtonClicked(tx: Transaction, type: ActionListener.Type) { - when (type) { - ActionListener.Type.COMPLETE_KYC -> { - when (tx) { - is TransactionWithdrawal -> tx.kycUrl - is TransactionDeposit -> tx.kycUrl - is TransactionPeerPullCredit -> tx.kycUrl - is TransactionPeerPushCredit -> tx.kycUrl - else -> null - }?.let { kycUrl -> - launchInAppBrowser(requireContext(), kycUrl) - } - } - - ActionListener.Type.CONFIRM_WITH_BANK -> { - if (tx !is TransactionWithdrawal) return - if (tx.withdrawalDetails !is TalerBankIntegrationApi) return - tx.withdrawalDetails.bankConfirmationUrl?.let { url -> - launchInAppBrowser(requireContext(), url) - } - } - - ActionListener.Type.CONFIRM_MANUAL, - ActionListener.Type.SHOW_WIRE_QR -> lifecycleScope.launch { - when (tx) { - is TransactionWithdrawal -> { - if (tx.withdrawalDetails !is ManualTransfer) return@launch - if (tx.withdrawalDetails.exchangeCreditAccountDetails.isNullOrEmpty()) return@launch - findNavController().navigate( - R.id.nav_wire_transfer_details, - bundleOf("showQrCodes" to (type == ActionListener.Type.SHOW_WIRE_QR)) - ) - - } - - is TransactionDeposit -> { - if (tx.kycAuthTransferInfo == null) return@launch - findNavController().navigate( - R.id.nav_wire_transfer_details, - bundleOf("showQrCodes" to (type == ActionListener.Type.SHOW_WIRE_QR)) - ) - } - - else -> {} - } - } - } - } - private fun showDialog(tt: TransactionAction, onAction: () -> Unit) { MaterialAlertDialogBuilder(requireContext(), R.style.MaterialAlertDialog_Material3) .setTitle(dialogTitle(tt)) diff --git a/wallet/src/main/java/net/taler/wallet/transactions/TransactionPeerFragment.kt b/wallet/src/main/java/net/taler/wallet/transactions/TransactionPeerFragment.kt @@ -63,12 +63,13 @@ import net.taler.wallet.BottomInsetsSpacer import net.taler.wallet.R import net.taler.wallet.compose.TalerSurface import net.taler.wallet.compose.collectAsStateLifecycleAware +import net.taler.wallet.launchInAppBrowser import net.taler.wallet.peer.TransactionPeerPullCreditComposable import net.taler.wallet.peer.TransactionPeerPullDebitComposable import net.taler.wallet.peer.TransactionPeerPushCreditComposable import net.taler.wallet.peer.TransactionPeerPushDebitComposable -class TransactionPeerFragment : TransactionDetailFragment(), ActionListener { +class TransactionPeerFragment : TransactionDetailFragment() { override fun onCreateView( inflater: LayoutInflater, @@ -82,7 +83,7 @@ class TransactionPeerFragment : TransactionDetailFragment(), ActionListener { TransactionPeerComposable( tx, devMode, exchangeManager.getSpecForCurrency(tx.amountRaw.currency, tx.scopes), - this@TransactionPeerFragment, + onConfirmKyc = { onConfirmKyc(it) }, ) { onTransitionButtonClicked(tx, it) } @@ -104,6 +105,10 @@ class TransactionPeerFragment : TransactionDetailFragment(), ActionListener { } } } + + fun onConfirmKyc(url: String) { + launchInAppBrowser(requireContext(), url) + } } @Composable @@ -111,7 +116,7 @@ fun TransactionPeerComposable( t: Transaction, devMode: Boolean, spec: CurrencySpecification?, - actionListener: ActionListener, + onConfirmKyc: (url: String) -> Unit, onTransition: (t: TransactionAction) -> Unit, ) { val scrollState = rememberScrollState() @@ -132,8 +137,8 @@ fun TransactionPeerComposable( ) when (t) { - is TransactionPeerPullCredit -> TransactionPeerPullCreditComposable(t, spec, actionListener) - is TransactionPeerPushCredit -> TransactionPeerPushCreditComposable(t, spec, actionListener) + is TransactionPeerPullCredit -> TransactionPeerPullCreditComposable(t, spec, onConfirmKyc) + is TransactionPeerPushCredit -> TransactionPeerPushCreditComposable(t, spec, onConfirmKyc) is TransactionPeerPullDebit -> TransactionPeerPullDebitComposable(t, spec) is TransactionPeerPushDebit -> TransactionPeerPushDebitComposable(t, spec) else -> error("unexpected transaction: ${t::class.simpleName}") diff --git a/wallet/src/main/java/net/taler/wallet/transactions/TransactionWithdrawalFragment.kt b/wallet/src/main/java/net/taler/wallet/transactions/TransactionWithdrawalFragment.kt @@ -23,11 +23,16 @@ import android.view.ViewGroup import androidx.compose.runtime.getValue import androidx.compose.runtime.remember import androidx.compose.ui.platform.ComposeView +import androidx.core.os.bundleOf +import androidx.navigation.fragment.findNavController +import net.taler.wallet.R import net.taler.wallet.compose.TalerSurface import net.taler.wallet.compose.collectAsStateLifecycleAware +import net.taler.wallet.launchInAppBrowser +import net.taler.wallet.transactions.WithdrawalDetails.TalerBankIntegrationApi import net.taler.wallet.withdraw.TransactionWithdrawalComposable -class TransactionWithdrawalFragment : TransactionDetailFragment(), ActionListener { +class TransactionWithdrawalFragment : TransactionDetailFragment() { override fun onCreateView( inflater: LayoutInflater, @@ -55,9 +60,10 @@ class TransactionWithdrawalFragment : TransactionDetailFragment(), ActionListene devMode = devMode, spec = exchangeManager.getSpecForCurrency(tx.amountRaw.currency, tx.scopes), qrCode = qrCode, - onConfirmBank = { onActionButtonClicked(tx, ActionListener.Type.CONFIRM_WITH_BANK) }, - onConfirmManual = { onActionButtonClicked(tx, ActionListener.Type.CONFIRM_MANUAL) }, - onShowQrCodes = { onActionButtonClicked(tx, ActionListener.Type.SHOW_WIRE_QR) }, + onConfirmKyc = { onConfirmKyc(it) }, + onConfirmBank = { onConfirmBank(tx) }, + onConfirmManual = { onWireTransferSteps() }, + onShowQrCodes = { onShowQrCodes() }, ) { onTransitionButtonClicked(tx, it) } @@ -65,4 +71,26 @@ class TransactionWithdrawalFragment : TransactionDetailFragment(), ActionListene } } } + + fun onConfirmKyc(url: String) { + launchInAppBrowser(requireContext(), url) + } + + fun onConfirmBank(tx: TransactionWithdrawal) { + if (tx.withdrawalDetails !is TalerBankIntegrationApi) return + tx.withdrawalDetails.bankConfirmationUrl?.let { url -> + launchInAppBrowser(requireContext(), url) + } + } + + fun onWireTransferSteps(showQrCodes: Boolean = false) { + findNavController().navigate( + R.id.nav_wire_transfer_details, + bundleOf("showQrCodes" to showQrCodes) + ) + } + + fun onShowQrCodes() { + onWireTransferSteps(showQrCodes = true) + } } diff --git a/wallet/src/main/java/net/taler/wallet/withdraw/TransactionWithdrawalComposable.kt b/wallet/src/main/java/net/taler/wallet/withdraw/TransactionWithdrawalComposable.kt @@ -17,19 +17,10 @@ package net.taler.wallet.withdraw import androidx.compose.foundation.layout.Column -import androidx.compose.foundation.layout.Spacer import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.padding -import androidx.compose.foundation.layout.size import androidx.compose.foundation.rememberScrollState import androidx.compose.foundation.verticalScroll -import androidx.compose.material.icons.Icons -import androidx.compose.material.icons.filled.AccountBalance -import androidx.compose.material.icons.filled.Link -import androidx.compose.material.icons.filled.QrCode -import androidx.compose.material3.Button -import androidx.compose.material3.ButtonDefaults -import androidx.compose.material3.Icon import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Surface import androidx.compose.material3.Text @@ -38,7 +29,6 @@ import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.res.stringResource -import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp import net.taler.common.Amount @@ -53,6 +43,7 @@ import net.taler.wallet.backend.TalerErrorInfo import net.taler.wallet.balances.ScopeInfo import net.taler.wallet.cleanExchange import net.taler.wallet.transactions.AmountType +import net.taler.wallet.transactions.WithdrawalActions import net.taler.wallet.transactions.ErrorTransactionButton import net.taler.wallet.transactions.TransactionAction import net.taler.wallet.transactions.TransactionAction.Abort @@ -68,7 +59,6 @@ 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.PaytoQrCode @Composable fun TransactionWithdrawalComposable( @@ -76,6 +66,7 @@ fun TransactionWithdrawalComposable( devMode: Boolean, qrCode: QrCodeSpec?, spec: CurrencySpecification?, + onConfirmKyc: (url: String) -> Unit, onConfirmBank: () -> Unit, onConfirmManual: () -> Unit, onShowQrCodes: () -> Unit, @@ -121,59 +112,13 @@ fun TransactionWithdrawalComposable( amountType = AmountType.Positive, ) - if (t.txState.minor == TransactionMinorState.BankConfirmTransfer) { - Button(onClick = onConfirmBank) { - val label = stringResource(R.string.withdraw_button_confirm_bank) - Icon( - Icons.Default.Link, - label, - modifier = Modifier.size(ButtonDefaults.IconSize) - ) - Spacer(Modifier.size(ButtonDefaults.IconSpacing)) - Text(label) - } - } else if (t.txState.minor == TransactionMinorState.ExchangeWaitReserve) { - Text( - text = stringResource(R.string.withdraw_manual_instruction_manual), - modifier = Modifier.padding(16.dp), - textAlign = TextAlign.Center, - style = MaterialTheme.typography.bodyLarge, - ) - - Button(onClick = onConfirmManual) { - Icon( - Icons.Default.AccountBalance, - contentDescription = null, - modifier = Modifier.size(ButtonDefaults.IconSize) - ) - Spacer(Modifier.size(ButtonDefaults.IconSpacing)) - Text(stringResource(R.string.withdraw_manual_ready_details_intro)) - } - - if (qrCode != null) { - 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 = qrCode, - ) - } else { - Button(onClick = onShowQrCodes) { - 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)) - } - } - } + WithdrawalActions(t, + mainQrCode = qrCode, + onConfirmKyc = onConfirmKyc, + onConfirmBank = onConfirmBank, + onConfirmManual = onConfirmManual, + onShowQrCodes = onShowQrCodes, + ) if (t.exchangeBaseUrl != null) { TransactionInfoComposable( @@ -232,7 +177,7 @@ fun TransactionWithdrawalComposableSingleQrPreview() { TransactionWithdrawalComposable(previewWithdrawalTx, true, QrCodeSpec(QrCodeSpec.Type.SPC, "something"), null, - {}, {}, {}, {}) + {}, {}, {}, {}, {}) } } @@ -243,6 +188,6 @@ fun TransactionWithdrawalComposableMultiQrPreview() { TransactionWithdrawalComposable(previewWithdrawalTx, true, null, null, - {}, {}, {}, {}) + {}, {}, {}, {}, {}) } } \ No newline at end of file