Add support for upgrades from warning sheet.

This commit is contained in:
Alex Hart
2024-11-06 13:07:34 -04:00
committed by Greyson Parrelli
parent 7f1d59f40a
commit 445b7ef76f
4 changed files with 49 additions and 17 deletions

View File

@@ -139,7 +139,7 @@ object BackupRepository {
@JvmStatic @JvmStatic
fun skipMediaRestore() { fun skipMediaRestore() {
// TODO [backups] -- Clear the error as necessary // TODO [backups] -- Clear the error as necessary, cancel anything remaining in the restore
} }
/** /**

View File

@@ -49,9 +49,10 @@ import org.signal.core.ui.Previews
import org.signal.core.ui.SignalPreview import org.signal.core.ui.SignalPreview
import org.thoughtcrime.securesms.R import org.thoughtcrime.securesms.R
import org.thoughtcrime.securesms.backup.v2.BackupRepository import org.thoughtcrime.securesms.backup.v2.BackupRepository
import org.thoughtcrime.securesms.backup.v2.ui.subscription.MessageBackupsType
import org.thoughtcrime.securesms.billing.launchManageBackupsSubscription import org.thoughtcrime.securesms.billing.launchManageBackupsSubscription
import org.thoughtcrime.securesms.billing.upgrade.UpgradeToPaidTierBottomSheet
import org.thoughtcrime.securesms.components.settings.app.AppSettingsActivity import org.thoughtcrime.securesms.components.settings.app.AppSettingsActivity
import org.thoughtcrime.securesms.compose.ComposeBottomSheetDialogFragment
import org.thoughtcrime.securesms.dependencies.AppDependencies 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
@@ -61,7 +62,7 @@ import org.signal.core.ui.R as CoreUiR
/** /**
* Notifies the user of an issue with their backup. * Notifies the user of an issue with their backup.
*/ */
class BackupAlertBottomSheet : ComposeBottomSheetDialogFragment() { class BackupAlertBottomSheet : UpgradeToPaidTierBottomSheet() {
companion object { companion object {
private const val ARG_ALERT = "alert" private const val ARG_ALERT = "alert"
@@ -79,24 +80,33 @@ class BackupAlertBottomSheet : ComposeBottomSheetDialogFragment() {
} }
@Composable @Composable
override fun SheetContent() { override fun UpgradeSheetContent(
paidBackupType: MessageBackupsType.Paid,
freeBackupType: MessageBackupsType.Free,
isSubscribeEnabled: Boolean,
onSubscribeClick: () -> Unit
) {
var pricePerMonth by remember { mutableStateOf("-") } var pricePerMonth by remember { mutableStateOf("-") }
val resources = LocalContext.current.resources val resources = LocalContext.current.resources
LaunchedEffect(Unit) { LaunchedEffect(paidBackupType.pricePerMonth) {
val price = AppDependencies.billingApi.queryProduct()?.price ?: return@LaunchedEffect pricePerMonth = FiatMoneyUtil.format(resources, paidBackupType.pricePerMonth, FiatMoneyUtil.formatOptions().trimZerosAfterDecimal())
pricePerMonth = FiatMoneyUtil.format(resources, price, FiatMoneyUtil.formatOptions().trimZerosAfterDecimal()) }
val performPrimaryAction = remember(onSubscribeClick) {
createPrimaryAction(onSubscribeClick)
} }
BackupAlertSheetContent( BackupAlertSheetContent(
backupAlert = backupAlert, backupAlert = backupAlert,
onPrimaryActionClick = this::performPrimaryAction, isSubscribeEnabled = isSubscribeEnabled,
onPrimaryActionClick = performPrimaryAction,
onSecondaryActionClick = this::performSecondaryAction onSecondaryActionClick = this::performSecondaryAction
) )
} }
@Stable @Stable
private fun performPrimaryAction() { private fun createPrimaryAction(onSubscribeClick: () -> Unit): () -> Unit = {
when (backupAlert) { when (backupAlert) {
is BackupAlert.CouldNotCompleteBackup -> { is BackupAlert.CouldNotCompleteBackup -> {
BackupMessagesJob.enqueue() BackupMessagesJob.enqueue()
@@ -104,11 +114,14 @@ class BackupAlertBottomSheet : ComposeBottomSheetDialogFragment() {
} }
BackupAlert.FailedToRenew -> launchManageBackupsSubscription() BackupAlert.FailedToRenew -> launchManageBackupsSubscription()
BackupAlert.MediaBackupsAreOff, BackupAlert.MediaWillBeDeletedToday -> { BackupAlert.MediaBackupsAreOff -> {
onSubscribeClick()
}
BackupAlert.MediaWillBeDeletedToday -> {
performFullMediaDownload() performFullMediaDownload()
} }
is BackupAlert.DiskFull -> Unit is BackupAlert.DiskFull -> Unit // dismiss the sheet and keep your restore paused until you free up space.
} }
dismissAllowingStateLoss() dismissAllowingStateLoss()
@@ -119,10 +132,7 @@ class BackupAlertBottomSheet : ComposeBottomSheetDialogFragment() {
when (backupAlert) { when (backupAlert) {
is BackupAlert.CouldNotCompleteBackup -> Unit is BackupAlert.CouldNotCompleteBackup -> Unit
BackupAlert.FailedToRenew -> Unit BackupAlert.FailedToRenew -> Unit
BackupAlert.MediaBackupsAreOff -> { BackupAlert.MediaBackupsAreOff -> Unit
// TODO [backups] - Silence and remind on last day
}
BackupAlert.MediaWillBeDeletedToday -> { BackupAlert.MediaWillBeDeletedToday -> {
displayLastChanceDialog() displayLastChanceDialog()
} }
@@ -182,6 +192,7 @@ class BackupAlertBottomSheet : ComposeBottomSheetDialogFragment() {
private fun BackupAlertSheetContent( private fun BackupAlertSheetContent(
backupAlert: BackupAlert, backupAlert: BackupAlert,
pricePerMonth: String = "", pricePerMonth: String = "",
isSubscribeEnabled: Boolean = true,
onPrimaryActionClick: () -> Unit = {}, onPrimaryActionClick: () -> Unit = {},
onSecondaryActionClick: () -> Unit = {} onSecondaryActionClick: () -> Unit = {}
) { ) {
@@ -250,6 +261,7 @@ private fun BackupAlertSheetContent(
val padBottom = if (secondaryActionResource > 0) 16.dp else 56.dp val padBottom = if (secondaryActionResource > 0) 16.dp else 56.dp
Buttons.LargeTonal( Buttons.LargeTonal(
enabled = isSubscribeEnabled,
onClick = onPrimaryActionClick, onClick = onPrimaryActionClick,
modifier = Modifier modifier = Modifier
.defaultMinSize(minWidth = 220.dp) .defaultMinSize(minWidth = 220.dp)
@@ -259,7 +271,11 @@ private fun BackupAlertSheetContent(
} }
if (secondaryActionResource > 0) { if (secondaryActionResource > 0) {
TextButton(onClick = onSecondaryActionClick, modifier = Modifier.padding(bottom = 32.dp)) { TextButton(
enabled = isSubscribeEnabled,
onClick = onSecondaryActionClick,
modifier = Modifier.padding(bottom = 32.dp)
) {
Text(text = stringResource(id = secondaryActionResource)) Text(text = stringResource(id = secondaryActionResource))
} }
} }
@@ -447,14 +463,28 @@ private fun BackupAlertSheetContentPreviewDiskFull() {
@Parcelize @Parcelize
sealed class BackupAlert : Parcelable { sealed class BackupAlert : Parcelable {
/**
* This value is driven by a watermarking system and will be dismissed and snoozed whenever the sheet is closed.
* This value is driven by failure to complete a backup within a timeout based on the user's chosen backup frequency.
*/
data class CouldNotCompleteBackup( data class CouldNotCompleteBackup(
val daysSinceLastBackup: Int val daysSinceLastBackup: Int
) : BackupAlert() ) : BackupAlert()
/**
* This value is driven by InAppPayment state, and will be automatically cleared when the sheet is displayed.
*/
data object FailedToRenew : BackupAlert() data object FailedToRenew : BackupAlert()
/**
* This value is driven by InAppPayment state, and will be automatically cleared when the sheet is displayed.
* This value is displayed if we hit an 'unexpected cancellation' of a user's backup.
*/
data object MediaBackupsAreOff : BackupAlert() data object MediaBackupsAreOff : BackupAlert()
/**
* TODO [backups] - This value is driven as "60D after the last time the user pinged their backup"
*/
data object MediaWillBeDeletedToday : BackupAlert() data object MediaWillBeDeletedToday : BackupAlert()
/** /**

View File

@@ -25,6 +25,8 @@ object BackupAlertDelegate {
BackupAlertBottomSheet.create(BackupAlert.CouldNotCompleteBackup(daysSinceLastBackup = SignalStore.backup.daysSinceLastBackup)).show(fragmentManager, null) BackupAlertBottomSheet.create(BackupAlert.CouldNotCompleteBackup(daysSinceLastBackup = SignalStore.backup.daysSinceLastBackup)).show(fragmentManager, null)
} }
// TODO [backups] Check if media will be deleted within 24hrs and display warning sheet.
// TODO [backups] // TODO [backups]
// Get unnotified backup download failures & display sheet // Get unnotified backup download failures & display sheet
} }

View File

@@ -134,7 +134,7 @@ class InAppPaymentsBottomSheetDelegate(
}.subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread()).subscribeBy { inAppPayments -> }.subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread()).subscribeBy { inAppPayments ->
for (payment in inAppPayments) { for (payment in inAppPayments) {
if (isPaymentProcessingError(payment.state, payment.data)) { if (isPaymentProcessingError(payment.state, payment.data)) {
BackupAlertBottomSheet.create(BackupAlert.CouldNotCompleteBackup(daysSinceLastBackup = SignalStore.backup.daysSinceLastBackup)).show(fragmentManager, null) BackupAlertBottomSheet.create(BackupAlert.FailedToRenew).show(fragmentManager, null)
} else if (isUnexpectedCancellation(payment.state, payment.data)) { } else if (isUnexpectedCancellation(payment.state, payment.data)) {
BackupAlertBottomSheet.create(BackupAlert.MediaBackupsAreOff).show(fragmentManager, null) BackupAlertBottomSheet.create(BackupAlert.MediaBackupsAreOff).show(fragmentManager, null)
} }