mirror of
https://github.com/signalapp/Signal-Android.git
synced 2025-12-20 11:08:31 +00:00
Add MediaTTL to subscriptions configuration and wire in.
This commit is contained in:
committed by
Greyson Parrelli
parent
bf3012bd8a
commit
61f91d6b83
@@ -99,6 +99,7 @@ import java.io.OutputStream
|
|||||||
import java.time.ZonedDateTime
|
import java.time.ZonedDateTime
|
||||||
import java.util.Locale
|
import java.util.Locale
|
||||||
import java.util.concurrent.atomic.AtomicLong
|
import java.util.concurrent.atomic.AtomicLong
|
||||||
|
import kotlin.time.Duration.Companion.days
|
||||||
import kotlin.time.Duration.Companion.milliseconds
|
import kotlin.time.Duration.Companion.milliseconds
|
||||||
import org.signal.libsignal.messagebackup.MessageBackupKey as LibSignalMessageBackupKey
|
import org.signal.libsignal.messagebackup.MessageBackupKey as LibSignalMessageBackupKey
|
||||||
|
|
||||||
@@ -1147,10 +1148,12 @@ object BackupRepository {
|
|||||||
private suspend fun getPaidType(): MessageBackupsType? {
|
private suspend fun getPaidType(): MessageBackupsType? {
|
||||||
val config = getSubscriptionsConfiguration()
|
val config = getSubscriptionsConfiguration()
|
||||||
val product = AppDependencies.billingApi.queryProduct() ?: return null
|
val product = AppDependencies.billingApi.queryProduct() ?: return null
|
||||||
|
val backupLevelConfiguration = config.backupConfiguration.backupLevelConfigurationMap[SubscriptionsConfiguration.BACKUPS_LEVEL] ?: return null
|
||||||
|
|
||||||
return MessageBackupsType.Paid(
|
return MessageBackupsType.Paid(
|
||||||
pricePerMonth = product.price,
|
pricePerMonth = product.price,
|
||||||
storageAllowanceBytes = config.backupConfiguration.backupLevelConfigurationMap[SubscriptionsConfiguration.BACKUPS_LEVEL]!!.storageAllowanceBytes
|
storageAllowanceBytes = backupLevelConfiguration.storageAllowanceBytes,
|
||||||
|
mediaTtl = backupLevelConfiguration.mediaTtlDays.days
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -57,6 +57,7 @@ import org.thoughtcrime.securesms.dependencies.AppDependencies
|
|||||||
import org.thoughtcrime.securesms.jobs.BackupMessagesJob
|
import org.thoughtcrime.securesms.jobs.BackupMessagesJob
|
||||||
import org.thoughtcrime.securesms.jobs.BackupRestoreMediaJob
|
import org.thoughtcrime.securesms.jobs.BackupRestoreMediaJob
|
||||||
import org.thoughtcrime.securesms.payments.FiatMoneyUtil
|
import org.thoughtcrime.securesms.payments.FiatMoneyUtil
|
||||||
|
import kotlin.time.Duration
|
||||||
import kotlin.time.Duration.Companion.days
|
import kotlin.time.Duration.Companion.days
|
||||||
import kotlin.time.Duration.Companion.milliseconds
|
import kotlin.time.Duration.Companion.milliseconds
|
||||||
import org.signal.core.ui.R as CoreUiR
|
import org.signal.core.ui.R as CoreUiR
|
||||||
@@ -102,6 +103,7 @@ class BackupAlertBottomSheet : UpgradeToPaidTierBottomSheet() {
|
|||||||
BackupAlertSheetContent(
|
BackupAlertSheetContent(
|
||||||
backupAlert = backupAlert,
|
backupAlert = backupAlert,
|
||||||
isSubscribeEnabled = isSubscribeEnabled,
|
isSubscribeEnabled = isSubscribeEnabled,
|
||||||
|
mediaTtl = paidBackupType.mediaTtl,
|
||||||
onPrimaryActionClick = performPrimaryAction,
|
onPrimaryActionClick = performPrimaryAction,
|
||||||
onSecondaryActionClick = this::performSecondaryAction
|
onSecondaryActionClick = this::performSecondaryAction
|
||||||
)
|
)
|
||||||
@@ -195,6 +197,7 @@ private fun BackupAlertSheetContent(
|
|||||||
backupAlert: BackupAlert,
|
backupAlert: BackupAlert,
|
||||||
pricePerMonth: String = "",
|
pricePerMonth: String = "",
|
||||||
isSubscribeEnabled: Boolean = true,
|
isSubscribeEnabled: Boolean = true,
|
||||||
|
mediaTtl: Duration,
|
||||||
onPrimaryActionClick: () -> Unit = {},
|
onPrimaryActionClick: () -> Unit = {},
|
||||||
onSecondaryActionClick: () -> Unit = {}
|
onSecondaryActionClick: () -> Unit = {}
|
||||||
) {
|
) {
|
||||||
@@ -254,7 +257,7 @@ private fun BackupAlertSheetContent(
|
|||||||
)
|
)
|
||||||
|
|
||||||
BackupAlert.FailedToRenew -> PaymentProcessingBody()
|
BackupAlert.FailedToRenew -> PaymentProcessingBody()
|
||||||
is BackupAlert.MediaBackupsAreOff -> MediaBackupsAreOffBody(backupAlert.endOfPeriodSeconds)
|
is BackupAlert.MediaBackupsAreOff -> MediaBackupsAreOffBody(backupAlert.endOfPeriodSeconds, mediaTtl)
|
||||||
BackupAlert.MediaWillBeDeletedToday -> MediaWillBeDeletedTodayBody()
|
BackupAlert.MediaWillBeDeletedToday -> MediaWillBeDeletedTodayBody()
|
||||||
is BackupAlert.DiskFull -> DiskFullBody(requiredSpace = backupAlert.requiredSpace)
|
is BackupAlert.DiskFull -> DiskFullBody(requiredSpace = backupAlert.requiredSpace)
|
||||||
}
|
}
|
||||||
@@ -308,10 +311,10 @@ private fun PaymentProcessingBody() {
|
|||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
private fun MediaBackupsAreOffBody(
|
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 + mediaTtl }.inWholeDays.toInt()
|
||||||
val daysUntilDeletion = remember { endOfPeriodSeconds.days + 60.days }.inWholeDays.toInt()
|
|
||||||
|
|
||||||
Text(
|
Text(
|
||||||
text = pluralStringResource(id = R.plurals.BackupAlertBottomSheet__your_backup_plan_has_expired, daysUntilDeletion, daysUntilDeletion),
|
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() {
|
private fun BackupAlertSheetContentPreviewGeneric() {
|
||||||
Previews.BottomSheetPreview {
|
Previews.BottomSheetPreview {
|
||||||
BackupAlertSheetContent(
|
BackupAlertSheetContent(
|
||||||
backupAlert = BackupAlert.CouldNotCompleteBackup(daysSinceLastBackup = 7)
|
backupAlert = BackupAlert.CouldNotCompleteBackup(daysSinceLastBackup = 7),
|
||||||
|
mediaTtl = 60.days
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -426,7 +430,8 @@ private fun BackupAlertSheetContentPreviewGeneric() {
|
|||||||
private fun BackupAlertSheetContentPreviewPayment() {
|
private fun BackupAlertSheetContentPreviewPayment() {
|
||||||
Previews.BottomSheetPreview {
|
Previews.BottomSheetPreview {
|
||||||
BackupAlertSheetContent(
|
BackupAlertSheetContent(
|
||||||
backupAlert = BackupAlert.FailedToRenew
|
backupAlert = BackupAlert.FailedToRenew,
|
||||||
|
mediaTtl = 60.days
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -437,7 +442,8 @@ private fun BackupAlertSheetContentPreviewMedia() {
|
|||||||
Previews.BottomSheetPreview {
|
Previews.BottomSheetPreview {
|
||||||
BackupAlertSheetContent(
|
BackupAlertSheetContent(
|
||||||
backupAlert = BackupAlert.MediaBackupsAreOff(endOfPeriodSeconds = System.currentTimeMillis().milliseconds.inWholeSeconds),
|
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() {
|
private fun BackupAlertSheetContentPreviewDelete() {
|
||||||
Previews.BottomSheetPreview {
|
Previews.BottomSheetPreview {
|
||||||
BackupAlertSheetContent(
|
BackupAlertSheetContent(
|
||||||
backupAlert = BackupAlert.MediaWillBeDeletedToday
|
backupAlert = BackupAlert.MediaWillBeDeletedToday,
|
||||||
|
mediaTtl = 60.days
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -457,7 +464,8 @@ private fun BackupAlertSheetContentPreviewDelete() {
|
|||||||
private fun BackupAlertSheetContentPreviewDiskFull() {
|
private fun BackupAlertSheetContentPreviewDiskFull() {
|
||||||
Previews.BottomSheetPreview {
|
Previews.BottomSheetPreview {
|
||||||
BackupAlertSheetContent(
|
BackupAlertSheetContent(
|
||||||
backupAlert = BackupAlert.DiskFull(requiredSpace = "12GB")
|
backupAlert = BackupAlert.DiskFull(requiredSpace = "12GB"),
|
||||||
|
mediaTtl = 60.days
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ package org.thoughtcrime.securesms.backup.v2.ui.subscription
|
|||||||
import androidx.compose.runtime.Stable
|
import androidx.compose.runtime.Stable
|
||||||
import org.signal.core.util.money.FiatMoney
|
import org.signal.core.util.money.FiatMoney
|
||||||
import org.thoughtcrime.securesms.backup.v2.MessageBackupTier
|
import org.thoughtcrime.securesms.backup.v2.MessageBackupTier
|
||||||
|
import kotlin.time.Duration
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Represents a type of backup a user can select.
|
* Represents a type of backup a user can select.
|
||||||
@@ -19,7 +20,8 @@ sealed interface MessageBackupsType {
|
|||||||
|
|
||||||
data class Paid(
|
data class Paid(
|
||||||
val pricePerMonth: FiatMoney,
|
val pricePerMonth: FiatMoney,
|
||||||
val storageAllowanceBytes: Long
|
val storageAllowanceBytes: Long,
|
||||||
|
val mediaTtl: Duration
|
||||||
) : MessageBackupsType {
|
) : MessageBackupsType {
|
||||||
override val tier: MessageBackupTier = MessageBackupTier.PAID
|
override val tier: MessageBackupTier = MessageBackupTier.PAID
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -59,6 +59,7 @@ import org.thoughtcrime.securesms.payments.FiatMoneyUtil
|
|||||||
import org.thoughtcrime.securesms.util.ByteUnit
|
import org.thoughtcrime.securesms.util.ByteUnit
|
||||||
import java.math.BigDecimal
|
import java.math.BigDecimal
|
||||||
import java.util.Currency
|
import java.util.Currency
|
||||||
|
import kotlin.time.Duration.Companion.days
|
||||||
import org.signal.core.ui.R as CoreUiR
|
import org.signal.core.ui.R as CoreUiR
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -369,7 +370,8 @@ fun testBackupTypes(): List<MessageBackupsType> {
|
|||||||
),
|
),
|
||||||
MessageBackupsType.Paid(
|
MessageBackupsType.Paid(
|
||||||
pricePerMonth = FiatMoney(BigDecimal.ONE, Currency.getInstance("USD")),
|
pricePerMonth = FiatMoney(BigDecimal.ONE, Currency.getInstance("USD")),
|
||||||
storageAllowanceBytes = 107374182400
|
storageAllowanceBytes = 107374182400,
|
||||||
|
mediaTtl = 30.days
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -51,6 +51,7 @@ import org.thoughtcrime.securesms.util.navigation.safeNavigate
|
|||||||
import java.math.BigDecimal
|
import java.math.BigDecimal
|
||||||
import java.util.Currency
|
import java.util.Currency
|
||||||
import java.util.Locale
|
import java.util.Locale
|
||||||
|
import kotlin.time.Duration.Companion.days
|
||||||
import kotlin.time.Duration.Companion.seconds
|
import kotlin.time.Duration.Companion.seconds
|
||||||
import org.signal.core.ui.R as CoreUiR
|
import org.signal.core.ui.R as CoreUiR
|
||||||
|
|
||||||
@@ -342,7 +343,8 @@ private fun BackupsSettingsContentPreview() {
|
|||||||
enabledState = BackupsSettingsState.EnabledState.Active(
|
enabledState = BackupsSettingsState.EnabledState.Active(
|
||||||
type = MessageBackupsType.Paid(
|
type = MessageBackupsType.Paid(
|
||||||
pricePerMonth = FiatMoney(BigDecimal.valueOf(4), Currency.getInstance("CAD")),
|
pricePerMonth = FiatMoney(BigDecimal.valueOf(4), Currency.getInstance("CAD")),
|
||||||
storageAllowanceBytes = 1_000_000
|
storageAllowanceBytes = 1_000_000,
|
||||||
|
mediaTtl = 30.days
|
||||||
),
|
),
|
||||||
expiresAt = 0.seconds,
|
expiresAt = 0.seconds,
|
||||||
lastBackupAt = 0.seconds
|
lastBackupAt = 0.seconds
|
||||||
@@ -388,7 +390,8 @@ private fun ActivePaidBackupsRowPreview() {
|
|||||||
enabledState = BackupsSettingsState.EnabledState.Active(
|
enabledState = BackupsSettingsState.EnabledState.Active(
|
||||||
type = MessageBackupsType.Paid(
|
type = MessageBackupsType.Paid(
|
||||||
pricePerMonth = FiatMoney(BigDecimal.valueOf(4), Currency.getInstance("CAD")),
|
pricePerMonth = FiatMoney(BigDecimal.valueOf(4), Currency.getInstance("CAD")),
|
||||||
storageAllowanceBytes = 1_000_000
|
storageAllowanceBytes = 1_000_000,
|
||||||
|
mediaTtl = 30.days
|
||||||
),
|
),
|
||||||
expiresAt = 0.seconds,
|
expiresAt = 0.seconds,
|
||||||
lastBackupAt = 0.seconds
|
lastBackupAt = 0.seconds
|
||||||
|
|||||||
@@ -101,7 +101,8 @@ class BackupsSettingsViewModel : ViewModel() {
|
|||||||
activeSubscription.activeSubscription.amount,
|
activeSubscription.activeSubscription.amount,
|
||||||
Currency.getInstance(activeSubscription.activeSubscription.currency)
|
Currency.getInstance(activeSubscription.activeSubscription.currency)
|
||||||
),
|
),
|
||||||
storageAllowanceBytes = backupType.storageAllowanceBytes
|
storageAllowanceBytes = backupType.storageAllowanceBytes,
|
||||||
|
mediaTtl = backupType.mediaTtl
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -1225,7 +1225,8 @@ private fun SubscriptionMismatchMissingGooglePlayCardPreview() {
|
|||||||
state = RemoteBackupsSettingsState.BackupState.SubscriptionMismatchMissingGooglePlay(
|
state = RemoteBackupsSettingsState.BackupState.SubscriptionMismatchMissingGooglePlay(
|
||||||
messageBackupsType = MessageBackupsType.Paid(
|
messageBackupsType = MessageBackupsType.Paid(
|
||||||
pricePerMonth = FiatMoney(BigDecimal.valueOf(3), Currency.getInstance("CAD")),
|
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
|
renewalTime = System.currentTimeMillis().milliseconds + 30.days
|
||||||
)
|
)
|
||||||
@@ -1242,7 +1243,8 @@ private fun BackupCardPreview() {
|
|||||||
backupState = RemoteBackupsSettingsState.BackupState.ActivePaid(
|
backupState = RemoteBackupsSettingsState.BackupState.ActivePaid(
|
||||||
messageBackupsType = MessageBackupsType.Paid(
|
messageBackupsType = MessageBackupsType.Paid(
|
||||||
pricePerMonth = FiatMoney(BigDecimal.valueOf(3), Currency.getInstance("CAD")),
|
pricePerMonth = FiatMoney(BigDecimal.valueOf(3), Currency.getInstance("CAD")),
|
||||||
storageAllowanceBytes = 100_000_000
|
storageAllowanceBytes = 100_000_000,
|
||||||
|
mediaTtl = 30.days
|
||||||
),
|
),
|
||||||
renewalTime = 1727193018.seconds,
|
renewalTime = 1727193018.seconds,
|
||||||
price = FiatMoney(BigDecimal.valueOf(3), Currency.getInstance("CAD"))
|
price = FiatMoney(BigDecimal.valueOf(3), Currency.getInstance("CAD"))
|
||||||
@@ -1253,7 +1255,8 @@ private fun BackupCardPreview() {
|
|||||||
backupState = RemoteBackupsSettingsState.BackupState.Canceled(
|
backupState = RemoteBackupsSettingsState.BackupState.Canceled(
|
||||||
messageBackupsType = MessageBackupsType.Paid(
|
messageBackupsType = MessageBackupsType.Paid(
|
||||||
pricePerMonth = FiatMoney(BigDecimal.valueOf(3), Currency.getInstance("CAD")),
|
pricePerMonth = FiatMoney(BigDecimal.valueOf(3), Currency.getInstance("CAD")),
|
||||||
storageAllowanceBytes = 100_000_000
|
storageAllowanceBytes = 100_000_000,
|
||||||
|
mediaTtl = 30.days
|
||||||
),
|
),
|
||||||
renewalTime = 1727193018.seconds
|
renewalTime = 1727193018.seconds
|
||||||
)
|
)
|
||||||
@@ -1263,7 +1266,8 @@ private fun BackupCardPreview() {
|
|||||||
backupState = RemoteBackupsSettingsState.BackupState.Inactive(
|
backupState = RemoteBackupsSettingsState.BackupState.Inactive(
|
||||||
messageBackupsType = MessageBackupsType.Paid(
|
messageBackupsType = MessageBackupsType.Paid(
|
||||||
pricePerMonth = FiatMoney(BigDecimal.valueOf(3), Currency.getInstance("CAD")),
|
pricePerMonth = FiatMoney(BigDecimal.valueOf(3), Currency.getInstance("CAD")),
|
||||||
storageAllowanceBytes = 100_000_000
|
storageAllowanceBytes = 100_000_000,
|
||||||
|
mediaTtl = 30.days
|
||||||
),
|
),
|
||||||
renewalTime = 1727193018.seconds
|
renewalTime = 1727193018.seconds
|
||||||
)
|
)
|
||||||
@@ -1273,7 +1277,8 @@ private fun BackupCardPreview() {
|
|||||||
backupState = RemoteBackupsSettingsState.BackupState.ActivePaid(
|
backupState = RemoteBackupsSettingsState.BackupState.ActivePaid(
|
||||||
messageBackupsType = MessageBackupsType.Paid(
|
messageBackupsType = MessageBackupsType.Paid(
|
||||||
pricePerMonth = FiatMoney(BigDecimal.valueOf(3), Currency.getInstance("CAD")),
|
pricePerMonth = FiatMoney(BigDecimal.valueOf(3), Currency.getInstance("CAD")),
|
||||||
storageAllowanceBytes = 100_000_000
|
storageAllowanceBytes = 100_000_000,
|
||||||
|
mediaTtl = 30.days
|
||||||
),
|
),
|
||||||
renewalTime = 1727193018.seconds,
|
renewalTime = 1727193018.seconds,
|
||||||
price = FiatMoney(BigDecimal.valueOf(3), Currency.getInstance("CAD"))
|
price = FiatMoney(BigDecimal.valueOf(3), Currency.getInstance("CAD"))
|
||||||
|
|||||||
@@ -108,6 +108,9 @@ public class SubscriptionsConfiguration {
|
|||||||
@JsonProperty("playProductId")
|
@JsonProperty("playProductId")
|
||||||
private String playProductId;
|
private String playProductId;
|
||||||
|
|
||||||
|
@JsonProperty("mediaTtlDays")
|
||||||
|
private long mediaTtlDays;
|
||||||
|
|
||||||
public long getStorageAllowanceBytes() {
|
public long getStorageAllowanceBytes() {
|
||||||
return storageAllowanceBytes;
|
return storageAllowanceBytes;
|
||||||
}
|
}
|
||||||
@@ -115,6 +118,10 @@ public class SubscriptionsConfiguration {
|
|||||||
public String getPlayProductId() {
|
public String getPlayProductId() {
|
||||||
return playProductId;
|
return playProductId;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public long getMediaTtlDays() {
|
||||||
|
return mediaTtlDays;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public Map<String, CurrencyConfiguration> getCurrencies() {
|
public Map<String, CurrencyConfiguration> getCurrencies() {
|
||||||
|
|||||||
Reference in New Issue
Block a user