mirror of
https://github.com/signalapp/Signal-Android.git
synced 2026-04-23 02:10:44 +01:00
Implement donations one-time pending state.
This commit is contained in:
committed by
Cody Henthorne
parent
57135ea2c6
commit
627c47b155
@@ -14,8 +14,10 @@ import org.signal.libsignal.zkgroup.receipts.ReceiptCredentialRequestContext
|
||||
import org.signal.libsignal.zkgroup.receipts.ReceiptSerial
|
||||
import org.thoughtcrime.securesms.badges.Badges
|
||||
import org.thoughtcrime.securesms.badges.models.Badge
|
||||
import org.thoughtcrime.securesms.components.settings.app.subscription.PendingOneTimeDonationSerializer.isExpired
|
||||
import org.thoughtcrime.securesms.database.model.databaseprotos.BadgeList
|
||||
import org.thoughtcrime.securesms.database.model.databaseprotos.DonationCompletedQueue
|
||||
import org.thoughtcrime.securesms.database.model.databaseprotos.PendingOneTimeDonation
|
||||
import org.thoughtcrime.securesms.dependencies.ApplicationDependencies
|
||||
import org.thoughtcrime.securesms.jobs.SubscriptionReceiptRequestResponseJob
|
||||
import org.thoughtcrime.securesms.payments.currency.CurrencyUtil
|
||||
@@ -29,6 +31,7 @@ import org.whispersystems.signalservice.internal.util.JsonUtil
|
||||
import java.security.SecureRandom
|
||||
import java.util.Currency
|
||||
import java.util.Locale
|
||||
import java.util.Optional
|
||||
import java.util.concurrent.TimeUnit
|
||||
|
||||
internal class DonationsValues internal constructor(store: KeyValueStore) : SignalStoreValues(store) {
|
||||
@@ -115,6 +118,12 @@ internal class DonationsValues internal constructor(store: KeyValueStore) : Sign
|
||||
* Popped from whenever we enter the conversation list.
|
||||
*/
|
||||
private const val DONATION_COMPLETE_QUEUE = "donation.complete.queue"
|
||||
|
||||
/**
|
||||
* The current one-time donation we are processing, if we are doing so. This is used for showing
|
||||
* the donation processing / donation pending state in the ManageDonationsFragment.
|
||||
*/
|
||||
private const val PENDING_ONE_TIME_DONATION = "pending.one.time.donation"
|
||||
}
|
||||
|
||||
override fun onFirstEverAppLaunch() = Unit
|
||||
@@ -142,6 +151,14 @@ internal class DonationsValues internal constructor(store: KeyValueStore) : Sign
|
||||
private val oneTimeCurrencyPublisher: Subject<Currency> by lazy { BehaviorSubject.createDefault(getOneTimeCurrency()) }
|
||||
val observableOneTimeCurrency: Observable<Currency> by lazy { oneTimeCurrencyPublisher }
|
||||
|
||||
private var _pendingOneTimeDonation: PendingOneTimeDonation? by protoValue(PENDING_ONE_TIME_DONATION, PendingOneTimeDonation.ADAPTER)
|
||||
private val pendingOneTimeDonationPublisher: Subject<Optional<PendingOneTimeDonation>> by lazy { BehaviorSubject.createDefault(Optional.ofNullable(_pendingOneTimeDonation)) }
|
||||
val observablePendingOneTimeDonation: Observable<Optional<PendingOneTimeDonation>> by lazy {
|
||||
pendingOneTimeDonationPublisher.map { optionalPendingOneTimeDonation ->
|
||||
optionalPendingOneTimeDonation.filter { !it.isExpired }
|
||||
}
|
||||
}
|
||||
|
||||
fun getSubscriptionCurrency(): Currency {
|
||||
val currencyCode = getString(KEY_SUBSCRIPTION_CURRENCY_CODE, null)
|
||||
val currency: Currency? = if (currencyCode == null) {
|
||||
@@ -501,6 +518,13 @@ internal class DonationsValues internal constructor(store: KeyValueStore) : Sign
|
||||
}
|
||||
}
|
||||
|
||||
fun getPendingOneTimeDonation(): PendingOneTimeDonation? = _pendingOneTimeDonation.takeUnless { it?.isExpired == true }
|
||||
|
||||
fun setPendingOneTimeDonation(pendingOneTimeDonation: PendingOneTimeDonation?) {
|
||||
this._pendingOneTimeDonation = pendingOneTimeDonation
|
||||
pendingOneTimeDonationPublisher.onNext(Optional.ofNullable(pendingOneTimeDonation))
|
||||
}
|
||||
|
||||
private fun generateRequestCredential(): ReceiptCredentialRequestContext {
|
||||
Log.d(TAG, "Generating request credentials context for token redemption...", true)
|
||||
val secureRandom = SecureRandom()
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package org.thoughtcrime.securesms.keyvalue
|
||||
|
||||
import com.squareup.wire.ProtoAdapter
|
||||
import org.signal.core.util.LongSerializer
|
||||
import kotlin.reflect.KProperty
|
||||
|
||||
@@ -31,6 +32,10 @@ internal fun <T : Any?> SignalStoreValues.enumValue(key: String, default: T, ser
|
||||
return KeyValueEnumValue(key, default, serializer, this.store)
|
||||
}
|
||||
|
||||
internal fun <M> SignalStoreValues.protoValue(key: String, adapter: ProtoAdapter<M>): SignalStoreValueDelegate<M?> {
|
||||
return KeyValueProtoValue(key, adapter, this.store)
|
||||
}
|
||||
|
||||
/**
|
||||
* Kotlin delegate that serves as a base for all other value types. This allows us to only expose this sealed
|
||||
* class to callers and protect the individual implementations as private behind the various extension functions.
|
||||
@@ -109,6 +114,28 @@ private class BlobValue(private val key: String, private val default: ByteArray,
|
||||
}
|
||||
}
|
||||
|
||||
private class KeyValueProtoValue<M>(
|
||||
private val key: String,
|
||||
private val adapter: ProtoAdapter<M>,
|
||||
store: KeyValueStore
|
||||
) : SignalStoreValueDelegate<M?>(store) {
|
||||
override fun getValue(values: KeyValueStore): M? {
|
||||
return if (values.containsKey(key)) {
|
||||
adapter.decode(values.getBlob(key, null))
|
||||
} else {
|
||||
null
|
||||
}
|
||||
}
|
||||
|
||||
override fun setValue(values: KeyValueStore, value: M?) {
|
||||
if (value != null) {
|
||||
values.beginWrite().putBlob(key, adapter.encode(value)).apply()
|
||||
} else {
|
||||
values.beginWrite().remove(key).apply()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private class KeyValueEnumValue<T>(private val key: String, private val default: T, private val serializer: LongSerializer<T>, store: KeyValueStore) : SignalStoreValueDelegate<T>(store) {
|
||||
override fun getValue(values: KeyValueStore): T {
|
||||
return if (values.containsKey(key)) {
|
||||
|
||||
Reference in New Issue
Block a user