mirror of
https://github.com/signalapp/Signal-Android.git
synced 2025-12-23 04:28:35 +00:00
Prevent "Free" tier from being upgraded in the background.
This commit is contained in:
@@ -169,7 +169,7 @@ private fun BackupsSettingsContent(
|
||||
OtherWaysToBackUpHeading()
|
||||
}
|
||||
|
||||
is BackupState.ActiveFree, is BackupState.ActivePaid -> {
|
||||
is BackupState.ActiveFree, is BackupState.ActivePaid, is BackupState.Canceled -> {
|
||||
ActiveBackupsRow(
|
||||
backupState = backupsSettingsState.backupState,
|
||||
onBackupsRowClick = onBackupsRowClick,
|
||||
@@ -210,15 +210,6 @@ private fun BackupsSettingsContent(
|
||||
OtherWaysToBackUpHeading()
|
||||
}
|
||||
|
||||
is BackupState.Canceled -> {
|
||||
ActiveBackupsRow(
|
||||
backupState = backupsSettingsState.backupState,
|
||||
lastBackupAt = backupsSettingsState.lastBackupAt
|
||||
)
|
||||
|
||||
OtherWaysToBackUpHeading()
|
||||
}
|
||||
|
||||
is BackupState.SubscriptionMismatchMissingGooglePlay -> {
|
||||
ActiveBackupsRow(
|
||||
backupState = backupsSettingsState.backupState,
|
||||
@@ -421,13 +412,25 @@ private fun ActiveBackupsRow(
|
||||
|
||||
when (val type = backupState.messageBackupsType) {
|
||||
is MessageBackupsType.Paid -> {
|
||||
Text(
|
||||
text = stringResource(
|
||||
val body = if (backupState is BackupState.Canceled) {
|
||||
stringResource(R.string.BackupsSettingsFragment__subscription_canceled)
|
||||
} else {
|
||||
stringResource(
|
||||
R.string.BackupsSettingsFragment_s_month_renews_s,
|
||||
FiatMoneyUtil.format(LocalContext.current.resources, type.pricePerMonth),
|
||||
DateUtils.formatDateWithYear(Locale.getDefault(), backupState.renewalTime.inWholeMilliseconds)
|
||||
),
|
||||
color = MaterialTheme.colorScheme.onSurfaceVariant,
|
||||
)
|
||||
}
|
||||
|
||||
val color = if (backupState is BackupState.Canceled) {
|
||||
MaterialTheme.colorScheme.error
|
||||
} else {
|
||||
MaterialTheme.colorScheme.onSurfaceVariant
|
||||
}
|
||||
|
||||
Text(
|
||||
text = body,
|
||||
color = color,
|
||||
style = MaterialTheme.typography.bodyMedium
|
||||
)
|
||||
}
|
||||
|
||||
@@ -71,43 +71,43 @@ class BackupSubscriptionCheckJob private constructor(parameters: Parameters) : C
|
||||
|
||||
override suspend fun doRun(): Result {
|
||||
if (!SignalStore.account.isRegistered) {
|
||||
Log.i(TAG, "User is not registered. Clearing mismatch value and exiting.")
|
||||
Log.i(TAG, "User is not registered. Clearing mismatch value and exiting.", true)
|
||||
SignalStore.backup.subscriptionStateMismatchDetected = false
|
||||
return Result.success()
|
||||
}
|
||||
|
||||
if (!RemoteConfig.messageBackups) {
|
||||
Log.i(TAG, "Message backups feature is not available. Clearing mismatch value and exiting.")
|
||||
Log.i(TAG, "Message backups feature is not available. Clearing mismatch value and exiting.", true)
|
||||
SignalStore.backup.subscriptionStateMismatchDetected = false
|
||||
return Result.success()
|
||||
}
|
||||
|
||||
if (!AppDependencies.billingApi.isApiAvailable()) {
|
||||
Log.i(TAG, "Google Play Billing API is not available on this device. Clearing mismatch value and exiting.")
|
||||
Log.i(TAG, "Google Play Billing API is not available on this device. Clearing mismatch value and exiting.", true)
|
||||
SignalStore.backup.subscriptionStateMismatchDetected = false
|
||||
return Result.success()
|
||||
}
|
||||
|
||||
if (SignalStore.backup.deletionState != DeletionState.NONE) {
|
||||
Log.i(TAG, "User is in the process of or has delete their backup. Clearing mismatch value and exiting.")
|
||||
Log.i(TAG, "User is in the process of or has delete their backup. Clearing mismatch value and exiting.", true)
|
||||
SignalStore.backup.subscriptionStateMismatchDetected = false
|
||||
return Result.success()
|
||||
}
|
||||
|
||||
if (!SignalStore.backup.areBackupsEnabled) {
|
||||
Log.i(TAG, "Backups are not enabled on this device. Clearing mismatch value and exiting.")
|
||||
Log.i(TAG, "Backups are not enabled on this device. Clearing mismatch value and exiting.", true)
|
||||
SignalStore.backup.subscriptionStateMismatchDetected = false
|
||||
return Result.success()
|
||||
}
|
||||
|
||||
val purchase: BillingPurchaseResult = AppDependencies.billingApi.queryPurchases()
|
||||
Log.i(TAG, "Retrieved purchase result from Billing api: $purchase")
|
||||
Log.i(TAG, "Retrieved purchase result from Billing api: $purchase", true)
|
||||
|
||||
val hasActivePurchase = purchase is BillingPurchaseResult.Success && purchase.isAcknowledged
|
||||
val product: BillingProduct? = AppDependencies.billingApi.queryProduct()
|
||||
|
||||
if (product == null) {
|
||||
Log.w(TAG, "Google Play Billing product not available. Exiting.")
|
||||
Log.w(TAG, "Google Play Billing product not available. Exiting.", true)
|
||||
return Result.failure()
|
||||
}
|
||||
|
||||
@@ -115,7 +115,7 @@ class BackupSubscriptionCheckJob private constructor(parameters: Parameters) : C
|
||||
val inAppPayment = SignalDatabase.inAppPayments.getLatestInAppPaymentByType(InAppPaymentType.RECURRING_BACKUP)
|
||||
|
||||
if (inAppPayment?.state == InAppPaymentTable.State.PENDING) {
|
||||
Log.i(TAG, "User has a pending in-app payment. Clearing mismatch value and re-checking later.")
|
||||
Log.i(TAG, "User has a pending in-app payment. Clearing mismatch value and re-checking later.", true)
|
||||
SignalStore.backup.subscriptionStateMismatchDetected = false
|
||||
return Result.success()
|
||||
}
|
||||
@@ -125,9 +125,12 @@ class BackupSubscriptionCheckJob private constructor(parameters: Parameters) : C
|
||||
|
||||
checkForFailedOrCanceledSubscriptionState(activeSubscription)
|
||||
|
||||
Log.i(TAG, "Synchronizing backup tier with value from server.")
|
||||
BackupRepository.getBackupTier().runIfSuccessful {
|
||||
SignalStore.backup.backupTier = it
|
||||
val isSignalSubscriptionFailedOrCanceled = activeSubscription?.isFailedPayment == true || activeSubscription?.isCanceled == true
|
||||
if (hasActiveSignalSubscription && !isSignalSubscriptionFailedOrCanceled) {
|
||||
Log.i(TAG, "Detected an active, non-failed, non-canceled signal subscription. Synchronizing backup tier with value from server.", true)
|
||||
BackupRepository.getBackupTier().runIfSuccessful {
|
||||
SignalStore.backup.backupTier = it
|
||||
}
|
||||
}
|
||||
|
||||
val hasActivePaidBackupTier = SignalStore.backup.backupTier == MessageBackupTier.PAID
|
||||
@@ -135,14 +138,14 @@ class BackupSubscriptionCheckJob private constructor(parameters: Parameters) : C
|
||||
val hasValidInactiveState = !hasActivePaidBackupTier && !hasActiveSignalSubscription && !hasActivePurchase
|
||||
|
||||
val purchaseToken = if (hasActivePurchase) {
|
||||
(purchase as BillingPurchaseResult.Success).purchaseToken
|
||||
purchase.purchaseToken
|
||||
} else {
|
||||
null
|
||||
}
|
||||
|
||||
val hasTokenMismatch = purchaseToken?.let { hasLocalDevicePurchaseTokenMismatch(purchaseToken) } == true
|
||||
if (hasActiveSignalSubscription && hasTokenMismatch) {
|
||||
Log.i(TAG, "Encountered token mismatch with an active Signal subscription. Attempting to redeem against latest token.")
|
||||
Log.i(TAG, "Encountered token mismatch with an active Signal subscription. Attempting to redeem against latest token.", true)
|
||||
enqueueRedemptionForNewToken(purchaseToken, product.price)
|
||||
SignalStore.backup.subscriptionStateMismatchDetected = false
|
||||
return Result.success()
|
||||
@@ -152,9 +155,17 @@ class BackupSubscriptionCheckJob private constructor(parameters: Parameters) : C
|
||||
SignalStore.backup.subscriptionStateMismatchDetected = false
|
||||
return Result.success()
|
||||
} else {
|
||||
Log.w(TAG, "State mismatch: (hasActivePaidBackupTier: $hasActivePaidBackupTier, hasActiveSignalSubscription: $hasActiveSignalSubscription, hasActivePurchase: $hasActivePurchase). Setting mismatch value and exiting.", true)
|
||||
SignalStore.backup.subscriptionStateMismatchDetected = true
|
||||
return Result.success()
|
||||
val isGooglePlayBillingCanceled = purchase is BillingPurchaseResult.Success && !purchase.isAutoRenewing
|
||||
|
||||
if (isGooglePlayBillingCanceled && (!hasActiveSignalSubscription || isSignalSubscriptionFailedOrCanceled)) {
|
||||
Log.i(TAG, "Valid cancel state. Clearing mismatch. (isGooglePlayBillingCanceled: true, hasActiveSignalSubscription: $hasActiveSignalSubscription, isSignalSubscriptionFailedOrCanceled: $isSignalSubscriptionFailedOrCanceled", true)
|
||||
SignalStore.backup.subscriptionStateMismatchDetected = false
|
||||
return Result.success()
|
||||
} else {
|
||||
Log.w(TAG, "State mismatch: (hasActivePaidBackupTier: $hasActivePaidBackupTier, hasActiveSignalSubscription: $hasActiveSignalSubscription, hasActivePurchase: $hasActivePurchase). Setting mismatch value and exiting.", true)
|
||||
SignalStore.backup.subscriptionStateMismatchDetected = true
|
||||
return Result.success()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8072,6 +8072,8 @@
|
||||
<string name="BackupsSettingsFragment_s_month_renews_s">%1$s/month, renews %2$s</string>
|
||||
<!-- Subtitle for row for active backup, placeholder is last date of backup -->
|
||||
<string name="BackupsSettingsFragment_last_backup_s">Last backup %1$s</string>
|
||||
<!-- Subtitle for row for canceled backup -->
|
||||
<string name="BackupsSettingsFragment__subscription_canceled">Subscription canceled</string>
|
||||
<!-- Subtitle for row for no backup ever created -->
|
||||
<string name="BackupsSettingsFragment_automatic_backups_with_signals">Automatic backups with Signal\'s secure end-to-end encrypted storage service.</string>
|
||||
<!-- Subtitle for row for backups that are active but subscription not found -->
|
||||
|
||||
Reference in New Issue
Block a user