Rewrite in-app-payment flows to prepare for backups support.

This commit is contained in:
Alex Hart
2024-04-19 17:04:15 -03:00
committed by Cody Henthorne
parent b36b00a11c
commit d719edf104
123 changed files with 5429 additions and 1586 deletions

View File

@@ -11,9 +11,11 @@ import org.thoughtcrime.securesms.backup.v2.database.restoreSelfFromBackup
import org.thoughtcrime.securesms.backup.v2.proto.AccountData
import org.thoughtcrime.securesms.backup.v2.proto.Frame
import org.thoughtcrime.securesms.backup.v2.stream.BackupFrameEmitter
import org.thoughtcrime.securesms.components.settings.app.subscription.InAppPaymentsRepository
import org.thoughtcrime.securesms.components.settings.app.usernamelinks.UsernameQrCodeColorScheme
import org.thoughtcrime.securesms.database.SignalDatabase
import org.thoughtcrime.securesms.database.SignalDatabase.Companion.recipients
import org.thoughtcrime.securesms.database.model.InAppPaymentSubscriberRecord
import org.thoughtcrime.securesms.dependencies.ApplicationDependencies
import org.thoughtcrime.securesms.jobs.RetrieveProfileAvatarJob
import org.thoughtcrime.securesms.keyvalue.PhoneNumberPrivacyValues
@@ -21,7 +23,6 @@ import org.thoughtcrime.securesms.keyvalue.PhoneNumberPrivacyValues.PhoneNumberD
import org.thoughtcrime.securesms.keyvalue.SignalStore
import org.thoughtcrime.securesms.recipients.Recipient
import org.thoughtcrime.securesms.recipients.RecipientId
import org.thoughtcrime.securesms.subscription.Subscriber
import org.thoughtcrime.securesms.util.ProfileUtil
import org.thoughtcrime.securesms.util.TextSecurePreferences
import org.whispersystems.signalservice.api.push.UsernameLinkComponents
@@ -38,7 +39,7 @@ object AccountDataProcessor {
val self = Recipient.self().fresh()
val record = recipients.getRecordForSync(self.id)
val subscriber: Subscriber? = SignalStore.donationsValues().getSubscriber()
val subscriber: InAppPaymentSubscriberRecord? = InAppPaymentsRepository.getSubscriber(InAppPaymentSubscriberRecord.Type.DONATION)
emitter.emit(
Frame(
@@ -47,7 +48,7 @@ object AccountDataProcessor {
givenName = self.profileName.givenName,
familyName = self.profileName.familyName,
avatarUrlPath = self.profileAvatar ?: "",
subscriptionManuallyCancelled = SignalStore.donationsValues().isUserManuallyCancelled(),
subscriptionManuallyCancelled = InAppPaymentsRepository.isUserManuallyCancelled(InAppPaymentSubscriberRecord.Type.DONATION),
username = self.username.getOrNull(),
subscriberId = subscriber?.subscriberId?.bytes?.toByteString() ?: defaultAccountRecord.subscriberId,
subscriberCurrencyCode = subscriber?.currencyCode ?: defaultAccountRecord.subscriberCurrencyCode,
@@ -101,15 +102,23 @@ object AccountDataProcessor {
SignalStore.storyValues().userHasSeenGroupStoryEducationSheet = settings.hasSeenGroupStoryEducationSheet
SignalStore.storyValues().viewedReceiptsEnabled = settings.storyViewReceiptsEnabled ?: settings.readReceipts
if (accountData.subscriptionManuallyCancelled) {
SignalStore.donationsValues().updateLocalStateForManualCancellation()
} else {
SignalStore.donationsValues().clearUserManuallyCancelled()
if (accountData.subscriberId.size > 0) {
val remoteSubscriberId = SubscriberId.fromBytes(accountData.subscriberId.toByteArray())
val localSubscriber = InAppPaymentsRepository.getSubscriber(InAppPaymentSubscriberRecord.Type.DONATION)
val subscriber = InAppPaymentSubscriberRecord(
remoteSubscriberId,
accountData.subscriberCurrencyCode,
InAppPaymentSubscriberRecord.Type.DONATION,
localSubscriber?.requiresCancel ?: false,
InAppPaymentsRepository.getLatestPaymentMethodType(InAppPaymentSubscriberRecord.Type.DONATION)
)
InAppPaymentsRepository.setSubscriber(subscriber)
}
if (accountData.subscriberId.size > 0) {
val subscriber = Subscriber(SubscriberId.fromBytes(accountData.subscriberId.toByteArray()), accountData.subscriberCurrencyCode)
SignalStore.donationsValues().setSubscriber(subscriber)
if (accountData.subscriptionManuallyCancelled) {
SignalStore.donationsValues().updateLocalStateForManualCancellation(InAppPaymentSubscriberRecord.Type.DONATION)
}
if (accountData.avatarUrlPath.isNotEmpty()) {

View File

@@ -35,8 +35,8 @@ import org.signal.core.ui.Buttons
import org.signal.core.ui.Previews
import org.thoughtcrime.securesms.R
import org.thoughtcrime.securesms.backup.v2.MessageBackupTier
import org.thoughtcrime.securesms.components.settings.app.subscription.donate.gateway.GatewayResponse
import org.thoughtcrime.securesms.components.settings.app.subscription.models.GooglePayButton
import org.thoughtcrime.securesms.database.model.databaseprotos.InAppPaymentData
import org.thoughtcrime.securesms.databinding.PaypalButtonBinding
import org.thoughtcrime.securesms.payments.FiatMoneyUtil
@@ -44,9 +44,9 @@ import org.thoughtcrime.securesms.payments.FiatMoneyUtil
@Composable
fun MessageBackupsCheckoutSheet(
messageBackupTier: MessageBackupTier,
availablePaymentGateways: List<GatewayResponse.Gateway>,
availablePaymentMethods: List<InAppPaymentData.PaymentMethodType>,
onDismissRequest: () -> Unit,
onPaymentGatewaySelected: (GatewayResponse.Gateway) -> Unit
onPaymentMethodSelected: (InAppPaymentData.PaymentMethodType) -> Unit
) {
ModalBottomSheet(
onDismissRequest = onDismissRequest,
@@ -55,8 +55,8 @@ fun MessageBackupsCheckoutSheet(
) {
SheetContent(
messageBackupTier = messageBackupTier,
availablePaymentGateways = availablePaymentGateways,
onPaymentGatewaySelected = onPaymentGatewaySelected
availablePaymentGateways = availablePaymentMethods,
onPaymentGatewaySelected = onPaymentMethodSelected
)
}
}
@@ -64,8 +64,8 @@ fun MessageBackupsCheckoutSheet(
@Composable
private fun SheetContent(
messageBackupTier: MessageBackupTier,
availablePaymentGateways: List<GatewayResponse.Gateway>,
onPaymentGatewaySelected: (GatewayResponse.Gateway) -> Unit
availablePaymentGateways: List<InAppPaymentData.PaymentMethodType>,
onPaymentGatewaySelected: (InAppPaymentData.PaymentMethodType) -> Unit
) {
val resources = LocalContext.current.resources
val backupTypeDetails = remember(messageBackupTier) {
@@ -101,25 +101,27 @@ private fun SheetContent(
) {
availablePaymentGateways.forEach {
when (it) {
GatewayResponse.Gateway.GOOGLE_PAY -> GooglePayButton {
onPaymentGatewaySelected(GatewayResponse.Gateway.GOOGLE_PAY)
InAppPaymentData.PaymentMethodType.GOOGLE_PAY -> GooglePayButton {
onPaymentGatewaySelected(InAppPaymentData.PaymentMethodType.GOOGLE_PAY)
}
GatewayResponse.Gateway.PAYPAL -> PayPalButton {
onPaymentGatewaySelected(GatewayResponse.Gateway.PAYPAL)
InAppPaymentData.PaymentMethodType.PAYPAL -> PayPalButton {
onPaymentGatewaySelected(InAppPaymentData.PaymentMethodType.PAYPAL)
}
GatewayResponse.Gateway.CREDIT_CARD -> CreditOrDebitCardButton {
onPaymentGatewaySelected(GatewayResponse.Gateway.CREDIT_CARD)
InAppPaymentData.PaymentMethodType.CARD -> CreditOrDebitCardButton {
onPaymentGatewaySelected(InAppPaymentData.PaymentMethodType.CARD)
}
GatewayResponse.Gateway.SEPA_DEBIT -> SepaButton {
onPaymentGatewaySelected(GatewayResponse.Gateway.SEPA_DEBIT)
InAppPaymentData.PaymentMethodType.SEPA_DEBIT -> SepaButton {
onPaymentGatewaySelected(InAppPaymentData.PaymentMethodType.SEPA_DEBIT)
}
GatewayResponse.Gateway.IDEAL -> IdealButton {
onPaymentGatewaySelected(GatewayResponse.Gateway.IDEAL)
InAppPaymentData.PaymentMethodType.IDEAL -> IdealButton {
onPaymentGatewaySelected(InAppPaymentData.PaymentMethodType.IDEAL)
}
InAppPaymentData.PaymentMethodType.UNKNOWN -> error("Unsupported payment method type $it")
}
}
}
@@ -221,7 +223,7 @@ private fun CreditOrDebitCardButton(
@Preview
@Composable
private fun MessageBackupsCheckoutSheetPreview() {
val availablePaymentGateways = GatewayResponse.Gateway.values().toList()
val availablePaymentGateways = InAppPaymentData.PaymentMethodType.values().toList() - InAppPaymentData.PaymentMethodType.UNKNOWN
Previews.Preview {
Column(

View File

@@ -104,10 +104,10 @@ class MessageBackupsFlowActivity : PassphraseRequiredActivity() {
dialog(route = MessageBackupsScreen.CHECKOUT_SHEET.name) {
MessageBackupsCheckoutSheet(
messageBackupTier = state.selectedMessageBackupTier!!,
availablePaymentGateways = state.availablePaymentGateways,
availablePaymentMethods = state.availablePaymentMethods,
onDismissRequest = navController::popOrFinish,
onPaymentGatewaySelected = {
viewModel.onPaymentGatewayUpdated(it)
onPaymentMethodSelected = {
viewModel.onPaymentMethodUpdated(it)
MessageBackupsScreen.CHECKOUT_SHEET.next()
}
)

View File

@@ -6,7 +6,7 @@
package org.thoughtcrime.securesms.backup.v2.ui.subscription
import org.thoughtcrime.securesms.backup.v2.MessageBackupTier
import org.thoughtcrime.securesms.components.settings.app.subscription.donate.gateway.GatewayResponse
import org.thoughtcrime.securesms.database.model.databaseprotos.InAppPaymentData
import org.thoughtcrime.securesms.keyvalue.SignalStore
import org.thoughtcrime.securesms.lock.v2.PinKeyboardType
@@ -14,8 +14,8 @@ data class MessageBackupsFlowState(
val selectedMessageBackupTier: MessageBackupTier? = null,
val currentMessageBackupTier: MessageBackupTier? = null,
val availableBackupTiers: List<MessageBackupTier> = emptyList(),
val selectedPaymentGateway: GatewayResponse.Gateway? = null,
val availablePaymentGateways: List<GatewayResponse.Gateway> = emptyList(),
val selectedPaymentMethod: InAppPaymentData.PaymentMethodType? = null,
val availablePaymentMethods: List<InAppPaymentData.PaymentMethodType> = emptyList(),
val pin: String = "",
val pinKeyboardType: PinKeyboardType = SignalStore.pinValues().keyboardType
)

View File

@@ -10,7 +10,7 @@ import androidx.compose.runtime.State
import androidx.compose.runtime.mutableStateOf
import androidx.lifecycle.ViewModel
import org.thoughtcrime.securesms.backup.v2.MessageBackupTier
import org.thoughtcrime.securesms.components.settings.app.subscription.donate.gateway.GatewayResponse
import org.thoughtcrime.securesms.database.model.databaseprotos.InAppPaymentData
import org.thoughtcrime.securesms.keyvalue.SignalStore
import org.thoughtcrime.securesms.lock.v2.PinKeyboardType
import org.thoughtcrime.securesms.lock.v2.SvrConstants
@@ -51,8 +51,8 @@ class MessageBackupsFlowViewModel : ViewModel() {
internalState.value = state.value.copy(pinKeyboardType = pinKeyboardType)
}
fun onPaymentGatewayUpdated(gateway: GatewayResponse.Gateway) {
internalState.value = state.value.copy(selectedPaymentGateway = gateway)
fun onPaymentMethodUpdated(paymentMethod: InAppPaymentData.PaymentMethodType) {
internalState.value = state.value.copy(selectedPaymentMethod = paymentMethod)
}
fun onMessageBackupTierUpdated(messageBackupTier: MessageBackupTier) {