mirror of
https://github.com/signalapp/Signal-Android.git
synced 2026-04-21 09:20:19 +01:00
Add backup upgrade availability checks.
This commit is contained in:
@@ -0,0 +1,36 @@
|
||||
/*
|
||||
* Copyright 2025 Signal Messenger, LLC
|
||||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
|
||||
package org.thoughtcrime.securesms.backup.v2.ui.subscription
|
||||
|
||||
import android.content.Context
|
||||
import com.google.android.gms.common.GoogleApiAvailability
|
||||
import org.thoughtcrime.securesms.dependencies.AppDependencies
|
||||
|
||||
/**
|
||||
* Delegate object for checking whether backup upgrade prompts should be shown to the user.
|
||||
*/
|
||||
object BackupUpgradeAvailabilityChecker {
|
||||
|
||||
/**
|
||||
* Best effort check for upgrade access. We check availability and show proper dialogs in the checkout
|
||||
* flow, so this is fine as "best effort"
|
||||
*/
|
||||
suspend fun isUpgradeAvailable(
|
||||
context: Context
|
||||
): Boolean {
|
||||
val googlePlayServicesCode = GoogleApiAvailability.getInstance().isGooglePlayServicesAvailable(context)
|
||||
val googlePlayServicesAvailability = GooglePlayServicesAvailability.fromCode(googlePlayServicesCode)
|
||||
|
||||
return when (googlePlayServicesAvailability) {
|
||||
GooglePlayServicesAvailability.UNKNOWN, GooglePlayServicesAvailability.SERVICE_MISSING, GooglePlayServicesAvailability.SERVICE_DISABLED, GooglePlayServicesAvailability.SERVICE_INVALID -> false
|
||||
GooglePlayServicesAvailability.SERVICE_VERSION_UPDATE_REQUIRED, GooglePlayServicesAvailability.SERVICE_UPDATING -> true
|
||||
GooglePlayServicesAvailability.SUCCESS -> {
|
||||
val billingResponseCode = AppDependencies.billingApi.getApiAvailability()
|
||||
billingResponseCode.isSuccess
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -507,6 +507,7 @@ private fun RemoteBackupsSettingsContent(
|
||||
backupState = state.backupState,
|
||||
onBackupTypeActionButtonClicked = contentCallbacks::onBackupTypeActionClick,
|
||||
isPaidTierPricingAvailable = state.isPaidTierPricingAvailable,
|
||||
isGooglePlayServicesAvailable = state.isGooglePlayServicesAvailable,
|
||||
buttonsEnabled = backupDeleteState.isIdle()
|
||||
)
|
||||
}
|
||||
@@ -994,6 +995,7 @@ private fun LazyListScope.appendBackupDetailsItems(
|
||||
private fun BackupCard(
|
||||
backupState: BackupState.WithTypeAndRenewalTime,
|
||||
isPaidTierPricingAvailable: Boolean,
|
||||
isGooglePlayServicesAvailable: Boolean,
|
||||
buttonsEnabled: Boolean,
|
||||
onBackupTypeActionButtonClicked: (MessageBackupTier) -> Unit = {}
|
||||
) {
|
||||
@@ -1085,7 +1087,7 @@ private fun BackupCard(
|
||||
)
|
||||
}
|
||||
|
||||
if (backupState.isActive() && isPaidTierPricingAvailable) {
|
||||
if (backupState.isActive() && isPaidTierPricingAvailable && isGooglePlayServicesAvailable) {
|
||||
val buttonText = when (messageBackupsType) {
|
||||
is MessageBackupsType.Paid -> stringResource(R.string.RemoteBackupsSettingsFragment__manage_or_cancel)
|
||||
is MessageBackupsType.Free -> stringResource(R.string.RemoteBackupsSettingsFragment__upgrade)
|
||||
@@ -1857,6 +1859,7 @@ private fun BackupCardPreview() {
|
||||
price = FiatMoney(BigDecimal.valueOf(3), Currency.getInstance("CAD"))
|
||||
),
|
||||
isPaidTierPricingAvailable = true,
|
||||
isGooglePlayServicesAvailable = true,
|
||||
buttonsEnabled = true
|
||||
)
|
||||
}
|
||||
@@ -1872,6 +1875,7 @@ private fun BackupCardPreview() {
|
||||
renewalTime = 1727193018.seconds
|
||||
),
|
||||
isPaidTierPricingAvailable = true,
|
||||
isGooglePlayServicesAvailable = true,
|
||||
buttonsEnabled = true
|
||||
)
|
||||
}
|
||||
@@ -1887,6 +1891,7 @@ private fun BackupCardPreview() {
|
||||
renewalTime = 1727193018.seconds
|
||||
),
|
||||
isPaidTierPricingAvailable = true,
|
||||
isGooglePlayServicesAvailable = true,
|
||||
buttonsEnabled = true
|
||||
)
|
||||
}
|
||||
@@ -1903,6 +1908,7 @@ private fun BackupCardPreview() {
|
||||
price = FiatMoney(BigDecimal.valueOf(3), Currency.getInstance("CAD"))
|
||||
),
|
||||
isPaidTierPricingAvailable = true,
|
||||
isGooglePlayServicesAvailable = true,
|
||||
buttonsEnabled = true
|
||||
)
|
||||
}
|
||||
@@ -1915,6 +1921,7 @@ private fun BackupCardPreview() {
|
||||
)
|
||||
),
|
||||
isPaidTierPricingAvailable = true,
|
||||
isGooglePlayServicesAvailable = true,
|
||||
buttonsEnabled = true
|
||||
)
|
||||
}
|
||||
@@ -1927,6 +1934,7 @@ private fun BackupCardPreview() {
|
||||
)
|
||||
),
|
||||
isPaidTierPricingAvailable = false,
|
||||
isGooglePlayServicesAvailable = true,
|
||||
buttonsEnabled = true
|
||||
)
|
||||
}
|
||||
|
||||
@@ -32,7 +32,8 @@ data class RemoteBackupsSettingsState(
|
||||
val backupMediaDetails: BackupMediaDetails? = null,
|
||||
val showBackupCreateFailedError: Boolean = false,
|
||||
val showBackupCreateCouldNotCompleteError: Boolean = false,
|
||||
val freeTierMediaRetentionDays: Int = -1
|
||||
val freeTierMediaRetentionDays: Int = -1,
|
||||
val isGooglePlayServicesAvailable: Boolean = false
|
||||
) {
|
||||
|
||||
data class BackupMediaDetails(
|
||||
|
||||
@@ -34,6 +34,7 @@ import org.thoughtcrime.securesms.backup.v2.ArchiveRestoreProgress
|
||||
import org.thoughtcrime.securesms.backup.v2.ArchiveRestoreProgressState.RestoreStatus
|
||||
import org.thoughtcrime.securesms.backup.v2.BackupRepository
|
||||
import org.thoughtcrime.securesms.backup.v2.MessageBackupTier
|
||||
import org.thoughtcrime.securesms.backup.v2.ui.subscription.BackupUpgradeAvailabilityChecker
|
||||
import org.thoughtcrime.securesms.backup.v2.ui.subscription.MessageBackupsType
|
||||
import org.thoughtcrime.securesms.components.settings.app.backups.BackupState
|
||||
import org.thoughtcrime.securesms.components.settings.app.backups.BackupStateObserver
|
||||
@@ -101,6 +102,12 @@ class RemoteBackupsSettingsViewModel : ViewModel() {
|
||||
}
|
||||
}
|
||||
|
||||
viewModelScope.launch {
|
||||
_state.update {
|
||||
it.copy(isGooglePlayServicesAvailable = BackupUpgradeAvailabilityChecker.isUpgradeAvailable(AppDependencies.application))
|
||||
}
|
||||
}
|
||||
|
||||
viewModelScope.launch(Dispatchers.IO) {
|
||||
refreshBackupMediaSizeState()
|
||||
}
|
||||
|
||||
@@ -16,6 +16,7 @@ import kotlinx.coroutines.flow.update
|
||||
import kotlinx.coroutines.launch
|
||||
import org.signal.core.util.concurrent.SignalExecutors
|
||||
import org.thoughtcrime.securesms.backup.v2.MessageBackupTier
|
||||
import org.thoughtcrime.securesms.backup.v2.ui.subscription.BackupUpgradeAvailabilityChecker
|
||||
import org.thoughtcrime.securesms.components.settings.app.subscription.InAppPaymentsRepository
|
||||
import org.thoughtcrime.securesms.database.InAppPaymentTable
|
||||
import org.thoughtcrime.securesms.database.MediaTable
|
||||
@@ -133,7 +134,7 @@ class ManageStorageSettingsViewModel : ViewModel() {
|
||||
|
||||
private suspend fun getOnDeviceStorageOptimizationState(): OnDeviceStorageOptimizationState {
|
||||
return when {
|
||||
!SignalStore.backup.areBackupsEnabled || !AppDependencies.billingApi.getApiAvailability().isSuccess || (!RemoteConfig.internalUser && !Environment.IS_STAGING) -> OnDeviceStorageOptimizationState.FEATURE_NOT_AVAILABLE
|
||||
!SignalStore.backup.areBackupsEnabled || !BackupUpgradeAvailabilityChecker.isUpgradeAvailable(AppDependencies.application) || (!RemoteConfig.internalUser && !Environment.IS_STAGING) -> OnDeviceStorageOptimizationState.FEATURE_NOT_AVAILABLE
|
||||
SignalStore.backup.backupTier != MessageBackupTier.PAID -> OnDeviceStorageOptimizationState.REQUIRES_PAID_TIER
|
||||
SignalStore.backup.optimizeStorage -> OnDeviceStorageOptimizationState.ENABLED
|
||||
else -> OnDeviceStorageOptimizationState.DISABLED
|
||||
|
||||
@@ -118,6 +118,7 @@ import org.thoughtcrime.securesms.MuteDialog
|
||||
import org.thoughtcrime.securesms.R
|
||||
import org.thoughtcrime.securesms.attachments.AttachmentSaver
|
||||
import org.thoughtcrime.securesms.audio.AudioRecorder
|
||||
import org.thoughtcrime.securesms.backup.v2.ui.subscription.BackupUpgradeAvailabilityChecker
|
||||
import org.thoughtcrime.securesms.badges.gifts.OpenableGift
|
||||
import org.thoughtcrime.securesms.badges.gifts.OpenableGiftItemDecoration
|
||||
import org.thoughtcrime.securesms.badges.gifts.viewgift.received.ViewReceivedGiftBottomSheet
|
||||
@@ -3069,10 +3070,14 @@ class ConversationFragment :
|
||||
}
|
||||
|
||||
override fun onDisplayMediaNoLongerAvailableSheet() {
|
||||
if (SignalStore.backup.areBackupsEnabled) {
|
||||
UpgradeToStartMediaBackupSheet().show(parentFragmentManager, BottomSheetUtil.STANDARD_BOTTOM_SHEET_FRAGMENT_TAG)
|
||||
} else {
|
||||
MediaNoLongerAvailableBottomSheet().show(parentFragmentManager, BottomSheetUtil.STANDARD_BOTTOM_SHEET_FRAGMENT_TAG)
|
||||
viewLifecycleOwner.lifecycleScope.launch {
|
||||
val isUpgradeAvailable = BackupUpgradeAvailabilityChecker.isUpgradeAvailable(requireContext())
|
||||
|
||||
if (SignalStore.backup.areBackupsEnabled && isUpgradeAvailable) {
|
||||
UpgradeToStartMediaBackupSheet().show(parentFragmentManager, BottomSheetUtil.STANDARD_BOTTOM_SHEET_FRAGMENT_TAG)
|
||||
} else {
|
||||
MediaNoLongerAvailableBottomSheet().show(parentFragmentManager, BottomSheetUtil.STANDARD_BOTTOM_SHEET_FRAGMENT_TAG)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user