summaryrefslogtreecommitdiff
path: root/wallet/src/main/java/net/taler/wallet/payment/PayTemplateComposable.kt
diff options
context:
space:
mode:
Diffstat (limited to 'wallet/src/main/java/net/taler/wallet/payment/PayTemplateComposable.kt')
-rw-r--r--wallet/src/main/java/net/taler/wallet/payment/PayTemplateComposable.kt216
1 files changed, 100 insertions, 116 deletions
diff --git a/wallet/src/main/java/net/taler/wallet/payment/PayTemplateComposable.kt b/wallet/src/main/java/net/taler/wallet/payment/PayTemplateComposable.kt
index c8c3ba0..a5812c0 100644
--- a/wallet/src/main/java/net/taler/wallet/payment/PayTemplateComposable.kt
+++ b/wallet/src/main/java/net/taler/wallet/payment/PayTemplateComposable.kt
@@ -16,7 +16,6 @@
package net.taler.wallet.payment
-import android.net.Uri
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
@@ -43,146 +42,130 @@ import androidx.compose.ui.text.input.KeyboardType
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import net.taler.common.Amount
-import net.taler.common.AmountParserException
import net.taler.wallet.AmountResult
import net.taler.wallet.R
import net.taler.wallet.compose.TalerSurface
import net.taler.wallet.deposit.CurrencyDropdown
-@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun PayTemplateComposable(
- uri: Uri,
+ summary: String?,
+ amountResult: AmountResult?,
currencies: List<String>,
payStatus: PayStatus,
onCreateAmount: (String, String) -> AmountResult,
onSubmit: (Map<String, String>) -> Unit,
onError: (resId: Int) -> Unit,
) {
- val queryParams = uri.queryParameterNames
-
- var summary by remember {
- mutableStateOf(
- // TODO pass this in as a parameter instead
- if ("summary" in queryParams) uri.getQueryParameter("summary") else null
- )
- }
- var amount by remember {
- mutableStateOf(
- // TODO don't do amount parsing in composable, but pass it in as a parameter
- if ("amount" in queryParams) {
- val amount = uri.getQueryParameter("amount")!!
- val parts = amount.split(':')
- when (parts.size) {
- 1 -> Amount.fromString(parts[0], "0")
- 2 -> Amount.fromString(parts[0], parts[1])
- // FIXME This will crash the app, we should show a proper error instead.
- else -> throw AmountParserException("Invalid Amount Format")
- }
- } else {
- null
+ // If wallet is empty, there's no way the user can pay something
+ if (amountResult is AmountResult.InvalidAmount) {
+ PayTemplateError(stringResource(R.string.receive_amount_invalid))
+ } else if (payStatus is PayStatus.InsufficientBalance || currencies.isEmpty()) {
+ PayTemplateError(stringResource(R.string.payment_balance_insufficient))
+ } else when (payStatus) {
+ is PayStatus.None -> PayTemplateDefault(
+ currencies = currencies,
+ summary = summary,
+ amount = amountResult?.let { (it as AmountResult.Success).amount },
+ onCreateAmount = onCreateAmount,
+ onError = onError,
+ onSubmit = { s, a ->
+ onSubmit(mutableMapOf<String, String>().apply {
+ s?.let { put("summary", it) }
+ a?.let { put("amount", it.toJSONString()) }
+ })
}
)
+ is PayStatus.Loading -> PayTemplateLoading()
+ is PayStatus.AlreadyPaid -> PayTemplateError(stringResource(R.string.payment_already_paid))
+
+ // TODO we should handle the other cases or explain why we don't handle them
+ else -> {}
}
+}
- // TODO we could think about splitting this up into separate composables
- // If wallet is empty, there's no way the user can pay something
- if (payStatus is PayStatus.InsufficientBalance || currencies.isEmpty()) {
- Box(
- modifier = Modifier.fillMaxSize(),
- contentAlignment = Center,
- ) {
- Text(
- text = stringResource(R.string.payment_balance_insufficient),
- style = MaterialTheme.typography.titleLarge,
- color = MaterialTheme.colorScheme.error,
+@OptIn(ExperimentalMaterial3Api::class)
+@Composable
+fun PayTemplateDefault(
+ currencies: List<String>,
+ summary: String? = null,
+ amount: Amount? = null,
+ onCreateAmount: (String, String) -> AmountResult,
+ onError: (msgRes: Int) -> Unit,
+ onSubmit: (summary: String?, amount: Amount?) -> Unit,
+) {
+ var localSummary by remember { mutableStateOf(summary) }
+ var localAmount by remember { mutableStateOf(amount) }
+
+ Column(horizontalAlignment = End) {
+ localSummary?.let { summary ->
+ OutlinedTextField(
+ modifier = Modifier
+ .padding(horizontal = 16.dp)
+ .fillMaxWidth(),
+ value = summary,
+ isError = summary.isBlank(),
+ onValueChange = { localSummary = it },
+ singleLine = true,
+ label = { Text(stringResource(R.string.withdraw_manual_ready_subject)) },
)
}
- } else when (payStatus) {
- is PayStatus.None -> {
- Column(horizontalAlignment = End) {
- if ("summary" in queryParams) {
- OutlinedTextField(
- modifier = Modifier
- .padding(horizontal = 16.dp)
- .fillMaxWidth(),
- value = summary!!,
- isError = summary!!.isBlank(),
- onValueChange = { summary = it },
- singleLine = true,
- label = { Text(stringResource(R.string.withdraw_manual_ready_subject)) },
- )
- }
-
- if ("amount" in queryParams) {
- AmountField(
- modifier = Modifier
- .padding(16.dp)
- .fillMaxWidth(),
- amount = amount!!,
- currencies = currencies,
- onAmountChosen = { amount = it },
- )
- }
-
- Button(
- modifier = Modifier.padding(16.dp),
- enabled = summary == null || summary!!.isNotBlank(),
- onClick = {
- if (amount != null) {
- val result = onCreateAmount(
- amount!!.amountStr,
- amount!!.currency,
- )
- when (result) {
- AmountResult.InsufficientBalance -> {
- onError(R.string.payment_balance_insufficient)
- }
- AmountResult.InvalidAmount -> {
- onError(R.string.receive_amount_invalid)
- }
-
- else -> {
- onSubmit(
- mutableMapOf<String, String>().apply {
- summary?.let { put("summary", it) }
- amount?.let { put("amount", it.toJSONString()) }
- }
- )
- }
- }
- }
- },
- ) {
- Text(stringResource(R.string.payment_create_order))
- }
- }
+ localAmount?.let { amount ->
+ AmountField(
+ modifier = Modifier
+ .padding(16.dp)
+ .fillMaxWidth(),
+ amount = amount,
+ currencies = currencies,
+ onAmountChosen = { localAmount = it },
+ )
}
- is PayStatus.Loading -> {
- Box(
- modifier = Modifier.fillMaxSize(),
- contentAlignment = Center,
- ) { CircularProgressIndicator() }
+ Button(
+ modifier = Modifier.padding(16.dp),
+ enabled = localSummary == null || localSummary!!.isNotBlank(),
+ onClick = {
+ localAmount?.let { amount ->
+ val result = onCreateAmount(
+ amount.amountStr,
+ amount.currency,
+ )
+ when (result) {
+ AmountResult.InsufficientBalance -> onError(R.string.payment_balance_insufficient)
+ AmountResult.InvalidAmount -> onError(R.string.receive_amount_invalid)
+ else -> onSubmit(summary, amount)
+ }
+ }
+ },
+ ) {
+ Text(stringResource(R.string.payment_create_order))
}
+ }
+}
- is PayStatus.AlreadyPaid -> {
- Box(
- modifier = Modifier.fillMaxSize(),
- contentAlignment = Center,
- ) {
- Text(
- stringResource(R.string.payment_already_paid),
- style = MaterialTheme.typography.titleLarge,
- color = MaterialTheme.colorScheme.error,
- )
- }
- }
+@Composable
+fun PayTemplateError(message: String) {
+ Box(
+ modifier = Modifier.fillMaxSize(),
+ contentAlignment = Center,
+ ) {
+ Text(
+ text = message,
+ style = MaterialTheme.typography.titleLarge,
+ color = MaterialTheme.colorScheme.error,
+ )
+ }
+}
- // TODO we should handle the other cases or explain why we don't handle them
- else -> {}
+@Composable
+fun PayTemplateLoading() {
+ Box(
+ modifier = Modifier.fillMaxSize(),
+ contentAlignment = Center,
+ ) {
+ CircularProgressIndicator()
}
}
@@ -233,7 +216,8 @@ private fun AmountField(
fun PayTemplateComposablePreview() {
TalerSurface {
PayTemplateComposable(
- uri = Uri.parse("taler://pay-template/demo.backend.taler.net/test?amount=KUDOS&summary="),
+ summary = "Donation",
+ amountResult = AmountResult.Success(Amount("ARS", 20L, 0)),
currencies = listOf("KUDOS", "ARS"),
// TODO create previews for other states
payStatus = PayStatus.None,