summaryrefslogtreecommitdiff
path: root/wallet/src/main/java/net/taler/wallet/payment/PayTemplateOrderComposable.kt
diff options
context:
space:
mode:
Diffstat (limited to 'wallet/src/main/java/net/taler/wallet/payment/PayTemplateOrderComposable.kt')
-rw-r--r--wallet/src/main/java/net/taler/wallet/payment/PayTemplateOrderComposable.kt110
1 files changed, 77 insertions, 33 deletions
diff --git a/wallet/src/main/java/net/taler/wallet/payment/PayTemplateOrderComposable.kt b/wallet/src/main/java/net/taler/wallet/payment/PayTemplateOrderComposable.kt
index d6131c7..2febfbb 100644
--- a/wallet/src/main/java/net/taler/wallet/payment/PayTemplateOrderComposable.kt
+++ b/wallet/src/main/java/net/taler/wallet/payment/PayTemplateOrderComposable.kt
@@ -24,84 +24,118 @@ import androidx.compose.material3.Button
import androidx.compose.material3.OutlinedTextField
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
+import androidx.compose.runtime.LaunchedEffect
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.Companion.End
+import androidx.compose.ui.ExperimentalComposeUiApi
import androidx.compose.ui.Modifier
+import androidx.compose.ui.focus.FocusRequester
+import androidx.compose.ui.focus.focusRequester
+import androidx.compose.ui.focus.onFocusChanged
+import androidx.compose.ui.platform.LocalSoftwareKeyboardController
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import net.taler.common.Amount
+import net.taler.common.RelativeTime
import net.taler.wallet.AmountResult
import net.taler.wallet.R
import net.taler.wallet.compose.AmountInputField
import net.taler.wallet.compose.TalerSurface
import net.taler.wallet.deposit.CurrencyDropdown
+@OptIn(ExperimentalComposeUiApi::class)
@Composable
fun PayTemplateOrderComposable(
- currencies: List<String>, // assumed to have size > 0
- defaultSummary: String? = null,
- amountStatus: AmountFieldStatus,
+ usableCurrencies: List<String>, // non-empty intersection between the stored currencies and the ones supported by the merchant
+ templateDetails: WalletTemplateDetails,
onCreateAmount: (String, String) -> AmountResult,
onError: (msgRes: Int) -> Unit,
- onSubmit: (summary: String?, amount: Amount?) -> Unit,
+ onSubmit: (params: TemplateParams) -> Unit,
) {
- val amountDefault = amountStatus as? AmountFieldStatus.Default
+ val defaultSummary = templateDetails.defaultSummary
+ val defaultAmount = templateDetails.defaultAmount
+ val defaultCurrency = templateDetails.defaultCurrency
- var summary by remember { mutableStateOf(defaultSummary) }
- var currency by remember { mutableStateOf(amountDefault?.currency ?: currencies[0]) }
- var amount by remember { mutableStateOf(amountDefault?.amountStr ?: "0") }
+ val summaryFocusRequester = remember { FocusRequester() }
+ val keyboardController = LocalSoftwareKeyboardController.current
+
+ var summary by remember { mutableStateOf(defaultSummary ?: "") }
+ var currency by remember { mutableStateOf(defaultCurrency ?: usableCurrencies[0]) }
+ var amount by remember { mutableStateOf(defaultAmount?.amountStr ?: "0") }
Column(horizontalAlignment = End) {
- if (defaultSummary != null) OutlinedTextField(
+ OutlinedTextField(
modifier = Modifier
.padding(horizontal = 16.dp)
- .fillMaxWidth(),
- value = summary ?: "",
- isError = summary.isNullOrBlank(),
+ .fillMaxWidth()
+ .focusRequester(summaryFocusRequester)
+ .onFocusChanged {
+ if (it.isFocused) {
+ keyboardController?.show()
+ }
+ },
+ value = summary,
+ isError = templateDetails.isSummaryEditable() && summary.isBlank(),
onValueChange = { summary = it },
singleLine = true,
+ readOnly = !templateDetails.isSummaryEditable(),
label = { Text(stringResource(R.string.withdraw_manual_ready_subject)) },
)
- if (amountDefault != null) AmountField(
+
+ AmountField(
modifier = Modifier
.padding(16.dp)
.fillMaxWidth(),
amount = amount,
currency = currency,
- currencies = currencies,
- fixedCurrency = (amountStatus as? AmountFieldStatus.Default)?.currency != null,
+ currencies = usableCurrencies,
+ readOnlyCurrency = !templateDetails.isCurrencyEditable(usableCurrencies),
+ readOnlyAmount = !templateDetails.isAmountEditable(),
onAmountChosen = { a, c ->
amount = a
currency = c
},
)
+
Button(
modifier = Modifier.padding(16.dp),
- enabled = defaultSummary == null || !summary.isNullOrBlank(),
+ enabled = !templateDetails.isSummaryEditable() || summary.isNotBlank(),
onClick = {
when (val res = onCreateAmount(amount, currency)) {
is AmountResult.InsufficientBalance -> onError(R.string.payment_balance_insufficient)
- is AmountResult.InvalidAmount -> onError(R.string.receive_amount_invalid)
- is AmountResult.Success -> onSubmit(summary, res.amount)
+ is AmountResult.InvalidAmount -> onError(R.string.amount_invalid)
+ // NOTE: it is important to nullify non-editable values!
+ is AmountResult.Success -> onSubmit(TemplateParams(
+ summary = if (templateDetails.isSummaryEditable()) summary else null,
+ amount = if(templateDetails.isAmountEditable()) res.amount else null,
+ ))
}
},
) {
Text(stringResource(R.string.payment_create_order))
}
}
+
+ LaunchedEffect(Unit) {
+ if (templateDetails.isSummaryEditable()
+ && templateDetails.defaultSummary == null) {
+ summaryFocusRequester.requestFocus()
+ }
+ }
}
@Composable
private fun AmountField(
modifier: Modifier = Modifier,
currencies: List<String>,
- fixedCurrency: Boolean,
amount: String,
currency: String,
+ readOnlyAmount: Boolean = true,
+ readOnlyCurrency: Boolean = true,
onAmountChosen: (amount: String, currency: String) -> Unit,
) {
Row(
@@ -113,30 +147,42 @@ private fun AmountField(
.weight(1f),
value = amount,
onValueChange = { onAmountChosen(it, currency) },
- label = { Text(stringResource(R.string.send_amount)) }
+ label = { Text(stringResource(R.string.amount_send)) },
+ readOnly = readOnlyAmount,
)
+
CurrencyDropdown(
modifier = Modifier.weight(1f),
initialCurrency = currency,
currencies = currencies,
onCurrencyChanged = { onAmountChosen(amount, it) },
- readOnly = fixedCurrency,
+ readOnly = readOnlyCurrency,
)
}
}
+val defaultTemplateDetails = WalletTemplateDetails(
+ templateContract = TemplateContractDetails(
+ minimumAge = 18,
+ payDuration = RelativeTime.forever(),
+ ),
+ editableDefaults = TemplateContractDetailsDefaults(
+ summary = "Donation",
+ amount = Amount.fromJSONString("KUDOS:10.0"),
+ ),
+)
+
@Preview
@Composable
fun PayTemplateDefaultPreview() {
TalerSurface {
PayTemplateOrderComposable(
- defaultSummary = "Donation",
- amountStatus = AmountFieldStatus.Default("20", "ARS"),
- currencies = listOf("KUDOS", "ARS"),
+ templateDetails = defaultTemplateDetails,
+ usableCurrencies = listOf("KUDOS", "ARS"),
onCreateAmount = { text, currency ->
AmountResult.Success(amount = Amount.fromString(currency, text))
},
- onSubmit = { _, _ -> },
+ onSubmit = { _ -> },
onError = { },
)
}
@@ -147,13 +193,12 @@ fun PayTemplateDefaultPreview() {
fun PayTemplateFixedAmountPreview() {
TalerSurface {
PayTemplateOrderComposable(
- defaultSummary = "default summary",
- amountStatus = AmountFieldStatus.FixedAmount,
- currencies = listOf("KUDOS", "ARS"),
+ templateDetails = defaultTemplateDetails,
+ usableCurrencies = listOf("KUDOS", "ARS"),
onCreateAmount = { text, currency ->
AmountResult.Success(amount = Amount.fromString(currency, text))
},
- onSubmit = { _, _ -> },
+ onSubmit = { _ -> },
onError = { },
)
}
@@ -164,13 +209,12 @@ fun PayTemplateFixedAmountPreview() {
fun PayTemplateBlankSubjectPreview() {
TalerSurface {
PayTemplateOrderComposable(
- defaultSummary = "",
- amountStatus = AmountFieldStatus.FixedAmount,
- currencies = listOf("KUDOS", "ARS"),
+ templateDetails = defaultTemplateDetails,
+ usableCurrencies = listOf("KUDOS", "ARS"),
onCreateAmount = { text, currency ->
AmountResult.Success(amount = Amount.fromString(currency, text))
},
- onSubmit = { _, _ -> },
+ onSubmit = { _ -> },
onError = { },
)
}