diff --git a/app/src/main/java/org/thoughtcrime/securesms/backup/v2/ui/status/BackupStatusRow.kt b/app/src/main/java/org/thoughtcrime/securesms/backup/v2/ui/status/BackupStatusRow.kt index b6f688bc09..18d6d2da1e 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/backup/v2/ui/status/BackupStatusRow.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/backup/v2/ui/status/BackupStatusRow.kt @@ -9,7 +9,6 @@ import androidx.compose.foundation.background import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Row -import androidx.compose.foundation.layout.defaultMinSize import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.size import androidx.compose.foundation.shape.CircleShape @@ -21,12 +20,14 @@ import androidx.compose.material3.LinearProgressIndicator import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Text import androidx.compose.runtime.Composable +import androidx.compose.runtime.remember 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.AnnotatedString import androidx.compose.ui.text.LinkAnnotation import androidx.compose.ui.text.Placeholder import androidx.compose.ui.text.PlaceholderVerticalAlign @@ -46,28 +47,48 @@ import org.signal.core.ui.R as CoreUiR private val YELLOW_DOT = Color(0xFFFFCC00) +/** + * Specifies what kind of restore this is. Slightly different messaging + * is utilized for downloads. + */ +enum class RestoreType { + /** + * Restoring, when the user has downloads enabled but is restoring optimized media. + */ + RESTORE, + + /** + * Downloading, when the user has opted to turn off and delete download, and we are + * downloading optimized media. + */ + DOWNLOAD +} + /** * Backup status displayable as a row on a settings page. */ @Composable fun BackupStatusRow( backupStatusData: BackupStatusData, + restoreType: RestoreType = RestoreType.RESTORE, onSkipClick: () -> Unit = {}, onCancelClick: (() -> Unit)? = null, onLearnMoreClick: () -> Unit = {} ) { - Column { + Column( + modifier = Modifier.padding(top = 8.dp, bottom = 12.dp) + ) { if (backupStatusData !is BackupStatusData.CouldNotCompleteBackup && backupStatusData !is BackupStatusData.BackupFailed ) { Row( verticalAlignment = Alignment.CenterVertically, - modifier = Modifier.padding(horizontal = dimensionResource(CoreUiR.dimen.gutter)).defaultMinSize(minHeight = 48.dp) + modifier = Modifier.padding(horizontal = dimensionResource(CoreUiR.dimen.gutter)) ) { LinearProgressIndicator( color = progressColor(backupStatusData), progress = { backupStatusData.progress }, - modifier = Modifier.weight(1f) + modifier = Modifier.weight(1f).padding(vertical = 12.dp) ) if (onCancelClick != null) { @@ -85,21 +106,21 @@ fun BackupStatusRow( when (backupStatusData) { is BackupStatusData.RestoringMedia -> { - Text( - text = getRestoringMediaString(backupStatusData), - color = MaterialTheme.colorScheme.onSurfaceVariant, - modifier = Modifier.padding(horizontal = dimensionResource(CoreUiR.dimen.gutter)) - ) + val string = when (restoreType) { + RestoreType.RESTORE -> getRestoringMediaString(backupStatusData) + RestoreType.DOWNLOAD -> getDownloadingMediaString(backupStatusData) + } + + BackupAlertText(text = string) } is BackupStatusData.NotEnoughFreeSpace -> { - Text( + BackupAlertText( text = stringResource( R.string.BackupStatusRow__not_enough_space, backupStatusData.requiredSpace, "%d".format((backupStatusData.progress * 100).roundToInt()) - ), - modifier = Modifier.padding(horizontal = dimensionResource(CoreUiR.dimen.gutter)) + ) ) Rows.TextRow( @@ -121,14 +142,13 @@ fun BackupStatusRow( } ) - Text( + BackupAlertText( text = buildAnnotatedString { appendInlineContent("yellow_bullet") append(" ") append(stringResource(R.string.BackupStatusRow__your_last_backup)) }, - inlineContent = inlineContentMap, - modifier = Modifier.padding(horizontal = dimensionResource(CoreUiR.dimen.gutter)) + inlineContent = inlineContentMap ) } BackupStatusData.BackupFailed -> { @@ -144,7 +164,7 @@ fun BackupStatusRow( } ) - Text( + BackupAlertText( text = buildAnnotatedString { appendInlineContent("yellow_bullet") append(" ") @@ -161,14 +181,32 @@ fun BackupStatusRow( append(stringResource(R.string.BackupStatusRow__learn_more)) } }, - inlineContent = inlineContentMap, - modifier = Modifier.padding(horizontal = dimensionResource(CoreUiR.dimen.gutter)) + inlineContent = inlineContentMap ) } } } } +@Composable +private fun BackupAlertText(text: String) { + BackupAlertText( + text = remember(text) { AnnotatedString(text) }, + inlineContent = emptyMap() + ) +} + +@Composable +private fun BackupAlertText(text: AnnotatedString, inlineContent: Map) { + Text( + text = text, + color = MaterialTheme.colorScheme.onSurfaceVariant, + style = MaterialTheme.typography.bodyMedium, + modifier = Modifier.padding(horizontal = dimensionResource(CoreUiR.dimen.gutter)), + inlineContent = inlineContent + ) +} + @Composable private fun getRestoringMediaString(backupStatusData: BackupStatusData.RestoringMedia): String { return when (backupStatusData.restoreStatus) { @@ -187,6 +225,24 @@ private fun getRestoringMediaString(backupStatusData: BackupStatusData.Restoring } } +@Composable +private fun getDownloadingMediaString(backupStatusData: BackupStatusData.RestoringMedia): String { + return when (backupStatusData.restoreStatus) { + BackupStatusData.RestoreStatus.NORMAL -> { + stringResource( + R.string.BackupStatusRow__downloading_s_of_s_s, + backupStatusData.bytesDownloaded.toUnitString(2), + backupStatusData.bytesTotal.toUnitString(2), + "%d".format((backupStatusData.progress * 100).roundToInt()) + ) + } + BackupStatusData.RestoreStatus.LOW_BATTERY -> stringResource(R.string.BackupStatusRow__download_device_has_low_battery) + BackupStatusData.RestoreStatus.WAITING_FOR_INTERNET -> stringResource(R.string.BackupStatusRow__download_no_internet) + BackupStatusData.RestoreStatus.WAITING_FOR_WIFI -> stringResource(R.string.BackupStatusRow__download_waiting_for_wifi) + BackupStatusData.RestoreStatus.FINISHED -> stringResource(R.string.BackupStatus__restore_complete) + } +} + @Composable private fun progressColor(backupStatusData: BackupStatusData): Color { return if (backupStatusData is BackupStatusData.RestoringMedia && backupStatusData.restoreStatus == BackupStatusData.RestoreStatus.NORMAL) { diff --git a/app/src/main/java/org/thoughtcrime/securesms/components/settings/app/backups/remote/RemoteBackupsSettingsFragment.kt b/app/src/main/java/org/thoughtcrime/securesms/components/settings/app/backups/remote/RemoteBackupsSettingsFragment.kt index 2a4e3f2922..503e2000d5 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/components/settings/app/backups/remote/RemoteBackupsSettingsFragment.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/components/settings/app/backups/remote/RemoteBackupsSettingsFragment.kt @@ -99,6 +99,7 @@ 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.status.RestoreType import org.thoughtcrime.securesms.backup.v2.ui.subscription.MessageBackupsType import org.thoughtcrime.securesms.billing.launchManageBackupsSubscription import org.thoughtcrime.securesms.components.compose.BetaHeader @@ -402,7 +403,7 @@ private fun RemoteBackupsSettingsContent( if (backupDeleteState != DeletionState.NONE && backupDeleteState != DeletionState.CLEAR_LOCAL_STATE) { contentCallbacks.onDialogDismissed() } - + if (backupDeleteState == DeletionState.AWAITING_MEDIA_DOWNLOAD) { contentCallbacks.onDisplayDownloadingBackupDialog() } @@ -655,6 +656,7 @@ private fun LazyListScope.appendRestoreFromBackupStatusData( item { BackupStatusRow( backupStatusData = backupRestoreState.backupStatusData, + restoreType = RestoreType.DOWNLOAD, onCancelClick = if (isCancelable) contentCallbacks::onCancelMediaRestore else null, onSkipClick = contentCallbacks::onDisplaySkipMediaRestoreProtectionDialog, onLearnMoreClick = contentCallbacks::onLearnMoreAboutBackupFailure diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 127b094762..a3e5a7e220 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -7942,6 +7942,14 @@ Restore paused: No internet… Restore paused: Device has low battery + + Downloading: %1$s of %2$s (%3$s%%) + + Download paused: Waiting for Wi-Fi… + + Download paused: No internet… + + Download paused: Device has low battery Not enough space to download your Backup. To continue free up %1$s of space.