diff --git a/wallet/src/main/java/net/taler/wallet/transactions/TransitionsComposable.kt b/wallet/src/main/java/net/taler/wallet/transactions/TransitionsComposable.kt
index f654604f..e0045197 100644
--- a/wallet/src/main/java/net/taler/wallet/transactions/TransitionsComposable.kt
+++ b/wallet/src/main/java/net/taler/wallet/transactions/TransitionsComposable.kt
@@ -18,6 +18,7 @@ package net.taler.wallet.transactions
import androidx.compose.foundation.layout.Arrangement.Center
import androidx.compose.foundation.layout.Column
+import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.ExperimentalLayoutApi
import androidx.compose.foundation.layout.FlowRow
import androidx.compose.foundation.layout.Row
@@ -27,6 +28,7 @@ import androidx.compose.foundation.verticalScroll
import androidx.compose.material3.AlertDialog
import androidx.compose.material3.Button
import androidx.compose.material3.ButtonDefaults
+import androidx.compose.material3.CardDefaults
import androidx.compose.material3.Icon
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Text
@@ -42,11 +44,15 @@ import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.font.FontFamily
+import androidx.compose.ui.text.font.FontWeight
+import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import kotlinx.serialization.json.Json
import net.taler.lib.android.copyToClipBoard
import net.taler.wallet.R
+import net.taler.wallet.backend.TalerErrorInfo
+import net.taler.wallet.compose.Banner
import net.taler.wallet.transactions.TransactionAction.*
@OptIn(ExperimentalLayoutApi::class)
@@ -99,9 +105,19 @@ fun TransitionsComposable(
})
}
+ // Developer mode has the raw JSON (ErrorTransactionButton); everybody
+ // else gets told that the wallet is stuck on an error and why.
+ val error = t.error
+ if (error != null && !devMode) {
+ TransactionErrorBanner(error)
+ }
+
FlowRow(horizontalArrangement = Center) {
t.txActions.forEach {
- if (it in arrayOf(Resume, Suspend, Retry)) {
+ if (it == Retry && error != null) {
+ // a failing transaction can be retried by anybody
+ TransitionComposable(it, onTransition)
+ } else if (it in arrayOf(Resume, Suspend, Retry)) {
if (devMode) TransitionComposable(it, onTransition)
} else {
TransitionComposable(it, onTransition)
@@ -117,6 +133,42 @@ fun TransitionsComposable(
}
}
+@Composable
+fun TransactionErrorBanner(error: TalerErrorInfo) {
+ Banner(
+ modifier = Modifier.padding(top = 16.dp),
+ colors = CardDefaults.cardColors(
+ containerColor = MaterialTheme.colorScheme.errorContainer,
+ contentColor = MaterialTheme.colorScheme.onErrorContainer,
+ ),
+ ) {
+ Column(Modifier.fillMaxWidth()) {
+ Text(
+ text = stringResource(R.string.transaction_error_title),
+ fontWeight = FontWeight.Bold,
+ textAlign = TextAlign.Center,
+ modifier = Modifier.fillMaxWidth(),
+ )
+ Text(
+ text = error.userFacingMsg.ifEmpty {
+ stringResource(R.string.error_code_only, error.rawCode)
+ },
+ textAlign = TextAlign.Center,
+ modifier = Modifier
+ .fillMaxWidth()
+ .padding(top = 8.dp),
+ )
+ Text(
+ text = stringResource(R.string.transaction_error_retry_hint),
+ textAlign = TextAlign.Center,
+ modifier = Modifier
+ .fillMaxWidth()
+ .padding(top = 8.dp),
+ )
+ }
+ }
+}
+
@Composable
fun TransitionComposable(t: TransactionAction, onClick: (t: TransactionAction) -> Unit) {
var showConfirmDialog by remember { mutableStateOf(false) }
diff --git a/wallet/src/main/res/values/strings.xml b/wallet/src/main/res/values/strings.xml
index 89750709..8ac36512 100644
--- a/wallet/src/main/res/values/strings.xml
+++ b/wallet/src/main/res/values/strings.xml
@@ -210,6 +210,8 @@ GNU Taler is immune to many types of fraud such as credit card data theft, phish
This transaction has failed or been abandoned
This transaction is finalizing
This transaction is pending
+ The wallet reported a problem
+ The wallet will retry automatically. You can also retry now.
Waiting for authorization in the bank
This transaction would exceed a limit set by the payment service. To increase the limit, follow the instructions linked below.
You need to prove having control over the bank account for the deposit. To continue, follow the instructions linked below.