Update TransferProgressIndicator to support indeterminate progress.

Showing exact progress for sticker pack downloads is more complicated than necessary. This PR updates `TransferProgressIndicator` to support displaying indeterminate progress.

#### Changeset
- Display indeterminate progress when installing a sticker pack.
- Remove cancel button from `AvailableStickerPackRow`.
- Decrease progress indicator size to match updated design.
This commit is contained in:
Jeffrey Starke
2025-04-21 11:20:13 -04:00
committed by Cody Henthorne
parent b246e62504
commit dd6c39f7eb
5 changed files with 76 additions and 56 deletions

View File

@@ -14,13 +14,11 @@ import androidx.compose.material3.MaterialTheme
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.StrokeCap
import androidx.compose.ui.graphics.painter.Painter
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.graphics.vector.ImageVector
import androidx.compose.ui.semantics.clearAndSetSemantics
import androidx.compose.ui.semantics.contentDescription
import androidx.compose.ui.unit.dp
import org.signal.core.ui.compose.clickableContainer
import org.thoughtcrime.securesms.R
/**
* A button that can be used to start, cancel, show progress, and show completion of a data transfer.
@@ -51,7 +49,7 @@ private fun StartTransferButton(
)
) {
Icon(
painter = state.iconPainter,
imageVector = state.icon,
tint = MaterialTheme.colorScheme.onSurface,
contentDescription = null,
modifier = Modifier
@@ -68,34 +66,61 @@ private fun ProgressIndicator(
) {
Box(
modifier = modifier
.clickableContainer(
contentDescription = null,
onClickLabel = state.cancelButtonOnClickLabel,
onClick = state.onCancelClick
)
.padding(8.dp)
) {
Icon(
painter = painterResource(R.drawable.symbol_stop_24),
tint = MaterialTheme.colorScheme.onSurface,
contentDescription = null,
modifier = Modifier
.matchParentSize()
.padding(6.dp)
)
CircularProgressIndicator(
progress = { state.progress },
strokeWidth = 2.dp,
strokeCap = StrokeCap.Round,
trackColor = MaterialTheme.colorScheme.surfaceContainerHighest,
color = MaterialTheme.colorScheme.onSurface,
modifier = Modifier
.matchParentSize()
.clearAndSetSemantics {
contentDescription = state.cancelButtonContentDesc
.then(
if (state.cancelAction != null) {
Modifier.clickableContainer(
contentDescription = null,
onClickLabel = state.cancelAction.onClickLabel,
onClick = state.cancelAction.onClick
)
} else {
Modifier
}
)
)
.padding(10.dp)
) {
state.icon?.let { icon ->
Icon(
imageVector = icon,
tint = MaterialTheme.colorScheme.onSurface,
contentDescription = null,
modifier = Modifier
.matchParentSize()
.padding(6.dp)
)
}
val indicatorModifier = Modifier
.matchParentSize()
.then(
if (state.cancelAction != null) {
Modifier.clearAndSetSemantics {
contentDescription = state.cancelAction.contentDesc
}
} else {
Modifier
}
)
val progress = state.progress
if (progress == null) {
CircularProgressIndicator(
strokeWidth = 2.dp,
strokeCap = StrokeCap.Round,
trackColor = MaterialTheme.colorScheme.surfaceContainerHighest,
color = MaterialTheme.colorScheme.onSurface,
modifier = indicatorModifier
)
} else {
CircularProgressIndicator(
progress = { progress },
strokeWidth = 2.dp,
strokeCap = StrokeCap.Round,
trackColor = MaterialTheme.colorScheme.surfaceContainerHighest,
color = MaterialTheme.colorScheme.onSurface,
modifier = indicatorModifier
)
}
}
}
@@ -105,7 +130,7 @@ private fun CompleteIcon(
modifier: Modifier = Modifier
) {
Icon(
painter = state.iconPainter,
imageVector = state.icon,
tint = MaterialTheme.colorScheme.onSurface,
contentDescription = state.iconContentDesc,
modifier = modifier.padding(12.dp)
@@ -114,21 +139,27 @@ private fun CompleteIcon(
sealed interface TransferProgressState {
data class Ready(
val iconPainter: Painter,
val icon: ImageVector,
val startButtonContentDesc: String,
val startButtonOnClickLabel: String,
val onStartClick: () -> Unit
) : TransferProgressState
data class InProgress(
val progress: Float,
val cancelButtonContentDesc: String,
val cancelButtonOnClickLabel: String,
val onCancelClick: () -> Unit = {}
) : TransferProgressState
val icon: ImageVector? = null,
val progress: Float? = null,
val cancelAction: CancelAction? = null
) : TransferProgressState {
data class CancelAction(
val contentDesc: String,
val onClickLabel: String,
val onClick: () -> Unit
)
}
data class Complete(
val iconPainter: Painter,
val icon: ImageVector,
val iconContentDesc: String
) : TransferProgressState
}

View File

@@ -279,7 +279,7 @@ private fun AvailableStickersContentPreview() {
title = "Bandit the Cat",
author = "Agnes Lee",
isBlessed = false,
downloadStatus = DownloadStatus.InProgress(progress = 0.37f)
downloadStatus = DownloadStatus.InProgress
),
StickerPreviewDataFactory.availablePack(
title = "Day by Day",

View File

@@ -58,7 +58,7 @@ data class AvailableStickerPack(
) {
sealed class DownloadStatus {
data object NotDownloaded : DownloadStatus()
data class InProgress(val progress: Float) : DownloadStatus()
data object InProgress : DownloadStatus()
data object Downloaded : DownloadStatus()
}
}

View File

@@ -20,7 +20,6 @@ import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.vector.ImageVector
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.res.vectorResource
import androidx.compose.ui.unit.dp
@@ -54,7 +53,6 @@ fun StickerPackSectionHeader(
fun AvailableStickerPackRow(
pack: AvailableStickerPack,
onStartDownloadClick: () -> Unit = {},
onCancelDownloadClick: () -> Unit = {},
modifier: Modifier = Modifier
) {
Row(
@@ -74,21 +72,16 @@ fun AvailableStickerPackRow(
TransferProgressIndicator(
state = when (pack.downloadStatus) {
DownloadStatus.NotDownloaded -> TransferProgressState.Ready(
iconPainter = painterResource(id = R.drawable.symbol_arrow_circle_down_24),
icon = ImageVector.vectorResource(id = R.drawable.symbol_arrow_circle_down_24),
startButtonContentDesc = stringResource(R.string.StickerManagement_accessibility_download),
startButtonOnClickLabel = stringResource(R.string.StickerManagement_accessibility_download_pack, pack.record.title),
onStartClick = onStartDownloadClick
)
is DownloadStatus.InProgress -> TransferProgressState.InProgress(
progress = pack.downloadStatus.progress,
cancelButtonContentDesc = stringResource(R.string.StickerManagement_accessibility_cancel),
cancelButtonOnClickLabel = stringResource(R.string.StickerManagement_accessibility_cancel_downloading_pack, pack.record.title),
onCancelClick = onCancelDownloadClick
)
is DownloadStatus.InProgress -> TransferProgressState.InProgress()
DownloadStatus.Downloaded -> TransferProgressState.Complete(
iconPainter = painterResource(id = R.drawable.symbol_check_24),
icon = ImageVector.vectorResource(id = R.drawable.symbol_check_24),
iconContentDesc = stringResource(R.string.StickerManagement_accessibility_downloaded_checkmark, pack.record.title)
)
}
@@ -227,7 +220,7 @@ private fun AvailableStickerPackRowPreviewDownloading() = SignalTheme {
title = "Bandit the Cat",
author = "Agnes Lee",
isBlessed = false,
downloadStatus = DownloadStatus.InProgress(progress = 0.37f)
downloadStatus = DownloadStatus.InProgress
)
)
}

View File

@@ -2808,16 +2808,12 @@
<string name="StickerManagement_signal_artist_series_header">Signal artist series</string>
<!-- Accessibility label for the button to download a sticker pack. The placeholder is the sticker pack name. -->
<string name="StickerManagement_accessibility_download_pack">Download %s sticker pack</string>
<!-- Accessibility label for the button to cancel a sticker pack download. The placeholder is the sticker pack name. -->
<string name="StickerManagement_accessibility_cancel_downloading_pack">Cancel downloading %s sticker pack</string>
<!-- Accessibility label for the icon that is displayed after a sticker pack has been downloaded. The placeholder is the sticker pack name. -->
<string name="StickerManagement_accessibility_downloaded_checkmark">Downloaded checkmark</string>
<!-- Accessibility label for the sticker pack drag and drop handle used to reorder the list. -->
<string name="StickerManagement_accessibility_drag_handle">Drag and drop handle</string>
<!-- Accessibility label for the button to download a sticker pack. -->
<string name="StickerManagement_accessibility_download">Download</string>
<!-- Accessibility label for the button to cancel downloading a sticker pack. -->
<string name="StickerManagement_accessibility_cancel">Cancel</string>
<!-- StickerManagementAdapter -->
<string name="StickerManagementAdapter_no_stickers_installed">No stickers installed</string>