From d1163e31e904ac59d0739169257a8e3fdc7986a7 Mon Sep 17 00:00:00 2001 From: Torsten Grote Date: Wed, 17 Aug 2022 15:40:16 -0300 Subject: [wallet] Add ability to cancel/delete transactions --- .../transactions/TransactionDetailFragment.kt | 31 +++++++++- .../wallet/transactions/TransactionManager.kt | 10 +++- .../transactions/TransactionPaymentFragment.kt | 7 ++- .../transactions/TransactionRefreshFragment.kt | 9 ++- .../transactions/TransactionRefundFragment.kt | 7 ++- .../transactions/TransactionWithdrawalFragment.kt | 66 +++++++++++++++------- .../wallet/transactions/TransactionsFragment.kt | 7 +-- 7 files changed, 102 insertions(+), 35 deletions(-) (limited to 'wallet/src/main/java/net/taler/wallet/transactions') diff --git a/wallet/src/main/java/net/taler/wallet/transactions/TransactionDetailFragment.kt b/wallet/src/main/java/net/taler/wallet/transactions/TransactionDetailFragment.kt index 128ca04..f21818f 100644 --- a/wallet/src/main/java/net/taler/wallet/transactions/TransactionDetailFragment.kt +++ b/wallet/src/main/java/net/taler/wallet/transactions/TransactionDetailFragment.kt @@ -23,8 +23,11 @@ import android.view.Menu import android.view.MenuInflater import android.view.MenuItem import android.widget.TextView +import androidx.annotation.StringRes +import androidx.appcompat.app.AlertDialog import androidx.fragment.app.Fragment import androidx.fragment.app.activityViewModels +import androidx.navigation.fragment.findNavController import net.taler.common.Amount import net.taler.common.startActivitySafe import net.taler.wallet.MainViewModel @@ -67,7 +70,7 @@ abstract class TransactionDetailFragment : Fragment() { feeView: TextView, info: TransactionInfo, raw: Amount, - fee: Amount + fee: Amount, ) { orderAmountView.text = raw.toString() feeView.text = getString(R.string.amount_negative, fee.toString()) @@ -85,4 +88,30 @@ abstract class TransactionDetailFragment : Fragment() { orderIdView.text = getString(R.string.transaction_order_id, info.orderId) } + @StringRes + protected open val deleteDialogTitle = R.string.transactions_delete + @StringRes + protected open val deleteDialogMessage = R.string.transactions_delete_dialog_message + @StringRes + protected open val deleteDialogButton = R.string.transactions_delete + + protected fun onDeleteButtonClicked(t: Transaction) { + AlertDialog.Builder(requireContext(), R.style.DialogTheme) + .setTitle(deleteDialogTitle) + .setMessage(deleteDialogMessage) + .setPositiveButton(R.string.cancel) { dialog, _ -> + dialog.cancel() + } + .setNegativeButton(deleteDialogButton) { dialog, _ -> + deleteTransaction(t) + dialog.dismiss() + } + .show() + } + + private fun deleteTransaction(t: Transaction) { + transactionManager.deleteTransaction(t.transactionId) + findNavController().popBackStack() + } + } diff --git a/wallet/src/main/java/net/taler/wallet/transactions/TransactionManager.kt b/wallet/src/main/java/net/taler/wallet/transactions/TransactionManager.kt index ea257a8..d1020e2 100644 --- a/wallet/src/main/java/net/taler/wallet/transactions/TransactionManager.kt +++ b/wallet/src/main/java/net/taler/wallet/transactions/TransactionManager.kt @@ -25,7 +25,6 @@ import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.launch import net.taler.wallet.TAG import net.taler.wallet.backend.WalletBackendApi -import java.util.HashMap import java.util.LinkedList sealed class TransactionsResult { @@ -96,7 +95,14 @@ class TransactionManager( }.onError { Log.e(TAG, "Error deleteTransaction $it") }.onSuccess { - // no op + // re-load transactions as our list is stale otherwise + loadTransactions() + } + } + + fun deleteTransactions(transactionIds: List) { + transactionIds.forEach { id -> + deleteTransaction(id) } } diff --git a/wallet/src/main/java/net/taler/wallet/transactions/TransactionPaymentFragment.kt b/wallet/src/main/java/net/taler/wallet/transactions/TransactionPaymentFragment.kt index 84c5c77..e2e4f9f 100644 --- a/wallet/src/main/java/net/taler/wallet/transactions/TransactionPaymentFragment.kt +++ b/wallet/src/main/java/net/taler/wallet/transactions/TransactionPaymentFragment.kt @@ -30,8 +30,8 @@ class TransactionPaymentFragment : TransactionDetailFragment() { override fun onCreateView( inflater: LayoutInflater, container: ViewGroup?, - savedInstanceState: Bundle? - ): View? { + savedInstanceState: Bundle?, + ): View { ui = FragmentTransactionPaymentBinding.inflate(inflater, container, false) return ui.root } @@ -51,6 +51,9 @@ class TransactionPaymentFragment : TransactionDetailFragment() { t.amountRaw, fee ) + ui.deleteButton.setOnClickListener { + onDeleteButtonClicked(t) + } } } diff --git a/wallet/src/main/java/net/taler/wallet/transactions/TransactionRefreshFragment.kt b/wallet/src/main/java/net/taler/wallet/transactions/TransactionRefreshFragment.kt index 717dd33..d44db43 100644 --- a/wallet/src/main/java/net/taler/wallet/transactions/TransactionRefreshFragment.kt +++ b/wallet/src/main/java/net/taler/wallet/transactions/TransactionRefreshFragment.kt @@ -33,8 +33,8 @@ class TransactionRefreshFragment : TransactionDetailFragment() { override fun onCreateView( inflater: LayoutInflater, container: ViewGroup?, - savedInstanceState: Bundle? - ): View? { + savedInstanceState: Bundle?, + ): View { ui = FragmentTransactionWithdrawalBinding.inflate(inflater, container, false) return ui.root } @@ -50,7 +50,10 @@ class TransactionRefreshFragment : TransactionDetailFragment() { ui.chosenAmountView.visibility = GONE val fee = t.amountEffective ui.feeView.text = getString(R.string.amount_negative, fee.toString()) - ui. exchangeView.text = cleanExchange(t.exchangeBaseUrl) + ui.exchangeView.text = cleanExchange(t.exchangeBaseUrl) + ui.deleteButton.setOnClickListener { + onDeleteButtonClicked(t) + } } } diff --git a/wallet/src/main/java/net/taler/wallet/transactions/TransactionRefundFragment.kt b/wallet/src/main/java/net/taler/wallet/transactions/TransactionRefundFragment.kt index 6628d6c..5e6eef4 100644 --- a/wallet/src/main/java/net/taler/wallet/transactions/TransactionRefundFragment.kt +++ b/wallet/src/main/java/net/taler/wallet/transactions/TransactionRefundFragment.kt @@ -32,8 +32,8 @@ class TransactionRefundFragment : TransactionDetailFragment() { override fun onCreateView( inflater: LayoutInflater, container: ViewGroup?, - savedInstanceState: Bundle? - ): View? { + savedInstanceState: Bundle?, + ): View { ui = FragmentTransactionPaymentBinding.inflate(inflater, container, false) return ui.root } @@ -56,6 +56,9 @@ class TransactionRefundFragment : TransactionDetailFragment() { t.amountRaw, fee ) + ui.deleteButton.setOnClickListener { + onDeleteButtonClicked(t) + } } } diff --git a/wallet/src/main/java/net/taler/wallet/transactions/TransactionWithdrawalFragment.kt b/wallet/src/main/java/net/taler/wallet/transactions/TransactionWithdrawalFragment.kt index a11f8ba..ff8d272 100644 --- a/wallet/src/main/java/net/taler/wallet/transactions/TransactionWithdrawalFragment.kt +++ b/wallet/src/main/java/net/taler/wallet/transactions/TransactionWithdrawalFragment.kt @@ -31,6 +31,8 @@ import net.taler.wallet.MainViewModel import net.taler.wallet.R import net.taler.wallet.cleanExchange import net.taler.wallet.databinding.FragmentTransactionWithdrawalBinding +import net.taler.wallet.transactions.WithdrawalDetails.ManualTransfer +import net.taler.wallet.transactions.WithdrawalDetails.TalerBankIntegrationApi import net.taler.wallet.withdraw.createManualTransferRequired class TransactionWithdrawalFragment : TransactionDetailFragment() { @@ -54,33 +56,55 @@ class TransactionWithdrawalFragment : TransactionDetailFragment() { ui.effectiveAmountLabel.text = getString(R.string.withdraw_total) ui.effectiveAmountView.text = t.amountEffective.toString() - if (t.pending && t.withdrawalDetails is WithdrawalDetails.TalerBankIntegrationApi && - !t.confirmed && t.withdrawalDetails.bankConfirmationUrl != null - ) { - val i = Intent(ACTION_VIEW).apply { - data = Uri.parse(t.withdrawalDetails.bankConfirmationUrl) - } - ui.confirmWithdrawalButton.setOnClickListener { startActivitySafe(i) } - } else if (t.pending && !t.confirmed && t.withdrawalDetails is WithdrawalDetails.ManualTransfer) { - ui.confirmWithdrawalButton.setText(R.string.withdraw_manual_ready_details_intro) - ui.confirmWithdrawalButton.setOnClickListener { - val status = createManualTransferRequired( - amount = t.amountRaw, - exchangeBaseUrl = t.exchangeBaseUrl, - // TODO what if there's more than one or no URI? - uriStr = t.withdrawalDetails.exchangePaytoUris[0], - transactionId = t.transactionId, - ) - withdrawManager.viewManualWithdrawal(status) - findNavController().navigate(R.id.action_nav_transactions_detail_withdrawal_to_nav_exchange_manual_withdrawal_success) - } - } else ui.confirmWithdrawalButton.visibility = View.GONE + setupConfirmWithdrawalButton(t) ui.chosenAmountLabel.text = getString(R.string.amount_chosen) ui.chosenAmountView.text = getString(R.string.amount_positive, t.amountRaw.toString()) val fee = t.amountRaw - t.amountEffective ui.feeView.text = getString(R.string.amount_negative, fee.toString()) ui.exchangeView.text = cleanExchange(t.exchangeBaseUrl) + if (t.pending) { + ui.deleteButton.setIconResource(R.drawable.ic_cancel) + ui.deleteButton.setText(R.string.cancel) + } + ui.deleteButton.setOnClickListener { + onDeleteButtonClicked(t) + } + } + + override val deleteDialogTitle: Int + get() = if (transaction?.pending == true) R.string.cancel else super.deleteDialogTitle + override val deleteDialogMessage: Int + get() = if (transaction?.pending == true) R.string.transactions_cancel_dialog_message + else super.deleteDialogMessage + override val deleteDialogButton: Int + get() = if (transaction?.pending == true) R.string.ok else super.deleteDialogButton + + private fun setupConfirmWithdrawalButton(t: TransactionWithdrawal) { + if (t.pending && !t.confirmed) { + if (t.withdrawalDetails is TalerBankIntegrationApi && + t.withdrawalDetails.bankConfirmationUrl != null + ) { + val i = Intent(ACTION_VIEW).apply { + data = Uri.parse(t.withdrawalDetails.bankConfirmationUrl) + } + ui.confirmWithdrawalButton.setOnClickListener { startActivitySafe(i) } + } else if (t.withdrawalDetails is ManualTransfer) { + ui.confirmWithdrawalButton.setText(R.string.withdraw_manual_ready_details_intro) + ui.confirmWithdrawalButton.setOnClickListener { + val status = createManualTransferRequired( + amount = t.amountRaw, + exchangeBaseUrl = t.exchangeBaseUrl, + // TODO what if there's more than one or no URI? + uriStr = t.withdrawalDetails.exchangePaytoUris[0], + transactionId = t.transactionId, + ) + withdrawManager.viewManualWithdrawal(status) + findNavController().navigate( + R.id.action_nav_transactions_detail_withdrawal_to_nav_exchange_manual_withdrawal_success) + } + } else ui.confirmWithdrawalButton.visibility = View.GONE + } else ui.confirmWithdrawalButton.visibility = View.GONE } } diff --git a/wallet/src/main/java/net/taler/wallet/transactions/TransactionsFragment.kt b/wallet/src/main/java/net/taler/wallet/transactions/TransactionsFragment.kt index ff2574f..fddaaec 100644 --- a/wallet/src/main/java/net/taler/wallet/transactions/TransactionsFragment.kt +++ b/wallet/src/main/java/net/taler/wallet/transactions/TransactionsFragment.kt @@ -25,8 +25,6 @@ import android.view.MenuItem import android.view.View import android.view.View.INVISIBLE import android.view.ViewGroup -import android.widget.Toast -import android.widget.Toast.LENGTH_LONG import androidx.appcompat.widget.SearchView import androidx.appcompat.widget.SearchView.OnQueryTextListener import androidx.fragment.app.Fragment @@ -211,8 +209,9 @@ class TransactionsFragment : Fragment(), OnTransactionClickListener, ActionMode. override fun onActionItemClicked(mode: ActionMode, item: MenuItem): Boolean { when (item.itemId) { R.id.transaction_delete -> { - val s = "Not yet implemented. Pester Florian! ;)" - Toast.makeText(requireContext(), s, LENGTH_LONG).show() + tracker?.selection?.toList()?.let { transactionIds -> + transactionManager.deleteTransactions(transactionIds) + } mode.finish() } R.id.transaction_select_all -> transactionAdapter.selectAll() -- cgit v1.2.3