Add MediaTTL to subscriptions configuration and wire in.

This commit is contained in:
Alex Hart 2024-11-14 10:38:28 -04:00 committed by Greyson Parrelli
parent bf3012bd8a
commit 61f91d6b83
8 changed files with 51 additions and 20 deletions

View file

@ -99,6 +99,7 @@ import java.io.OutputStream
import java.time.ZonedDateTime
import java.util.Locale
import java.util.concurrent.atomic.AtomicLong
import kotlin.time.Duration.Companion.days
import kotlin.time.Duration.Companion.milliseconds
import org.signal.libsignal.messagebackup.MessageBackupKey as LibSignalMessageBackupKey
@ -1147,10 +1148,12 @@ object BackupRepository {
private suspend fun getPaidType(): MessageBackupsType? {
val config = getSubscriptionsConfiguration()
val product = AppDependencies.billingApi.queryProduct() ?: return null
val backupLevelConfiguration = config.backupConfiguration.backupLevelConfigurationMap[SubscriptionsConfiguration.BACKUPS_LEVEL] ?: return null
return MessageBackupsType.Paid(
pricePerMonth = product.price,
storageAllowanceBytes = config.backupConfiguration.backupLevelConfigurationMap[SubscriptionsConfiguration.BACKUPS_LEVEL]!!.storageAllowanceBytes
storageAllowanceBytes = backupLevelConfiguration.storageAllowanceBytes,
mediaTtl = backupLevelConfiguration.mediaTtlDays.days
)
}

View file

@ -57,6 +57,7 @@ import org.thoughtcrime.securesms.dependencies.AppDependencies
import org.thoughtcrime.securesms.jobs.BackupMessagesJob
import org.thoughtcrime.securesms.jobs.BackupRestoreMediaJob
import org.thoughtcrime.securesms.payments.FiatMoneyUtil
import kotlin.time.Duration
import kotlin.time.Duration.Companion.days
import kotlin.time.Duration.Companion.milliseconds
import org.signal.core.ui.R as CoreUiR
@ -102,6 +103,7 @@ class BackupAlertBottomSheet : UpgradeToPaidTierBottomSheet() {
BackupAlertSheetContent(
backupAlert = backupAlert,
isSubscribeEnabled = isSubscribeEnabled,
mediaTtl = paidBackupType.mediaTtl,
onPrimaryActionClick = performPrimaryAction,
onSecondaryActionClick = this::performSecondaryAction
)
@ -195,6 +197,7 @@ private fun BackupAlertSheetContent(
backupAlert: BackupAlert,
pricePerMonth: String = "",
isSubscribeEnabled: Boolean = true,
mediaTtl: Duration,
onPrimaryActionClick: () -> Unit = {},
onSecondaryActionClick: () -> Unit = {}
) {
@ -254,7 +257,7 @@ private fun BackupAlertSheetContent(
)
BackupAlert.FailedToRenew -> PaymentProcessingBody()
is BackupAlert.MediaBackupsAreOff -> MediaBackupsAreOffBody(backupAlert.endOfPeriodSeconds)
is BackupAlert.MediaBackupsAreOff -> MediaBackupsAreOffBody(backupAlert.endOfPeriodSeconds, mediaTtl)
BackupAlert.MediaWillBeDeletedToday -> MediaWillBeDeletedTodayBody()
is BackupAlert.DiskFull -> DiskFullBody(requiredSpace = backupAlert.requiredSpace)
}
@ -308,10 +311,10 @@ private fun PaymentProcessingBody() {
@Composable
private fun MediaBackupsAreOffBody(
endOfPeriodSeconds: Long
endOfPeriodSeconds: Long,
mediaTtl: Duration
) {
// TODO [backups] Get value from config to calculate days until deletion.
val daysUntilDeletion = remember { endOfPeriodSeconds.days + 60.days }.inWholeDays.toInt()
val daysUntilDeletion = remember { endOfPeriodSeconds.days + mediaTtl }.inWholeDays.toInt()
Text(
text = pluralStringResource(id = R.plurals.BackupAlertBottomSheet__your_backup_plan_has_expired, daysUntilDeletion, daysUntilDeletion),
@ -416,7 +419,8 @@ private fun rememberSecondaryActionResource(backupAlert: BackupAlert): Int {
private fun BackupAlertSheetContentPreviewGeneric() {
Previews.BottomSheetPreview {
BackupAlertSheetContent(
backupAlert = BackupAlert.CouldNotCompleteBackup(daysSinceLastBackup = 7)
backupAlert = BackupAlert.CouldNotCompleteBackup(daysSinceLastBackup = 7),
mediaTtl = 60.days
)
}
}
@ -426,7 +430,8 @@ private fun BackupAlertSheetContentPreviewGeneric() {
private fun BackupAlertSheetContentPreviewPayment() {
Previews.BottomSheetPreview {
BackupAlertSheetContent(
backupAlert = BackupAlert.FailedToRenew
backupAlert = BackupAlert.FailedToRenew,
mediaTtl = 60.days
)
}
}
@ -437,7 +442,8 @@ private fun BackupAlertSheetContentPreviewMedia() {
Previews.BottomSheetPreview {
BackupAlertSheetContent(
backupAlert = BackupAlert.MediaBackupsAreOff(endOfPeriodSeconds = System.currentTimeMillis().milliseconds.inWholeSeconds),
pricePerMonth = "$2.99"
pricePerMonth = "$2.99",
mediaTtl = 60.days
)
}
}
@ -447,7 +453,8 @@ private fun BackupAlertSheetContentPreviewMedia() {
private fun BackupAlertSheetContentPreviewDelete() {
Previews.BottomSheetPreview {
BackupAlertSheetContent(
backupAlert = BackupAlert.MediaWillBeDeletedToday
backupAlert = BackupAlert.MediaWillBeDeletedToday,
mediaTtl = 60.days
)
}
}
@ -457,7 +464,8 @@ private fun BackupAlertSheetContentPreviewDelete() {
private fun BackupAlertSheetContentPreviewDiskFull() {
Previews.BottomSheetPreview {
BackupAlertSheetContent(
backupAlert = BackupAlert.DiskFull(requiredSpace = "12GB")
backupAlert = BackupAlert.DiskFull(requiredSpace = "12GB"),
mediaTtl = 60.days
)
}
}

View file

@ -8,6 +8,7 @@ package org.thoughtcrime.securesms.backup.v2.ui.subscription
import androidx.compose.runtime.Stable
import org.signal.core.util.money.FiatMoney
import org.thoughtcrime.securesms.backup.v2.MessageBackupTier
import kotlin.time.Duration
/**
* Represents a type of backup a user can select.
@ -19,7 +20,8 @@ sealed interface MessageBackupsType {
data class Paid(
val pricePerMonth: FiatMoney,
val storageAllowanceBytes: Long
val storageAllowanceBytes: Long,
val mediaTtl: Duration
) : MessageBackupsType {
override val tier: MessageBackupTier = MessageBackupTier.PAID
}

View file

@ -59,6 +59,7 @@ import org.thoughtcrime.securesms.payments.FiatMoneyUtil
import org.thoughtcrime.securesms.util.ByteUnit
import java.math.BigDecimal
import java.util.Currency
import kotlin.time.Duration.Companion.days
import org.signal.core.ui.R as CoreUiR
/**
@ -369,7 +370,8 @@ fun testBackupTypes(): List<MessageBackupsType> {
),
MessageBackupsType.Paid(
pricePerMonth = FiatMoney(BigDecimal.ONE, Currency.getInstance("USD")),
storageAllowanceBytes = 107374182400
storageAllowanceBytes = 107374182400,
mediaTtl = 30.days
)
)
}

View file

@ -51,6 +51,7 @@ import org.thoughtcrime.securesms.util.navigation.safeNavigate
import java.math.BigDecimal
import java.util.Currency
import java.util.Locale
import kotlin.time.Duration.Companion.days
import kotlin.time.Duration.Companion.seconds
import org.signal.core.ui.R as CoreUiR
@ -342,7 +343,8 @@ private fun BackupsSettingsContentPreview() {
enabledState = BackupsSettingsState.EnabledState.Active(
type = MessageBackupsType.Paid(
pricePerMonth = FiatMoney(BigDecimal.valueOf(4), Currency.getInstance("CAD")),
storageAllowanceBytes = 1_000_000
storageAllowanceBytes = 1_000_000,
mediaTtl = 30.days
),
expiresAt = 0.seconds,
lastBackupAt = 0.seconds
@ -388,7 +390,8 @@ private fun ActivePaidBackupsRowPreview() {
enabledState = BackupsSettingsState.EnabledState.Active(
type = MessageBackupsType.Paid(
pricePerMonth = FiatMoney(BigDecimal.valueOf(4), Currency.getInstance("CAD")),
storageAllowanceBytes = 1_000_000
storageAllowanceBytes = 1_000_000,
mediaTtl = 30.days
),
expiresAt = 0.seconds,
lastBackupAt = 0.seconds

View file

@ -101,7 +101,8 @@ class BackupsSettingsViewModel : ViewModel() {
activeSubscription.activeSubscription.amount,
Currency.getInstance(activeSubscription.activeSubscription.currency)
),
storageAllowanceBytes = backupType.storageAllowanceBytes
storageAllowanceBytes = backupType.storageAllowanceBytes,
mediaTtl = backupType.mediaTtl
)
)
} else {

View file

@ -1225,7 +1225,8 @@ private fun SubscriptionMismatchMissingGooglePlayCardPreview() {
state = RemoteBackupsSettingsState.BackupState.SubscriptionMismatchMissingGooglePlay(
messageBackupsType = MessageBackupsType.Paid(
pricePerMonth = FiatMoney(BigDecimal.valueOf(3), Currency.getInstance("CAD")),
storageAllowanceBytes = 100_000_000
storageAllowanceBytes = 100_000_000,
mediaTtl = 30.days
),
renewalTime = System.currentTimeMillis().milliseconds + 30.days
)
@ -1242,7 +1243,8 @@ private fun BackupCardPreview() {
backupState = RemoteBackupsSettingsState.BackupState.ActivePaid(
messageBackupsType = MessageBackupsType.Paid(
pricePerMonth = FiatMoney(BigDecimal.valueOf(3), Currency.getInstance("CAD")),
storageAllowanceBytes = 100_000_000
storageAllowanceBytes = 100_000_000,
mediaTtl = 30.days
),
renewalTime = 1727193018.seconds,
price = FiatMoney(BigDecimal.valueOf(3), Currency.getInstance("CAD"))
@ -1253,7 +1255,8 @@ private fun BackupCardPreview() {
backupState = RemoteBackupsSettingsState.BackupState.Canceled(
messageBackupsType = MessageBackupsType.Paid(
pricePerMonth = FiatMoney(BigDecimal.valueOf(3), Currency.getInstance("CAD")),
storageAllowanceBytes = 100_000_000
storageAllowanceBytes = 100_000_000,
mediaTtl = 30.days
),
renewalTime = 1727193018.seconds
)
@ -1263,7 +1266,8 @@ private fun BackupCardPreview() {
backupState = RemoteBackupsSettingsState.BackupState.Inactive(
messageBackupsType = MessageBackupsType.Paid(
pricePerMonth = FiatMoney(BigDecimal.valueOf(3), Currency.getInstance("CAD")),
storageAllowanceBytes = 100_000_000
storageAllowanceBytes = 100_000_000,
mediaTtl = 30.days
),
renewalTime = 1727193018.seconds
)
@ -1273,7 +1277,8 @@ private fun BackupCardPreview() {
backupState = RemoteBackupsSettingsState.BackupState.ActivePaid(
messageBackupsType = MessageBackupsType.Paid(
pricePerMonth = FiatMoney(BigDecimal.valueOf(3), Currency.getInstance("CAD")),
storageAllowanceBytes = 100_000_000
storageAllowanceBytes = 100_000_000,
mediaTtl = 30.days
),
renewalTime = 1727193018.seconds,
price = FiatMoney(BigDecimal.valueOf(3), Currency.getInstance("CAD"))

View file

@ -108,6 +108,9 @@ public class SubscriptionsConfiguration {
@JsonProperty("playProductId")
private String playProductId;
@JsonProperty("mediaTtlDays")
private long mediaTtlDays;
public long getStorageAllowanceBytes() {
return storageAllowanceBytes;
}
@ -115,6 +118,10 @@ public class SubscriptionsConfiguration {
public String getPlayProductId() {
return playProductId;
}
public long getMediaTtlDays() {
return mediaTtlDays;
}
}
public Map<String, CurrencyConfiguration> getCurrencies() {