gnunet-svn
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[taler-taler-android] 06/14: [wallet] Additional refactoring of pay temp


From: gnunet
Subject: [taler-taler-android] 06/14: [wallet] Additional refactoring of pay templates
Date: Tue, 26 Sep 2023 18:31:26 +0200

This is an automated email from the git hooks/post-receive script.

torsten-grote pushed a commit to branch master
in repository taler-android.

commit 68a3c7ca5c615c35e3066780b909d2acb9eb3c8a
Author: Iván Ávalos <avalos@disroot.org>
AuthorDate: Tue Aug 29 11:45:00 2023 -0600

    [wallet] Additional refactoring of pay templates
---
 .../taler/wallet/payment/PayTemplateComposable.kt  | 216 ++++++++++-----------
 .../taler/wallet/payment/PayTemplateFragment.kt    |  22 ++-
 2 files changed, 119 insertions(+), 119 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,
diff --git 
a/wallet/src/main/java/net/taler/wallet/payment/PayTemplateFragment.kt 
b/wallet/src/main/java/net/taler/wallet/payment/PayTemplateFragment.kt
index 1812db0..93fe48c 100644
--- a/wallet/src/main/java/net/taler/wallet/payment/PayTemplateFragment.kt
+++ b/wallet/src/main/java/net/taler/wallet/payment/PayTemplateFragment.kt
@@ -29,7 +29,9 @@ import androidx.fragment.app.activityViewModels
 import androidx.lifecycle.asFlow
 import androidx.navigation.NavOptions
 import androidx.navigation.fragment.findNavController
+import net.taler.common.Amount
 import net.taler.common.showError
+import net.taler.wallet.AmountResult
 import net.taler.wallet.MainViewModel
 import net.taler.wallet.R
 import net.taler.wallet.compose.TalerSurface
@@ -49,6 +51,21 @@ class PayTemplateFragment : Fragment() {
         uriString = arguments?.getString("uri") ?: error("no amount passed")
         uri = Uri.parse(uriString)
 
+        val queryParams = uri.queryParameterNames
+
+        val summary = if ("summary" in queryParams)
+            uri.getQueryParameter("summary")!! else null
+
+        val amountResult = if ("amount" in queryParams) {
+            val amount = uri.getQueryParameter("amount")!!
+            val parts = amount.split(':')
+            when (parts.size) {
+                1 -> AmountResult.Success(Amount.fromString(parts[0], "0"))
+                2 -> AmountResult.Success(Amount.fromString(parts[0], 
parts[1]))
+                else -> AmountResult.InvalidAmount
+            }
+        } else null
+
         return ComposeView(requireContext()).apply {
             setContent {
                 val payStatus by model.paymentManager.payStatus
@@ -56,8 +73,9 @@ class PayTemplateFragment : Fragment() {
                     .collectAsState(initial = PayStatus.None)
                 TalerSurface {
                     PayTemplateComposable(
-                        uri = uri,
                         currencies = model.getCurrencies(),
+                        summary = summary,
+                        amountResult = amountResult,
                         payStatus = payStatus,
                         onCreateAmount = { text, currency ->
                             model.createAmount(text, currency)
@@ -72,8 +90,6 @@ class PayTemplateFragment : Fragment() {
 
     override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
         super.onViewCreated(view, savedInstanceState)
-        // TODO: this is not ideal, if the template is fixed, the
-        //  user shouldn't even have to go through this fragment.
         if (uri.queryParameterNames?.isEmpty() == true) {
             createOrder(emptyMap())
         }

-- 
To stop receiving notification emails like this one, please contact
gnunet@gnunet.org.



reply via email to

[Prev in Thread] Current Thread [Next in Thread]