gnunet-svn
[Top][All Lists]
Advanced

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

[taler-taler-android] 03/14: [wallet] first cleanup of payment template


From: gnunet
Subject: [taler-taler-android] 03/14: [wallet] first cleanup of payment template work
Date: Tue, 26 Sep 2023 18:31:23 +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 aa1be463c2a79d673f1dd2dd31538649a1cfb83c
Author: Torsten Grote <t@grobox.de>
AuthorDate: Fri Aug 18 10:36:04 2023 +0200

    [wallet] first cleanup of payment template work
    
    the PayTemplateComposable still needs refactoring
---
 .../net/taler/wallet/deposit/PayToUriFragment.kt   |  12 +-
 ...emplateFragment.kt => PayTemplateComposable.kt} |  80 ++------
 .../taler/wallet/payment/PayTemplateFragment.kt    | 219 ++-------------------
 .../net/taler/wallet/payment/PaymentManager.kt     |   4 +-
 4 files changed, 35 insertions(+), 280 deletions(-)

diff --git a/wallet/src/main/java/net/taler/wallet/deposit/PayToUriFragment.kt 
b/wallet/src/main/java/net/taler/wallet/deposit/PayToUriFragment.kt
index 243f589..81f3617 100644
--- a/wallet/src/main/java/net/taler/wallet/deposit/PayToUriFragment.kt
+++ b/wallet/src/main/java/net/taler/wallet/deposit/PayToUriFragment.kt
@@ -49,6 +49,7 @@ import androidx.compose.runtime.remember
 import androidx.compose.runtime.saveable.rememberSaveable
 import androidx.compose.runtime.setValue
 import androidx.compose.ui.Alignment
+import androidx.compose.ui.Alignment.Companion.Center
 import androidx.compose.ui.Modifier
 import androidx.compose.ui.focus.FocusRequester
 import androidx.compose.ui.focus.focusRequester
@@ -157,7 +158,7 @@ private fun PayToComposable(
         CurrencyDropdown(
             modifier = Modifier
                 .fillMaxSize()
-                .wrapContentSize(Alignment.Center),
+                .wrapContentSize(Center),
             currencies = currencies,
             onCurrencyChanged = { c -> currency = c },
         )
@@ -190,14 +191,13 @@ private fun PayToComposable(
 @OptIn(ExperimentalMaterial3Api::class)
 @Composable
 fun CurrencyDropdown(
-    modifier: Modifier = Modifier,
-    initialCurrency: String? = null,
     currencies: List<String>,
     onCurrencyChanged: (String) -> Unit,
+    modifier: Modifier = Modifier,
+    initialCurrency: String? = null,
 ) {
-    val initialIndex = currencies.indexOf(initialCurrency)
-        .let { if (it < 0) null else it }
-    var selectedIndex by remember { mutableStateOf(initialIndex ?: 0) }
+    val initialIndex = currencies.indexOf(initialCurrency).let { if (it < 0) 0 
else it }
+    var selectedIndex by remember { mutableStateOf(initialIndex) }
     var expanded by remember { mutableStateOf(false) }
     Box(
         modifier = modifier,
diff --git 
a/wallet/src/main/java/net/taler/wallet/payment/PayTemplateFragment.kt 
b/wallet/src/main/java/net/taler/wallet/payment/PayTemplateComposable.kt
similarity index 77%
copy from wallet/src/main/java/net/taler/wallet/payment/PayTemplateFragment.kt
copy to wallet/src/main/java/net/taler/wallet/payment/PayTemplateComposable.kt
index 633ab20..3279c71 100644
--- a/wallet/src/main/java/net/taler/wallet/payment/PayTemplateFragment.kt
+++ b/wallet/src/main/java/net/taler/wallet/payment/PayTemplateComposable.kt
@@ -17,10 +17,6 @@
 package net.taler.wallet.payment
 
 import android.net.Uri
-import android.os.Bundle
-import android.view.LayoutInflater
-import android.view.View
-import android.view.ViewGroup
 import androidx.compose.foundation.layout.Box
 import androidx.compose.foundation.layout.Column
 import androidx.compose.foundation.layout.Row
@@ -41,76 +37,21 @@ import androidx.compose.runtime.mutableStateOf
 import androidx.compose.runtime.remember
 import androidx.compose.runtime.setValue
 import androidx.compose.ui.Alignment
+import androidx.compose.ui.Alignment.Companion.Center
 import androidx.compose.ui.Modifier
-import androidx.compose.ui.platform.ComposeView
 import androidx.compose.ui.res.stringResource
 import androidx.compose.ui.text.input.KeyboardType
 import androidx.compose.ui.unit.dp
 import androidx.fragment.app.Fragment
-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.AmountParserException
 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
 import net.taler.wallet.deposit.CurrencyDropdown
 
-class PayTemplateFragment: Fragment() {
-    private val model: MainViewModel by activityViewModels()
-    private var uriString: String? = null
-    private var uri: Uri? = null
-
-    override fun onCreateView(
-        inflater: LayoutInflater,
-        container: ViewGroup?,
-        savedInstanceState: Bundle?
-    ): View {
-        uriString = arguments?.getString("uri") ?: error("no amount passed")
-        uri = Uri.parse(uriString)
-        val currencies = model.getCurrencies()
-
-        return ComposeView(requireContext()).apply {
-            setContent {
-                TalerSurface {
-                    PayTemplateComposable(
-                        uri = uri!!,
-                        currencies = currencies,
-                        fragment = this@PayTemplateFragment,
-                        model = model,
-                        onSubmit = { createOrder(it) },
-                    )
-                }
-            }
-        }
-    }
-
-    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())
-        }
-    }
-
-    private fun createOrder(params: Map<String, String>) {
-        uriString ?: return
-        model.paymentManager.preparePayForTemplate(uriString!!, 
params,).invokeOnCompletion {
-            if (model.paymentManager.payStatus.value is PayStatus.Prepared) {
-                val navOptions = NavOptions.Builder()
-                    .setPopUpTo(R.id.nav_main, true)
-                    .build()
-                findNavController()
-                    .navigate(R.id.action_global_promptPayment, null, 
navOptions)
-            }
-        }
-    }
-}
 
 @OptIn(ExperimentalMaterial3Api::class)
 @Composable
@@ -147,10 +88,10 @@ fun PayTemplateComposable(
     if (payStatus is PayStatus.InsufficientBalance || currencies.isEmpty()) {
         Box(
             modifier = Modifier.fillMaxSize(),
-            contentAlignment = Alignment.Center,
+            contentAlignment = Center,
         ) {
             Text(
-                stringResource(R.string.payment_balance_insufficient),
+                text = stringResource(R.string.payment_balance_insufficient),
                 style = MaterialTheme.typography.titleLarge,
                 color = MaterialTheme.colorScheme.error,
             )
@@ -217,13 +158,13 @@ fun PayTemplateComposable(
         is PayStatus.Loading -> {
             Box(
                 modifier = Modifier.fillMaxSize(),
-                contentAlignment = Alignment.Center,
+                contentAlignment = Center,
             ) { CircularProgressIndicator() }
         }
         is PayStatus.AlreadyPaid -> {
             Box(
                 modifier = Modifier.fillMaxSize(),
-                contentAlignment = Alignment.Center,
+                contentAlignment = Center,
             ) {
                 Text(
                     stringResource(R.string.payment_already_paid),
@@ -275,4 +216,13 @@ private fun AmountField(
             },
         )
     }
-}
\ No newline at end of file
+}
+
+// TODO cleanup composable
+//@Preview
+//@Composable
+//fun PayTemplateComposablePreview() {
+//    TalerSurface {
+//        PayTemplateComposable(Uri.EMPTY, listOf("KUDOS"))
+//    }
+//}
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 633ab20..080d319 100644
--- a/wallet/src/main/java/net/taler/wallet/payment/PayTemplateFragment.kt
+++ b/wallet/src/main/java/net/taler/wallet/payment/PayTemplateFragment.kt
@@ -21,65 +21,35 @@ import android.os.Bundle
 import android.view.LayoutInflater
 import android.view.View
 import android.view.ViewGroup
-import androidx.compose.foundation.layout.Box
-import androidx.compose.foundation.layout.Column
-import androidx.compose.foundation.layout.Row
-import androidx.compose.foundation.layout.fillMaxSize
-import androidx.compose.foundation.layout.fillMaxWidth
-import androidx.compose.foundation.layout.padding
-import androidx.compose.foundation.text.KeyboardOptions
-import androidx.compose.material3.Button
-import androidx.compose.material3.CircularProgressIndicator
-import androidx.compose.material3.ExperimentalMaterial3Api
-import androidx.compose.material3.MaterialTheme
-import androidx.compose.material3.OutlinedTextField
-import androidx.compose.material3.Text
-import androidx.compose.runtime.Composable
-import androidx.compose.runtime.collectAsState
-import androidx.compose.runtime.getValue
-import androidx.compose.runtime.mutableStateOf
-import androidx.compose.runtime.remember
-import androidx.compose.runtime.setValue
-import androidx.compose.ui.Alignment
-import androidx.compose.ui.Modifier
 import androidx.compose.ui.platform.ComposeView
-import androidx.compose.ui.res.stringResource
-import androidx.compose.ui.text.input.KeyboardType
-import androidx.compose.ui.unit.dp
 import androidx.fragment.app.Fragment
 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.AmountParserException
-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
-import net.taler.wallet.deposit.CurrencyDropdown
 
-class PayTemplateFragment: Fragment() {
+class PayTemplateFragment : Fragment() {
+
     private val model: MainViewModel by activityViewModels()
-    private var uriString: String? = null
-    private var uri: Uri? = null
+    private lateinit var uriString: String
+    private lateinit var uri: Uri
 
     override fun onCreateView(
         inflater: LayoutInflater,
         container: ViewGroup?,
-        savedInstanceState: Bundle?
+        savedInstanceState: Bundle?,
     ): View {
         uriString = arguments?.getString("uri") ?: error("no amount passed")
         uri = Uri.parse(uriString)
-        val currencies = model.getCurrencies()
 
         return ComposeView(requireContext()).apply {
             setContent {
                 TalerSurface {
                     PayTemplateComposable(
-                        uri = uri!!,
-                        currencies = currencies,
+                        uri = uri,
+                        currencies = model.getCurrencies(),
                         fragment = this@PayTemplateFragment,
                         model = model,
                         onSubmit = { createOrder(it) },
@@ -93,186 +63,21 @@ class PayTemplateFragment: Fragment() {
         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) {
+        if (uri.queryParameterNames?.isEmpty() == true) {
             createOrder(emptyMap())
         }
     }
 
     private fun createOrder(params: Map<String, String>) {
-        uriString ?: return
-        model.paymentManager.preparePayForTemplate(uriString!!, 
params,).invokeOnCompletion {
+        model.paymentManager.preparePayForTemplate(uriString, 
params).invokeOnCompletion {
+            // TODO maybe better to observe/collect payStatus instead of 
invokeOnCompletion
+            //  and then only reacting to one of the possible payStatus values
             if (model.paymentManager.payStatus.value is PayStatus.Prepared) {
                 val navOptions = NavOptions.Builder()
                     .setPopUpTo(R.id.nav_main, true)
                     .build()
-                findNavController()
-                    .navigate(R.id.action_global_promptPayment, null, 
navOptions)
+                findNavController().navigate(R.id.action_global_promptPayment, 
null, navOptions)
             }
         }
     }
 }
-
-@OptIn(ExperimentalMaterial3Api::class)
-@Composable
-fun PayTemplateComposable(
-    uri: Uri,
-    currencies: List<String>,
-    fragment: Fragment,
-    model: MainViewModel,
-    onSubmit: (Map<String, String>) -> Unit,
-) {
-    val queryParams = uri.queryParameterNames
-
-    var summary by remember { mutableStateOf(
-        if ("summary" in queryParams)
-            uri.getQueryParameter("summary") else null,
-    ) }
-
-    var amount by remember { mutableStateOf(
-        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])
-                else -> throw AmountParserException("Invalid Amount Format")
-            }
-        } else null,
-    ) }
-
-    val payStatus by model.paymentManager.payStatus.asFlow()
-        .collectAsState(initial = PayStatus.None)
-
-    // 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 = Alignment.Center,
-        ) {
-            Text(
-                stringResource(R.string.payment_balance_insufficient),
-                style = MaterialTheme.typography.titleLarge,
-                color = MaterialTheme.colorScheme.error,
-            )
-        }
-    } else when (payStatus) {
-        is PayStatus.None -> {
-            Column(horizontalAlignment = Alignment.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 = model.createAmount(
-                                amount!!.amountStr,
-                                amount!!.currency,
-                            )
-                            when (result) {
-                                AmountResult.InsufficientBalance -> {
-                                    
fragment.showError(R.string.payment_balance_insufficient)
-                                }
-                                AmountResult.InvalidAmount -> {
-                                    
fragment.showError(R.string.receive_amount_invalid)
-                                }
-                                else -> {
-                                    onSubmit(
-                                        mutableMapOf<String, String>().apply {
-                                            if (summary != null) 
put("summary", summary!!)
-                                            if (amount != null) put("amount", 
amount!!.toJSONString())
-                                        }
-                                    )
-                                }
-                            }
-                        }
-                    },
-                ) {
-                    Text(stringResource(R.string.payment_create_order))
-                }
-            }
-        }
-        is PayStatus.Loading -> {
-            Box(
-                modifier = Modifier.fillMaxSize(),
-                contentAlignment = Alignment.Center,
-            ) { CircularProgressIndicator() }
-        }
-        is PayStatus.AlreadyPaid -> {
-            Box(
-                modifier = Modifier.fillMaxSize(),
-                contentAlignment = Alignment.Center,
-            ) {
-                Text(
-                    stringResource(R.string.payment_already_paid),
-                    style = MaterialTheme.typography.titleLarge,
-                    color = MaterialTheme.colorScheme.error,
-                )
-            }
-        }
-        else -> {}
-    }
-}
-
-@Composable
-@OptIn(ExperimentalMaterial3Api::class)
-private fun AmountField(
-    modifier: Modifier = Modifier,
-    currencies: List<String>,
-    amount: Amount,
-    onAmountChosen: (Amount) -> Unit,
-) {
-    Row(
-        modifier = modifier,
-    ) {
-        val amountText = if (amount.value == 0L) "" else 
amount.value.toString()
-        val currency = currencies.find { amount.currency == it } ?: 
currencies[0]
-        OutlinedTextField(
-            modifier = Modifier
-                .padding(end = 16.dp)
-                .weight(1f),
-            value = amountText,
-            placeholder = { Text("0") },
-            onValueChange = { input ->
-                if (input.isNotBlank()) {
-                    onAmountChosen(Amount.fromString(currency, input))
-                } else {
-                    onAmountChosen(Amount.zero(currency))
-                }
-            },
-            keyboardOptions = KeyboardOptions.Default.copy(keyboardType = 
KeyboardType.Decimal),
-            singleLine = true,
-            label = { Text(stringResource(R.string.send_amount)) },
-        )
-        CurrencyDropdown(
-            modifier = Modifier.weight(1f),
-            initialCurrency = currency,
-            currencies = currencies,
-            onCurrencyChanged = { c ->
-                onAmountChosen(Amount.fromString(c, amount.amountStr))
-            },
-        )
-    }
-}
\ No newline at end of file
diff --git a/wallet/src/main/java/net/taler/wallet/payment/PaymentManager.kt 
b/wallet/src/main/java/net/taler/wallet/payment/PaymentManager.kt
index c98e0b2..627c05d 100644
--- a/wallet/src/main/java/net/taler/wallet/payment/PaymentManager.kt
+++ b/wallet/src/main/java/net/taler/wallet/payment/PaymentManager.kt
@@ -116,8 +116,8 @@ class PaymentManager(
             mPayStatus.value = when (response) {
                 is PaymentPossibleResponse -> response.toPayStatusPrepared()
                 is InsufficientBalanceResponse -> InsufficientBalance(
-                    response.contractTerms,
-                    response.amountRaw
+                    contractTerms = response.contractTerms,
+                    amountRaw = response.amountRaw,
                 )
                 is AlreadyConfirmedResponse -> AlreadyPaid
             }

-- 
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]