From c17d6c2334964a2fd35b87fae2a00597945d5704 Mon Sep 17 00:00:00 2001 From: Alex Hart Date: Wed, 11 Oct 2023 08:55:18 -0400 Subject: [PATCH] Implement gateway ordering. --- .../donate/gateway/GatewayOrderStrategy.kt | 47 ++++++ .../gateway/GatewaySelectorBottomSheet.kt | 136 +++++++++++------- .../donate/gateway/GatewaySelectorState.kt | 1 + .../gateway/GatewaySelectorViewModel.kt | 1 + 4 files changed, 131 insertions(+), 54 deletions(-) create mode 100644 app/src/main/java/org/thoughtcrime/securesms/components/settings/app/subscription/donate/gateway/GatewayOrderStrategy.kt diff --git a/app/src/main/java/org/thoughtcrime/securesms/components/settings/app/subscription/donate/gateway/GatewayOrderStrategy.kt b/app/src/main/java/org/thoughtcrime/securesms/components/settings/app/subscription/donate/gateway/GatewayOrderStrategy.kt new file mode 100644 index 0000000000..d1e37f2cf0 --- /dev/null +++ b/app/src/main/java/org/thoughtcrime/securesms/components/settings/app/subscription/donate/gateway/GatewayOrderStrategy.kt @@ -0,0 +1,47 @@ +/* + * Copyright 2023 Signal Messenger, LLC + * SPDX-License-Identifier: AGPL-3.0-only + */ + +package org.thoughtcrime.securesms.components.settings.app.subscription.donate.gateway + +import com.google.i18n.phonenumbers.PhoneNumberUtil +import org.signal.core.util.orNull +import org.thoughtcrime.securesms.recipients.Recipient + +sealed interface GatewayOrderStrategy { + + val orderedGateways: Set + + private object Default : GatewayOrderStrategy { + override val orderedGateways: Set = setOf( + GatewayResponse.Gateway.CREDIT_CARD, + GatewayResponse.Gateway.PAYPAL, + GatewayResponse.Gateway.GOOGLE_PAY, + GatewayResponse.Gateway.SEPA_DEBIT + ) + } + + private object NorthAmerica : GatewayOrderStrategy { + + override val orderedGateways: Set = setOf( + GatewayResponse.Gateway.GOOGLE_PAY, + GatewayResponse.Gateway.PAYPAL, + GatewayResponse.Gateway.CREDIT_CARD, + GatewayResponse.Gateway.SEPA_DEBIT + ) + } + + companion object { + fun getStrategy(): GatewayOrderStrategy { + val self = Recipient.self() + val e164 = self.e164.orNull() ?: return Default + + return if (PhoneNumberUtil.getInstance().parse(e164, "").countryCode == 1) { + NorthAmerica + } else { + Default + } + } + } +} diff --git a/app/src/main/java/org/thoughtcrime/securesms/components/settings/app/subscription/donate/gateway/GatewaySelectorBottomSheet.kt b/app/src/main/java/org/thoughtcrime/securesms/components/settings/app/subscription/donate/gateway/GatewaySelectorBottomSheet.kt index be00df20b9..0b83bfc3c8 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/components/settings/app/subscription/donate/gateway/GatewaySelectorBottomSheet.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/components/settings/app/subscription/donate/gateway/GatewaySelectorBottomSheet.kt @@ -72,66 +72,94 @@ class GatewaySelectorBottomSheet : DSLSettingsBottomSheetFragment() { return@configure } - if (state.isGooglePayAvailable) { - customPref( - GooglePayButton.Model( - isEnabled = true, - onClick = { - findNavController().popBackStack() - val response = GatewayResponse(GatewayResponse.Gateway.GOOGLE_PAY, args.request) - setFragmentResult(REQUEST_KEY, bundleOf(REQUEST_KEY to response)) - } - ) - ) - } - - if (state.isPayPalAvailable) { - space(8.dp) - - customPref( - PayPalButton.Model( - onClick = { - findNavController().popBackStack() - val response = GatewayResponse(GatewayResponse.Gateway.PAYPAL, args.request) - setFragmentResult(REQUEST_KEY, bundleOf(REQUEST_KEY to response)) - }, - isEnabled = true - ) - ) - } - - if (state.isCreditCardAvailable) { - space(8.dp) - - primaryButton( - text = DSLSettingsText.from(R.string.GatewaySelectorBottomSheet__credit_or_debit_card), - icon = DSLSettingsIcon.from(R.drawable.credit_card, R.color.signal_colorOnPrimary), - onClick = { - findNavController().popBackStack() - val response = GatewayResponse(GatewayResponse.Gateway.CREDIT_CARD, args.request) - setFragmentResult(REQUEST_KEY, bundleOf(REQUEST_KEY to response)) - } - ) - } - - if (state.isSEPADebitAvailable) { - space(8.dp) - - tonalButton( - 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)) - } - ) + state.gatewayOrderStrategy.orderedGateways.forEachIndexed { index, gateway -> + val isFirst = index == 0 + when (gateway) { + GatewayResponse.Gateway.GOOGLE_PAY -> renderGooglePayButton(state, isFirst) + GatewayResponse.Gateway.PAYPAL -> renderPayPalButton(state, isFirst) + GatewayResponse.Gateway.CREDIT_CARD -> renderCreditCardButton(state, isFirst) + GatewayResponse.Gateway.SEPA_DEBIT -> renderSEPADebitButton(state, isFirst) + } } space(16.dp) } } + private fun DSLConfiguration.renderGooglePayButton(state: GatewaySelectorState, isFirstButton: Boolean) { + if (state.isGooglePayAvailable) { + if (!isFirstButton) { + space(8.dp) + } + + customPref( + GooglePayButton.Model( + isEnabled = true, + onClick = { + findNavController().popBackStack() + val response = GatewayResponse(GatewayResponse.Gateway.GOOGLE_PAY, args.request) + setFragmentResult(REQUEST_KEY, bundleOf(REQUEST_KEY to response)) + } + ) + ) + } + } + + private fun DSLConfiguration.renderPayPalButton(state: GatewaySelectorState, isFirstButton: Boolean) { + if (state.isPayPalAvailable) { + if (!isFirstButton) { + space(8.dp) + } + + customPref( + PayPalButton.Model( + onClick = { + findNavController().popBackStack() + val response = GatewayResponse(GatewayResponse.Gateway.PAYPAL, args.request) + setFragmentResult(REQUEST_KEY, bundleOf(REQUEST_KEY to response)) + }, + isEnabled = true + ) + ) + } + } + + private fun DSLConfiguration.renderCreditCardButton(state: GatewaySelectorState, isFirstButton: Boolean) { + if (state.isCreditCardAvailable) { + if (!isFirstButton) { + space(8.dp) + } + + primaryButton( + text = DSLSettingsText.from(R.string.GatewaySelectorBottomSheet__credit_or_debit_card), + icon = DSLSettingsIcon.from(R.drawable.credit_card, R.color.signal_colorOnCustom), + onClick = { + findNavController().popBackStack() + val response = GatewayResponse(GatewayResponse.Gateway.CREDIT_CARD, args.request) + setFragmentResult(REQUEST_KEY, bundleOf(REQUEST_KEY to response)) + } + ) + } + } + + private fun DSLConfiguration.renderSEPADebitButton(state: GatewaySelectorState, isFirstButton: Boolean) { + if (state.isSEPADebitAvailable) { + if (!isFirstButton) { + space(8.dp) + } + + tonalButton( + 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)) + } + ) + } + } + companion object { const val REQUEST_KEY = "payment_checkout_mode" diff --git a/app/src/main/java/org/thoughtcrime/securesms/components/settings/app/subscription/donate/gateway/GatewaySelectorState.kt b/app/src/main/java/org/thoughtcrime/securesms/components/settings/app/subscription/donate/gateway/GatewaySelectorState.kt index 5ac7a58ee5..ea05aceaad 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/components/settings/app/subscription/donate/gateway/GatewaySelectorState.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/components/settings/app/subscription/donate/gateway/GatewaySelectorState.kt @@ -3,6 +3,7 @@ package org.thoughtcrime.securesms.components.settings.app.subscription.donate.g import org.thoughtcrime.securesms.badges.models.Badge data class GatewaySelectorState( + val gatewayOrderStrategy: GatewayOrderStrategy, val loading: Boolean = true, val badge: Badge, val isGooglePayAvailable: Boolean = false, diff --git a/app/src/main/java/org/thoughtcrime/securesms/components/settings/app/subscription/donate/gateway/GatewaySelectorViewModel.kt b/app/src/main/java/org/thoughtcrime/securesms/components/settings/app/subscription/donate/gateway/GatewaySelectorViewModel.kt index 6061cd5134..dc88aeba80 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/components/settings/app/subscription/donate/gateway/GatewaySelectorViewModel.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/components/settings/app/subscription/donate/gateway/GatewaySelectorViewModel.kt @@ -21,6 +21,7 @@ class GatewaySelectorViewModel( private val store = RxStore( GatewaySelectorState( + gatewayOrderStrategy = GatewayOrderStrategy.getStrategy(), badge = args.request.badge, isGooglePayAvailable = InAppDonations.isPaymentSourceAvailable(PaymentSourceType.Stripe.GooglePay, args.request.donateToSignalType), isCreditCardAvailable = InAppDonations.isPaymentSourceAvailable(PaymentSourceType.Stripe.CreditCard, args.request.donateToSignalType),