From d6dd2cc6339282895684d2414c5d92a6a2ebb5dc Mon Sep 17 00:00:00 2001 From: Alex Hart Date: Tue, 3 Jun 2025 10:38:34 -0300 Subject: [PATCH] Polish backup type selection UI. --- .../MessageBackupsKeyVerifyScreen.kt | 5 ++ .../subscription/MessageBackupsTypeFeature.kt | 3 +- .../MessageBackupsTypeSelectionScreen.kt | 50 ++++++++++--------- app/src/main/res/values/strings.xml | 8 +-- 4 files changed, 39 insertions(+), 27 deletions(-) diff --git a/app/src/main/java/org/thoughtcrime/securesms/backup/v2/ui/subscription/MessageBackupsKeyVerifyScreen.kt b/app/src/main/java/org/thoughtcrime/securesms/backup/v2/ui/subscription/MessageBackupsKeyVerifyScreen.kt index 7629c531dc..35d25f075a 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/backup/v2/ui/subscription/MessageBackupsKeyVerifyScreen.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/backup/v2/ui/subscription/MessageBackupsKeyVerifyScreen.kt @@ -30,6 +30,7 @@ import androidx.compose.material3.Surface import androidx.compose.material3.Text import androidx.compose.material3.TextButton import androidx.compose.material3.TextField +import androidx.compose.material3.TextFieldDefaults import androidx.compose.material3.rememberModalBottomSheetState import androidx.compose.runtime.Composable import androidx.compose.runtime.getValue @@ -160,6 +161,10 @@ fun MessageBackupsKeyVerifyScreen( } } ), + colors = TextFieldDefaults.colors( + focusedContainerColor = MaterialTheme.colorScheme.surfaceVariant, + unfocusedContainerColor = MaterialTheme.colorScheme.surfaceVariant + ), supportingText = { if (showError) Text(text = stringResource(R.string.MessageBackupsKeyVerifyScreen__incorrect_backup_key)) }, isError = showError, minLines = 4, diff --git a/app/src/main/java/org/thoughtcrime/securesms/backup/v2/ui/subscription/MessageBackupsTypeFeature.kt b/app/src/main/java/org/thoughtcrime/securesms/backup/v2/ui/subscription/MessageBackupsTypeFeature.kt index 612ece35dc..32a9fce4d8 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/backup/v2/ui/subscription/MessageBackupsTypeFeature.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/backup/v2/ui/subscription/MessageBackupsTypeFeature.kt @@ -8,6 +8,7 @@ package org.thoughtcrime.securesms.backup.v2.ui.subscription import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.size import androidx.compose.material3.Icon import androidx.compose.material3.LocalContentColor import androidx.compose.material3.MaterialTheme @@ -47,7 +48,7 @@ fun MessageBackupsTypeFeatureRow( painter = painterResource(id = messageBackupsTypeFeature.iconResourceId), contentDescription = null, tint = iconTint, - modifier = Modifier.padding(end = 8.dp) + modifier = Modifier.padding(end = 8.dp).size(20.dp) ) Text( diff --git a/app/src/main/java/org/thoughtcrime/securesms/backup/v2/ui/subscription/MessageBackupsTypeSelectionScreen.kt b/app/src/main/java/org/thoughtcrime/securesms/backup/v2/ui/subscription/MessageBackupsTypeSelectionScreen.kt index ad20be87ca..7c4e056ac2 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/backup/v2/ui/subscription/MessageBackupsTypeSelectionScreen.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/backup/v2/ui/subscription/MessageBackupsTypeSelectionScreen.kt @@ -118,9 +118,9 @@ fun MessageBackupsTypeSelectionScreen( val readMoreString = buildAnnotatedString { append(stringResource(id = R.string.MessageBackupsTypeSelectionScreen__all_backups_are_end_to_end_encrypted)) - val readMore = stringResource(id = R.string.MessageBackupsTypeSelectionScreen__read_more) + val readMore = stringResource(id = R.string.MessageBackupsTypeSelectionScreen__learn_more) append(" ") - withAnnotation(tag = "URL", annotation = "read-more") { + withAnnotation(tag = "URL", annotation = "learn-more") { withStyle( style = SpanStyle( color = primaryColor @@ -133,7 +133,7 @@ fun MessageBackupsTypeSelectionScreen( ClickableText( text = readMoreString, - style = MaterialTheme.typography.bodyLarge.copy(textAlign = TextAlign.Center, color = MaterialTheme.colorScheme.onSurface), + style = MaterialTheme.typography.bodyLarge.copy(textAlign = TextAlign.Center, color = MaterialTheme.colorScheme.onSurfaceVariant), onClick = { offset -> readMoreString .getStringAnnotations(tag = "URL", start = offset, end = offset) @@ -159,22 +159,31 @@ fun MessageBackupsTypeSelectionScreen( val hasCurrentBackupTier = currentBackupTier != null - Buttons.LargePrimary( + Buttons.LargeTonal( onClick = onNextClicked, enabled = isNextEnabled, modifier = Modifier .fillMaxWidth() .padding(vertical = if (hasCurrentBackupTier) 10.dp else 16.dp) ) { - Text( - text = stringResource( - id = if (currentBackupTier == null) { - R.string.MessageBackupsTypeSelectionScreen__next - } else { - R.string.MessageBackupsTypeSelectionScreen__change_backup_type + val text: String = if (currentBackupTier == null) { + if (selectedBackupTier == MessageBackupTier.PAID && availableBackupTypes.map { it.tier }.contains(selectedBackupTier)) { + val paidTier = availableBackupTypes.first { it.tier == MessageBackupTier.PAID } as MessageBackupsType.Paid + val context = LocalContext.current + + val price = remember(paidTier) { + FiatMoneyUtil.format(context.resources, paidTier.pricePerMonth, FiatMoneyUtil.formatOptions().trimZerosAfterDecimal()) } - ) - ) + + stringResource(R.string.MessageBackupsTypeSelectionScreen__subscribe_for_x_month, price) + } else { + stringResource(R.string.MessageBackupsTypeSelectionScreen__subscribe) + } + } else { + stringResource(R.string.MessageBackupsTypeSelectionScreen__change_backup_type) + } + + Text(text = text) } when (stage) { @@ -243,17 +252,11 @@ fun MessageBackupsTypeBlock( Color.Transparent } - val background = if (isSelected) { - MaterialTheme.colorScheme.secondaryContainer - } else { - SignalTheme.colors.colorSurface2 - } - Column( modifier = modifier .fillMaxWidth() - .background(color = background, shape = RoundedCornerShape(18.dp)) - .border(width = 2.dp, color = borderColor, shape = RoundedCornerShape(18.dp)) + .background(color = SignalTheme.colors.colorSurface2, shape = RoundedCornerShape(18.dp)) + .border(width = 3.5.dp, color = borderColor, shape = RoundedCornerShape(18.dp)) .clip(shape = RoundedCornerShape(18.dp)) .clickable(onClick = onSelected, enabled = enabled) .padding(vertical = 16.dp, horizontal = 20.dp) @@ -264,11 +267,12 @@ fun MessageBackupsTypeBlock( text = stringResource(R.string.MessageBackupsTypeSelectionScreen__current_plan), glyphStart = SignalSymbols.Glyph.CHECK ), + style = MaterialTheme.typography.bodyMedium, color = MaterialTheme.colorScheme.onSurfaceVariant, modifier = Modifier .padding(bottom = 12.dp) .background( - color = SignalTheme.colors.colorTransparent1, + color = SignalTheme.colors.colorTransparentInverse2, shape = RoundedCornerShape(14.dp) ) .padding(vertical = 4.dp, horizontal = 12.dp) @@ -285,7 +289,7 @@ fun MessageBackupsTypeBlock( is MessageBackupsType.Free -> pluralStringResource(id = R.plurals.MessageBackupsTypeSelectionScreen__text_plus_d_days_of_media, messageBackupsType.mediaRetentionDays, messageBackupsType.mediaRetentionDays) is MessageBackupsType.Paid -> stringResource(id = R.string.MessageBackupsTypeSelectionScreen__text_plus_all_your_media) }, - style = MaterialTheme.typography.titleMedium + style = MaterialTheme.typography.bodyLarge ) val featureIconTint = if (isSelected) { @@ -295,7 +299,7 @@ fun MessageBackupsTypeBlock( } Column( - verticalArrangement = spacedBy(4.dp), + verticalArrangement = spacedBy(12.dp), modifier = Modifier .padding(top = 8.dp) .padding(horizontal = 16.dp) diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index a3e5a7e220..2a2c32d993 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -8337,9 +8337,11 @@ All backups are end-to-end encrypted. Signal is a non-profit—paying for backups helps support our mission. - Read more - - Next + Learn more + + Subscribe + + Subscribe for %1$s/month Change backup type