commit a8ae6141e54e5b8ee49c50a35254ad436790a86c
parent e1a53420dbfc672a06d969d9b758e6bab1a607cd
Author: Iván Ávalos <avalos@disroot.org>
Date: Wed, 19 Jun 2024 15:55:06 -0600
[wallet] Render an alert for some transaction states
bug 0008955
Diffstat:
9 files changed, 155 insertions(+), 0 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
@@ -48,6 +48,7 @@ import net.taler.wallet.transactions.TransactionAmountComposable
import net.taler.wallet.transactions.TransactionDeposit
import net.taler.wallet.transactions.TransactionMajorState.Pending
import net.taler.wallet.transactions.TransactionState
+import net.taler.wallet.transactions.TransactionStateComposable
import net.taler.wallet.transactions.TransitionsComposable
@Composable
@@ -65,6 +66,9 @@ fun TransactionDepositComposable(
horizontalAlignment = Alignment.CenterHorizontally,
) {
val context = LocalContext.current
+
+ TransactionStateComposable(state = t.txState)
+
Text(
modifier = Modifier.padding(16.dp),
text = t.timestamp.ms.toAbsoluteTime(context).toString(),
diff --git a/wallet/src/main/java/net/taler/wallet/payment/TransactionPaymentComposable.kt b/wallet/src/main/java/net/taler/wallet/payment/TransactionPaymentComposable.kt
@@ -52,6 +52,7 @@ import net.taler.wallet.transactions.TransactionLinkComposable
import net.taler.wallet.transactions.TransactionMajorState.Pending
import net.taler.wallet.transactions.TransactionPayment
import net.taler.wallet.transactions.TransactionState
+import net.taler.wallet.transactions.TransactionStateComposable
import net.taler.wallet.transactions.TransitionsComposable
@Composable
@@ -70,6 +71,9 @@ fun TransactionPaymentComposable(
horizontalAlignment = CenterHorizontally,
) {
val context = LocalContext.current
+
+ TransactionStateComposable(state = t.txState)
+
Text(
modifier = Modifier.padding(16.dp),
text = t.timestamp.ms.toAbsoluteTime(context).toString(),
diff --git a/wallet/src/main/java/net/taler/wallet/refund/TransactionRefundComposable.kt b/wallet/src/main/java/net/taler/wallet/refund/TransactionRefundComposable.kt
@@ -49,6 +49,7 @@ import net.taler.wallet.transactions.TransactionInfoComposable
import net.taler.wallet.transactions.TransactionMajorState.Pending
import net.taler.wallet.transactions.TransactionRefund
import net.taler.wallet.transactions.TransactionState
+import net.taler.wallet.transactions.TransactionStateComposable
import net.taler.wallet.transactions.TransitionsComposable
@Composable
@@ -66,21 +67,27 @@ fun TransactionRefundComposable(
horizontalAlignment = CenterHorizontally,
) {
val context = LocalContext.current
+
+ TransactionStateComposable(state = t.txState)
+
Text(
modifier = Modifier.padding(16.dp),
text = t.timestamp.ms.toAbsoluteTime(context).toString(),
style = MaterialTheme.typography.bodyLarge,
)
+
TransactionAmountComposable(
label = stringResource(id = R.string.transaction_refund),
amount = t.amountEffective.withSpec(spec),
amountType = AmountType.Positive,
)
+
TransactionAmountComposable(
label = stringResource(id = R.string.transaction_order_total),
amount = t.amountRaw.withSpec(spec),
amountType = AmountType.Neutral,
)
+
if (t.amountRaw > t.amountEffective) {
val fee = t.amountRaw - t.amountEffective
TransactionAmountComposable(
@@ -89,11 +96,14 @@ fun TransactionRefundComposable(
amountType = AmountType.Negative,
)
}
+
TransactionInfoComposable(
label = stringResource(id = R.string.transaction_order),
info = t.paymentInfo?.summary ?: "",
)
+
TransitionsComposable(t, devMode, onTransition)
+
if (devMode && t.error != null) {
ErrorTransactionButton(error = t.error)
}
diff --git a/wallet/src/main/java/net/taler/wallet/transactions/TransactionLossFragment.kt b/wallet/src/main/java/net/taler/wallet/transactions/TransactionLossFragment.kt
@@ -92,6 +92,8 @@ fun TransitionLossComposable(
.verticalScroll(scrollState),
horizontalAlignment = Alignment.CenterHorizontally,
) {
+ TransactionStateComposable(state = t.txState)
+
Text(
modifier = Modifier.padding(16.dp),
text = t.timestamp.ms.toAbsoluteTime(context).toString(),
diff --git a/wallet/src/main/java/net/taler/wallet/transactions/TransactionPeerFragment.kt b/wallet/src/main/java/net/taler/wallet/transactions/TransactionPeerFragment.kt
@@ -82,11 +82,15 @@ fun TransactionPeerComposable(
horizontalAlignment = CenterHorizontally,
) {
val context = LocalContext.current
+
+ TransactionStateComposable(state = t.txState)
+
Text(
modifier = Modifier.padding(16.dp),
text = t.timestamp.ms.toAbsoluteTime(context).toString(),
style = MaterialTheme.typography.bodyLarge,
)
+
when (t) {
is TransactionPeerPullCredit -> TransactionPeerPullCreditComposable(t, spec)
is TransactionPeerPushCredit -> TransactionPeerPushCreditComposable(t, spec)
@@ -94,7 +98,9 @@ fun TransactionPeerComposable(
is TransactionPeerPushDebit -> TransactionPeerPushDebitComposable(t, spec)
else -> error("unexpected transaction: ${t::class.simpleName}")
}
+
TransitionsComposable(t, devMode, onTransition)
+
if (devMode && t.error != null) {
ErrorTransactionButton(error = t.error!!)
}
diff --git a/wallet/src/main/java/net/taler/wallet/transactions/TransactionRefreshFragment.kt b/wallet/src/main/java/net/taler/wallet/transactions/TransactionRefreshFragment.kt
@@ -85,16 +85,21 @@ private fun TransactionRefreshComposable(
horizontalAlignment = CenterHorizontally,
) {
val context = LocalContext.current
+
+ TransactionStateComposable(state = t.txState)
+
Text(
modifier = Modifier.padding(16.dp),
text = t.timestamp.ms.toAbsoluteTime(context).toString(),
style = MaterialTheme.typography.bodyLarge,
)
+
TransactionAmountComposable(
label = stringResource(id = R.string.amount_fee),
amount = t.amountEffective.withSpec(spec),
amountType = AmountType.Negative,
)
+
TransitionsComposable(t, devMode, onTransition)
if (devMode && t.error != null) {
ErrorTransactionButton(error = t.error)
diff --git a/wallet/src/main/java/net/taler/wallet/transactions/TransactionStateComposable.kt b/wallet/src/main/java/net/taler/wallet/transactions/TransactionStateComposable.kt
@@ -0,0 +1,113 @@
+/*
+ * This file is part of GNU Taler
+ * (C) 2024 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 android.content.res.Configuration
+import androidx.compose.foundation.layout.Column
+import androidx.compose.foundation.layout.fillMaxWidth
+import androidx.compose.foundation.layout.padding
+import androidx.compose.material3.Card
+import androidx.compose.material3.CardDefaults
+import androidx.compose.material3.MaterialTheme
+import androidx.compose.material3.ShapeDefaults
+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.tooling.preview.Preview
+import androidx.compose.ui.unit.dp
+import net.taler.wallet.R
+import net.taler.wallet.compose.TalerSurface
+import net.taler.wallet.transactions.TransactionMajorState.Aborted
+import net.taler.wallet.transactions.TransactionMajorState.Aborting
+import net.taler.wallet.transactions.TransactionMajorState.Done
+import net.taler.wallet.transactions.TransactionMajorState.Expired
+import net.taler.wallet.transactions.TransactionMajorState.Failed
+import net.taler.wallet.transactions.TransactionMajorState.Suspended
+import net.taler.wallet.transactions.TransactionMajorState.Pending
+
+@Composable
+fun TransactionStateComposable(
+ modifier: Modifier = Modifier,
+ state: TransactionState,
+) {
+ val message = when (state.major) {
+ Pending -> stringResource(R.string.transaction_state_pending)
+ Aborted -> stringResource(R.string.transaction_state_aborted)
+ Aborting -> stringResource(R.string.transaction_state_aborting)
+ Suspended -> stringResource(R.string.transaction_state_suspended)
+ Failed -> stringResource(R.string.transaction_state_failed)
+ Expired -> stringResource(R.string.transaction_state_expired)
+ else -> return
+ }
+
+ val cardColor = when (state.major) {
+ Aborted, Aborting, Failed, Expired -> MaterialTheme.colorScheme.errorContainer
+ Pending, Suspended -> MaterialTheme.colorScheme.surfaceVariant
+ else -> return
+ }
+
+ val textColor = when (state.major) {
+ Aborted, Aborting, Failed, Expired -> MaterialTheme.colorScheme.onErrorContainer
+ Pending, Suspended -> MaterialTheme.colorScheme.onSurfaceVariant
+ else -> return
+ }
+
+ Card(
+ modifier = modifier
+ .padding(horizontal = 9.dp)
+ .fillMaxWidth(),
+ colors = CardDefaults.cardColors(
+ containerColor = cardColor,
+ ),
+ shape = ShapeDefaults.ExtraSmall,
+ ) {
+ Text(
+ modifier = Modifier
+ .padding(10.dp)
+ .fillMaxWidth(),
+ text = message,
+ style = MaterialTheme.typography.labelLarge,
+ color = textColor,
+ textAlign = TextAlign.Center,
+ )
+ }
+}
+
+@Preview
+@Composable
+fun TransactionStateComposablePreview() {
+ TalerSurface {
+ Column {
+ val modifier = Modifier.padding(vertical = 6.dp)
+ TransactionStateComposable(modifier, state = TransactionState(Pending))
+ TransactionStateComposable(modifier, state = TransactionState(Aborted))
+ TransactionStateComposable(modifier, state = TransactionState(Aborting))
+ TransactionStateComposable(modifier, state = TransactionState(Suspended))
+ TransactionStateComposable(modifier, state = TransactionState(Failed))
+ TransactionStateComposable(modifier, state = TransactionState(Expired))
+ TransactionStateComposable(modifier, state = TransactionState(Done))
+ }
+ }
+}
+
+@Preview(uiMode = Configuration.UI_MODE_NIGHT_YES)
+@Composable
+fun TransactionStateComposableNightPreview() {
+ TransactionStateComposablePreview()
+}
+\ No newline at end of file
diff --git a/wallet/src/main/java/net/taler/wallet/withdraw/TransactionWithdrawalComposable.kt b/wallet/src/main/java/net/taler/wallet/withdraw/TransactionWithdrawalComposable.kt
@@ -52,6 +52,7 @@ import net.taler.wallet.transactions.TransactionAmountComposable
import net.taler.wallet.transactions.TransactionInfoComposable
import net.taler.wallet.transactions.TransactionMajorState.Pending
import net.taler.wallet.transactions.TransactionState
+import net.taler.wallet.transactions.TransactionStateComposable
import net.taler.wallet.transactions.TransactionWithdrawal
import net.taler.wallet.transactions.TransitionsComposable
import net.taler.wallet.transactions.WithdrawalDetails.ManualTransfer
@@ -73,6 +74,9 @@ fun TransactionWithdrawalComposable(
horizontalAlignment = Alignment.CenterHorizontally,
) {
val context = LocalContext.current
+
+ TransactionStateComposable(state = t.txState)
+
Text(
modifier = Modifier.padding(16.dp),
text = t.timestamp.ms.toAbsoluteTime(context).toString(),
diff --git a/wallet/src/main/res/values/strings.xml b/wallet/src/main/res/values/strings.xml
@@ -129,6 +129,12 @@ GNU Taler is immune against many types of fraud, such as phishing of credit card
<string name="transaction_pending">PENDING</string>
<string name="transaction_refresh">Coin expiry change fee</string>
<string name="transaction_refund">Refund</string>
+ <string name="transaction_state_aborted">This transaction was aborted</string>
+ <string name="transaction_state_aborting">This transaction is aborting</string>
+ <string name="transaction_state_expired">This transaction has expired</string>
+ <string name="transaction_state_failed">This transaction has failed</string>
+ <string name="transaction_state_pending">This transaction is pending</string>
+ <string name="transaction_state_suspended">This transaction is suspended</string>
<string name="transactions_abort">Abort</string>
<string name="transactions_abort_dialog_message">Are you sure you want to abort this transaction? Funds still in transit might get lost.</string>
<string name="transactions_abort_dialog_title">Abort Transaction</string>