From 99acf606d9ba85e9637da3c4ac1070ffcc8358a4 Mon Sep 17 00:00:00 2001 From: Michelle Tang Date: Mon, 3 Aug 2026 13:36:50 -0400 Subject: [PATCH] Improve banner design. --- .../status/ArchiveRestoreStatusBannerView.kt | 9 +- .../banners/PendingGroupJoinRequestsBanner.kt | 90 +++++++++++++++---- .../banner/banners/UsernameOutOfSyncBanner.kt | 2 +- .../banner/ui/compose/DefaultBanner.kt | 50 ++++++----- .../securesms/megaphone/MegaphoneComponent.kt | 2 +- .../main/res/layout/review_banner_view.xml | 27 +++--- .../res/values-night/material3_colors.xml | 1 + .../src/main/res/values/material3_colors.xml | 2 + 8 files changed, 128 insertions(+), 55 deletions(-) diff --git a/app/src/main/java/org/thoughtcrime/securesms/backup/v2/ui/status/ArchiveRestoreStatusBannerView.kt b/app/src/main/java/org/thoughtcrime/securesms/backup/v2/ui/status/ArchiveRestoreStatusBannerView.kt index ccf3dc950d..7032c5d33e 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/backup/v2/ui/status/ArchiveRestoreStatusBannerView.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/backup/v2/ui/status/ArchiveRestoreStatusBannerView.kt @@ -5,7 +5,7 @@ package org.thoughtcrime.securesms.backup.v2.ui.status -import androidx.compose.foundation.border +import androidx.compose.foundation.background import androidx.compose.foundation.clickable import androidx.compose.foundation.interaction.MutableInteractionSource import androidx.compose.foundation.layout.Arrangement @@ -31,6 +31,7 @@ import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.StrokeCap +import androidx.compose.ui.res.colorResource import androidx.compose.ui.res.painterResource import androidx.compose.ui.res.stringResource import androidx.compose.ui.unit.dp @@ -69,7 +70,10 @@ fun ArchiveRestoreStatusBanner( verticalAlignment = Alignment.CenterVertically, modifier = Modifier .padding(contentPadding) - .border(1.dp, color = MaterialTheme.colorScheme.outline.copy(alpha = 0.38f), shape = RoundedCornerShape(12.dp)) + .background( + color = colorResource(CoreUiR.color.signal_colorSurface2), + shape = RoundedCornerShape(24.dp) + ) .fillMaxWidth() .defaultMinSize(minHeight = 48.dp) .clickable(onClick = onBannerClick) @@ -119,6 +123,7 @@ fun ArchiveRestoreStatusBanner( CircularProgressIndicator( progress = { data.progress!! }, strokeWidth = 3.dp, + color = MaterialTheme.colorScheme.onSurface, strokeCap = StrokeCap.Round, modifier = Modifier .size(24.dp, 24.dp) diff --git a/app/src/main/java/org/thoughtcrime/securesms/banner/banners/PendingGroupJoinRequestsBanner.kt b/app/src/main/java/org/thoughtcrime/securesms/banner/banners/PendingGroupJoinRequestsBanner.kt index 90a735a65c..edf3729213 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/banner/banners/PendingGroupJoinRequestsBanner.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/banner/banners/PendingGroupJoinRequestsBanner.kt @@ -5,22 +5,40 @@ package org.thoughtcrime.securesms.banner.banners +import androidx.compose.foundation.background import androidx.compose.foundation.layout.PaddingValues +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.size +import androidx.compose.foundation.shape.RoundedCornerShape +import androidx.compose.material3.ButtonDefaults +import androidx.compose.material3.Icon +import androidx.compose.material3.IconButton +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.Text +import androidx.compose.material3.TextButton import androidx.compose.runtime.Composable import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember import androidx.compose.runtime.setValue +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.draw.clip +import androidx.compose.ui.graphics.vector.ImageVector +import androidx.compose.ui.res.colorResource import androidx.compose.ui.res.pluralStringResource +import androidx.compose.ui.res.stringResource +import androidx.compose.ui.res.vectorResource import androidx.compose.ui.unit.dp import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.flowOf import org.signal.core.ui.compose.DayNightPreviews import org.signal.core.ui.compose.Previews +import org.signal.core.ui.compose.SignalIcons import org.thoughtcrime.securesms.R import org.thoughtcrime.securesms.banner.Banner -import org.thoughtcrime.securesms.banner.ui.compose.Action -import org.thoughtcrime.securesms.banner.ui.compose.DefaultBanner +import org.signal.core.ui.R as CoreUiR /** * Shows the number of pending requests to join the group. @@ -51,19 +69,61 @@ private fun Banner(contentPadding: PaddingValues, suggestionsSize: Int, onViewCl return } - DefaultBanner( - title = null, - body = pluralStringResource( - id = R.plurals.PendingGroupJoinRequestsReminder_d_pending_member_requests, - count = suggestionsSize, - suggestionsSize - ), - onDismissListener = { visible = false }, - actions = listOf( - Action(R.string.PendingGroupJoinRequestsReminder_view, onClick = onViewClicked) - ), - paddingValues = contentPadding - ) + Row( + verticalAlignment = Alignment.CenterVertically, + modifier = Modifier + .padding(horizontal = 12.dp, vertical = 8.dp) + .clip(RoundedCornerShape(24.dp)) + .background(color = colorResource(CoreUiR.color.signal_colorSurface2)) + .padding(horizontal = 16.dp) + ) { + Icon( + imageVector = ImageVector.vectorResource(R.drawable.symbol_group_24), + tint = MaterialTheme.colorScheme.onSurface, + contentDescription = null, + modifier = Modifier.padding(end = 16.dp) + ) + + Text( + text = pluralStringResource( + id = R.plurals.PendingGroupJoinRequestsReminder_d_pending_member_requests, + count = suggestionsSize, + suggestionsSize + ), + color = MaterialTheme.colorScheme.onSurface, + style = MaterialTheme.typography.bodyLarge, + modifier = Modifier + .weight(1f) + .padding() + ) + + TextButton( + onClick = onViewClicked, + colors = ButtonDefaults.textButtonColors( + containerColor = colorResource(CoreUiR.color.signal_colorSurface5), + contentColor = MaterialTheme.colorScheme.onSurface + ), + modifier = Modifier.padding(horizontal = 8.dp, vertical = 4.dp) + ) { + Text( + text = stringResource(id = R.string.PendingGroupJoinRequestsReminder_view), + style = MaterialTheme.typography.labelLarge, + modifier = Modifier.padding(horizontal = 12.dp) + ) + } + + IconButton( + onClick = { visible = false }, + modifier = Modifier.size(24.dp) + + ) { + Icon( + imageVector = SignalIcons.X.imageVector, + contentDescription = stringResource(id = R.string.InviteActivity_cancel), + tint = MaterialTheme.colorScheme.onSurfaceVariant + ) + } + } } @DayNightPreviews diff --git a/app/src/main/java/org/thoughtcrime/securesms/banner/banners/UsernameOutOfSyncBanner.kt b/app/src/main/java/org/thoughtcrime/securesms/banner/banners/UsernameOutOfSyncBanner.kt index 5e9e039e73..53885119f5 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/banner/banners/UsernameOutOfSyncBanner.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/banner/banners/UsernameOutOfSyncBanner.kt @@ -59,7 +59,7 @@ private fun Banner(contentPadding: PaddingValues, usernameSyncState: UsernameSyn } else { stringResource(id = R.string.UsernameOutOfSyncReminder__link_corrupt) }, - importance = Importance.ERROR, + importance = Importance.NORMAL, actions = listOf( Action(R.string.UsernameOutOfSyncReminder__fix_now) { onFixClicked(usernameSyncState) diff --git a/app/src/main/java/org/thoughtcrime/securesms/banner/ui/compose/DefaultBanner.kt b/app/src/main/java/org/thoughtcrime/securesms/banner/ui/compose/DefaultBanner.kt index d06f551b58..f26300bbd5 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/banner/ui/compose/DefaultBanner.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/banner/ui/compose/DefaultBanner.kt @@ -6,7 +6,7 @@ package org.thoughtcrime.securesms.banner.ui.compose import androidx.compose.foundation.background -import androidx.compose.foundation.border +import androidx.compose.foundation.isSystemInDarkTheme import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column @@ -28,6 +28,7 @@ import androidx.compose.runtime.Composable import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.draw.clip +import androidx.compose.ui.graphics.Color import androidx.compose.ui.res.colorResource import androidx.compose.ui.res.pluralStringResource import androidx.compose.ui.res.stringResource @@ -56,40 +57,36 @@ fun DefaultBanner( progressPercent: Int = -1, paddingValues: PaddingValues ) { + val isDarkTheme = isSystemInDarkTheme() Box( modifier = Modifier .padding(paddingValues) - .clip(RoundedCornerShape(12.dp)) + .clip(RoundedCornerShape(24.dp)) .background( color = when (importance) { - Importance.NORMAL -> MaterialTheme.colorScheme.surface + Importance.NORMAL -> colorResource(CoreUiR.color.signal_colorSurface2) Importance.ERROR -> colorResource(id = R.color.reminder_background) } ) - .border( - width = 1.dp, - color = colorResource(id = CoreUiR.color.signal_colorOutline_38), - shape = RoundedCornerShape(12.dp) - ) ) { Row( verticalAlignment = Alignment.CenterVertically, modifier = Modifier - .defaultMinSize(minHeight = 74.dp) + .defaultMinSize(minHeight = 54.dp) ) { Column { Row(modifier = Modifier.fillMaxWidth()) { Column( modifier = Modifier .weight(1f) - .padding(start = 16.dp, top = 16.dp) + .padding(start = 16.dp, end = 16.dp, top = 16.dp) ) { if (title.isNotNullOrBlank()) { Text( text = title, color = when (importance) { Importance.NORMAL -> MaterialTheme.colorScheme.onSurface - Importance.ERROR -> colorResource(id = CoreUiR.color.signal_light_colorOnSurface) + Importance.ERROR -> if (isDarkTheme) Color(0xFFC79869) else colorResource(id = CoreUiR.color.signal_light_colorOnSurface) }, style = MaterialTheme.typography.bodyLarge ) @@ -99,7 +96,7 @@ fun DefaultBanner( text = body, color = when (importance) { Importance.NORMAL -> MaterialTheme.colorScheme.onSurfaceVariant - Importance.ERROR -> colorResource(id = CoreUiR.color.signal_light_colorOnSurface) + Importance.ERROR -> if (isDarkTheme) Color(0xFFC79869) else colorResource(id = CoreUiR.color.signal_light_colorOnSurface) }, style = MaterialTheme.typography.bodyMedium ) @@ -133,26 +130,26 @@ fun DefaultBanner( style = MaterialTheme.typography.bodySmall, color = when (importance) { Importance.NORMAL -> MaterialTheme.colorScheme.onSurfaceVariant - Importance.ERROR -> colorResource(id = CoreUiR.color.signal_light_colorOnSurface) + Importance.ERROR -> if (isDarkTheme) Color(0xFFC79869) else colorResource(id = CoreUiR.color.signal_light_colorOnSurface) } ) } - Box(modifier = Modifier.size(48.dp)) { - if (onDismissListener != null) { + if (onDismissListener != null) { + Box(modifier = Modifier.size(40.dp)) { IconButton( onClick = { onHideListener?.invoke() onDismissListener() }, - modifier = Modifier.size(48.dp) + modifier = Modifier.size(40.dp) ) { Icon( imageVector = SignalIcons.X.imageVector, contentDescription = stringResource(id = R.string.InviteActivity_cancel), tint = when (importance) { Importance.NORMAL -> MaterialTheme.colorScheme.onSurfaceVariant - Importance.ERROR -> colorResource(id = CoreUiR.color.signal_light_colorOnSurface) + Importance.ERROR -> colorResource(id = CoreUiR.color.signal_colorOnSurface) } ) } @@ -163,22 +160,31 @@ fun DefaultBanner( horizontalArrangement = Arrangement.End, modifier = Modifier .fillMaxWidth() - .padding(end = 8.dp) + .padding(end = 8.dp, bottom = 8.dp) ) { for (action in actions) { TextButton( onClick = action.onClick, colors = when (importance) { - Importance.NORMAL -> ButtonDefaults.textButtonColors() - Importance.ERROR -> ButtonDefaults.textButtonColors(contentColor = colorResource(CoreUiR.color.signal_light_colorPrimary)) - } + Importance.NORMAL -> ButtonDefaults.textButtonColors( + containerColor = colorResource(CoreUiR.color.signal_colorSurface5), + contentColor = MaterialTheme.colorScheme.onSurface + ) + Importance.ERROR -> ButtonDefaults.textButtonColors( + containerColor = if (isDarkTheme) Color(0xFF392D22) else Color(0xFFF5E1B8), + contentColor = if (isDarkTheme) Color(0xFFC79869) else colorResource(id = CoreUiR.color.signal_colorNeutralInverse) + ) + }, + modifier = Modifier.padding(horizontal = 8.dp) ) { Text( text = if (!action.isPluralizedLabel) { stringResource(id = action.label) } else { pluralStringResource(id = action.label, count = action.pluralQuantity) - } + }, + style = MaterialTheme.typography.labelLarge, + modifier = Modifier.padding(horizontal = 12.dp) ) } } diff --git a/app/src/main/java/org/thoughtcrime/securesms/megaphone/MegaphoneComponent.kt b/app/src/main/java/org/thoughtcrime/securesms/megaphone/MegaphoneComponent.kt index 8f231a3066..884d449177 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/megaphone/MegaphoneComponent.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/megaphone/MegaphoneComponent.kt @@ -124,7 +124,7 @@ private fun BasicMegaphone( Card( elevation = CardDefaults.outlinedCardElevation(), border = BorderStroke(1.dp, MaterialTheme.colorScheme.outline.copy(alpha = 0.38f)), - shape = RoundedCornerShape(12.dp), + shape = RoundedCornerShape(24.dp), colors = CardDefaults.cardColors( containerColor = MaterialTheme.colorScheme.background ), diff --git a/app/src/main/res/layout/review_banner_view.xml b/app/src/main/res/layout/review_banner_view.xml index 5406e84c4f..72ff88ee95 100644 --- a/app/src/main/res/layout/review_banner_view.xml +++ b/app/src/main/res/layout/review_banner_view.xml @@ -14,11 +14,9 @@ android:layout_marginVertical="11dp" android:background="@color/signal_background_primary" android:minHeight="66dp" - app:cardCornerRadius="12dp" - app:cardBackgroundColor="@color/signal_colorSurface" - app:cardElevation="0dp" - app:strokeColor="@color/signal_colorOutline_38" - app:strokeWidth="1dp"> + app:cardCornerRadius="24dp" + app:cardBackgroundColor="@color/signal_colorSurface2" + app:cardElevation="0dp"> + app:srcCompat="@drawable/symbol_x_24" /> #3F4249 #5D5E62 + #26221D \ No newline at end of file diff --git a/core/ui/src/main/res/values/material3_colors.xml b/core/ui/src/main/res/values/material3_colors.xml index 3987d175a1..45de06b7de 100644 --- a/core/ui/src/main/res/values/material3_colors.xml +++ b/core/ui/src/main/res/values/material3_colors.xml @@ -65,4 +65,6 @@ #D5D8DE #B8BCC5 + + #faf0dc \ No newline at end of file