mirror of
https://github.com/signalapp/Signal-Android.git
synced 2025-12-24 04:58:45 +00:00
BackupStatusRow to display backup restore status in settings fragment.
This commit is contained in:
committed by
Greyson Parrelli
parent
b073005ff9
commit
dd4d674a61
@@ -55,7 +55,7 @@ private const val NONE = -1
|
||||
*/
|
||||
@OptIn(ExperimentalLayoutApi::class)
|
||||
@Composable
|
||||
fun BackupStatus(
|
||||
fun BackupStatusBanner(
|
||||
data: BackupStatusData,
|
||||
onSkipClick: () -> Unit = {},
|
||||
onDismissClick: () -> Unit = {},
|
||||
@@ -150,13 +150,13 @@ fun BackupStatus(
|
||||
fun BackupStatusBannerPreview() {
|
||||
Previews.Preview {
|
||||
Column {
|
||||
BackupStatus(
|
||||
BackupStatusBanner(
|
||||
data = BackupStatusData.RestoringMedia(5755000.bytes, 1253.mebiBytes)
|
||||
)
|
||||
|
||||
HorizontalDivider()
|
||||
|
||||
BackupStatus(
|
||||
BackupStatusBanner(
|
||||
data = BackupStatusData.RestoringMedia(
|
||||
bytesDownloaded = 55000.bytes,
|
||||
bytesTotal = 1253.mebiBytes,
|
||||
@@ -166,7 +166,7 @@ fun BackupStatusBannerPreview() {
|
||||
|
||||
HorizontalDivider()
|
||||
|
||||
BackupStatus(
|
||||
BackupStatusBanner(
|
||||
data = BackupStatusData.RestoringMedia(
|
||||
bytesDownloaded = 55000.bytes,
|
||||
bytesTotal = 1253.mebiBytes,
|
||||
@@ -176,7 +176,7 @@ fun BackupStatusBannerPreview() {
|
||||
|
||||
HorizontalDivider()
|
||||
|
||||
BackupStatus(
|
||||
BackupStatusBanner(
|
||||
data = BackupStatusData.RestoringMedia(
|
||||
bytesDownloaded = 55000.bytes,
|
||||
bytesTotal = 1253.mebiBytes,
|
||||
@@ -186,13 +186,13 @@ fun BackupStatusBannerPreview() {
|
||||
|
||||
HorizontalDivider()
|
||||
|
||||
BackupStatus(
|
||||
BackupStatusBanner(
|
||||
data = BackupStatusData.NotEnoughFreeSpace(40900.kibiBytes)
|
||||
)
|
||||
|
||||
HorizontalDivider()
|
||||
|
||||
BackupStatus(
|
||||
BackupStatusBanner(
|
||||
data = BackupStatusData.CouldNotCompleteBackup
|
||||
)
|
||||
}
|
||||
@@ -241,7 +241,7 @@ sealed interface BackupStatusData {
|
||||
class NotEnoughFreeSpace(
|
||||
requiredSpace: ByteSize
|
||||
) : BackupStatusData {
|
||||
private val requiredSpace = requiredSpace.toUnitString(maxPlaces = 2)
|
||||
val requiredSpace = requiredSpace.toUnitString(maxPlaces = 2)
|
||||
|
||||
override val iconRes: Int = R.drawable.symbol_backup_error_24
|
||||
|
||||
|
||||
@@ -0,0 +1,240 @@
|
||||
/*
|
||||
* Copyright 2024 Signal Messenger, LLC
|
||||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
|
||||
package org.thoughtcrime.securesms.backup.v2.ui.status
|
||||
|
||||
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.padding
|
||||
import androidx.compose.foundation.layout.size
|
||||
import androidx.compose.foundation.shape.CircleShape
|
||||
import androidx.compose.foundation.text.InlineTextContent
|
||||
import androidx.compose.foundation.text.appendInlineContent
|
||||
import androidx.compose.material3.Icon
|
||||
import androidx.compose.material3.IconButton
|
||||
import androidx.compose.material3.LinearProgressIndicator
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
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.Placeholder
|
||||
import androidx.compose.ui.text.PlaceholderVerticalAlign
|
||||
import androidx.compose.ui.text.buildAnnotatedString
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.compose.ui.unit.sp
|
||||
import org.signal.core.ui.Previews
|
||||
import org.signal.core.ui.Rows
|
||||
import org.signal.core.ui.SignalPreview
|
||||
import org.signal.core.util.ByteSize
|
||||
import org.thoughtcrime.securesms.R
|
||||
import kotlin.math.roundToInt
|
||||
|
||||
/**
|
||||
* Backup status displayable as a row on a settings page.
|
||||
*/
|
||||
@Composable
|
||||
fun BackupStatusRow(
|
||||
backupStatusData: BackupStatusData,
|
||||
onSkipClick: () -> Unit = {},
|
||||
onCancelClick: () -> Unit = {}
|
||||
) {
|
||||
Column {
|
||||
if (backupStatusData !is BackupStatusData.CouldNotCompleteBackup) {
|
||||
Row(
|
||||
verticalAlignment = Alignment.CenterVertically,
|
||||
modifier = Modifier.padding(horizontal = dimensionResource(R.dimen.core_ui__gutter))
|
||||
) {
|
||||
LinearProgressIndicator(
|
||||
color = progressColor(backupStatusData),
|
||||
progress = { backupStatusData.progress },
|
||||
modifier = Modifier.weight(1f)
|
||||
)
|
||||
|
||||
IconButton(
|
||||
onClick = onCancelClick
|
||||
) {
|
||||
Icon(
|
||||
painter = painterResource(R.drawable.symbol_x_24),
|
||||
contentDescription = stringResource(R.string.BackupStatusRow__cancel_download)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
when (backupStatusData) {
|
||||
is BackupStatusData.RestoringMedia -> {
|
||||
Text(
|
||||
text = getRestoringMediaString(backupStatusData),
|
||||
modifier = Modifier.padding(horizontal = dimensionResource(R.dimen.core_ui__gutter))
|
||||
)
|
||||
}
|
||||
|
||||
is BackupStatusData.NotEnoughFreeSpace -> {
|
||||
Text(
|
||||
text = stringResource(
|
||||
R.string.BackupStatusRow__not_enough_space,
|
||||
backupStatusData.requiredSpace,
|
||||
"%d".format((backupStatusData.progress * 100).roundToInt())
|
||||
),
|
||||
modifier = Modifier.padding(horizontal = dimensionResource(R.dimen.core_ui__gutter))
|
||||
)
|
||||
|
||||
Rows.TextRow(
|
||||
text = stringResource(R.string.BackupStatusRow__skip_download),
|
||||
onClick = onSkipClick
|
||||
)
|
||||
}
|
||||
|
||||
BackupStatusData.CouldNotCompleteBackup -> {
|
||||
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))
|
||||
},
|
||||
inlineContent = inlineContentMap,
|
||||
modifier = Modifier.padding(horizontal = dimensionResource(R.dimen.core_ui__gutter))
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun getRestoringMediaString(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.BackupStatus__status_device_has_low_battery)
|
||||
BackupStatusData.RestoreStatus.WAITING_FOR_INTERNET -> stringResource(R.string.BackupStatus__status_no_internet)
|
||||
BackupStatusData.RestoreStatus.WAITING_FOR_WIFI -> stringResource(R.string.BackupStatus__status_waiting_for_wifi)
|
||||
BackupStatusData.RestoreStatus.FINISHED -> stringResource(R.string.BackupStatus__restore_complete)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun progressColor(backupStatusData: BackupStatusData): Color {
|
||||
return when (backupStatusData) {
|
||||
is BackupStatusData.RestoringMedia -> MaterialTheme.colorScheme.primary
|
||||
else -> backupStatusData.iconColors.foreground
|
||||
}
|
||||
}
|
||||
|
||||
@SignalPreview
|
||||
@Composable
|
||||
fun BackupStatusRowNormalPreview() {
|
||||
Previews.Preview {
|
||||
BackupStatusRow(
|
||||
backupStatusData = BackupStatusData.RestoringMedia(
|
||||
bytesTotal = ByteSize(100),
|
||||
bytesDownloaded = ByteSize(50),
|
||||
restoreStatus = BackupStatusData.RestoreStatus.NORMAL
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@SignalPreview
|
||||
@Composable
|
||||
fun BackupStatusRowWaitingForWifiPreview() {
|
||||
Previews.Preview {
|
||||
BackupStatusRow(
|
||||
backupStatusData = BackupStatusData.RestoringMedia(
|
||||
bytesTotal = ByteSize(100),
|
||||
bytesDownloaded = ByteSize(50),
|
||||
restoreStatus = BackupStatusData.RestoreStatus.WAITING_FOR_WIFI
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@SignalPreview
|
||||
@Composable
|
||||
fun BackupStatusRowWaitingForInternetPreview() {
|
||||
Previews.Preview {
|
||||
BackupStatusRow(
|
||||
backupStatusData = BackupStatusData.RestoringMedia(
|
||||
bytesTotal = ByteSize(100),
|
||||
bytesDownloaded = ByteSize(50),
|
||||
restoreStatus = BackupStatusData.RestoreStatus.WAITING_FOR_INTERNET
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@SignalPreview
|
||||
@Composable
|
||||
fun BackupStatusRowLowBatteryPreview() {
|
||||
Previews.Preview {
|
||||
BackupStatusRow(
|
||||
backupStatusData = BackupStatusData.RestoringMedia(
|
||||
bytesTotal = ByteSize(100),
|
||||
bytesDownloaded = ByteSize(50),
|
||||
restoreStatus = BackupStatusData.RestoreStatus.LOW_BATTERY
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@SignalPreview
|
||||
@Composable
|
||||
fun BackupStatusRowFinishedPreview() {
|
||||
Previews.Preview {
|
||||
BackupStatusRow(
|
||||
backupStatusData = BackupStatusData.RestoringMedia(
|
||||
bytesTotal = ByteSize(100),
|
||||
bytesDownloaded = ByteSize(50),
|
||||
restoreStatus = BackupStatusData.RestoreStatus.FINISHED
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@SignalPreview
|
||||
@Composable
|
||||
fun BackupStatusRowNotEnoughFreeSpacePreview() {
|
||||
Previews.Preview {
|
||||
BackupStatusRow(
|
||||
backupStatusData = BackupStatusData.NotEnoughFreeSpace(
|
||||
requiredSpace = ByteSize(50)
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@SignalPreview
|
||||
@Composable
|
||||
fun BackupStatusRowCouldNotCompleteBackupPreview() {
|
||||
Previews.Preview {
|
||||
BackupStatusRow(
|
||||
backupStatusData = BackupStatusData.CouldNotCompleteBackup
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -23,7 +23,7 @@ import kotlinx.coroutines.flow.flowOn
|
||||
import kotlinx.coroutines.flow.map
|
||||
import org.signal.core.util.bytes
|
||||
import org.signal.core.util.throttleLatest
|
||||
import org.thoughtcrime.securesms.backup.v2.ui.status.BackupStatus
|
||||
import org.thoughtcrime.securesms.backup.v2.ui.status.BackupStatusBanner
|
||||
import org.thoughtcrime.securesms.backup.v2.ui.status.BackupStatusData
|
||||
import org.thoughtcrime.securesms.banner.Banner
|
||||
import org.thoughtcrime.securesms.database.DatabaseObserver
|
||||
@@ -71,7 +71,7 @@ class MediaRestoreProgressBanner(private val listener: RestoreProgressBannerList
|
||||
|
||||
@Composable
|
||||
override fun DisplayBanner(model: BackupStatusData, contentPadding: PaddingValues) {
|
||||
BackupStatus(
|
||||
BackupStatusBanner(
|
||||
data = model,
|
||||
onSkipClick = listener::onSkip,
|
||||
onDismissClick = listener::onDismissComplete
|
||||
|
||||
@@ -7443,6 +7443,17 @@
|
||||
<!-- Status subtitle for banner when restoring media. Placeholders are size already restored and total size to restore. e.g., 4.5MB of 100MB -->
|
||||
<string name="BackupStatus__status_size_of_size">%1$s of %2$s</string>
|
||||
|
||||
<!-- BackupStatusRow -->
|
||||
<!-- Content description for x icon at the end of the linear progress indicator -->
|
||||
<string name="BackupStatusRow__cancel_download">Cancel download</string>
|
||||
<!-- Backup progress. Placeholders are size restored, size to restore, and percent, i.e. 50MB of 100MB (50%) -->
|
||||
<string name="BackupStatusRow__downloading_s_of_s_s">Downloading: %1$s of %2$s (%3$s%%)</string>
|
||||
<!-- Notice that there is not enough free space to continue restore. Placeholder is required space, for example 1.6GB -->
|
||||
<string name="BackupStatusRow__not_enough_space">Not enough space to download your Backup. To continue free up %1$s of space.</string>
|
||||
<!-- 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>
|
||||
|
||||
<!-- BackupsTypeSettingsFragment -->
|
||||
<!-- Displayed as the user\'s payment method as a label in a preference row -->
|
||||
|
||||
Reference in New Issue
Block a user