diff --git a/app/src/main/java/org/thoughtcrime/securesms/badges/view/ViewBadgeBottomSheetDialogFragment.kt b/app/src/main/java/org/thoughtcrime/securesms/badges/view/ViewBadgeBottomSheetDialogFragment.kt index fceff079df..ececce800d 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/badges/view/ViewBadgeBottomSheetDialogFragment.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/badges/view/ViewBadgeBottomSheetDialogFragment.kt @@ -18,12 +18,12 @@ import org.thoughtcrime.securesms.badges.models.LargeBadge import org.thoughtcrime.securesms.components.FixedRoundedCornerBottomSheetDialogFragment import org.thoughtcrime.securesms.components.ViewBinderDelegate import org.thoughtcrime.securesms.components.settings.app.AppSettingsActivity +import org.thoughtcrime.securesms.components.settings.app.subscription.InAppDonations import org.thoughtcrime.securesms.databinding.ViewBadgeBottomSheetDialogFragmentBinding import org.thoughtcrime.securesms.recipients.Recipient import org.thoughtcrime.securesms.recipients.RecipientId import org.thoughtcrime.securesms.util.BottomSheetUtil import org.thoughtcrime.securesms.util.CommunicationActions -import org.thoughtcrime.securesms.util.PlayServicesUtil import org.thoughtcrime.securesms.util.ViewUtil import org.thoughtcrime.securesms.util.adapter.mapping.MappingAdapter import org.thoughtcrime.securesms.util.visible @@ -57,7 +57,7 @@ class ViewBadgeBottomSheetDialogFragment : FixedRoundedCornerBottomSheetDialogFr } @Suppress("CascadeIf") - if (PlayServicesUtil.getPlayServicesStatus(requireContext()) != PlayServicesUtil.PlayServicesStatus.SUCCESS) { + if (InAppDonations.hasAtLeastOnePaymentMethodAvailable()) { binding.noSupport.visible = true binding.action.icon = ContextCompat.getDrawable(requireContext(), R.drawable.ic_open_20) binding.action.setText(R.string.preferences__donate_to_signal) diff --git a/app/src/main/java/org/thoughtcrime/securesms/components/settings/app/AppSettingsFragment.kt b/app/src/main/java/org/thoughtcrime/securesms/components/settings/app/AppSettingsFragment.kt index e7ed71524c..837f6afe71 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/components/settings/app/AppSettingsFragment.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/components/settings/app/AppSettingsFragment.kt @@ -14,13 +14,13 @@ import org.thoughtcrime.securesms.components.settings.DSLSettingsIcon import org.thoughtcrime.securesms.components.settings.DSLSettingsText import org.thoughtcrime.securesms.components.settings.PreferenceModel import org.thoughtcrime.securesms.components.settings.PreferenceViewHolder +import org.thoughtcrime.securesms.components.settings.app.subscription.InAppDonations import org.thoughtcrime.securesms.components.settings.configure import org.thoughtcrime.securesms.keyvalue.SignalStore import org.thoughtcrime.securesms.phonenumbers.PhoneNumberFormatter import org.thoughtcrime.securesms.recipients.Recipient import org.thoughtcrime.securesms.stories.Stories.isFeatureFlagEnabled import org.thoughtcrime.securesms.util.FeatureFlags -import org.thoughtcrime.securesms.util.PlayServicesUtil import org.thoughtcrime.securesms.util.Util import org.thoughtcrime.securesms.util.adapter.mapping.LayoutFactory import org.thoughtcrime.securesms.util.adapter.mapping.MappingAdapter @@ -71,7 +71,7 @@ class AppSettingsFragment : DSLSettingsFragment(R.string.text_secure_normal__men } ) - if (PlayServicesUtil.getPlayServicesStatus(requireContext()) == PlayServicesUtil.PlayServicesStatus.SUCCESS) { + if (InAppDonations.hasAtLeastOnePaymentMethodAvailable()) { clickPref( title = DSLSettingsText.from(R.string.preferences__donate_to_signal), icon = DSLSettingsIcon.from(R.drawable.ic_heart_24), diff --git a/app/src/main/java/org/thoughtcrime/securesms/components/settings/app/subscription/InAppDonations.kt b/app/src/main/java/org/thoughtcrime/securesms/components/settings/app/subscription/InAppDonations.kt new file mode 100644 index 0000000000..e01e349845 --- /dev/null +++ b/app/src/main/java/org/thoughtcrime/securesms/components/settings/app/subscription/InAppDonations.kt @@ -0,0 +1,44 @@ +package org.thoughtcrime.securesms.components.settings.app.subscription + +import org.thoughtcrime.securesms.dependencies.ApplicationDependencies +import org.thoughtcrime.securesms.util.FeatureFlags +import org.thoughtcrime.securesms.util.PlayServicesUtil + +/** + * Helper object to determine in-app donations availability. + */ +object InAppDonations { + + /** + * The user is: + * + * - Able to use Credit Cards and is in a region where they are able to be accepted. + * - Able to access Google Play services (and thus possibly able to use Google Pay). + * - Able to use PayPal and is in a region where it is able to be accepted. + */ + fun hasAtLeastOnePaymentMethodAvailable(): Boolean { + return isCreditCardAvailable() || isPayPalAvailable() || isPlayServicesAvailable() + } + + /** + * Whether the user is in a region that supports credit cards, based off local phone number. + */ + fun isCreditCardAvailable(): Boolean { + return FeatureFlags.creditCardPayments() + } + + /** + * Whether the user is in a region that supports PayPal, based off local phone number. + */ + fun isPayPalAvailable(): Boolean { + return false + } + + /** + * Whether Play Services is available. This will *not* tell you whether a user has Google Pay set up, but is + * enough information to determine whether we can display Google Pay as an option. + */ + private fun isPlayServicesAvailable(): Boolean { + return PlayServicesUtil.getPlayServicesStatus(ApplicationDependencies.getApplication()) == PlayServicesUtil.PlayServicesStatus.SUCCESS + } +} diff --git a/app/src/main/java/org/thoughtcrime/securesms/components/settings/app/subscription/donate/DonateToSignalFragment.kt b/app/src/main/java/org/thoughtcrime/securesms/components/settings/app/subscription/donate/DonateToSignalFragment.kt index 9cc8077892..bc5fecf61b 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/components/settings/app/subscription/donate/DonateToSignalFragment.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/components/settings/app/subscription/donate/DonateToSignalFragment.kt @@ -34,6 +34,7 @@ import org.thoughtcrime.securesms.components.settings.DSLConfiguration import org.thoughtcrime.securesms.components.settings.DSLSettingsFragment import org.thoughtcrime.securesms.components.settings.DSLSettingsText import org.thoughtcrime.securesms.components.settings.app.subscription.DonationPaymentComponent +import org.thoughtcrime.securesms.components.settings.app.subscription.InAppDonations import org.thoughtcrime.securesms.components.settings.app.subscription.boost.Boost import org.thoughtcrime.securesms.components.settings.app.subscription.donate.card.CreditCardFragment import org.thoughtcrime.securesms.components.settings.app.subscription.donate.card.CreditCardResult @@ -53,7 +54,6 @@ import org.thoughtcrime.securesms.components.settings.configure import org.thoughtcrime.securesms.databinding.DonateToSignalFragmentBinding import org.thoughtcrime.securesms.payments.FiatMoneyUtil import org.thoughtcrime.securesms.subscription.Subscription -import org.thoughtcrime.securesms.util.FeatureFlags import org.thoughtcrime.securesms.util.LifecycleDisposable import org.thoughtcrime.securesms.util.Material3OnScrollHelper import org.thoughtcrime.securesms.util.Projection @@ -457,7 +457,7 @@ class DonateToSignalFragment : DSLSettingsFragment( } private fun launchCreditCard(gatewayResponse: GatewayResponse) { - if (FeatureFlags.creditCardPayments()) { + if (InAppDonations.isCreditCardAvailable()) { findNavController().safeNavigate(DonateToSignalFragmentDirections.actionDonateToSignalFragmentToCreditCardFragment(gatewayResponse.request)) } else { error("Credit cards are not currently enabled.") 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 23198366f8..cda080c66f 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 @@ -16,6 +16,7 @@ import org.thoughtcrime.securesms.components.settings.DSLSettingsIcon import org.thoughtcrime.securesms.components.settings.DSLSettingsText import org.thoughtcrime.securesms.components.settings.NO_TINT import org.thoughtcrime.securesms.components.settings.app.subscription.DonationPaymentComponent +import org.thoughtcrime.securesms.components.settings.app.subscription.InAppDonations import org.thoughtcrime.securesms.components.settings.app.subscription.donate.DonateToSignalType import org.thoughtcrime.securesms.components.settings.app.subscription.models.GooglePayButton import org.thoughtcrime.securesms.components.settings.configure @@ -81,7 +82,7 @@ class GatewaySelectorBottomSheet : DSLSettingsBottomSheetFragment() { // PayPal // Credit Card - if (state.isCreditCardAvailable) { + if (InAppDonations.isCreditCardAvailable()) { space(12.dp) primaryButton( 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 16878744d2..4a7ecc77cd 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 @@ -1,11 +1,8 @@ package org.thoughtcrime.securesms.components.settings.app.subscription.donate.gateway import org.thoughtcrime.securesms.badges.models.Badge -import org.thoughtcrime.securesms.util.FeatureFlags data class GatewaySelectorState( val badge: Badge, - val isGooglePayAvailable: Boolean = false, - val isPayPalAvailable: Boolean = false, - val isCreditCardAvailable: Boolean = FeatureFlags.creditCardPayments() + 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 6b2d905517..fcf8b37324 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 @@ -2,6 +2,8 @@ package org.thoughtcrime.securesms.components.settings.app.subscription.donate.g import androidx.lifecycle.ViewModel import androidx.lifecycle.ViewModelProvider +import io.reactivex.rxjava3.disposables.CompositeDisposable +import io.reactivex.rxjava3.kotlin.plusAssign import io.reactivex.rxjava3.kotlin.subscribeBy import org.thoughtcrime.securesms.components.settings.app.subscription.DonationPaymentRepository import org.thoughtcrime.securesms.util.rx.RxStore @@ -12,6 +14,7 @@ class GatewaySelectorViewModel( ) : ViewModel() { private val store = RxStore(GatewaySelectorState(args.request.badge)) + private val disposables = CompositeDisposable() val state = store.stateFlowable @@ -21,10 +24,11 @@ class GatewaySelectorViewModel( override fun onCleared() { store.dispose() + disposables.clear() } private fun checkIfGooglePayIsAvailable() { - repository.isGooglePayAvailable().subscribeBy( + disposables += repository.isGooglePayAvailable().subscribeBy( onComplete = { store.update { it.copy(isGooglePayAvailable = true) } }, diff --git a/app/src/main/java/org/thoughtcrime/securesms/megaphone/Megaphones.java b/app/src/main/java/org/thoughtcrime/securesms/megaphone/Megaphones.java index 2cd92124b8..aeb29df81d 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/megaphone/Megaphones.java +++ b/app/src/main/java/org/thoughtcrime/securesms/megaphone/Megaphones.java @@ -18,6 +18,7 @@ import org.signal.core.util.logging.Log; import org.thoughtcrime.securesms.R; import org.thoughtcrime.securesms.badges.models.Badge; import org.thoughtcrime.securesms.components.settings.app.AppSettingsActivity; +import org.thoughtcrime.securesms.components.settings.app.subscription.InAppDonations; import org.thoughtcrime.securesms.database.model.MegaphoneRecord; import org.thoughtcrime.securesms.database.model.RemoteMegaphoneRecord; import org.thoughtcrime.securesms.dependencies.ApplicationDependencies; @@ -36,7 +37,6 @@ import org.thoughtcrime.securesms.profiles.manage.ManageProfileActivity; import org.thoughtcrime.securesms.recipients.Recipient; import org.thoughtcrime.securesms.util.FeatureFlags; import org.thoughtcrime.securesms.util.LocaleFeatureFlags; -import org.thoughtcrime.securesms.util.PlayServicesUtil; import org.thoughtcrime.securesms.util.ServiceUtil; import org.thoughtcrime.securesms.util.VersionTracker; import org.thoughtcrime.securesms.util.dynamiclanguage.DynamicLanguageContextWrapper; @@ -396,7 +396,7 @@ public final class Megaphones { return timeSinceLastDonatePrompt > MIN_TIME_BETWEEN_DONATE_MEGAPHONES && VersionTracker.getDaysSinceFirstInstalled(context) >= 7 && LocaleFeatureFlags.isInDonateMegaphone() && - PlayServicesUtil.getPlayServicesStatus(context) == PlayServicesUtil.PlayServicesStatus.SUCCESS && + InAppDonations.INSTANCE.hasAtLeastOnePaymentMethodAvailable() && Recipient.self() .getBadges() .stream() diff --git a/app/src/main/java/org/thoughtcrime/securesms/megaphone/RemoteMegaphoneRepository.kt b/app/src/main/java/org/thoughtcrime/securesms/megaphone/RemoteMegaphoneRepository.kt index cee2a5c608..1ef6a4cb38 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/megaphone/RemoteMegaphoneRepository.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/megaphone/RemoteMegaphoneRepository.kt @@ -10,6 +10,7 @@ import org.signal.core.util.concurrent.SignalExecutors import org.signal.core.util.logging.Log import org.thoughtcrime.securesms.badges.models.Badge import org.thoughtcrime.securesms.components.settings.app.AppSettingsActivity +import org.thoughtcrime.securesms.components.settings.app.subscription.InAppDonations import org.thoughtcrime.securesms.database.RemoteMegaphoneDatabase import org.thoughtcrime.securesms.database.SignalDatabase import org.thoughtcrime.securesms.database.model.RemoteMegaphoneRecord @@ -20,7 +21,6 @@ import org.thoughtcrime.securesms.providers.BlobProvider import org.thoughtcrime.securesms.recipients.Recipient import org.thoughtcrime.securesms.util.FeatureFlags import org.thoughtcrime.securesms.util.LocaleFeatureFlags -import org.thoughtcrime.securesms.util.PlayServicesUtil import org.thoughtcrime.securesms.util.VersionTracker import java.util.Objects import kotlin.math.min @@ -121,7 +121,7 @@ object RemoteMegaphoneRepository { private fun shouldShowDonateMegaphone(): Boolean { return VersionTracker.getDaysSinceFirstInstalled(context) >= 7 && - PlayServicesUtil.getPlayServicesStatus(context) == PlayServicesUtil.PlayServicesStatus.SUCCESS && + InAppDonations.hasAtLeastOnePaymentMethodAvailable() && Recipient.self() .badges .stream()