taler-android

Android apps for GNU Taler (wallet, PoS, cashier)
Log | Files | Refs | README | LICENSE

commit a30a93992f3acc7295095dd684395f43b874bf55
parent dc86881ab67c826c326b9a1c9384320427e79702
Author: Iván Ávalos <avalos@disroot.org>
Date:   Fri,  2 May 2025 13:53:21 +0200

[wallet] unify cta-withdraw-review with iOS

bug 0009783

Diffstat:
Mwallet/src/main/java/net/taler/wallet/withdraw/PromptWithdrawFragment.kt | 77+++++++++++------------------------------------------------------------------
Mwallet/src/main/java/net/taler/wallet/withdraw/WithdrawalShowInfo.kt | 108+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++------
Mwallet/src/main/res/values/strings.xml | 6++++--
3 files changed, 116 insertions(+), 75 deletions(-)

diff --git a/wallet/src/main/java/net/taler/wallet/withdraw/PromptWithdrawFragment.kt b/wallet/src/main/java/net/taler/wallet/withdraw/PromptWithdrawFragment.kt @@ -20,6 +20,7 @@ import android.os.Bundle import android.view.LayoutInflater import android.view.View import android.view.ViewGroup +import androidx.appcompat.app.AppCompatActivity import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.padding @@ -33,7 +34,6 @@ import androidx.compose.runtime.remember import androidx.compose.ui.Alignment.Companion.Center import androidx.compose.ui.Modifier import androidx.compose.ui.platform.ComposeView -import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp import androidx.core.os.bundleOf import androidx.fragment.app.Fragment @@ -51,12 +51,10 @@ import net.taler.common.EventObserver import net.taler.wallet.MainViewModel import net.taler.wallet.R import net.taler.wallet.backend.TalerErrorInfo -import net.taler.wallet.balances.ScopeInfo import net.taler.wallet.compose.LoadingScreen import net.taler.wallet.compose.TalerSurface import net.taler.wallet.compose.collectAsStateLifecycleAware import net.taler.wallet.exchanges.ExchangeItem -import net.taler.wallet.exchanges.ExchangeTosStatus import net.taler.wallet.exchanges.SelectExchangeDialogFragment import net.taler.wallet.withdraw.WithdrawStatus.Status.AlreadyConfirmed import net.taler.wallet.withdraw.WithdrawStatus.Status.Error @@ -67,7 +65,6 @@ import net.taler.wallet.withdraw.WithdrawStatus.Status.None import net.taler.wallet.withdraw.WithdrawStatus.Status.Success import net.taler.wallet.withdraw.WithdrawStatus.Status.TosReviewRequired import net.taler.wallet.withdraw.WithdrawStatus.Status.Updating -import net.taler.wallet.withdraw.WithdrawalOperationStatusFlag.Pending class PromptWithdrawFragment: Fragment() { private val model: MainViewModel by activityViewModels() @@ -136,6 +133,16 @@ class PromptWithdrawFragment: Fragment() { } } + LaunchedEffect(currencySpec, amount) { + (requireActivity() as AppCompatActivity).apply { + supportActionBar?.title = currencySpec?.symbol?.let { symbol -> + getString(R.string.nav_prompt_withdraw_currency, symbol) + } ?: amount?.currency?.let { currency -> + getString(R.string.nav_prompt_withdraw_currency, currency) + } ?: getString(R.string.nav_prompt_withdraw) + } + } + TalerSurface { status.let { s -> if (defaultCurrency == null) { @@ -287,66 +294,4 @@ fun WithdrawalError( color = MaterialTheme.colorScheme.error, ) } -} - -@Preview -@Composable -fun WithdrawalShowInfoPreview() { - TalerSurface { - WithdrawalShowInfo( - WithdrawStatus( - status = Updating, - talerWithdrawUri = "taler://", - currency = "KUDOS", - exchangeBaseUrl = "exchange.head.taler.net", - transactionId = "tx:343434", - error = null, - uriInfo = WithdrawalDetailsForUri( - amount = null, - currency = "KUDOS", - editableAmount = true, - status = Pending, - maxAmount = Amount.fromJSONString("KUDOS:10"), - wireFee = Amount.fromJSONString("KUDOS:0.2"), - defaultExchangeBaseUrl = "exchange.head.taler.net", - possibleExchanges = listOf( - ExchangeItem( - exchangeBaseUrl = "exchange.demo.taler.net", - currency = "KUDOS", - paytoUris = emptyList(), - scopeInfo = null, - tosStatus = ExchangeTosStatus.Accepted, - ), - ExchangeItem( - exchangeBaseUrl = "exchange.head.taler.net", - currency = "KUDOS", - paytoUris = emptyList(), - scopeInfo = null, - tosStatus = ExchangeTosStatus.Accepted, - ), - ), - ), - amountInfo = WithdrawalDetailsForAmount( - tosAccepted = true, - amountRaw = Amount.fromJSONString("KUDOS:10.1"), - amountEffective = Amount.fromJSONString("KUDOS:10.2"), - withdrawalAccountsList = emptyList(), - ageRestrictionOptions = listOf(18, 23), - scopeInfo = ScopeInfo.Exchange( - currency = "KUDOS", - url = "exchange.head.taler.net", - ), - ) - ), - devMode = true, - defaultCurrency = "KUDOS", - editableCurrency = true, - currencies = listOf("KUDOS", "TESTKUDOS", "NETZBON"), - spec = null, - onSelectExchange = {}, - onSelectAmount = {}, - onTosReview = {}, - onConfirm = {}, - ) - } } \ No newline at end of file diff --git a/wallet/src/main/java/net/taler/wallet/withdraw/WithdrawalShowInfo.kt b/wallet/src/main/java/net/taler/wallet/withdraw/WithdrawalShowInfo.kt @@ -46,14 +46,19 @@ import androidx.compose.ui.focus.FocusRequester import androidx.compose.ui.focus.focusRequester 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.CurrencySpecification import net.taler.wallet.R +import net.taler.wallet.balances.ScopeInfo import net.taler.wallet.cleanExchange import net.taler.wallet.compose.AmountCurrencyField import net.taler.wallet.compose.BottomButtonBox +import net.taler.wallet.compose.TalerSurface import net.taler.wallet.compose.WarningLabel +import net.taler.wallet.exchanges.ExchangeItem +import net.taler.wallet.exchanges.ExchangeTosStatus import net.taler.wallet.systemBarsPaddingBottom import net.taler.wallet.transactions.AmountType import net.taler.wallet.transactions.TransactionAmountComposable @@ -62,6 +67,7 @@ import net.taler.wallet.useDebounce import net.taler.wallet.withdraw.WithdrawStatus.Status.Error import net.taler.wallet.withdraw.WithdrawStatus.Status.TosReviewRequired import net.taler.wallet.withdraw.WithdrawStatus.Status.Updating +import net.taler.wallet.withdraw.WithdrawalOperationStatusFlag.Pending @Composable fun WithdrawalShowInfo( @@ -117,7 +123,12 @@ fun WithdrawalShowInfo( .fillMaxWidth(), horizontalAlignment = Alignment.CenterHorizontally, ) { - if (status.isCashAcceptor) { + if (status.status == TosReviewRequired) { + Text( + modifier = Modifier.padding(16.dp), + text = stringResource(R.string.withdraw_review_terms), + ) + } else if (status.isCashAcceptor) { WarningLabel( label = stringResource(R.string.withdraw_cash_acceptor), modifier = Modifier @@ -149,6 +160,10 @@ fun WithdrawalShowInfo( } }, ) + + LaunchedEffect(Unit) { + focusRequester.requestFocus() + } } else { TransactionAmountComposable( label = if (wireFee.isZero()) { @@ -170,7 +185,7 @@ fun WithdrawalShowInfo( return } - if (!wireFee.isZero()) { + if (status.status != TosReviewRequired && !wireFee.isZero()) { TransactionAmountComposable( label = stringResource(R.string.amount_fee), amount = wireFee, @@ -206,7 +221,7 @@ fun WithdrawalShowInfo( var expanded by remember { mutableStateOf(false) } - if (ageRestrictionOptions.isNotEmpty()) { + if (status.status != TosReviewRequired && ageRestrictionOptions.isNotEmpty()) { TransactionInfoComposable( label = stringResource(R.string.withdraw_restrict_age), info = selectedAge?.toString() @@ -271,10 +286,89 @@ fun WithdrawalShowInfo( } } } +} - LaunchedEffect(editableAmount) { - if (editableAmount) { - focusRequester.requestFocus() - } +private fun buildPreviewWithdrawStatus( + status: WithdrawStatus.Status, +) = WithdrawStatus( + status = status, + talerWithdrawUri = "taler://", + currency = "KUDOS", + exchangeBaseUrl = "exchange.head.taler.net", + transactionId = "tx:343434", + error = null, + uriInfo = WithdrawalDetailsForUri( + amount = null, + currency = "KUDOS", + editableAmount = true, + status = Pending, + maxAmount = Amount.fromJSONString("KUDOS:10"), + wireFee = Amount.fromJSONString("KUDOS:0.2"), + defaultExchangeBaseUrl = "exchange.head.taler.net", + possibleExchanges = listOf( + ExchangeItem( + exchangeBaseUrl = "exchange.demo.taler.net", + currency = "KUDOS", + paytoUris = emptyList(), + scopeInfo = null, + tosStatus = ExchangeTosStatus.Accepted, + ), + ExchangeItem( + exchangeBaseUrl = "exchange.head.taler.net", + currency = "KUDOS", + paytoUris = emptyList(), + scopeInfo = null, + tosStatus = ExchangeTosStatus.Accepted, + ), + ), + ), + amountInfo = WithdrawalDetailsForAmount( + tosAccepted = true, + amountRaw = Amount.fromJSONString("KUDOS:10.1"), + amountEffective = Amount.fromJSONString("KUDOS:10.2"), + withdrawalAccountsList = emptyList(), + ageRestrictionOptions = listOf(18, 23), + scopeInfo = ScopeInfo.Exchange( + currency = "KUDOS", + url = "exchange.head.taler.net", + ), + ) +) + +@Preview +@Composable +fun WithdrawalShowInfoUpdatingPreview() { + TalerSurface { + WithdrawalShowInfo( + status = buildPreviewWithdrawStatus(Updating), + devMode = true, + defaultCurrency = "KUDOS", + editableCurrency = true, + currencies = listOf("KUDOS", "TESTKUDOS", "NETZBON"), + spec = null, + onSelectExchange = {}, + onSelectAmount = {}, + onTosReview = {}, + onConfirm = {}, + ) + } +} + +@Preview +@Composable +fun WithdrawalShowInfoTosReviewPreview() { + TalerSurface { + WithdrawalShowInfo( + status = buildPreviewWithdrawStatus(TosReviewRequired), + devMode = true, + defaultCurrency = "KUDOS", + editableCurrency = true, + currencies = listOf("KUDOS", "TESTKUDOS", "NETZBON"), + spec = null, + onSelectExchange = {}, + onSelectAmount = {}, + onTosReview = {}, + onConfirm = {}, + ) } } \ No newline at end of file diff --git a/wallet/src/main/res/values/strings.xml b/wallet/src/main/res/values/strings.xml @@ -43,6 +43,7 @@ GNU Taler is immune against many types of fraud, such as phishing of credit card <string name="nav_exchange_fees">Provider fees</string> <string name="nav_exchange_tos">PSP\'s terms of service</string> <string name="nav_prompt_withdraw">Withdraw from bank</string> + <string name="nav_prompt_withdraw_currency">Withdraw %1$s</string> <!-- General --> @@ -276,7 +277,7 @@ GNU Taler is immune against many types of fraud, such as phishing of credit card <string name="withdraw_button_confirm">Confirm withdraw</string> <string name="withdraw_button_confirm_bank">Authorize in bank</string> <string name="withdraw_button_label">Withdraw</string> - <string name="withdraw_button_tos">Review terms</string> + <string name="withdraw_button_tos">Terms of service</string> <string name="withdraw_cash_acceptor">The amount to be withdrawn will be determined by the cash acceptor</string> <string name="withdraw_error_already_confirmed">Withdrawal is already confirmed</string> <string name="withdraw_error_message">Withdrawing is currently not possible. Please try again later!</string> @@ -298,9 +299,10 @@ GNU Taler is immune against many types of fraud, such as phishing of credit card <string name="withdraw_manual_ready_warning">Make sure to use the correct subject, otherwise the money will not arrive in this wallet.</string> <string name="withdraw_restrict_age">Restrict usage to age</string> <string name="withdraw_restrict_age_unrestricted">Unrestricted</string> + <string name="withdraw_review_terms">You must first accept the payment service\'s terms of service before you can withdraw electronic cash to your wallet.</string> <string name="withdraw_select_amount">Select amount</string> <string name="withdraw_subtitle">Select target bank account</string> - <string name="withdraw_title">Withdrawal</string> + <string name="withdraw_title">Withdraw</string> <string name="withdraw_waiting_confirm">Waiting for confirmation</string> <!-- Exchanges -->