2021-10-12 18:55:54 +00:00
|
|
|
package org.thoughtcrime.securesms.keyvalue
|
|
|
|
|
2022-05-16 19:19:26 +00:00
|
|
|
import androidx.annotation.WorkerThread
|
2021-10-12 18:55:54 +00:00
|
|
|
import io.reactivex.rxjava3.core.Observable
|
|
|
|
import io.reactivex.rxjava3.subjects.BehaviorSubject
|
|
|
|
import io.reactivex.rxjava3.subjects.Subject
|
2021-11-22 19:57:20 +00:00
|
|
|
import org.signal.core.util.logging.Log
|
2021-10-12 18:55:54 +00:00
|
|
|
import org.signal.donations.StripeApi
|
2021-10-28 16:59:05 +00:00
|
|
|
import org.thoughtcrime.securesms.badges.Badges
|
|
|
|
import org.thoughtcrime.securesms.badges.models.Badge
|
|
|
|
import org.thoughtcrime.securesms.database.model.databaseprotos.BadgeList
|
2022-05-16 19:19:26 +00:00
|
|
|
import org.thoughtcrime.securesms.jobs.SubscriptionReceiptRequestResponseJob
|
2021-10-13 12:42:16 +00:00
|
|
|
import org.thoughtcrime.securesms.payments.currency.CurrencyUtil
|
2021-10-21 19:39:02 +00:00
|
|
|
import org.thoughtcrime.securesms.subscription.LevelUpdateOperation
|
|
|
|
import org.thoughtcrime.securesms.subscription.Subscriber
|
2022-04-18 19:37:12 +00:00
|
|
|
import org.whispersystems.signalservice.api.subscriptions.ActiveSubscription
|
2021-10-21 19:39:02 +00:00
|
|
|
import org.whispersystems.signalservice.api.subscriptions.IdempotencyKey
|
|
|
|
import org.whispersystems.signalservice.api.subscriptions.SubscriberId
|
2022-04-18 19:37:12 +00:00
|
|
|
import org.whispersystems.signalservice.internal.util.JsonUtil
|
2021-10-12 18:55:54 +00:00
|
|
|
import java.util.Currency
|
|
|
|
import java.util.Locale
|
2021-11-23 21:14:40 +00:00
|
|
|
import java.util.concurrent.TimeUnit
|
2021-10-12 18:55:54 +00:00
|
|
|
|
|
|
|
internal class DonationsValues internal constructor(store: KeyValueStore) : SignalStoreValues(store) {
|
|
|
|
|
|
|
|
companion object {
|
2021-11-22 19:57:20 +00:00
|
|
|
private val TAG = Log.tag(DonationsValues::class.java)
|
|
|
|
|
2021-10-21 19:39:02 +00:00
|
|
|
private const val KEY_SUBSCRIPTION_CURRENCY_CODE = "donation.currency.code"
|
2022-05-02 17:29:42 +00:00
|
|
|
private const val KEY_CURRENCY_CODE_ONE_TIME = "donation.currency.code.boost"
|
2021-10-21 19:39:02 +00:00
|
|
|
private const val KEY_SUBSCRIBER_ID_PREFIX = "donation.subscriber.id."
|
|
|
|
private const val KEY_LAST_KEEP_ALIVE_LAUNCH = "donation.last.successful.ping"
|
2021-11-23 21:14:40 +00:00
|
|
|
private const val KEY_LAST_END_OF_PERIOD_SECONDS = "donation.last.end.of.period"
|
2021-10-28 16:59:05 +00:00
|
|
|
private const val EXPIRED_BADGE = "donation.expired.badge"
|
2022-05-02 17:29:42 +00:00
|
|
|
private const val EXPIRED_GIFT_BADGE = "donation.expired.gift.badge"
|
2021-10-29 17:05:22 +00:00
|
|
|
private const val USER_MANUALLY_CANCELLED = "donation.user.manually.cancelled"
|
2021-11-05 18:21:27 +00:00
|
|
|
private const val KEY_LEVEL_OPERATION_PREFIX = "donation.level.operation."
|
|
|
|
private const val KEY_LEVEL_HISTORY = "donation.level.history"
|
2021-11-11 18:59:30 +00:00
|
|
|
private const val DISPLAY_BADGES_ON_PROFILE = "donation.display.badges.on.profile"
|
2021-11-15 17:47:51 +00:00
|
|
|
private const val SUBSCRIPTION_REDEMPTION_FAILED = "donation.subscription.redemption.failed"
|
2021-11-19 19:30:15 +00:00
|
|
|
private const val SHOULD_CANCEL_SUBSCRIPTION_BEFORE_NEXT_SUBSCRIBE_ATTEMPT = "donation.should.cancel.subscription.before.next.subscribe.attempt"
|
2022-04-18 19:37:12 +00:00
|
|
|
private const val SUBSCRIPTION_CANCELATION_CHARGE_FAILURE = "donation.subscription.cancelation.charge.failure"
|
2022-02-10 18:26:59 +00:00
|
|
|
private const val SUBSCRIPTION_CANCELATION_REASON = "donation.subscription.cancelation.reason"
|
2022-04-08 16:07:19 +00:00
|
|
|
private const val SUBSCRIPTION_CANCELATION_TIMESTAMP = "donation.subscription.cancelation.timestamp"
|
|
|
|
private const val SUBSCRIPTION_CANCELATION_WATERMARK = "donation.subscription.cancelation.watermark"
|
2022-02-10 18:26:59 +00:00
|
|
|
private const val SHOW_CANT_PROCESS_DIALOG = "show.cant.process.dialog"
|
2021-10-12 18:55:54 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
override fun onFirstEverAppLaunch() = Unit
|
|
|
|
|
2021-10-28 16:59:05 +00:00
|
|
|
override fun getKeysToIncludeInBackup(): MutableList<String> = mutableListOf(
|
2022-05-02 17:29:42 +00:00
|
|
|
KEY_CURRENCY_CODE_ONE_TIME,
|
2021-11-08 19:14:50 +00:00
|
|
|
KEY_LAST_KEEP_ALIVE_LAUNCH,
|
2021-11-23 21:14:40 +00:00
|
|
|
KEY_LAST_END_OF_PERIOD_SECONDS,
|
2022-02-10 18:26:59 +00:00
|
|
|
SHOULD_CANCEL_SUBSCRIPTION_BEFORE_NEXT_SUBSCRIBE_ATTEMPT,
|
|
|
|
SUBSCRIPTION_CANCELATION_REASON,
|
2022-04-08 16:07:19 +00:00
|
|
|
SUBSCRIPTION_CANCELATION_TIMESTAMP,
|
|
|
|
SUBSCRIPTION_CANCELATION_WATERMARK,
|
2022-02-10 18:26:59 +00:00
|
|
|
SHOW_CANT_PROCESS_DIALOG
|
2021-10-28 16:59:05 +00:00
|
|
|
)
|
2021-10-12 18:55:54 +00:00
|
|
|
|
2021-10-21 19:39:02 +00:00
|
|
|
private val subscriptionCurrencyPublisher: Subject<Currency> by lazy { BehaviorSubject.createDefault(getSubscriptionCurrency()) }
|
|
|
|
val observableSubscriptionCurrency: Observable<Currency> by lazy { subscriptionCurrencyPublisher }
|
2021-10-12 18:55:54 +00:00
|
|
|
|
2022-05-02 17:29:42 +00:00
|
|
|
private val oneTimeCurrencyPublisher: Subject<Currency> by lazy { BehaviorSubject.createDefault(getOneTimeCurrency()) }
|
|
|
|
val observableOneTimeCurrency: Observable<Currency> by lazy { oneTimeCurrencyPublisher }
|
2021-10-21 19:39:02 +00:00
|
|
|
|
|
|
|
fun getSubscriptionCurrency(): Currency {
|
|
|
|
val currencyCode = getString(KEY_SUBSCRIPTION_CURRENCY_CODE, null)
|
2021-10-13 12:42:16 +00:00
|
|
|
val currency: Currency? = if (currencyCode == null) {
|
|
|
|
val localeCurrency = CurrencyUtil.getCurrencyByLocale(Locale.getDefault())
|
|
|
|
if (localeCurrency == null) {
|
2021-11-17 20:08:28 +00:00
|
|
|
val e164: String? = SignalStore.account().e164
|
2021-10-13 12:42:16 +00:00
|
|
|
if (e164 == null) {
|
|
|
|
null
|
|
|
|
} else {
|
|
|
|
CurrencyUtil.getCurrencyByE164(e164)
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
localeCurrency
|
|
|
|
}
|
2021-10-12 18:55:54 +00:00
|
|
|
} else {
|
2021-10-13 12:42:16 +00:00
|
|
|
CurrencyUtil.getCurrencyByCurrencyCode(currencyCode)
|
2021-10-12 18:55:54 +00:00
|
|
|
}
|
|
|
|
|
2022-05-18 18:05:17 +00:00
|
|
|
return if (currency != null && StripeApi.Validation.supportedCurrencyCodes.contains(currency.currencyCode.uppercase(Locale.ROOT))) {
|
2021-10-12 18:55:54 +00:00
|
|
|
currency
|
|
|
|
} else {
|
|
|
|
Currency.getInstance("USD")
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-05-02 17:29:42 +00:00
|
|
|
fun getOneTimeCurrency(): Currency {
|
|
|
|
val oneTimeCurrency = getString(KEY_CURRENCY_CODE_ONE_TIME, null)
|
|
|
|
return if (oneTimeCurrency == null) {
|
2021-10-21 19:39:02 +00:00
|
|
|
val currency = getSubscriptionCurrency()
|
2022-05-02 17:29:42 +00:00
|
|
|
setOneTimeCurrency(currency)
|
2021-10-21 19:39:02 +00:00
|
|
|
currency
|
|
|
|
} else {
|
2022-05-02 17:29:42 +00:00
|
|
|
Currency.getInstance(oneTimeCurrency)
|
2021-10-21 19:39:02 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-05-02 17:29:42 +00:00
|
|
|
fun setOneTimeCurrency(currency: Currency) {
|
|
|
|
putString(KEY_CURRENCY_CODE_ONE_TIME, currency.currencyCode)
|
|
|
|
oneTimeCurrencyPublisher.onNext(currency)
|
2021-10-21 19:39:02 +00:00
|
|
|
}
|
|
|
|
|
2021-10-28 16:59:05 +00:00
|
|
|
fun getSubscriber(currency: Currency): Subscriber? {
|
|
|
|
val currencyCode = currency.currencyCode
|
2021-10-21 19:39:02 +00:00
|
|
|
val subscriberIdBytes = getBlob("$KEY_SUBSCRIBER_ID_PREFIX$currencyCode", null)
|
|
|
|
|
|
|
|
return if (subscriberIdBytes == null) {
|
|
|
|
null
|
|
|
|
} else {
|
|
|
|
Subscriber(SubscriberId.fromBytes(subscriberIdBytes), currencyCode)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-10-28 16:59:05 +00:00
|
|
|
fun getSubscriber(): Subscriber? {
|
|
|
|
return getSubscriber(getSubscriptionCurrency())
|
|
|
|
}
|
|
|
|
|
2021-10-21 19:39:02 +00:00
|
|
|
fun requireSubscriber(): Subscriber {
|
|
|
|
return getSubscriber() ?: throw Exception("Subscriber ID is not set.")
|
|
|
|
}
|
|
|
|
|
|
|
|
fun setSubscriber(subscriber: Subscriber) {
|
2022-03-21 13:07:20 +00:00
|
|
|
Log.i(TAG, "Setting subscriber for currency ${subscriber.currencyCode}", Exception(), true)
|
2021-10-21 19:39:02 +00:00
|
|
|
val currencyCode = subscriber.currencyCode
|
2021-10-28 16:59:05 +00:00
|
|
|
store.beginWrite()
|
|
|
|
.putBlob("$KEY_SUBSCRIBER_ID_PREFIX$currencyCode", subscriber.subscriberId.bytes)
|
|
|
|
.putString(KEY_SUBSCRIPTION_CURRENCY_CODE, currencyCode)
|
|
|
|
.apply()
|
|
|
|
|
|
|
|
subscriptionCurrencyPublisher.onNext(Currency.getInstance(currencyCode))
|
2021-10-21 19:39:02 +00:00
|
|
|
}
|
|
|
|
|
2021-11-05 18:21:27 +00:00
|
|
|
fun getLevelOperation(level: String): LevelUpdateOperation? {
|
|
|
|
val idempotencyKey = getBlob("${KEY_LEVEL_OPERATION_PREFIX}$level", null)
|
|
|
|
return if (idempotencyKey != null) {
|
|
|
|
LevelUpdateOperation(IdempotencyKey.fromBytes(idempotencyKey), level)
|
2021-10-21 19:39:02 +00:00
|
|
|
} else {
|
2021-11-05 18:21:27 +00:00
|
|
|
null
|
2021-10-21 19:39:02 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
fun setLevelOperation(levelUpdateOperation: LevelUpdateOperation) {
|
2021-11-05 18:21:27 +00:00
|
|
|
addLevelToHistory(levelUpdateOperation.level)
|
|
|
|
putBlob("$KEY_LEVEL_OPERATION_PREFIX${levelUpdateOperation.level}", levelUpdateOperation.idempotencyKey.bytes)
|
2021-10-21 19:39:02 +00:00
|
|
|
}
|
|
|
|
|
2021-11-05 18:21:27 +00:00
|
|
|
private fun getLevelHistory(): Set<String> {
|
|
|
|
return getString(KEY_LEVEL_HISTORY, "").split(",").toSet()
|
|
|
|
}
|
|
|
|
|
|
|
|
private fun addLevelToHistory(level: String) {
|
|
|
|
val levels = getLevelHistory() + level
|
|
|
|
putString(KEY_LEVEL_HISTORY, levels.joinToString(","))
|
|
|
|
}
|
|
|
|
|
|
|
|
fun clearLevelOperations() {
|
|
|
|
val levelHistory = getLevelHistory()
|
|
|
|
val write = store.beginWrite()
|
|
|
|
for (level in levelHistory) {
|
|
|
|
write.remove("${KEY_LEVEL_OPERATION_PREFIX}$level")
|
|
|
|
}
|
|
|
|
write.apply()
|
2021-10-21 19:39:02 +00:00
|
|
|
}
|
|
|
|
|
2021-10-28 16:59:05 +00:00
|
|
|
fun setExpiredBadge(badge: Badge?) {
|
|
|
|
if (badge != null) {
|
|
|
|
putBlob(EXPIRED_BADGE, Badges.toDatabaseBadge(badge).toByteArray())
|
|
|
|
} else {
|
|
|
|
remove(EXPIRED_BADGE)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
fun getExpiredBadge(): Badge? {
|
|
|
|
val badgeBytes = getBlob(EXPIRED_BADGE, null) ?: return null
|
|
|
|
|
|
|
|
return Badges.fromDatabaseBadge(BadgeList.Badge.parseFrom(badgeBytes))
|
|
|
|
}
|
|
|
|
|
2022-05-02 17:29:42 +00:00
|
|
|
fun setExpiredGiftBadge(badge: Badge?) {
|
|
|
|
if (badge != null) {
|
|
|
|
putBlob(EXPIRED_GIFT_BADGE, Badges.toDatabaseBadge(badge).toByteArray())
|
|
|
|
} else {
|
|
|
|
remove(EXPIRED_GIFT_BADGE)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
fun getExpiredGiftBadge(): Badge? {
|
|
|
|
val badgeBytes = getBlob(EXPIRED_GIFT_BADGE, null) ?: return null
|
|
|
|
|
|
|
|
return Badges.fromDatabaseBadge(BadgeList.Badge.parseFrom(badgeBytes))
|
|
|
|
}
|
|
|
|
|
2021-10-21 19:39:02 +00:00
|
|
|
fun getLastKeepAliveLaunchTime(): Long {
|
|
|
|
return getLong(KEY_LAST_KEEP_ALIVE_LAUNCH, 0L)
|
|
|
|
}
|
|
|
|
|
|
|
|
fun setLastKeepAliveLaunchTime(timestamp: Long) {
|
|
|
|
putLong(KEY_LAST_KEEP_ALIVE_LAUNCH, timestamp)
|
|
|
|
}
|
|
|
|
|
|
|
|
fun getLastEndOfPeriod(): Long {
|
2021-11-23 21:14:40 +00:00
|
|
|
return getLong(KEY_LAST_END_OF_PERIOD_SECONDS, 0L)
|
2021-10-21 19:39:02 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
fun setLastEndOfPeriod(timestamp: Long) {
|
2021-11-23 21:14:40 +00:00
|
|
|
putLong(KEY_LAST_END_OF_PERIOD_SECONDS, timestamp)
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* True if the local user is likely a sustainer, otherwise false. Note the term 'likely', because this is based on cached data. Any serious decisions that
|
|
|
|
* rely on this should make a network request to determine subscription status.
|
|
|
|
*/
|
|
|
|
fun isLikelyASustainer(): Boolean {
|
|
|
|
return TimeUnit.SECONDS.toMillis(getLastEndOfPeriod()) > System.currentTimeMillis()
|
2021-10-21 19:39:02 +00:00
|
|
|
}
|
|
|
|
|
2021-10-29 17:05:22 +00:00
|
|
|
fun isUserManuallyCancelled(): Boolean {
|
|
|
|
return getBoolean(USER_MANUALLY_CANCELLED, false)
|
|
|
|
}
|
|
|
|
|
|
|
|
fun markUserManuallyCancelled() {
|
|
|
|
putBoolean(USER_MANUALLY_CANCELLED, true)
|
|
|
|
}
|
|
|
|
|
|
|
|
fun clearUserManuallyCancelled() {
|
|
|
|
remove(USER_MANUALLY_CANCELLED)
|
|
|
|
}
|
2021-11-11 18:59:30 +00:00
|
|
|
|
|
|
|
fun setDisplayBadgesOnProfile(enabled: Boolean) {
|
|
|
|
putBoolean(DISPLAY_BADGES_ON_PROFILE, enabled)
|
|
|
|
}
|
|
|
|
|
|
|
|
fun getDisplayBadgesOnProfile(): Boolean {
|
|
|
|
return getBoolean(DISPLAY_BADGES_ON_PROFILE, false)
|
|
|
|
}
|
2021-11-15 17:47:51 +00:00
|
|
|
|
|
|
|
fun getSubscriptionRedemptionFailed(): Boolean {
|
|
|
|
return getBoolean(SUBSCRIPTION_REDEMPTION_FAILED, false)
|
|
|
|
}
|
|
|
|
|
|
|
|
fun markSubscriptionRedemptionFailed() {
|
2021-11-22 19:57:20 +00:00
|
|
|
Log.w(TAG, "markSubscriptionRedemptionFailed()", Throwable(), true)
|
2021-11-15 17:47:51 +00:00
|
|
|
putBoolean(SUBSCRIPTION_REDEMPTION_FAILED, true)
|
|
|
|
}
|
|
|
|
|
|
|
|
fun clearSubscriptionRedemptionFailed() {
|
|
|
|
putBoolean(SUBSCRIPTION_REDEMPTION_FAILED, false)
|
|
|
|
}
|
2021-11-19 19:30:15 +00:00
|
|
|
|
2022-04-18 19:37:12 +00:00
|
|
|
fun setUnexpectedSubscriptionCancelationChargeFailure(chargeFailure: ActiveSubscription.ChargeFailure?) {
|
|
|
|
if (chargeFailure == null) {
|
|
|
|
remove(SUBSCRIPTION_CANCELATION_CHARGE_FAILURE)
|
|
|
|
} else {
|
|
|
|
putString(SUBSCRIPTION_CANCELATION_CHARGE_FAILURE, JsonUtil.toJson(chargeFailure))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
fun getUnexpectedSubscriptionCancelationChargeFailure(): ActiveSubscription.ChargeFailure? {
|
|
|
|
val json = getString(SUBSCRIPTION_CANCELATION_CHARGE_FAILURE, null)
|
|
|
|
return if (json.isNullOrEmpty()) {
|
|
|
|
null
|
|
|
|
} else {
|
|
|
|
JsonUtil.fromJson(json, ActiveSubscription.ChargeFailure::class.java)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-02-10 18:26:59 +00:00
|
|
|
var unexpectedSubscriptionCancelationReason: String? by stringValue(SUBSCRIPTION_CANCELATION_REASON, null)
|
2022-04-08 16:07:19 +00:00
|
|
|
var unexpectedSubscriptionCancelationTimestamp: Long by longValue(SUBSCRIPTION_CANCELATION_TIMESTAMP, 0L)
|
|
|
|
var unexpectedSubscriptionCancelationWatermark: Long by longValue(SUBSCRIPTION_CANCELATION_WATERMARK, 0L)
|
2022-02-10 18:26:59 +00:00
|
|
|
|
2022-04-04 16:50:54 +00:00
|
|
|
@get:JvmName("showCantProcessDialog")
|
2022-02-10 18:26:59 +00:00
|
|
|
var showCantProcessDialog: Boolean by booleanValue(SHOW_CANT_PROCESS_DIALOG, true)
|
|
|
|
|
2021-11-19 19:30:15 +00:00
|
|
|
/**
|
|
|
|
* Denotes that the previous attempt to subscribe failed in some way. Either an
|
|
|
|
* automatic renewal failed resulting in an unexpected expiration, or payment failed
|
|
|
|
* on Stripe's end.
|
|
|
|
*
|
|
|
|
* Before trying to resubscribe, we should first ensure there are no subscriptions set
|
|
|
|
* on the server. Otherwise, we could get into a situation where the user is unable to
|
|
|
|
* resubscribe.
|
|
|
|
*/
|
|
|
|
var shouldCancelSubscriptionBeforeNextSubscribeAttempt: Boolean
|
|
|
|
get() = getBoolean(SHOULD_CANCEL_SUBSCRIPTION_BEFORE_NEXT_SUBSCRIBE_ATTEMPT, false)
|
|
|
|
set(value) = putBoolean(SHOULD_CANCEL_SUBSCRIPTION_BEFORE_NEXT_SUBSCRIBE_ATTEMPT, value)
|
2022-05-16 19:19:26 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Consolidates a bunch of data clears that should occur whenever a user manually cancels their
|
|
|
|
* subscription:
|
|
|
|
*
|
|
|
|
* 1. Clears keep-alive flag
|
|
|
|
* 1. Clears level operation
|
|
|
|
* 1. Marks the user as manually cancelled
|
|
|
|
* 1. Clears out unexpected cancelation state
|
|
|
|
* 1. Clears expired badge if it is for a subscription
|
|
|
|
*/
|
|
|
|
@WorkerThread
|
|
|
|
fun updateLocalStateForManualCancellation() {
|
|
|
|
synchronized(SubscriptionReceiptRequestResponseJob.MUTEX) {
|
|
|
|
Log.d(TAG, "[updateLocalStateForManualCancellation] Clearing donation values.")
|
|
|
|
|
|
|
|
setLastEndOfPeriod(0L)
|
|
|
|
clearLevelOperations()
|
|
|
|
markUserManuallyCancelled()
|
|
|
|
shouldCancelSubscriptionBeforeNextSubscribeAttempt = false
|
|
|
|
setUnexpectedSubscriptionCancelationChargeFailure(null)
|
|
|
|
unexpectedSubscriptionCancelationReason = null
|
|
|
|
unexpectedSubscriptionCancelationTimestamp = 0L
|
|
|
|
|
|
|
|
val expiredBadge = getExpiredBadge()
|
|
|
|
if (expiredBadge != null && expiredBadge.isSubscription()) {
|
|
|
|
Log.d(TAG, "[updateLocalStateForManualCancellation] Clearing expired badge.")
|
|
|
|
setExpiredBadge(null)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Consolidates a bunch of data clears that should occur whenever a user begins a new subscription:
|
|
|
|
*
|
|
|
|
* 1. Manual cancellation marker
|
|
|
|
* 1. Any set level operations
|
|
|
|
* 1. Unexpected cancelation flags
|
|
|
|
* 1. Expired badge, if it is of a subscription
|
|
|
|
*/
|
|
|
|
@WorkerThread
|
|
|
|
fun updateLocalStateForLocalSubscribe() {
|
|
|
|
synchronized(SubscriptionReceiptRequestResponseJob.MUTEX) {
|
|
|
|
Log.d(TAG, "[updateLocalStateForLocalSubscribe] Clearing donation values.")
|
|
|
|
|
|
|
|
clearUserManuallyCancelled()
|
|
|
|
clearLevelOperations()
|
|
|
|
shouldCancelSubscriptionBeforeNextSubscribeAttempt = false
|
|
|
|
setUnexpectedSubscriptionCancelationChargeFailure(null)
|
|
|
|
unexpectedSubscriptionCancelationReason = null
|
|
|
|
unexpectedSubscriptionCancelationTimestamp = 0L
|
|
|
|
|
|
|
|
val expiredBadge = getExpiredBadge()
|
|
|
|
if (expiredBadge != null && expiredBadge.isSubscription()) {
|
|
|
|
Log.d(TAG, "[updateLocalStateForLocalSubscribe] Clearing expired badge.")
|
|
|
|
setExpiredBadge(null)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2021-10-12 18:55:54 +00:00
|
|
|
}
|