[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.
- [taler-taler-android] branch master updated (d7196a0 -> e7e2763), gnunet, 2023/09/26
- [taler-taler-android] 03/14: [wallet] first cleanup of payment template work,
gnunet <=
- [taler-taler-android] 01/14: [wallet] Initial version of template support, gnunet, 2023/09/26
- [taler-taler-android] 10/14: [wallet] Improved AmountInputField with a VisualTransformation, gnunet, 2023/09/26
- [taler-taler-android] 11/14: [wallet] fix: AmountInputField reacts to external changes, gnunet, 2023/09/26
- [taler-taler-android] 05/14: [wallet] add some potential TODOs for pay templates, gnunet, 2023/09/26
- [taler-taler-android] 09/14: [wallet] Support 0.x fractions in AmountInputField, gnunet, 2023/09/26
- [taler-taler-android] 04/14: [wallet] Improve internal logic of templates, gnunet, 2023/09/26
- [taler-taler-android] 08/14: [wallet] Refactor amount input into single composable, gnunet, 2023/09/26
- [taler-taler-android] 02/14: [wallet] Improved templates UX and PoS confirmation codes, gnunet, 2023/09/26
- [taler-taler-android] 14/14: [wallet] Fix back navigation after template prompt., gnunet, 2023/09/26
- [taler-taler-android] 13/14: [wallet] simplify pay templates, gnunet, 2023/09/26