From b943df1ce4bc9d79c28c1823f0597fe799795098 Mon Sep 17 00:00:00 2001 From: Alex Hart Date: Thu, 27 Jun 2024 09:56:42 -0300 Subject: [PATCH] Add translatable copy for backup alert fragment. --- .../backup/v2/ui/BackupAlertBottomSheet.kt | 96 ++++++++++++------- .../backup/v2/ui/BackupAlertDelegate.kt | 31 ++++++ .../ConversationListFragment.java | 2 + app/src/main/res/values/strings.xml | 24 +++++ 4 files changed, 121 insertions(+), 32 deletions(-) create mode 100644 app/src/main/java/org/thoughtcrime/securesms/backup/v2/ui/BackupAlertDelegate.kt diff --git a/app/src/main/java/org/thoughtcrime/securesms/backup/v2/ui/BackupAlertBottomSheet.kt b/app/src/main/java/org/thoughtcrime/securesms/backup/v2/ui/BackupAlertBottomSheet.kt index 16db7954e5..0e922f53dd 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/backup/v2/ui/BackupAlertBottomSheet.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/backup/v2/ui/BackupAlertBottomSheet.kt @@ -38,6 +38,7 @@ import org.signal.core.ui.Previews import org.signal.core.ui.SignalPreview import org.thoughtcrime.securesms.R import org.thoughtcrime.securesms.compose.ComposeBottomSheetDialogFragment +import org.thoughtcrime.securesms.database.model.databaseprotos.InAppPaymentData /** * Notifies the user of an issue with their backup. @@ -70,12 +71,10 @@ class BackupAlertBottomSheet : ComposeBottomSheetDialogFragment() { @Stable private fun performPrimaryAction() { when (backupAlert) { - BackupAlert.GENERIC -> { + BackupAlert.COULD_NOT_COMPLETE_BACKUP -> { // TODO [message-backups] -- Back up now } - BackupAlert.PAYMENT_PROCESSING -> { - // TODO [message-backups] -- Silence - } + BackupAlert.PAYMENT_PROCESSING -> Unit BackupAlert.MEDIA_BACKUPS_ARE_OFF -> { // TODO [message-backups] -- Download media now } @@ -91,7 +90,7 @@ class BackupAlertBottomSheet : ComposeBottomSheetDialogFragment() { @Stable private fun performSecondaryAction() { when (backupAlert) { - BackupAlert.GENERIC -> { + BackupAlert.COULD_NOT_COMPLETE_BACKUP -> { // TODO [message-backups] - Dismiss and notify later } BackupAlert.PAYMENT_PROCESSING -> error("PAYMENT_PROCESSING state does not support a secondary action.") @@ -101,9 +100,7 @@ class BackupAlertBottomSheet : ComposeBottomSheetDialogFragment() { BackupAlert.MEDIA_WILL_BE_DELETED_TODAY -> { // TODO [message-backups] - Silence forever } - BackupAlert.DISK_FULL -> { - // TODO [message-backups] - Silence forever, cancel any in-flight downloads? - } + BackupAlert.DISK_FULL -> Unit } dismissAllowingStateLoss() @@ -144,9 +141,13 @@ private fun BackupAlertSheetContent( ) when (backupAlert) { - BackupAlert.GENERIC -> GenericBody() - BackupAlert.PAYMENT_PROCESSING -> PaymentProcessingBody() - BackupAlert.MEDIA_BACKUPS_ARE_OFF -> MediaBackupsAreOffBody() + BackupAlert.COULD_NOT_COMPLETE_BACKUP -> CouldNotCompleteBackup( + daysSinceLastBackup = 7 // TODO [message-backups] + ) + BackupAlert.PAYMENT_PROCESSING -> PaymentProcessingBody( + paymentMethodType = InAppPaymentData.PaymentMethodType.GOOGLE_PAY // TODO [message-backups] -- Get this data from elsewhere... The active subscription object? + ) + BackupAlert.MEDIA_BACKUPS_ARE_OFF -> MediaBackupsAreOffBody(30) // TODO [message-backups] -- Get this value from backend BackupAlert.MEDIA_WILL_BE_DELETED_TODAY -> MediaWillBeDeletedTodayBody() BackupAlert.DISK_FULL -> DiskFullBody( requiredSpace = "12 GB", // TODO [message-backups] Where does this value come from? @@ -175,23 +176,54 @@ private fun BackupAlertSheetContent( } @Composable -private fun GenericBody() { - Text(text = "TODO", modifier = Modifier.padding(bottom = 60.dp)) +private fun CouldNotCompleteBackup( + daysSinceLastBackup: Int +) { + Text( + text = stringResource(id = R.string.BackupAlertBottomSheet__your_device_hasnt, daysSinceLastBackup), + modifier = Modifier.padding(bottom = 60.dp) + ) } @Composable -private fun PaymentProcessingBody() { - Text(text = "TODO", modifier = Modifier.padding(bottom = 60.dp)) +private fun PaymentProcessingBody(paymentMethodType: InAppPaymentData.PaymentMethodType) { + Text( + text = stringResource(id = R.string.BackupAlertBottomSheet__were_having_trouble_collecting__google_pay), + textAlign = TextAlign.Center, + modifier = Modifier.padding(bottom = 60.dp) + ) } @Composable -private fun MediaBackupsAreOffBody() { - Text(text = "TODO", modifier = Modifier.padding(bottom = 60.dp)) +private fun MediaBackupsAreOffBody( + daysUntilDeletion: Long +) { + Text( + text = stringResource(id = R.string.BackupAlertBottomSheet__your_signal_media_backup_plan, daysUntilDeletion), + textAlign = TextAlign.Center, + modifier = Modifier.padding(bottom = 24.dp) + ) + + Text( + text = stringResource(id = R.string.BackupAlertBottomSheet__you_can_begin_paying_for_backups_again), + textAlign = TextAlign.Center, + modifier = Modifier.padding(bottom = 36.dp) + ) } @Composable private fun MediaWillBeDeletedTodayBody() { - Text(text = "TODO", modifier = Modifier.padding(bottom = 60.dp)) + Text( + text = stringResource(id = R.string.BackupAlertBottomSheet__your_signal_media_backup_plan_has_been), + textAlign = TextAlign.Center, + modifier = Modifier.padding(bottom = 24.dp) + ) + + Text( + text = stringResource(id = R.string.BackupAlertBottomSheet__you_can_begin_paying_for_backups_again), + textAlign = TextAlign.Center, + modifier = Modifier.padding(bottom = 36.dp) + ) } @Composable @@ -216,7 +248,7 @@ private fun DiskFullBody( private fun rememberBackupsIconColors(backupAlert: BackupAlert): BackupsIconColors { return remember(backupAlert) { when (backupAlert) { - BackupAlert.GENERIC, BackupAlert.PAYMENT_PROCESSING, BackupAlert.DISK_FULL -> BackupsIconColors.Warning + BackupAlert.COULD_NOT_COMPLETE_BACKUP, BackupAlert.PAYMENT_PROCESSING, BackupAlert.DISK_FULL -> BackupsIconColors.Warning BackupAlert.MEDIA_BACKUPS_ARE_OFF, BackupAlert.MEDIA_WILL_BE_DELETED_TODAY -> BackupsIconColors.Error } } @@ -227,10 +259,10 @@ private fun rememberBackupsIconColors(backupAlert: BackupAlert): BackupsIconColo private fun rememberTitleResource(backupAlert: BackupAlert): Int { return remember(backupAlert) { when (backupAlert) { - BackupAlert.GENERIC -> R.string.default_error_msg // TODO [message-backups] -- Finalized copy - BackupAlert.PAYMENT_PROCESSING -> R.string.default_error_msg // TODO [message-backups] -- Finalized copy - BackupAlert.MEDIA_BACKUPS_ARE_OFF -> R.string.default_error_msg // TODO [message-backups] -- Finalized copy - BackupAlert.MEDIA_WILL_BE_DELETED_TODAY -> R.string.default_error_msg // TODO [message-backups] -- Finalized copy + BackupAlert.COULD_NOT_COMPLETE_BACKUP -> R.string.BackupAlertBottomSheet__couldnt_complete_backup + BackupAlert.PAYMENT_PROCESSING -> R.string.BackupAlertBottomSheet__cant_process_backup_payment + BackupAlert.MEDIA_BACKUPS_ARE_OFF -> R.string.BackupAlertBottomSheet__media_backups_are_off + BackupAlert.MEDIA_WILL_BE_DELETED_TODAY -> R.string.BackupAlertBottomSheet__your_media_will_be_deleted_today BackupAlert.DISK_FULL -> R.string.BackupAlertBottomSheet__cant_complete_download } } @@ -240,10 +272,10 @@ private fun rememberTitleResource(backupAlert: BackupAlert): Int { private fun rememberPrimaryActionResource(backupAlert: BackupAlert): Int { return remember(backupAlert) { when (backupAlert) { - BackupAlert.GENERIC -> android.R.string.ok // TODO [message-backups] -- Finalized copy - BackupAlert.PAYMENT_PROCESSING -> android.R.string.ok // TODO [message-backups] -- Finalized copy - BackupAlert.MEDIA_BACKUPS_ARE_OFF -> android.R.string.ok // TODO [message-backups] -- Finalized copy - BackupAlert.MEDIA_WILL_BE_DELETED_TODAY -> android.R.string.ok // TODO [message-backups] -- Finalized copy + BackupAlert.COULD_NOT_COMPLETE_BACKUP -> android.R.string.ok // TODO [message-backups] -- Finalized copy + BackupAlert.PAYMENT_PROCESSING -> android.R.string.ok + BackupAlert.MEDIA_BACKUPS_ARE_OFF -> R.string.BackupAlertBottomSheet__download_media_now + BackupAlert.MEDIA_WILL_BE_DELETED_TODAY -> R.string.BackupAlertBottomSheet__download_media_now BackupAlert.DISK_FULL -> android.R.string.ok } } @@ -253,10 +285,10 @@ private fun rememberPrimaryActionResource(backupAlert: BackupAlert): Int { private fun rememberSecondaryActionResource(backupAlert: BackupAlert): Int { return remember(backupAlert) { when (backupAlert) { - BackupAlert.GENERIC -> android.R.string.cancel // TODO [message-backups] -- Finalized copy + BackupAlert.COULD_NOT_COMPLETE_BACKUP -> android.R.string.cancel // TODO [message-backups] -- Finalized copy BackupAlert.PAYMENT_PROCESSING -> -1 - BackupAlert.MEDIA_BACKUPS_ARE_OFF -> android.R.string.cancel // TODO [message-backups] -- Finalized copy - BackupAlert.MEDIA_WILL_BE_DELETED_TODAY -> android.R.string.cancel // TODO [message-backups] -- Finalized copy + BackupAlert.MEDIA_BACKUPS_ARE_OFF -> R.string.BackupAlertBottomSheet__download_later + BackupAlert.MEDIA_WILL_BE_DELETED_TODAY -> R.string.BackupAlertBottomSheet__dont_download_media BackupAlert.DISK_FULL -> R.string.BackupAlertBottomSheet__skip } } @@ -267,7 +299,7 @@ private fun rememberSecondaryActionResource(backupAlert: BackupAlert): Int { private fun BackupAlertSheetContentPreviewGeneric() { Previews.BottomSheetPreview { BackupAlertSheetContent( - backupAlert = BackupAlert.GENERIC, + backupAlert = BackupAlert.COULD_NOT_COMPLETE_BACKUP, onPrimaryActionClick = {}, onSecondaryActionClick = {} ) @@ -324,7 +356,7 @@ private fun BackupAlertSheetContentPreviewDiskFull() { @Parcelize enum class BackupAlert : Parcelable { - GENERIC, + COULD_NOT_COMPLETE_BACKUP, PAYMENT_PROCESSING, MEDIA_BACKUPS_ARE_OFF, MEDIA_WILL_BE_DELETED_TODAY, diff --git a/app/src/main/java/org/thoughtcrime/securesms/backup/v2/ui/BackupAlertDelegate.kt b/app/src/main/java/org/thoughtcrime/securesms/backup/v2/ui/BackupAlertDelegate.kt new file mode 100644 index 0000000000..542e9bc6c5 --- /dev/null +++ b/app/src/main/java/org/thoughtcrime/securesms/backup/v2/ui/BackupAlertDelegate.kt @@ -0,0 +1,31 @@ +/* + * Copyright 2024 Signal Messenger, LLC + * SPDX-License-Identifier: AGPL-3.0-only + */ + +package org.thoughtcrime.securesms.backup.v2.ui + +import androidx.fragment.app.FragmentManager +import androidx.lifecycle.Lifecycle +import androidx.lifecycle.coroutineScope +import androidx.lifecycle.repeatOnLifecycle +import kotlinx.coroutines.launch + +/** + * Delegate that controls whether and which backup alert sheet is displayed. + */ +object BackupAlertDelegate { + @JvmStatic + fun delegate(fragmentManager: FragmentManager, lifecycle: Lifecycle) { + lifecycle.coroutineScope.launch { + lifecycle.repeatOnLifecycle(Lifecycle.State.RESUMED) { + // TODO [message-backups] + // 1. Get unnotified backup upload failures + // 2. Get unnotified backup download failures + // 3. Get unnotified backup payment failures + + // Decide which do display + } + } + } +} diff --git a/app/src/main/java/org/thoughtcrime/securesms/conversationlist/ConversationListFragment.java b/app/src/main/java/org/thoughtcrime/securesms/conversationlist/ConversationListFragment.java index 945a43ae67..5fda31912a 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/conversationlist/ConversationListFragment.java +++ b/app/src/main/java/org/thoughtcrime/securesms/conversationlist/ConversationListFragment.java @@ -90,6 +90,7 @@ import org.thoughtcrime.securesms.MainNavigator; import org.thoughtcrime.securesms.MuteDialog; import org.thoughtcrime.securesms.NewConversationActivity; import org.thoughtcrime.securesms.R; +import org.thoughtcrime.securesms.backup.v2.ui.BackupAlertDelegate; import org.thoughtcrime.securesms.badges.models.Badge; import org.thoughtcrime.securesms.badges.self.expired.ExpiredOneTimeBadgeBottomSheetDialogFragment; import org.thoughtcrime.securesms.badges.self.expired.MonthlyDonationCanceledBottomSheetDialogFragment; @@ -277,6 +278,7 @@ public class ConversationListFragment extends MainFragment implements ActionMode @Override public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { getViewLifecycleOwner().getLifecycle().addObserver(new TerminalDonationDelegate(getParentFragmentManager(), getViewLifecycleOwner())); + BackupAlertDelegate.delegate(getParentFragmentManager(), getViewLifecycleOwner().getLifecycle()); lifecycleDisposable = new LifecycleDisposable(); lifecycleDisposable.bindTo(getViewLifecycleOwner()); diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 5bd4540c05..9d0650b90c 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -6996,16 +6996,40 @@ Downloading backup data… + + Media backups are off + + Your Signal media backup plan has been canceled because we couldn\'t process your payment. You have %1$d days to download any media stored in your backup. After %1$d days, the media in your backup will be deleted. + + You can begin paying for backups again at any time to continue backing up all your media. + + Your media will be deleted today + + Your Signal media backup plan has been canceled because we couldn\'t process your payment. This is your last chance to download the media in your backup before it is deleted. Can\'t complete download Your device does not have enough free space. Free up to %1$s of space to download the media stored in your backup. If you choose \"Skip\" the media in your backup will be deleted in %1$d days. + + Can\'t process backup payment + + We\'re having trouble collecting your recurring monthly backup payment. Make sure your payment method is up to date. If it isn\'t, update it in Google Pay. Signal will try to process the payment again in a few days. + + Couldn\'t complete backup + + Your device hasn\'t completed a backup for %1$d days. Make sure your device is connected to wi-fi and tap \"Back up now.\" Learn more Skip + + Download media now + + Download later + + Don\'t download media