diff options
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.kt | 110 |
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 = { }, ) } |