mirror of
https://github.com/signalapp/Signal-Android.git
synced 2026-04-21 17:29:32 +01:00
Verify recipient before launching google pay sheet in badge gifting flow.
This commit is contained in:
@@ -34,6 +34,7 @@ import org.thoughtcrime.securesms.keyboard.KeyboardPage
|
||||
import org.thoughtcrime.securesms.keyboard.KeyboardPagerViewModel
|
||||
import org.thoughtcrime.securesms.keyboard.emoji.EmojiKeyboardPageFragment
|
||||
import org.thoughtcrime.securesms.keyboard.emoji.search.EmojiSearchFragment
|
||||
import org.thoughtcrime.securesms.util.Debouncer
|
||||
import org.thoughtcrime.securesms.util.LifecycleDisposable
|
||||
import org.thoughtcrime.securesms.util.fragments.requireListener
|
||||
|
||||
@@ -67,10 +68,12 @@ class GiftFlowConfirmationFragment :
|
||||
private val lifecycleDisposable = LifecycleDisposable()
|
||||
private var errorDialog: DialogInterface? = null
|
||||
private lateinit var processingDonationPaymentDialog: AlertDialog
|
||||
private lateinit var verifyingRecipientDonationPaymentDialog: AlertDialog
|
||||
private lateinit var donationPaymentComponent: DonationPaymentComponent
|
||||
private lateinit var textInputViewHolder: TextInput.MultilineViewHolder
|
||||
|
||||
private val eventPublisher = PublishSubject.create<TextInput.TextInputEvent>()
|
||||
private val debouncer = Debouncer(100L)
|
||||
|
||||
override fun bindAdapter(adapter: DSLSettingsAdapter) {
|
||||
RecipientPreference.register(adapter)
|
||||
@@ -85,6 +88,11 @@ class GiftFlowConfirmationFragment :
|
||||
.setCancelable(false)
|
||||
.create()
|
||||
|
||||
verifyingRecipientDonationPaymentDialog = MaterialAlertDialogBuilder(requireContext())
|
||||
.setView(R.layout.verifying_recipient_payment_dialog)
|
||||
.setCancelable(false)
|
||||
.create()
|
||||
|
||||
inputAwareLayout = requireView().findViewById(R.id.input_aware_layout)
|
||||
emojiKeyboard = requireView().findViewById(R.id.emoji_drawer)
|
||||
|
||||
@@ -122,10 +130,17 @@ class GiftFlowConfirmationFragment :
|
||||
lifecycleDisposable += viewModel.state.observeOn(AndroidSchedulers.mainThread()).subscribe { state ->
|
||||
adapter.submitList(getConfiguration(state).toMappingModelList())
|
||||
|
||||
if (state.stage == GiftFlowState.Stage.RECIPIENT_VERIFICATION) {
|
||||
debouncer.publish { verifyingRecipientDonationPaymentDialog.show() }
|
||||
} else {
|
||||
debouncer.clear()
|
||||
verifyingRecipientDonationPaymentDialog.dismiss()
|
||||
}
|
||||
|
||||
if (state.stage == GiftFlowState.Stage.PAYMENT_PIPELINE) {
|
||||
processingDonationPaymentDialog.show()
|
||||
} else {
|
||||
processingDonationPaymentDialog.hide()
|
||||
processingDonationPaymentDialog.dismiss()
|
||||
}
|
||||
|
||||
textInputViewHolder.bind(
|
||||
@@ -175,6 +190,8 @@ class GiftFlowConfirmationFragment :
|
||||
super.onDestroyView()
|
||||
textInputViewHolder.onDetachedFromWindow()
|
||||
processingDonationPaymentDialog.dismiss()
|
||||
debouncer.clear()
|
||||
verifyingRecipientDonationPaymentDialog.dismiss()
|
||||
}
|
||||
|
||||
private fun getConfiguration(giftFlowState: GiftFlowState): DSLConfiguration {
|
||||
|
||||
@@ -20,8 +20,9 @@ data class GiftFlowState(
|
||||
enum class Stage {
|
||||
INIT,
|
||||
READY,
|
||||
RECIPIENT_VERIFICATION,
|
||||
TOKEN_REQUEST,
|
||||
PAYMENT_PIPELINE,
|
||||
FAILURE
|
||||
FAILURE;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@ import android.content.Intent
|
||||
import androidx.lifecycle.ViewModel
|
||||
import androidx.lifecycle.ViewModelProvider
|
||||
import com.google.android.gms.wallet.PaymentData
|
||||
import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers
|
||||
import io.reactivex.rxjava3.core.Flowable
|
||||
import io.reactivex.rxjava3.core.Observable
|
||||
import io.reactivex.rxjava3.disposables.CompositeDisposable
|
||||
@@ -128,9 +129,20 @@ class GiftFlowViewModel(
|
||||
fun requestTokenFromGooglePay(label: String) {
|
||||
val giftLevel = store.state.giftLevel ?: return
|
||||
val giftPrice = store.state.giftPrices[store.state.currency] ?: return
|
||||
val giftRecipient = store.state.recipient?.id ?: return
|
||||
|
||||
this.giftToPurchase = Gift(giftLevel, giftPrice)
|
||||
donationPaymentRepository.requestTokenFromGooglePay(giftToPurchase!!.price, label, Gifts.GOOGLE_PAY_REQUEST_CODE)
|
||||
|
||||
store.update { it.copy(stage = GiftFlowState.Stage.RECIPIENT_VERIFICATION) }
|
||||
disposables += donationPaymentRepository.verifyRecipientIsAllowedToReceiveAGift(giftRecipient)
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribeBy(
|
||||
onComplete = {
|
||||
store.update { it.copy(stage = GiftFlowState.Stage.TOKEN_REQUEST) }
|
||||
donationPaymentRepository.requestTokenFromGooglePay(giftToPurchase!!.price, label, Gifts.GOOGLE_PAY_REQUEST_CODE)
|
||||
},
|
||||
onError = this::onPaymentFlowError
|
||||
)
|
||||
}
|
||||
|
||||
fun onActivityResult(
|
||||
@@ -153,16 +165,7 @@ class GiftFlowViewModel(
|
||||
store.update { it.copy(stage = GiftFlowState.Stage.PAYMENT_PIPELINE) }
|
||||
|
||||
donationPaymentRepository.continuePayment(gift.price, paymentData, recipient, store.state.additionalMessage?.toString(), gift.level).subscribeBy(
|
||||
onError = { throwable ->
|
||||
store.update { it.copy(stage = GiftFlowState.Stage.READY) }
|
||||
val donationError: DonationError = if (throwable is DonationError) {
|
||||
throwable
|
||||
} else {
|
||||
Log.w(TAG, "Failed to complete payment or redemption", throwable, true)
|
||||
DonationError.genericBadgeRedemptionFailure(DonationErrorSource.GIFT)
|
||||
}
|
||||
DonationError.routeDonationError(ApplicationDependencies.getApplication(), donationError)
|
||||
},
|
||||
onError = this@GiftFlowViewModel::onPaymentFlowError,
|
||||
onComplete = {
|
||||
store.update { it.copy(stage = GiftFlowState.Stage.READY) }
|
||||
eventPublisher.onNext(DonationEvent.PaymentConfirmationSuccess(store.state.giftBadge!!))
|
||||
@@ -185,6 +188,17 @@ class GiftFlowViewModel(
|
||||
)
|
||||
}
|
||||
|
||||
private fun onPaymentFlowError(throwable: Throwable) {
|
||||
store.update { it.copy(stage = GiftFlowState.Stage.READY) }
|
||||
val donationError: DonationError = if (throwable is DonationError) {
|
||||
throwable
|
||||
} else {
|
||||
Log.w(TAG, "Failed to complete payment or redemption", throwable, true)
|
||||
DonationError.genericBadgeRedemptionFailure(DonationErrorSource.GIFT)
|
||||
}
|
||||
DonationError.routeDonationError(ApplicationDependencies.getApplication(), donationError)
|
||||
}
|
||||
|
||||
private fun getLoadState(
|
||||
oldState: GiftFlowState,
|
||||
giftPrices: Map<Currency, FiatMoney>? = null,
|
||||
|
||||
Reference in New Issue
Block a user