Add SEPA max amount exceeded dialog.
This commit is contained in:
parent
43a13964bd
commit
95d7d26f11
10 changed files with 74 additions and 15 deletions
|
@ -14,6 +14,7 @@ import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers
|
|||
import io.reactivex.rxjava3.subjects.PublishSubject
|
||||
import org.signal.core.util.concurrent.LifecycleDisposable
|
||||
import org.signal.core.util.logging.Log
|
||||
import org.signal.core.util.money.FiatMoney
|
||||
import org.thoughtcrime.securesms.MainActivity
|
||||
import org.thoughtcrime.securesms.R
|
||||
import org.thoughtcrime.securesms.components.InputAwareLayout
|
||||
|
@ -286,6 +287,8 @@ class GiftFlowConfirmationFragment :
|
|||
|
||||
override fun onProcessorActionProcessed() = Unit
|
||||
|
||||
override fun showSepaEuroMaximumDialog(sepaEuroMaximum: FiatMoney) = error("Unsupported operation")
|
||||
|
||||
override fun onUserLaunchedAnExternalApplication() = Unit
|
||||
|
||||
override fun navigateToDonationPending(gatewayRequest: GatewayRequest) = error("Unsupported operation")
|
||||
|
|
|
@ -470,6 +470,15 @@ class DonateToSignalFragment :
|
|||
viewModel.refreshActiveSubscription()
|
||||
}
|
||||
|
||||
override fun showSepaEuroMaximumDialog(sepaEuroMaximum: FiatMoney) {
|
||||
val max = FiatMoneyUtil.format(resources, sepaEuroMaximum, FiatMoneyUtil.formatOptions().trimZerosAfterDecimal())
|
||||
MaterialAlertDialogBuilder(requireContext())
|
||||
.setTitle(R.string.DonateToSignal__donation_amount_too_high)
|
||||
.setMessage(getString(R.string.DonateToSignalFragment__you_can_send_up_to_s_via_bank_transfer, max))
|
||||
.setPositiveButton(android.R.string.ok, null)
|
||||
.show()
|
||||
}
|
||||
|
||||
override fun onUserLaunchedAnExternalApplication() = Unit
|
||||
|
||||
override fun navigateToDonationPending(gatewayRequest: GatewayRequest) {
|
||||
|
|
|
@ -36,7 +36,9 @@ import org.thoughtcrime.securesms.components.settings.app.subscription.errors.Do
|
|||
import org.thoughtcrime.securesms.components.settings.app.subscription.errors.DonationErrorParams
|
||||
import org.thoughtcrime.securesms.components.settings.app.subscription.errors.DonationErrorSource
|
||||
import org.thoughtcrime.securesms.keyvalue.SignalStore
|
||||
import org.thoughtcrime.securesms.payments.currency.CurrencyUtil
|
||||
import org.thoughtcrime.securesms.util.fragments.requireListener
|
||||
import java.math.BigDecimal
|
||||
import java.util.Currency
|
||||
|
||||
/**
|
||||
|
@ -77,8 +79,12 @@ class DonationCheckoutDelegate(
|
|||
registerGooglePayCallback()
|
||||
|
||||
fragment.setFragmentResultListener(GatewaySelectorBottomSheet.REQUEST_KEY) { _, bundle ->
|
||||
val response: GatewayResponse = bundle.getParcelableCompat(GatewaySelectorBottomSheet.REQUEST_KEY, GatewayResponse::class.java)!!
|
||||
handleGatewaySelectionResponse(response)
|
||||
if (bundle.containsKey(GatewaySelectorBottomSheet.FAILURE_KEY)) {
|
||||
callback.showSepaEuroMaximumDialog(FiatMoney(bundle.getSerializable(GatewaySelectorBottomSheet.SEPA_EURO_MAX) as BigDecimal, CurrencyUtil.EURO))
|
||||
} else {
|
||||
val response: GatewayResponse = bundle.getParcelableCompat(GatewaySelectorBottomSheet.REQUEST_KEY, GatewayResponse::class.java)!!
|
||||
handleGatewaySelectionResponse(response)
|
||||
}
|
||||
}
|
||||
|
||||
fragment.setFragmentResultListener(StripePaymentInProgressFragment.REQUEST_KEY) { _, bundle ->
|
||||
|
@ -342,5 +348,6 @@ class DonationCheckoutDelegate(
|
|||
fun navigateToBankTransferMandate(gatewayResponse: GatewayResponse)
|
||||
fun onPaymentComplete(gatewayRequest: GatewayRequest)
|
||||
fun onProcessorActionProcessed()
|
||||
fun showSepaEuroMaximumDialog(sepaEuroMaximum: FiatMoney)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -24,6 +24,7 @@ import org.thoughtcrime.securesms.components.settings.app.subscription.models.Pa
|
|||
import org.thoughtcrime.securesms.components.settings.configure
|
||||
import org.thoughtcrime.securesms.components.settings.models.IndeterminateLoadingCircle
|
||||
import org.thoughtcrime.securesms.payments.FiatMoneyUtil
|
||||
import org.thoughtcrime.securesms.payments.currency.CurrencyUtil
|
||||
import org.thoughtcrime.securesms.util.fragments.requireListener
|
||||
|
||||
/**
|
||||
|
@ -140,9 +141,18 @@ class GatewaySelectorBottomSheet : DSLSettingsBottomSheetFragment() {
|
|||
text = DSLSettingsText.from(R.string.GatewaySelectorBottomSheet__bank_transfer),
|
||||
icon = DSLSettingsIcon.from(R.drawable.bank_transfer),
|
||||
onClick = {
|
||||
findNavController().popBackStack()
|
||||
val response = GatewayResponse(GatewayResponse.Gateway.SEPA_DEBIT, args.request)
|
||||
setFragmentResult(REQUEST_KEY, bundleOf(REQUEST_KEY to response))
|
||||
if (state.sepaEuroMaximum != null &&
|
||||
args.request.fiat.currency == CurrencyUtil.EURO &&
|
||||
args.request.fiat.amount > state.sepaEuroMaximum.amount
|
||||
) {
|
||||
findNavController().popBackStack()
|
||||
|
||||
setFragmentResult(REQUEST_KEY, bundleOf(FAILURE_KEY to true, SEPA_EURO_MAX to state.sepaEuroMaximum.amount))
|
||||
} else {
|
||||
findNavController().popBackStack()
|
||||
val response = GatewayResponse(GatewayResponse.Gateway.SEPA_DEBIT, args.request)
|
||||
setFragmentResult(REQUEST_KEY, bundleOf(REQUEST_KEY to response))
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
||||
|
@ -164,6 +174,8 @@ class GatewaySelectorBottomSheet : DSLSettingsBottomSheetFragment() {
|
|||
|
||||
companion object {
|
||||
const val REQUEST_KEY = "payment_checkout_mode"
|
||||
const val FAILURE_KEY = "gateway_failure"
|
||||
const val SEPA_EURO_MAX = "sepa_euro_max"
|
||||
|
||||
fun DSLConfiguration.presentTitleAndSubtitle(context: Context, request: GatewayRequest) {
|
||||
when (request.donateToSignalType) {
|
||||
|
|
|
@ -1,7 +1,9 @@
|
|||
package org.thoughtcrime.securesms.components.settings.app.subscription.donate.gateway
|
||||
|
||||
import io.reactivex.rxjava3.core.Single
|
||||
import org.signal.core.util.money.FiatMoney
|
||||
import org.thoughtcrime.securesms.components.settings.app.subscription.getAvailablePaymentMethods
|
||||
import org.thoughtcrime.securesms.payments.currency.CurrencyUtil
|
||||
import org.whispersystems.signalservice.api.services.DonationsService
|
||||
import org.whispersystems.signalservice.internal.push.DonationsConfiguration
|
||||
import java.util.Locale
|
||||
|
@ -9,12 +11,12 @@ import java.util.Locale
|
|||
class GatewaySelectorRepository(
|
||||
private val donationsService: DonationsService
|
||||
) {
|
||||
fun getAvailableGateways(currencyCode: String): Single<Set<GatewayResponse.Gateway>> {
|
||||
fun getAvailableGatewayConfiguration(currencyCode: String): Single<GatewayConfiguration> {
|
||||
return Single.fromCallable {
|
||||
donationsService.getDonationsConfiguration(Locale.getDefault())
|
||||
}.flatMap { it.flattenResult() }
|
||||
.map { configuration ->
|
||||
configuration.getAvailablePaymentMethods(currencyCode).map {
|
||||
val available = configuration.getAvailablePaymentMethods(currencyCode).map {
|
||||
when (it) {
|
||||
DonationsConfiguration.PAYPAL -> listOf(GatewayResponse.Gateway.PAYPAL)
|
||||
DonationsConfiguration.CARD -> listOf(GatewayResponse.Gateway.CREDIT_CARD, GatewayResponse.Gateway.GOOGLE_PAY)
|
||||
|
@ -23,6 +25,16 @@ class GatewaySelectorRepository(
|
|||
else -> listOf()
|
||||
}
|
||||
}.flatten().toSet()
|
||||
|
||||
GatewayConfiguration(
|
||||
availableGateways = available,
|
||||
sepaEuroMaximum = if (configuration.sepaMaximumEuros != null) FiatMoney(configuration.sepaMaximumEuros, CurrencyUtil.EURO) else null
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
data class GatewayConfiguration(
|
||||
val availableGateways: Set<GatewayResponse.Gateway>,
|
||||
val sepaEuroMaximum: FiatMoney?
|
||||
)
|
||||
}
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
package org.thoughtcrime.securesms.components.settings.app.subscription.donate.gateway
|
||||
|
||||
import org.signal.core.util.money.FiatMoney
|
||||
import org.thoughtcrime.securesms.badges.models.Badge
|
||||
|
||||
data class GatewaySelectorState(
|
||||
|
@ -10,5 +11,6 @@ data class GatewaySelectorState(
|
|||
val isPayPalAvailable: Boolean = false,
|
||||
val isCreditCardAvailable: Boolean = false,
|
||||
val isSEPADebitAvailable: Boolean = false,
|
||||
val isIDEALAvailable: Boolean = false
|
||||
val isIDEALAvailable: Boolean = false,
|
||||
val sepaEuroMaximum: FiatMoney? = null
|
||||
)
|
||||
|
|
|
@ -36,17 +36,18 @@ class GatewaySelectorViewModel(
|
|||
|
||||
init {
|
||||
val isGooglePayAvailable = repository.isGooglePayAvailable().toSingleDefault(true).onErrorReturnItem(false)
|
||||
val availabilitySet = gatewaySelectorRepository.getAvailableGateways(currencyCode = args.request.currencyCode)
|
||||
disposables += Single.zip(isGooglePayAvailable, availabilitySet, ::Pair).subscribeBy { (googlePayAvailable, gatewaysAvailable) ->
|
||||
val gatewayConfiguration = gatewaySelectorRepository.getAvailableGatewayConfiguration(currencyCode = args.request.currencyCode)
|
||||
disposables += Single.zip(isGooglePayAvailable, gatewayConfiguration, ::Pair).subscribeBy { (googlePayAvailable, gatewayConfiguration) ->
|
||||
SignalStore.donationsValues().isGooglePayReady = googlePayAvailable
|
||||
store.update {
|
||||
it.copy(
|
||||
loading = false,
|
||||
isCreditCardAvailable = it.isCreditCardAvailable && gatewaysAvailable.contains(GatewayResponse.Gateway.CREDIT_CARD),
|
||||
isGooglePayAvailable = it.isGooglePayAvailable && googlePayAvailable && gatewaysAvailable.contains(GatewayResponse.Gateway.GOOGLE_PAY),
|
||||
isPayPalAvailable = it.isPayPalAvailable && gatewaysAvailable.contains(GatewayResponse.Gateway.PAYPAL),
|
||||
isSEPADebitAvailable = it.isSEPADebitAvailable && gatewaysAvailable.contains(GatewayResponse.Gateway.SEPA_DEBIT),
|
||||
isIDEALAvailable = it.isIDEALAvailable && gatewaysAvailable.contains(GatewayResponse.Gateway.IDEAL)
|
||||
isCreditCardAvailable = it.isCreditCardAvailable && gatewayConfiguration.availableGateways.contains(GatewayResponse.Gateway.CREDIT_CARD),
|
||||
isGooglePayAvailable = it.isGooglePayAvailable && googlePayAvailable && gatewayConfiguration.availableGateways.contains(GatewayResponse.Gateway.GOOGLE_PAY),
|
||||
isPayPalAvailable = it.isPayPalAvailable && gatewayConfiguration.availableGateways.contains(GatewayResponse.Gateway.PAYPAL),
|
||||
isSEPADebitAvailable = it.isSEPADebitAvailable && gatewayConfiguration.availableGateways.contains(GatewayResponse.Gateway.SEPA_DEBIT),
|
||||
isIDEALAvailable = it.isIDEALAvailable && gatewayConfiguration.availableGateways.contains(GatewayResponse.Gateway.IDEAL),
|
||||
sepaEuroMaximum = gatewayConfiguration.sepaEuroMaximum
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -15,6 +15,8 @@ import java.util.Locale;
|
|||
*/
|
||||
public final class CurrencyUtil {
|
||||
|
||||
public static Currency EURO = Currency.getInstance("EUR");
|
||||
|
||||
public static @Nullable Currency getCurrencyByCurrencyCode(@NonNull String currencyCode) {
|
||||
try {
|
||||
return Currency.getInstance(currencyCode);
|
||||
|
|
|
@ -5855,6 +5855,10 @@
|
|||
<string name="DonateToSignalFragment__your_payment_is_still_being_processed_onetime">Your donation is still being processed. This can take a few minutes depending on your connection. Please wait until this payment completes before making another donation.</string>
|
||||
<!-- Dialog body when a user opens the manage donations main screen and they have a pending iDEAL donation -->
|
||||
<string name="DonateToSignalFragment__your_ideal_payment_is_still_processing">Your iDEAL donation is still processing. Check your banking app to approve your payment before making another donation.</string>
|
||||
<!-- Dialog title shown when a user tries to donate an amount higher than is allowed for a given payment method. -->
|
||||
<string name="DonateToSignal__donation_amount_too_high">Donation amount too high</string>
|
||||
<!-- Dialog body shown when a user tries to donate an amount higher than is allowed for a given payment method, place holder is the maximum -->
|
||||
<string name="DonateToSignalFragment__you_can_send_up_to_s_via_bank_transfer">You can send up to %1$s via bank transfer. Try a different amount or a different payment method.</string>
|
||||
|
||||
<!-- Donation pill toggle monthly text -->
|
||||
<string name="DonationPillToggle__monthly">Monthly</string>
|
||||
|
|
|
@ -31,6 +31,9 @@ public class DonationsConfiguration {
|
|||
@JsonProperty("levels")
|
||||
private Map<Integer, LevelConfiguration> levels;
|
||||
|
||||
@JsonProperty("sepaMaximumEuros")
|
||||
private BigDecimal sepaMaximumEuros;
|
||||
|
||||
public static class CurrencyConfiguration {
|
||||
@JsonProperty("minimum")
|
||||
private BigDecimal minimum;
|
||||
|
@ -84,4 +87,8 @@ public class DonationsConfiguration {
|
|||
public Map<Integer, LevelConfiguration> getLevels() {
|
||||
return levels;
|
||||
}
|
||||
|
||||
public BigDecimal getSepaMaximumEuros() {
|
||||
return sepaMaximumEuros;
|
||||
}
|
||||
}
|
Loading…
Add table
Reference in a new issue