Add validation error UI.
This commit is contained in:
parent
756262c1fe
commit
3c086f347e
13 changed files with 191 additions and 22 deletions
|
@ -104,6 +104,10 @@ object ArchiveUploadProgress {
|
|||
updateState(PROGRESS_NONE)
|
||||
}
|
||||
|
||||
fun onValidationFailure() {
|
||||
updateState(PROGRESS_NONE)
|
||||
}
|
||||
|
||||
private fun updateState(state: ArchiveUploadProgressState, notify: Boolean = true) {
|
||||
uploadProgress = state
|
||||
SignalStore.backup.archiveUploadState = state
|
||||
|
|
|
@ -204,14 +204,27 @@ object BackupRepository {
|
|||
}
|
||||
|
||||
/**
|
||||
* Whether the "Could not complete backup" row should be displayed in settings.
|
||||
* Whether the "Backup Failed" row should be displayed in settings.
|
||||
* Shown when the initial backup creation has failed
|
||||
*/
|
||||
fun shouldDisplayBackupFailedSettingsRow(): Boolean {
|
||||
if (shouldNotDisplayBackupFailedMessaging()) {
|
||||
return false
|
||||
}
|
||||
|
||||
return SignalStore.backup.hasBackupFailure
|
||||
return !SignalStore.backup.hasBackupBeenUploaded && SignalStore.backup.hasBackupFailure
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether the "Could not complete backup" row should be displayed in settings.
|
||||
* Shown when a new backup could not be created but there is an existing one already
|
||||
*/
|
||||
fun shouldDisplayCouldNotCompleteBackupSettingsRow(): Boolean {
|
||||
if (shouldNotDisplayBackupFailedMessaging()) {
|
||||
return false
|
||||
}
|
||||
|
||||
return SignalStore.backup.hasBackupBeenUploaded && SignalStore.backup.hasBackupFailure
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -230,7 +243,8 @@ object BackupRepository {
|
|||
}
|
||||
|
||||
/**
|
||||
* Whether or not the "Could not complete backup" sheet should be displayed.
|
||||
* Whether or not the "Backup failed" sheet should be displayed.
|
||||
* Should only be displayed if this is the failure of the initial backup creation.
|
||||
*/
|
||||
@JvmStatic
|
||||
fun shouldDisplayBackupFailedSheet(): Boolean {
|
||||
|
@ -238,7 +252,19 @@ object BackupRepository {
|
|||
return false
|
||||
}
|
||||
|
||||
return System.currentTimeMillis().milliseconds > SignalStore.backup.nextBackupFailureSheetSnoozeTime
|
||||
return !SignalStore.backup.hasBackupBeenUploaded && System.currentTimeMillis().milliseconds > SignalStore.backup.nextBackupFailureSheetSnoozeTime
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether or not the "Could not complete backup" sheet should be displayed.
|
||||
*/
|
||||
@JvmStatic
|
||||
fun shouldDisplayCouldNotCompleteBackupSheet(): Boolean {
|
||||
if (shouldNotDisplayBackupFailedMessaging()) {
|
||||
return false
|
||||
}
|
||||
|
||||
return SignalStore.backup.hasBackupBeenUploaded && System.currentTimeMillis().milliseconds > SignalStore.backup.nextBackupFailureSheetSnoozeTime
|
||||
}
|
||||
|
||||
fun snoozeYourMediaWillBeDeletedTodaySheet() {
|
||||
|
@ -249,7 +275,7 @@ object BackupRepository {
|
|||
* Whether or not the "Your media will be deleted today" sheet should be displayed.
|
||||
*/
|
||||
suspend fun shouldDisplayYourMediaWillBeDeletedTodaySheet(): Boolean {
|
||||
if (shouldNotDisplayBackupFailedMessaging() || !SignalStore.backup.optimizeStorage) {
|
||||
if (shouldNotDisplayBackupFailedMessaging() || !SignalStore.backup.hasBackupBeenUploaded || !SignalStore.backup.optimizeStorage) {
|
||||
return false
|
||||
}
|
||||
|
||||
|
@ -285,7 +311,7 @@ object BackupRepository {
|
|||
}
|
||||
|
||||
private fun shouldNotDisplayBackupFailedMessaging(): Boolean {
|
||||
return !RemoteConfig.messageBackups || !SignalStore.backup.areBackupsEnabled || !SignalStore.backup.hasBackupBeenUploaded
|
||||
return !RemoteConfig.messageBackups || !SignalStore.backup.areBackupsEnabled
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -57,6 +57,8 @@ 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 org.thoughtcrime.securesms.util.CommunicationActions
|
||||
import org.thoughtcrime.securesms.util.PlayStoreUtil
|
||||
import kotlin.time.Duration
|
||||
import kotlin.time.Duration.Companion.days
|
||||
import kotlin.time.Duration.Companion.milliseconds
|
||||
|
@ -67,6 +69,8 @@ import org.signal.core.ui.R as CoreUiR
|
|||
*/
|
||||
class BackupAlertBottomSheet : UpgradeToPaidTierBottomSheet() {
|
||||
|
||||
override val peekHeightPercentage: Float = 0.75f
|
||||
|
||||
companion object {
|
||||
private const val ARG_ALERT = "alert"
|
||||
|
||||
|
@ -126,6 +130,8 @@ class BackupAlertBottomSheet : UpgradeToPaidTierBottomSheet() {
|
|||
}
|
||||
|
||||
is BackupAlert.DiskFull -> Unit
|
||||
is BackupAlert.BackupFailed ->
|
||||
PlayStoreUtil.openPlayStoreOrOurApkDownloadPage(requireContext())
|
||||
}
|
||||
|
||||
dismissAllowingStateLoss()
|
||||
|
@ -144,6 +150,8 @@ class BackupAlertBottomSheet : UpgradeToPaidTierBottomSheet() {
|
|||
is BackupAlert.DiskFull -> {
|
||||
displaySkipRestoreDialog()
|
||||
}
|
||||
// TODO [backups] - Update support URL with backups page
|
||||
BackupAlert.BackupFailed -> CommunicationActions.openBrowserLink(requireContext(), requireContext().getString(R.string.backup_support_url))
|
||||
}
|
||||
|
||||
dismissAllowingStateLoss()
|
||||
|
@ -153,7 +161,7 @@ class BackupAlertBottomSheet : UpgradeToPaidTierBottomSheet() {
|
|||
super.onDismiss(dialog)
|
||||
|
||||
when (backupAlert) {
|
||||
is BackupAlert.CouldNotCompleteBackup -> BackupRepository.markBackupFailedSheetDismissed()
|
||||
is BackupAlert.CouldNotCompleteBackup, BackupAlert.BackupFailed -> BackupRepository.markBackupFailedSheetDismissed()
|
||||
is BackupAlert.MediaWillBeDeletedToday -> BackupRepository.snoozeYourMediaWillBeDeletedTodaySheet()
|
||||
else -> Unit
|
||||
}
|
||||
|
@ -261,6 +269,7 @@ private fun BackupAlertSheetContent(
|
|||
is BackupAlert.MediaBackupsAreOff -> MediaBackupsAreOffBody(backupAlert.endOfPeriodSeconds, mediaTtl)
|
||||
BackupAlert.MediaWillBeDeletedToday -> MediaWillBeDeletedTodayBody()
|
||||
is BackupAlert.DiskFull -> DiskFullBody(requiredSpace = backupAlert.requiredSpace)
|
||||
BackupAlert.BackupFailed -> BackupFailedBody()
|
||||
}
|
||||
|
||||
val secondaryActionResource = rememberSecondaryActionResource(backupAlert = backupAlert)
|
||||
|
@ -366,12 +375,22 @@ private fun DiskFullBody(requiredSpace: String) {
|
|||
)
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun BackupFailedBody() {
|
||||
Text(
|
||||
text = stringResource(id = R.string.BackupAlertBottomSheet__an_error_occurred),
|
||||
textAlign = TextAlign.Center,
|
||||
color = MaterialTheme.colorScheme.onSurfaceVariant,
|
||||
modifier = Modifier.padding(bottom = 36.dp)
|
||||
)
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun rememberBackupsIconColors(backupAlert: BackupAlert): BackupsIconColors {
|
||||
return remember(backupAlert) {
|
||||
when (backupAlert) {
|
||||
BackupAlert.FailedToRenew, is BackupAlert.MediaBackupsAreOff -> error("Not icon-based options.")
|
||||
is BackupAlert.CouldNotCompleteBackup, is BackupAlert.DiskFull -> BackupsIconColors.Warning
|
||||
is BackupAlert.CouldNotCompleteBackup, BackupAlert.BackupFailed, is BackupAlert.DiskFull -> BackupsIconColors.Warning
|
||||
BackupAlert.MediaWillBeDeletedToday -> BackupsIconColors.Error
|
||||
}
|
||||
}
|
||||
|
@ -385,6 +404,7 @@ private fun titleString(backupAlert: BackupAlert): String {
|
|||
is BackupAlert.MediaBackupsAreOff -> stringResource(R.string.BackupAlertBottomSheet__your_backups_subscription_expired)
|
||||
BackupAlert.MediaWillBeDeletedToday -> stringResource(R.string.BackupAlertBottomSheet__your_media_will_be_deleted_today)
|
||||
is BackupAlert.DiskFull -> stringResource(R.string.BackupAlertBottomSheet__free_up_s_on_this_device, backupAlert.requiredSpace)
|
||||
BackupAlert.BackupFailed -> stringResource(R.string.BackupAlertBottomSheet__backup_failed)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -399,6 +419,7 @@ private fun primaryActionString(
|
|||
is BackupAlert.MediaBackupsAreOff -> stringResource(R.string.BackupAlertBottomSheet__subscribe_for_s_month, pricePerMonth)
|
||||
BackupAlert.MediaWillBeDeletedToday -> stringResource(R.string.BackupAlertBottomSheet__download_media_now)
|
||||
is BackupAlert.DiskFull -> stringResource(R.string.BackupAlertBottomSheet__got_it)
|
||||
is BackupAlert.BackupFailed -> stringResource(R.string.BackupAlertBottomSheet__check_for_update)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -411,6 +432,7 @@ private fun rememberSecondaryActionResource(backupAlert: BackupAlert): Int {
|
|||
is BackupAlert.MediaBackupsAreOff -> R.string.BackupAlertBottomSheet__not_now
|
||||
BackupAlert.MediaWillBeDeletedToday -> R.string.BackupAlertBottomSheet__dont_download_media
|
||||
is BackupAlert.DiskFull -> R.string.BackupAlertBottomSheet__skip_restore
|
||||
is BackupAlert.BackupFailed -> R.string.BackupAlertBottomSheet__learn_more
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -471,6 +493,17 @@ private fun BackupAlertSheetContentPreviewDiskFull() {
|
|||
}
|
||||
}
|
||||
|
||||
@SignalPreview
|
||||
@Composable
|
||||
private fun BackupAlertSheetContentPreviewBackupFailed() {
|
||||
Previews.BottomSheetPreview {
|
||||
BackupAlertSheetContent(
|
||||
backupAlert = BackupAlert.BackupFailed,
|
||||
mediaTtl = 60.days
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* All necessary information to display the sheet should be handed in through the specific alert.
|
||||
*/
|
||||
|
@ -485,6 +518,12 @@ sealed class BackupAlert : Parcelable {
|
|||
val daysSinceLastBackup: Int
|
||||
) : BackupAlert()
|
||||
|
||||
/**
|
||||
* This value is driven by the same watermarking system for [CouldNotCompleteBackup] so that only one of these sheets is shown by the system
|
||||
* This value is driven by failure to complete the initial backup.
|
||||
*/
|
||||
data object BackupFailed : BackupAlert()
|
||||
|
||||
/**
|
||||
* This value is driven by InAppPayment state, and will be automatically cleared when the sheet is displayed.
|
||||
*/
|
||||
|
|
|
@ -22,11 +22,11 @@ object BackupAlertDelegate {
|
|||
lifecycle.coroutineScope.launch {
|
||||
lifecycle.repeatOnLifecycle(Lifecycle.State.RESUMED) {
|
||||
if (BackupRepository.shouldDisplayBackupFailedSheet()) {
|
||||
BackupAlertBottomSheet.create(BackupAlert.BackupFailed).show(fragmentManager, null)
|
||||
} else if (BackupRepository.shouldDisplayCouldNotCompleteBackupSheet()) {
|
||||
BackupAlertBottomSheet.create(BackupAlert.CouldNotCompleteBackup(daysSinceLastBackup = SignalStore.backup.daysSinceLastBackup)).show(fragmentManager, null)
|
||||
}
|
||||
|
||||
if (BackupRepository.shouldDisplayYourMediaWillBeDeletedTodaySheet()) {
|
||||
BackupAlertBottomSheet.create(BackupAlert.MediaWillBeDeletedToday)
|
||||
} else if (BackupRepository.shouldDisplayYourMediaWillBeDeletedTodaySheet()) {
|
||||
BackupAlertBottomSheet.create(BackupAlert.MediaWillBeDeletedToday).show(fragmentManager, null)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -195,6 +195,12 @@ fun BackupStatusBannerPreview() {
|
|||
BackupStatusBanner(
|
||||
data = BackupStatusData.CouldNotCompleteBackup
|
||||
)
|
||||
|
||||
HorizontalDivider()
|
||||
|
||||
BackupStatusBanner(
|
||||
data = BackupStatusData.BackupFailed
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -235,6 +241,19 @@ sealed interface BackupStatusData {
|
|||
override val iconColors: BackupsIconColors = BackupsIconColors.Warning
|
||||
}
|
||||
|
||||
/**
|
||||
* Initial backup creation failure
|
||||
*/
|
||||
data object BackupFailed : BackupStatusData {
|
||||
override val iconRes: Int = R.drawable.symbol_backup_error_24
|
||||
|
||||
override val title: String
|
||||
@Composable
|
||||
get() = stringResource(androidx.biometric.R.string.default_error_msg)
|
||||
|
||||
override val iconColors: BackupsIconColors = BackupsIconColors.Warning
|
||||
}
|
||||
|
||||
/**
|
||||
* User does not have enough space on their device to complete backup restoration
|
||||
*/
|
||||
|
|
|
@ -20,17 +20,19 @@ import androidx.compose.material3.LinearProgressIndicator
|
|||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.setValue
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.res.dimensionResource
|
||||
import androidx.compose.ui.res.painterResource
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.text.LinkAnnotation
|
||||
import androidx.compose.ui.text.Placeholder
|
||||
import androidx.compose.ui.text.PlaceholderVerticalAlign
|
||||
import androidx.compose.ui.text.SpanStyle
|
||||
import androidx.compose.ui.text.TextLinkStyles
|
||||
import androidx.compose.ui.text.buildAnnotatedString
|
||||
import androidx.compose.ui.text.withLink
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.compose.ui.unit.sp
|
||||
import org.signal.core.ui.Previews
|
||||
|
@ -48,10 +50,13 @@ import org.signal.core.ui.R as CoreUiR
|
|||
fun BackupStatusRow(
|
||||
backupStatusData: BackupStatusData,
|
||||
onSkipClick: () -> Unit = {},
|
||||
onCancelClick: () -> Unit = {}
|
||||
onCancelClick: () -> Unit = {},
|
||||
onLearnMoreClick: () -> Unit = {}
|
||||
) {
|
||||
Column {
|
||||
if (backupStatusData !is BackupStatusData.CouldNotCompleteBackup) {
|
||||
if (backupStatusData !is BackupStatusData.CouldNotCompleteBackup &&
|
||||
backupStatusData !is BackupStatusData.BackupFailed
|
||||
) {
|
||||
Row(
|
||||
verticalAlignment = Alignment.CenterVertically,
|
||||
modifier = Modifier.padding(horizontal = dimensionResource(CoreUiR.dimen.gutter))
|
||||
|
@ -120,6 +125,40 @@ fun BackupStatusRow(
|
|||
modifier = Modifier.padding(horizontal = dimensionResource(CoreUiR.dimen.gutter))
|
||||
)
|
||||
}
|
||||
BackupStatusData.BackupFailed -> {
|
||||
val inlineContentMap = mapOf(
|
||||
"yellow_bullet" to InlineTextContent(
|
||||
Placeholder(12.sp, 12.sp, PlaceholderVerticalAlign.TextCenter)
|
||||
) {
|
||||
Box(
|
||||
modifier = Modifier
|
||||
.size(12.dp)
|
||||
.background(color = backupStatusData.iconColors.foreground, shape = CircleShape)
|
||||
)
|
||||
}
|
||||
)
|
||||
|
||||
Text(
|
||||
text = buildAnnotatedString {
|
||||
appendInlineContent("yellow_bullet")
|
||||
append(" ")
|
||||
append(stringResource(R.string.BackupStatusRow__your_last_backup_latest_version))
|
||||
append(" ")
|
||||
withLink(
|
||||
LinkAnnotation.Clickable(
|
||||
stringResource(R.string.BackupStatusRow__learn_more),
|
||||
styles = TextLinkStyles(style = SpanStyle(color = MaterialTheme.colorScheme.primary))
|
||||
) {
|
||||
onLearnMoreClick()
|
||||
}
|
||||
) {
|
||||
append(stringResource(R.string.BackupStatusRow__learn_more))
|
||||
}
|
||||
},
|
||||
inlineContent = inlineContentMap,
|
||||
modifier = Modifier.padding(horizontal = dimensionResource(CoreUiR.dimen.gutter))
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -241,3 +280,13 @@ fun BackupStatusRowCouldNotCompleteBackupPreview() {
|
|||
)
|
||||
}
|
||||
}
|
||||
|
||||
@SignalPreview
|
||||
@Composable
|
||||
fun BackupStatusRowBackupFailedPreview() {
|
||||
Previews.Preview {
|
||||
BackupStatusRow(
|
||||
backupStatusData = BackupStatusData.BackupFailed
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -215,7 +215,7 @@ private fun AppSettingsContent(
|
|||
}
|
||||
}
|
||||
|
||||
BackupFailureState.COULD_NOT_COMPLETE_BACKUP -> {
|
||||
BackupFailureState.BACKUP_FAILED, BackupFailureState.COULD_NOT_COMPLETE_BACKUP -> {
|
||||
item {
|
||||
Dividers.Default()
|
||||
|
||||
|
|
|
@ -72,6 +72,8 @@ class AppSettingsViewModel : ViewModel() {
|
|||
|
||||
private fun getBackupFailureState(): BackupFailureState {
|
||||
return if (BackupRepository.shouldDisplayBackupFailedSettingsRow()) {
|
||||
BackupFailureState.BACKUP_FAILED
|
||||
} else if (BackupRepository.shouldDisplayCouldNotCompleteBackupSettingsRow()) {
|
||||
BackupFailureState.COULD_NOT_COMPLETE_BACKUP
|
||||
} else if (SignalStore.backup.subscriptionStateMismatchDetected) {
|
||||
BackupFailureState.SUBSCRIPTION_STATE_MISMATCH
|
||||
|
|
|
@ -10,6 +10,7 @@ package org.thoughtcrime.securesms.components.settings.app
|
|||
*/
|
||||
enum class BackupFailureState {
|
||||
NONE,
|
||||
BACKUP_FAILED,
|
||||
COULD_NOT_COMPLETE_BACKUP,
|
||||
SUBSCRIPTION_STATE_MISMATCH
|
||||
}
|
||||
|
|
|
@ -83,6 +83,8 @@ import org.thoughtcrime.securesms.R
|
|||
import org.thoughtcrime.securesms.backup.ArchiveUploadProgress
|
||||
import org.thoughtcrime.securesms.backup.v2.BackupFrequency
|
||||
import org.thoughtcrime.securesms.backup.v2.MessageBackupTier
|
||||
import org.thoughtcrime.securesms.backup.v2.ui.BackupAlert
|
||||
import org.thoughtcrime.securesms.backup.v2.ui.BackupAlertBottomSheet
|
||||
import org.thoughtcrime.securesms.backup.v2.ui.status.BackupStatusData
|
||||
import org.thoughtcrime.securesms.backup.v2.ui.status.BackupStatusRow
|
||||
import org.thoughtcrime.securesms.backup.v2.ui.subscription.MessageBackupsType
|
||||
|
@ -233,6 +235,10 @@ class RemoteBackupsSettingsFragment : ComposeFragment() {
|
|||
requireActivity().finish()
|
||||
requireActivity().startActivity(AppSettingsActivity.help(requireContext(), HelpFragment.REMOTE_BACKUPS_INDEX))
|
||||
}
|
||||
|
||||
override fun onLearnMoreAboutBackupFailure() {
|
||||
BackupAlertBottomSheet.create(BackupAlert.BackupFailed).show(parentFragmentManager, null)
|
||||
}
|
||||
}
|
||||
|
||||
private fun displayBackupKey() {
|
||||
|
@ -314,6 +320,7 @@ private interface ContentCallbacks {
|
|||
fun onRenewLostSubscription() = Unit
|
||||
fun onLearnMoreAboutLostSubscription() = Unit
|
||||
fun onContactSupport() = Unit
|
||||
fun onLearnMoreAboutBackupFailure() = Unit
|
||||
}
|
||||
|
||||
@Composable
|
||||
|
@ -392,7 +399,8 @@ private fun RemoteBackupsSettingsContent(
|
|||
BackupStatusRow(
|
||||
backupStatusData = backupRestoreState.backupStatusData,
|
||||
onCancelClick = contentCallbacks::onCancelMediaRestore,
|
||||
onSkipClick = contentCallbacks::onSkipMediaRestore
|
||||
onSkipClick = contentCallbacks::onSkipMediaRestore,
|
||||
onLearnMoreClick = contentCallbacks::onLearnMoreAboutBackupFailure
|
||||
)
|
||||
}
|
||||
} else if (backupRestoreState is BackupRestoreState.Ready && backupState is RemoteBackupsSettingsState.BackupState.Canceled) {
|
||||
|
@ -420,7 +428,8 @@ private fun RemoteBackupsSettingsContent(
|
|||
BackupStatusRow(
|
||||
backupStatusData = backupRestoreState.backupStatusData,
|
||||
onCancelClick = contentCallbacks::onCancelMediaRestore,
|
||||
onSkipClick = contentCallbacks::onSkipMediaRestore
|
||||
onSkipClick = contentCallbacks::onSkipMediaRestore,
|
||||
onLearnMoreClick = contentCallbacks::onLearnMoreAboutBackupFailure
|
||||
)
|
||||
}
|
||||
}
|
||||
|
@ -920,8 +929,14 @@ private fun InProgressBackupRow(
|
|||
)
|
||||
}
|
||||
|
||||
val inProgressText = if (totalProgress == null || totalProgress == 0) {
|
||||
stringResource(R.string.RemoteBackupsSettingsFragment__processing_backup)
|
||||
} else {
|
||||
stringResource(R.string.RemoteBackupsSettingsFragment__d_slash_d, progress ?: 0, totalProgress)
|
||||
}
|
||||
|
||||
Text(
|
||||
text = stringResource(R.string.RemoteBackupsSettingsFragment__d_slash_d, progress ?: 0, totalProgress ?: 0),
|
||||
text = inProgressText,
|
||||
style = MaterialTheme.typography.bodyMedium,
|
||||
color = MaterialTheme.colorScheme.onSurfaceVariant
|
||||
)
|
||||
|
|
|
@ -92,6 +92,8 @@ class RemoteBackupsSettingsViewModel : ViewModel() {
|
|||
} else if (SignalStore.backup.totalRestorableAttachmentSize > 0L) {
|
||||
_restoreState.update { BackupRestoreState.Ready(SignalStore.backup.totalRestorableAttachmentSize.bytes.toUnitString()) }
|
||||
} else if (BackupRepository.shouldDisplayBackupFailedSettingsRow()) {
|
||||
_restoreState.update { BackupRestoreState.FromBackupStatusData(BackupStatusData.BackupFailed) }
|
||||
} else if (BackupRepository.shouldDisplayCouldNotCompleteBackupSettingsRow()) {
|
||||
_restoreState.update { BackupRestoreState.FromBackupStatusData(BackupStatusData.CouldNotCompleteBackup) }
|
||||
} else {
|
||||
_restoreState.update { BackupRestoreState.None }
|
||||
|
|
|
@ -101,8 +101,8 @@ class BackupMessagesJob private constructor(parameters: Parameters) : Job(parame
|
|||
return Result.retry(defaultBackoff())
|
||||
}
|
||||
is ArchiveValidator.ValidationResult.ValidationError -> {
|
||||
// TODO [backup] UX
|
||||
Log.w(TAG, "The backup file fails validation! Message: " + result.exception.message)
|
||||
ArchiveUploadProgress.onValidationFailure()
|
||||
return Result.failure()
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7504,6 +7504,12 @@
|
|||
<string name="BackupAlertBottomSheet__skip_restore_question">Skip restore?</string>
|
||||
<!-- Dialog text for skipping media restore -->
|
||||
<string name="BackupAlertBottomSheet__if_you_skip_restore_the">If you skip restore the remaining media and attachments in your backup can be downloaded at a later time when storage space becomes available.</string>
|
||||
<!-- Dialog title when a backup fails to be created -->
|
||||
<string name="BackupAlertBottomSheet__backup_failed">Backup failed</string>
|
||||
<!-- Dialog text for when a backup fails to be created and ways to fix it -->
|
||||
<string name="BackupAlertBottomSheet__an_error_occurred">An error occurred and your backup could not be completed. Make sure you\'re on the latest version of Signal and try again. If this problem persists, contact support.</string>
|
||||
<!-- Dialog action button that will allow you to check for any Signal version updates -->
|
||||
<string name="BackupAlertBottomSheet__check_for_update">Check for update</string>
|
||||
|
||||
<!-- BackupStatus -->
|
||||
<!-- Status title when user does not have enough free space to download their media. Placeholder is required disk space. -->
|
||||
|
@ -7536,7 +7542,11 @@
|
|||
<!-- Text row label to skip download -->
|
||||
<string name="BackupStatusRow__skip_download">Skip download</string>
|
||||
<!-- Text displayed when a backup could not be completed -->
|
||||
<string name="BackupStatusRow__your_last_backup">Your last backup couldn\'t be completed. Make sure your phone is connected to Wi-F and tap "Back up now" to try again.</string>
|
||||
<string name="BackupStatusRow__your_last_backup">Your last backup couldn\'t be completed. Make sure your phone is connected to Wi-Fi and tap \"Back up now\" to try again.</string>
|
||||
<!-- Text displayed when a backup could not be completed and to check that they are on the latest version of Signal -->
|
||||
<string name="BackupStatusRow__your_last_backup_latest_version">Your last backup couldn\'t be completed. Make sure you\'re on the latest version of Signal and try again.</string>
|
||||
<!-- Text displayed in a row to learn more about why a backup failed -->
|
||||
<string name="BackupStatusRow__learn_more">Learn more</string>
|
||||
|
||||
<!-- BackupsTypeSettingsFragment -->
|
||||
<!-- Displayed as the user\'s payment method as a label in a preference row -->
|
||||
|
@ -7740,6 +7750,8 @@
|
|||
<string name="RemoteBackupsSettingsFragment__renew">Renew</string>
|
||||
<!-- Button label to learn more about why subscription disappeared -->
|
||||
<string name="RemoteBackupsSettingsFragment__learn_more">Learn more</string>
|
||||
<!-- Linear progress dialog text shown when creating a backup -->
|
||||
<string name="RemoteBackupsSettingsFragment__processing_backup">Processing backup…</string>
|
||||
<!-- Displayed in row when backup is available for download and users subscription has expired. First placeholder is data size e.g. 12MB, second is days before expiration -->
|
||||
<plurals name="RemoteBackupsSettingsFragment__you_have_s_of_backup_data">
|
||||
<item quantity="one">You have %1$s of backup data that’s not on this device. Your backup will be deleted when your subscription ends in %2$d day.</item>
|
||||
|
|
Loading…
Add table
Reference in a new issue