diff --git a/app/src/main/java/dev/ipf/whitenoise/android/ui/MarkdownRenderer.kt b/app/src/main/java/dev/ipf/whitenoise/android/ui/MarkdownRenderer.kt index b8a75b9ef..92dfd545a 100644 --- a/app/src/main/java/dev/ipf/whitenoise/android/ui/MarkdownRenderer.kt +++ b/app/src/main/java/dev/ipf/whitenoise/android/ui/MarkdownRenderer.kt @@ -14,7 +14,6 @@ import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.width import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.material3.AlertDialog -import androidx.compose.material3.HorizontalDivider import androidx.compose.material3.LocalContentColor import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Text @@ -57,6 +56,7 @@ import dev.ipf.marmotkit.MarkdownNostrHrpFfi import dev.ipf.marmotkit.MarkdownTableCellFfi import dev.ipf.whitenoise.android.R import dev.ipf.whitenoise.android.core.ProfileSanitizer +import dev.ipf.whitenoise.android.ui.theme.AppDivider import java.util.Locale /** @@ -298,7 +298,7 @@ private fun MarkdownBlockView( onTextLayout = { onTextLayout?.invoke(it) }, ) MarkdownBlockFfi.ThematicBreak -> - HorizontalDivider(color = LocalContentColor.current.copy(alpha = 0.25f)) + AppDivider() is MarkdownBlockFfi.CodeBlock -> MarkdownCodeBlockView(block.content) is MarkdownBlockFfi.BlockQuote -> MarkdownBlockQuoteView(block.blocks, ctx, depth) is MarkdownBlockFfi.ListBlock -> MarkdownListView(block, ctx, depth) @@ -426,7 +426,7 @@ private fun MarkdownTableView( val rowsElided = markdownSiblingsElided(block.rows) Column(Modifier.fillMaxWidth(), verticalArrangement = Arrangement.spacedBy(4.dp)) { MarkdownTableRowView(block.header, block.alignments, header = true, ctx) - HorizontalDivider(color = LocalContentColor.current.copy(alpha = 0.25f)) + AppDivider() visibleRows.forEach { row -> MarkdownTableRowView(row, block.alignments, header = false, ctx) } diff --git a/app/src/main/java/dev/ipf/whitenoise/android/ui/account/AccountSelectorSheet.kt b/app/src/main/java/dev/ipf/whitenoise/android/ui/account/AccountSelectorSheet.kt index b9027e9de..7094bcea3 100644 --- a/app/src/main/java/dev/ipf/whitenoise/android/ui/account/AccountSelectorSheet.kt +++ b/app/src/main/java/dev/ipf/whitenoise/android/ui/account/AccountSelectorSheet.kt @@ -26,7 +26,6 @@ import androidx.compose.material3.Button import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.material3.ExperimentalMaterial3ExpressiveApi import androidx.compose.material3.FilledTonalButton -import androidx.compose.material3.HorizontalDivider import androidx.compose.material3.Icon import androidx.compose.material3.IconButton import androidx.compose.material3.ListItem @@ -62,6 +61,7 @@ import dev.ipf.whitenoise.android.ui.common.UnreadCountBadge import dev.ipf.whitenoise.android.ui.profile.AvatarFullScreenViewer import dev.ipf.whitenoise.android.ui.profile.rememberAvatarImageAvailable import dev.ipf.whitenoise.android.ui.settings.settingsRowAmoledSurfaceBorder +import dev.ipf.whitenoise.android.ui.theme.AppDivider import dev.ipf.whitenoise.android.ui.theme.amoledSheetContainerColor import dev.ipf.whitenoise.android.ui.theme.amoledSurfaceBorder import kotlinx.coroutines.CancellationException @@ -245,7 +245,7 @@ internal fun AccountSelectorSheet( } }, ) - HorizontalDivider() + AppDivider() } } } diff --git a/app/src/main/java/dev/ipf/whitenoise/android/ui/conversation/ConversationRows.kt b/app/src/main/java/dev/ipf/whitenoise/android/ui/conversation/ConversationRows.kt index 98086d927..e0d021bdc 100644 --- a/app/src/main/java/dev/ipf/whitenoise/android/ui/conversation/ConversationRows.kt +++ b/app/src/main/java/dev/ipf/whitenoise/android/ui/conversation/ConversationRows.kt @@ -28,7 +28,6 @@ import androidx.compose.material.icons.filled.Group import androidx.compose.material3.Button import androidx.compose.material3.DropdownMenu import androidx.compose.material3.DropdownMenuItem -import androidx.compose.material3.HorizontalDivider import androidx.compose.material3.Icon import androidx.compose.material3.MaterialTheme import androidx.compose.material3.MenuDefaults @@ -57,6 +56,7 @@ import dev.ipf.whitenoise.android.core.MessageDebugClassifier import dev.ipf.whitenoise.android.state.WhiteNoiseAppState import dev.ipf.whitenoise.android.ui.common.rememberGroupSystemCopy import dev.ipf.whitenoise.android.ui.group.disappearingMessagesLabel +import dev.ipf.whitenoise.android.ui.theme.AppDivider import dev.ipf.whitenoise.android.ui.theme.amoledSurfaceBorderStroke import java.time.Instant import java.time.LocalDate @@ -76,9 +76,8 @@ internal fun UnreadMessagesDivider(count: Int) { .padding(vertical = 12.dp), verticalAlignment = Alignment.CenterVertically, ) { - HorizontalDivider( + AppDivider( modifier = Modifier.weight(1f), - color = MaterialTheme.colorScheme.outlineVariant, ) Text( text = text, @@ -92,9 +91,8 @@ internal fun UnreadMessagesDivider(count: Int) { shape = RoundedCornerShape(12.dp), ).padding(horizontal = 10.dp, vertical = 4.dp), ) - HorizontalDivider( + AppDivider( modifier = Modifier.weight(1f), - color = MaterialTheme.colorScheme.outlineVariant, ) } } diff --git a/app/src/main/java/dev/ipf/whitenoise/android/ui/conversation/composer/MentionPicker.kt b/app/src/main/java/dev/ipf/whitenoise/android/ui/conversation/composer/MentionPicker.kt index 60a055d36..9c28b5996 100644 --- a/app/src/main/java/dev/ipf/whitenoise/android/ui/conversation/composer/MentionPicker.kt +++ b/app/src/main/java/dev/ipf/whitenoise/android/ui/conversation/composer/MentionPicker.kt @@ -14,7 +14,6 @@ import androidx.compose.foundation.lazy.LazyColumn import androidx.compose.foundation.lazy.grid.items import androidx.compose.foundation.lazy.items import androidx.compose.foundation.shape.RoundedCornerShape -import androidx.compose.material3.HorizontalDivider import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Surface import androidx.compose.material3.Text @@ -34,6 +33,7 @@ import androidx.compose.ui.unit.dp import dev.ipf.whitenoise.android.R import dev.ipf.whitenoise.android.core.MentionComposer import dev.ipf.whitenoise.android.ui.common.Avatar +import dev.ipf.whitenoise.android.ui.theme.AppDivider import dev.ipf.whitenoise.android.ui.theme.amoledSurfaceBorderStroke /** @@ -64,7 +64,7 @@ internal fun MentionPicker( color = MaterialTheme.colorScheme.onSurfaceVariant, modifier = Modifier.padding(horizontal = 16.dp, vertical = 8.dp), ) - HorizontalDivider(color = MaterialTheme.colorScheme.surfaceVariant) + AppDivider() LazyColumn(Modifier.fillMaxWidth()) { items(candidates, key = { it.accountIdHex }) { candidate -> val mentionLabel = stringResource(R.string.mention_picker_member, candidate.displayName) diff --git a/app/src/main/java/dev/ipf/whitenoise/android/ui/conversation/media/MediaControls.kt b/app/src/main/java/dev/ipf/whitenoise/android/ui/conversation/media/MediaControls.kt index 5a34b2158..c81146446 100644 --- a/app/src/main/java/dev/ipf/whitenoise/android/ui/conversation/media/MediaControls.kt +++ b/app/src/main/java/dev/ipf/whitenoise/android/ui/conversation/media/MediaControls.kt @@ -24,6 +24,7 @@ import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.vector.ImageVector import androidx.compose.ui.semantics.contentDescription import androidx.compose.ui.unit.dp +import dev.ipf.whitenoise.android.ui.theme.ScrimAlpha internal enum class OpenAttachmentResult { Opened, NoHandler, Error } @@ -47,7 +48,7 @@ internal fun MediaCircleAction( Surface( onClick = onClick, shape = CircleShape, - color = Color.Black.copy(alpha = 0.55f), + color = Color.Black.copy(alpha = ScrimAlpha.Strong), contentColor = Color.White, modifier = modifier.size(52.dp), ) { diff --git a/app/src/main/java/dev/ipf/whitenoise/android/ui/conversation/media/MediaImageBubbles.kt b/app/src/main/java/dev/ipf/whitenoise/android/ui/conversation/media/MediaImageBubbles.kt index 857d1fa95..427ad5b5a 100644 --- a/app/src/main/java/dev/ipf/whitenoise/android/ui/conversation/media/MediaImageBubbles.kt +++ b/app/src/main/java/dev/ipf/whitenoise/android/ui/conversation/media/MediaImageBubbles.kt @@ -57,6 +57,7 @@ import dev.ipf.whitenoise.android.state.ConversationController import dev.ipf.whitenoise.android.state.MediaAutoDownloadType import dev.ipf.whitenoise.android.state.TimelineMessage import dev.ipf.whitenoise.android.state.WhiteNoiseAppState +import dev.ipf.whitenoise.android.ui.theme.ScrimAlpha import dev.ipf.whitenoise.android.ui.theme.amoledSurfaceBorderStroke import kotlinx.coroutines.CancellationException import kotlinx.coroutines.Dispatchers @@ -320,7 +321,7 @@ internal fun MediaImageBubble( } if (uploading) { Surface( - color = Color.Black.copy(alpha = 0.55f), + color = Color.Black.copy(alpha = ScrimAlpha.Strong), shape = CircleShape, modifier = Modifier.size(48.dp), ) { @@ -664,7 +665,7 @@ internal fun MediaImageGridTile( modifier = Modifier .fillMaxSize() - .background(Color.Black.copy(alpha = 0.5f)), + .background(Color.Black.copy(alpha = ScrimAlpha.MediumEmphasis)), contentAlignment = Alignment.Center, ) { Text( @@ -677,7 +678,7 @@ internal fun MediaImageGridTile( } if (uploading) { Box( - modifier = Modifier.fillMaxSize().background(Color.Black.copy(alpha = 0.35f)), + modifier = Modifier.fillMaxSize().background(Color.Black.copy(alpha = ScrimAlpha.Light)), contentAlignment = Alignment.Center, ) { CircularProgressIndicator( diff --git a/app/src/main/java/dev/ipf/whitenoise/android/ui/conversation/media/MediaPending.kt b/app/src/main/java/dev/ipf/whitenoise/android/ui/conversation/media/MediaPending.kt index 6d5be3a0e..7175ca876 100644 --- a/app/src/main/java/dev/ipf/whitenoise/android/ui/conversation/media/MediaPending.kt +++ b/app/src/main/java/dev/ipf/whitenoise/android/ui/conversation/media/MediaPending.kt @@ -43,6 +43,7 @@ import androidx.compose.ui.unit.dp import dev.ipf.whitenoise.android.R import dev.ipf.whitenoise.android.media.MediaPipeline import dev.ipf.whitenoise.android.state.PendingAttachment +import dev.ipf.whitenoise.android.ui.theme.ScrimAlpha import dev.ipf.whitenoise.android.ui.theme.amoledSurfaceBorderStroke import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.withContext @@ -103,7 +104,7 @@ internal fun MediaPendingPlaceholder( contentScale = ContentScale.Crop, modifier = Modifier.fillMaxSize(), ) - Box(Modifier.matchParentSize().background(Color.Black.copy(alpha = 0.35f))) + Box(Modifier.matchParentSize().background(Color.Black.copy(alpha = ScrimAlpha.Light))) } PendingStatusOverlay( failed = failed, @@ -136,7 +137,7 @@ internal fun MediaPendingPlaceholder( ) } Box( - Modifier.matchParentSize().background(Color.Black.copy(alpha = 0.35f)), + Modifier.matchParentSize().background(Color.Black.copy(alpha = ScrimAlpha.Light)), ) PendingStatusOverlay( failed = failed, @@ -224,7 +225,7 @@ private fun PendingGridTile( } if (overflowCount > 0 && preview != null) { Box( - Modifier.fillMaxSize().background(Color.Black.copy(alpha = 0.5f)), + Modifier.fillMaxSize().background(Color.Black.copy(alpha = ScrimAlpha.MediumEmphasis)), contentAlignment = Alignment.Center, ) { Text( diff --git a/app/src/main/java/dev/ipf/whitenoise/android/ui/conversation/media/MediaPreview.kt b/app/src/main/java/dev/ipf/whitenoise/android/ui/conversation/media/MediaPreview.kt index 053e367eb..dad9233b7 100644 --- a/app/src/main/java/dev/ipf/whitenoise/android/ui/conversation/media/MediaPreview.kt +++ b/app/src/main/java/dev/ipf/whitenoise/android/ui/conversation/media/MediaPreview.kt @@ -69,6 +69,7 @@ import androidx.compose.ui.window.Dialog import androidx.compose.ui.window.DialogProperties import dev.ipf.whitenoise.android.R import dev.ipf.whitenoise.android.media.MediaPipeline +import dev.ipf.whitenoise.android.ui.theme.ScrimAlpha import dev.ipf.whitenoise.android.ui.theme.amoledSurfaceBorderStroke import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.currentCoroutineContext @@ -453,7 +454,7 @@ private fun HeroMediaPreview( ) } if (metadata?.isVideo == true) { - Surface(shape = CircleShape, color = Color.Black.copy(alpha = 0.55f)) { + Surface(shape = CircleShape, color = Color.Black.copy(alpha = ScrimAlpha.Strong)) { Icon( Icons.Default.PlayArrow, contentDescription = stringResource(R.string.reply_media_video), @@ -550,7 +551,7 @@ private fun PreviewStripThumb( } if (metadata?.isVideo == true) { Box(modifier = Modifier.fillMaxSize(), contentAlignment = Alignment.Center) { - Surface(shape = CircleShape, color = Color.Black.copy(alpha = 0.55f)) { + Surface(shape = CircleShape, color = Color.Black.copy(alpha = ScrimAlpha.Strong)) { Icon( Icons.Default.PlayArrow, contentDescription = null, diff --git a/app/src/main/java/dev/ipf/whitenoise/android/ui/conversation/media/MediaVideo.kt b/app/src/main/java/dev/ipf/whitenoise/android/ui/conversation/media/MediaVideo.kt index efbcdfaaf..38bc2338d 100644 --- a/app/src/main/java/dev/ipf/whitenoise/android/ui/conversation/media/MediaVideo.kt +++ b/app/src/main/java/dev/ipf/whitenoise/android/ui/conversation/media/MediaVideo.kt @@ -60,6 +60,7 @@ import dev.ipf.whitenoise.android.media.playbackErrorInvalidatesAttachmentCache import dev.ipf.whitenoise.android.state.ConversationController import dev.ipf.whitenoise.android.state.MediaAutoDownloadType import dev.ipf.whitenoise.android.state.WhiteNoiseAppState +import dev.ipf.whitenoise.android.ui.theme.ScrimAlpha import dev.ipf.whitenoise.android.ui.theme.amoledSurfaceBorderStroke import kotlinx.coroutines.CancellationException import kotlinx.coroutines.CompletableDeferred @@ -225,7 +226,7 @@ internal fun MediaVideoGridTile( Box(modifier = Modifier.fillMaxSize().background(MaterialTheme.colorScheme.surface)) } Surface( - color = Color.Black.copy(alpha = 0.55f), + color = Color.Black.copy(alpha = ScrimAlpha.Strong), shape = CircleShape, modifier = Modifier @@ -269,7 +270,7 @@ internal fun MediaVideoGridTile( modifier = Modifier .matchParentSize() - .background(Color.Black.copy(alpha = 0.45f)), + .background(Color.Black.copy(alpha = ScrimAlpha.Medium)), contentAlignment = Alignment.Center, ) { Text( @@ -281,7 +282,7 @@ internal fun MediaVideoGridTile( } if (uploading) { Box( - modifier = Modifier.matchParentSize().background(Color.Black.copy(alpha = 0.35f)), + modifier = Modifier.matchParentSize().background(Color.Black.copy(alpha = ScrimAlpha.Light)), contentAlignment = Alignment.Center, ) { CircularProgressIndicator( @@ -471,7 +472,7 @@ internal fun MediaVideoBubble( // When startDownload is gated off (policy says no auto-fetch), the // triangle becomes a download icon and tap consents to the fetch. Surface( - color = Color.Black.copy(alpha = 0.55f), + color = Color.Black.copy(alpha = ScrimAlpha.Strong), shape = CircleShape, modifier = Modifier @@ -572,7 +573,7 @@ internal fun MediaVideoBubble( // Duration pill bottom-start. Only shown once duration is known. if (durationMs > 0L) { Surface( - color = Color.Black.copy(alpha = 0.55f), + color = Color.Black.copy(alpha = ScrimAlpha.Strong), shape = RoundedCornerShape(6.dp), modifier = Modifier diff --git a/app/src/main/java/dev/ipf/whitenoise/android/ui/conversation/media/MediaViewer.kt b/app/src/main/java/dev/ipf/whitenoise/android/ui/conversation/media/MediaViewer.kt index 286360d0d..6bd1db79e 100644 --- a/app/src/main/java/dev/ipf/whitenoise/android/ui/conversation/media/MediaViewer.kt +++ b/app/src/main/java/dev/ipf/whitenoise/android/ui/conversation/media/MediaViewer.kt @@ -68,6 +68,7 @@ import dev.ipf.whitenoise.android.media.MediaPipeline import dev.ipf.whitenoise.android.media.MediaReferenceParser import dev.ipf.whitenoise.android.state.ConversationController import dev.ipf.whitenoise.android.state.WhiteNoiseAppState +import dev.ipf.whitenoise.android.ui.theme.ScrimAlpha import kotlinx.coroutines.CancellationException import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.flow.map @@ -300,7 +301,7 @@ internal fun FullScreenMediaViewer( .align(Alignment.BottomCenter) .background( Brush.verticalGradient( - listOf(Color.Transparent, Color.Black.copy(alpha = 0.6f)), + listOf(Color.Transparent, Color.Black.copy(alpha = ScrimAlpha.Gradient)), ), ).navigationBarsPadding() .padding(horizontal = 16.dp, vertical = 12.dp), diff --git a/app/src/main/java/dev/ipf/whitenoise/android/ui/conversation/media/RecentMedia.kt b/app/src/main/java/dev/ipf/whitenoise/android/ui/conversation/media/RecentMedia.kt index adc37a32c..eb89a476c 100644 --- a/app/src/main/java/dev/ipf/whitenoise/android/ui/conversation/media/RecentMedia.kt +++ b/app/src/main/java/dev/ipf/whitenoise/android/ui/conversation/media/RecentMedia.kt @@ -52,6 +52,7 @@ import androidx.lifecycle.Lifecycle import androidx.lifecycle.LifecycleEventObserver import androidx.lifecycle.compose.LocalLifecycleOwner import dev.ipf.whitenoise.android.R +import dev.ipf.whitenoise.android.ui.theme.ScrimAlpha import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.withContext @@ -271,7 +272,7 @@ private fun RecentThumb( .align(Alignment.Center) .size(24.dp) .clip(CircleShape) - .background(Color.Black.copy(alpha = 0.5f)), + .background(Color.Black.copy(alpha = ScrimAlpha.MediumEmphasis)), contentAlignment = Alignment.Center, ) { Icon( diff --git a/app/src/main/java/dev/ipf/whitenoise/android/ui/conversation/messages/MessageActions.kt b/app/src/main/java/dev/ipf/whitenoise/android/ui/conversation/messages/MessageActions.kt index b0afd70c9..4c3b07e32 100644 --- a/app/src/main/java/dev/ipf/whitenoise/android/ui/conversation/messages/MessageActions.kt +++ b/app/src/main/java/dev/ipf/whitenoise/android/ui/conversation/messages/MessageActions.kt @@ -33,7 +33,6 @@ import androidx.compose.material.icons.filled.Info import androidx.compose.material3.Button import androidx.compose.material3.ButtonDefaults import androidx.compose.material3.ExperimentalMaterial3Api -import androidx.compose.material3.HorizontalDivider import androidx.compose.material3.Icon import androidx.compose.material3.IconButton import androidx.compose.material3.MaterialTheme @@ -82,6 +81,7 @@ import dev.ipf.whitenoise.android.ui.chats.newchat.SelectionIndicator import dev.ipf.whitenoise.android.ui.common.rememberGroupTitleCopy import dev.ipf.whitenoise.android.ui.design.KeyboardSafePopup import dev.ipf.whitenoise.android.ui.resolveMentionsInPlaintext +import dev.ipf.whitenoise.android.ui.theme.AppDivider import dev.ipf.whitenoise.android.ui.theme.Dimens import dev.ipf.whitenoise.android.ui.theme.amoledSheetContainerColor import dev.ipf.whitenoise.android.ui.theme.amoledSurfaceBorderStroke @@ -243,7 +243,7 @@ internal fun MessageActionMenu( ) } } - HorizontalDivider() + AppDivider() } Column( modifier = Modifier.fillMaxWidth(), diff --git a/app/src/main/java/dev/ipf/whitenoise/android/ui/conversation/messages/MessageBubbleFooter.kt b/app/src/main/java/dev/ipf/whitenoise/android/ui/conversation/messages/MessageBubbleFooter.kt index f1214289e..89c32d076 100644 --- a/app/src/main/java/dev/ipf/whitenoise/android/ui/conversation/messages/MessageBubbleFooter.kt +++ b/app/src/main/java/dev/ipf/whitenoise/android/ui/conversation/messages/MessageBubbleFooter.kt @@ -18,6 +18,7 @@ import androidx.compose.ui.layout.Layout import androidx.compose.ui.unit.Constraints import androidx.compose.ui.unit.dp import dev.ipf.whitenoise.android.state.MessageStatus +import dev.ipf.whitenoise.android.ui.theme.ScrimAlpha // Gap between a bubble's text and its trailing inline footer. private val BubbleFooterGap = 8.dp @@ -30,7 +31,7 @@ private fun MediaScrimFooter( ) { Box( modifier - .background(Color.Black.copy(alpha = 0.4f), RoundedCornerShape(percent = 50)) + .background(Color.Black.copy(alpha = ScrimAlpha.LightEmphasis), RoundedCornerShape(percent = 50)) .padding(horizontal = 8.dp, vertical = 3.dp), ) { content() diff --git a/app/src/main/java/dev/ipf/whitenoise/android/ui/group/GroupDetailsScreen.kt b/app/src/main/java/dev/ipf/whitenoise/android/ui/group/GroupDetailsScreen.kt index 771ba1140..3409bec8e 100644 --- a/app/src/main/java/dev/ipf/whitenoise/android/ui/group/GroupDetailsScreen.kt +++ b/app/src/main/java/dev/ipf/whitenoise/android/ui/group/GroupDetailsScreen.kt @@ -56,7 +56,6 @@ import androidx.compose.material3.Button import androidx.compose.material3.CircularProgressIndicator import androidx.compose.material3.DropdownMenuItem import androidx.compose.material3.ExperimentalMaterial3Api -import androidx.compose.material3.HorizontalDivider import androidx.compose.material3.Icon import androidx.compose.material3.IconButton import androidx.compose.material3.MaterialTheme @@ -132,6 +131,7 @@ import dev.ipf.whitenoise.android.ui.medialibrary.rememberSharedMediaTiles import dev.ipf.whitenoise.android.ui.profile.AvatarFullScreenViewer import dev.ipf.whitenoise.android.ui.profile.rememberAvatarImageAvailable import dev.ipf.whitenoise.android.ui.settings.DiagnosticRow +import dev.ipf.whitenoise.android.ui.theme.AppDivider import dev.ipf.whitenoise.android.ui.theme.Dimens import dev.ipf.whitenoise.android.ui.theme.PillShape import dev.ipf.whitenoise.android.ui.theme.amoledSurfaceBorderStroke @@ -681,7 +681,7 @@ internal fun GroupDetailsScreen( ) } - HorizontalDivider(color = MaterialTheme.colorScheme.surfaceVariant.copy(alpha = 0.4f)) + AppDivider() SettingsActionRow( icon = Icons.Default.Schedule, title = stringResource(R.string.disappearing_messages), @@ -703,7 +703,7 @@ internal fun GroupDetailsScreen( appState.updateCollapseLongMessagesInGroup(controller.group.groupIdHex, it) }, ) - HorizontalDivider(color = MaterialTheme.colorScheme.surfaceVariant.copy(alpha = 0.4f)) + AppDivider() SectionHeader(stringResource(R.string.notifications)) SettingsActionRow( icon = Icons.Default.Notifications, @@ -787,7 +787,7 @@ internal fun GroupDetailsScreen( ) } - HorizontalDivider(color = MaterialTheme.colorScheme.surfaceVariant.copy(alpha = 0.4f)) + AppDivider() Row( modifier = Modifier.fillMaxWidth(), verticalAlignment = Alignment.CenterVertically, @@ -943,7 +943,7 @@ internal fun GroupDetailsScreen( } } - HorizontalDivider(color = MaterialTheme.colorScheme.surfaceVariant.copy(alpha = 0.4f)) + AppDivider() SectionHeader(stringResource(R.string.info)) Column( Modifier @@ -1038,7 +1038,7 @@ internal fun GroupDetailsScreen( // sole-admin and sole-member cases get their own confirm copy. On // failure the controller's lastMutationError surfaces inline here // (in addition to the snackbar) so the user can retry in place. - HorizontalDivider(color = MaterialTheme.colorScheme.surfaceVariant.copy(alpha = 0.4f)) + AppDivider() val selfMember = controller.members.firstOrNull { GroupProjector.isActiveAccountMember(it, activeAccountIdHex) } if (canEdit && selfMember != null) { @@ -1634,9 +1634,8 @@ private fun PushDeliveryDebugSection( ) info.tokens.forEachIndexed { index, token -> if (index > 0) { - HorizontalDivider( + AppDivider( modifier = Modifier.padding(vertical = 8.dp), - color = MaterialTheme.colorScheme.surfaceVariant.copy(alpha = 0.4f), ) } PushTokenDebugRows(token, appState, yesNo) diff --git a/app/src/main/java/dev/ipf/whitenoise/android/ui/group/GroupEditScreen.kt b/app/src/main/java/dev/ipf/whitenoise/android/ui/group/GroupEditScreen.kt index 3e817e8b6..3c70fcb49 100644 --- a/app/src/main/java/dev/ipf/whitenoise/android/ui/group/GroupEditScreen.kt +++ b/app/src/main/java/dev/ipf/whitenoise/android/ui/group/GroupEditScreen.kt @@ -55,6 +55,7 @@ import dev.ipf.whitenoise.android.ui.common.rememberGroupTitleCopy import dev.ipf.whitenoise.android.ui.profile.AvatarFullScreenViewer import dev.ipf.whitenoise.android.ui.profile.rememberAvatarImageAvailable import dev.ipf.whitenoise.android.ui.theme.Dimens +import dev.ipf.whitenoise.android.ui.theme.ScrimAlpha @OptIn(ExperimentalMaterial3Api::class) @Composable @@ -192,7 +193,7 @@ internal fun GroupEditScreen( .offset(x = 6.dp, y = 6.dp) .size(36.dp) .clip(CircleShape) - .background(Color.Black.copy(alpha = 0.62f)) + .background(Color.Black.copy(alpha = ScrimAlpha.Heavy)) .clickable( onClickLabel = editImageLabel, role = Role.Button, diff --git a/app/src/main/java/dev/ipf/whitenoise/android/ui/group/GroupImageSearch.kt b/app/src/main/java/dev/ipf/whitenoise/android/ui/group/GroupImageSearch.kt index d70752a00..fb8e76893 100644 --- a/app/src/main/java/dev/ipf/whitenoise/android/ui/group/GroupImageSearch.kt +++ b/app/src/main/java/dev/ipf/whitenoise/android/ui/group/GroupImageSearch.kt @@ -79,6 +79,7 @@ import dev.ipf.whitenoise.android.media.ImageSearchResult import dev.ipf.whitenoise.android.media.sanitizeHttpsAvatarUrl import dev.ipf.whitenoise.android.ui.common.Avatar import dev.ipf.whitenoise.android.ui.settings.subtitleRes +import dev.ipf.whitenoise.android.ui.theme.ScrimAlpha import dev.ipf.whitenoise.android.ui.theme.amoledSheetContainerColor import kotlinx.coroutines.CancellationException import kotlinx.coroutines.Job @@ -450,7 +451,7 @@ private fun GroupImageSearchTile( Modifier .fillMaxWidth() .align(Alignment.BottomCenter) - .background(Color.Black.copy(alpha = 0.5f)) + .background(Color.Black.copy(alpha = ScrimAlpha.MediumEmphasis)) .padding(horizontal = 6.dp, vertical = 4.dp), horizontalArrangement = Arrangement.spacedBy(6.dp), verticalAlignment = Alignment.CenterVertically, diff --git a/app/src/main/java/dev/ipf/whitenoise/android/ui/profile/ProfileEditScreen.kt b/app/src/main/java/dev/ipf/whitenoise/android/ui/profile/ProfileEditScreen.kt index 2c4901672..23c7550d7 100644 --- a/app/src/main/java/dev/ipf/whitenoise/android/ui/profile/ProfileEditScreen.kt +++ b/app/src/main/java/dev/ipf/whitenoise/android/ui/profile/ProfileEditScreen.kt @@ -68,6 +68,7 @@ import dev.ipf.whitenoise.android.ui.common.SectionCard import dev.ipf.whitenoise.android.ui.common.StickyFormActionBar import dev.ipf.whitenoise.android.ui.group.ImageSearchSheet import dev.ipf.whitenoise.android.ui.theme.Dimens +import dev.ipf.whitenoise.android.ui.theme.ScrimAlpha import kotlinx.coroutines.launch @OptIn(ExperimentalMaterial3Api::class) @@ -256,7 +257,7 @@ internal fun ProfileEditScreen( .offset(x = 6.dp, y = 6.dp) .size(36.dp) .clip(CircleShape) - .background(Color.Black.copy(alpha = 0.62f)) + .background(Color.Black.copy(alpha = ScrimAlpha.Heavy)) .clickable( onClickLabel = editPictureLabel, role = Role.Button, diff --git a/app/src/main/java/dev/ipf/whitenoise/android/ui/profile/ProfileSheet.kt b/app/src/main/java/dev/ipf/whitenoise/android/ui/profile/ProfileSheet.kt index 2e54ba49f..5ec4db1da 100644 --- a/app/src/main/java/dev/ipf/whitenoise/android/ui/profile/ProfileSheet.kt +++ b/app/src/main/java/dev/ipf/whitenoise/android/ui/profile/ProfileSheet.kt @@ -32,7 +32,6 @@ import androidx.compose.material3.AlertDialog import androidx.compose.material3.Button import androidx.compose.material3.CircularProgressIndicator import androidx.compose.material3.ExperimentalMaterial3Api -import androidx.compose.material3.HorizontalDivider import androidx.compose.material3.Icon import androidx.compose.material3.ListItem import androidx.compose.material3.ListItemDefaults @@ -53,7 +52,6 @@ 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.alpha import androidx.compose.ui.draw.clip import androidx.compose.ui.graphics.Color import androidx.compose.ui.input.key.key @@ -91,6 +89,7 @@ import dev.ipf.whitenoise.android.ui.common.SectionCard import dev.ipf.whitenoise.android.ui.common.rememberGroupTitleCopy import dev.ipf.whitenoise.android.ui.group.GroupMemberMenuAction import dev.ipf.whitenoise.android.ui.group.groupMemberMenuActions +import dev.ipf.whitenoise.android.ui.theme.AppDivider import dev.ipf.whitenoise.android.ui.theme.Dimens import dev.ipf.whitenoise.android.ui.theme.amoledSheetContainerColor import dev.ipf.whitenoise.android.ui.theme.amoledSurfaceBorder @@ -402,7 +401,7 @@ internal fun ProfileSheet( onOpen = { onOpenGroup(group, false) }, ) if (index != sharedGroups.lastIndex) { - HorizontalDivider(color = MaterialTheme.colorScheme.surfaceVariant.copy(alpha = 0.6f)) + AppDivider() } } } @@ -726,7 +725,7 @@ private fun ProfileSheetAdminActions( } } - HorizontalDivider(color = MaterialTheme.colorScheme.surfaceVariant.copy(alpha = 0.6f)) + AppDivider() Column( modifier = Modifier.fillMaxWidth(), verticalArrangement = Arrangement.spacedBy(8.dp), diff --git a/app/src/main/java/dev/ipf/whitenoise/android/ui/qr/QrScannerSheet.kt b/app/src/main/java/dev/ipf/whitenoise/android/ui/qr/QrScannerSheet.kt index 0a8e3030c..ee9ac1991 100644 --- a/app/src/main/java/dev/ipf/whitenoise/android/ui/qr/QrScannerSheet.kt +++ b/app/src/main/java/dev/ipf/whitenoise/android/ui/qr/QrScannerSheet.kt @@ -60,6 +60,7 @@ import com.google.mlkit.vision.barcode.common.Barcode import com.google.mlkit.vision.common.InputImage import dev.ipf.whitenoise.android.R import dev.ipf.whitenoise.android.ui.common.lifecycleOwner +import dev.ipf.whitenoise.android.ui.theme.ScrimAlpha import dev.ipf.whitenoise.android.ui.theme.amoledSheetContainerColor import kotlinx.coroutines.launch import java.util.concurrent.Executor @@ -120,7 +121,7 @@ internal fun QrScannerSheet( Modifier .padding( 16.dp, - ).background(Color.Black.copy(alpha = 0.55f), RoundedCornerShape(24.dp)) + ).background(Color.Black.copy(alpha = ScrimAlpha.Strong), RoundedCornerShape(24.dp)) .padding(horizontal = 14.dp, vertical = 8.dp), ) } diff --git a/app/src/main/java/dev/ipf/whitenoise/android/ui/settings/NotificationsScreen.kt b/app/src/main/java/dev/ipf/whitenoise/android/ui/settings/NotificationsScreen.kt index 2bdba4fcc..cc927ba8b 100644 --- a/app/src/main/java/dev/ipf/whitenoise/android/ui/settings/NotificationsScreen.kt +++ b/app/src/main/java/dev/ipf/whitenoise/android/ui/settings/NotificationsScreen.kt @@ -20,7 +20,6 @@ import androidx.compose.material.icons.automirrored.filled.ArrowBack import androidx.compose.material.icons.automirrored.filled.Forward import androidx.compose.material.icons.filled.Settings import androidx.compose.material3.ExperimentalMaterial3Api -import androidx.compose.material3.HorizontalDivider import androidx.compose.material3.Icon import androidx.compose.material3.IconButton import androidx.compose.material3.MaterialTheme @@ -43,6 +42,7 @@ import androidx.compose.ui.unit.dp import dev.ipf.whitenoise.android.R import dev.ipf.whitenoise.android.state.WhiteNoiseAppState import dev.ipf.whitenoise.android.ui.common.SectionCard +import dev.ipf.whitenoise.android.ui.theme.AppDivider import kotlinx.coroutines.launch @OptIn(ExperimentalMaterial3Api::class) @@ -113,7 +113,7 @@ internal fun NotificationsScreen( }, ) } - HorizontalDivider(Modifier.padding(vertical = 12.dp)) + AppDivider(Modifier.padding(vertical = 12.dp)) Row(Modifier.fillMaxWidth(), verticalAlignment = Alignment.CenterVertically) { Column(Modifier.weight(1f)) { Text(stringResource(R.string.keep_connected), style = MaterialTheme.typography.bodyLarge) @@ -133,7 +133,7 @@ internal fun NotificationsScreen( ) } val nativePushAvailable = appState.isNativePushAvailable() - HorizontalDivider(Modifier.padding(vertical = 12.dp)) + AppDivider(Modifier.padding(vertical = 12.dp)) Row(Modifier.fillMaxWidth(), verticalAlignment = Alignment.CenterVertically) { Column(Modifier.weight(1f)) { Text(stringResource(R.string.native_push), style = MaterialTheme.typography.bodyLarge) @@ -161,7 +161,7 @@ internal fun NotificationsScreen( }, ) } - HorizontalDivider(Modifier.padding(vertical = 12.dp)) + AppDivider(Modifier.padding(vertical = 12.dp)) // Per-type controls (sound, vibration, importance, lockscreen, // DND bypass) live in the OS notification details — Android's // native per-channel UI. We deep-link there instead of diff --git a/app/src/main/java/dev/ipf/whitenoise/android/ui/settings/SecurityPrivacyScreen.kt b/app/src/main/java/dev/ipf/whitenoise/android/ui/settings/SecurityPrivacyScreen.kt index 743df7478..5fbc9ec2f 100644 --- a/app/src/main/java/dev/ipf/whitenoise/android/ui/settings/SecurityPrivacyScreen.kt +++ b/app/src/main/java/dev/ipf/whitenoise/android/ui/settings/SecurityPrivacyScreen.kt @@ -15,7 +15,6 @@ import androidx.compose.material.icons.Icons import androidx.compose.material.icons.automirrored.filled.ArrowBack import androidx.compose.material3.AlertDialog import androidx.compose.material3.ExperimentalMaterial3Api -import androidx.compose.material3.HorizontalDivider import androidx.compose.material3.Icon import androidx.compose.material3.IconButton import androidx.compose.material3.MaterialTheme @@ -39,6 +38,7 @@ import dev.ipf.whitenoise.android.R import dev.ipf.whitenoise.android.state.AppLockDelay import dev.ipf.whitenoise.android.state.WhiteNoiseAppState import dev.ipf.whitenoise.android.ui.common.SectionCard +import dev.ipf.whitenoise.android.ui.theme.AppDivider import kotlinx.coroutines.delay @OptIn(ExperimentalMaterial3Api::class) @@ -103,21 +103,21 @@ internal fun SecurityPrivacyScreen( } } } - HorizontalDivider(Modifier.padding(vertical = 12.dp)) + AppDivider(Modifier.padding(vertical = 12.dp)) SettingsSwitchRow( title = stringResource(R.string.force_incognito_keyboard), subtitle = stringResource(R.string.force_incognito_keyboard_subtitle), checked = appState.forceIncognitoKeyboard, onCheckedChange = { appState.updateForceIncognitoKeyboard(it) }, ) - HorizontalDivider(Modifier.padding(vertical = 12.dp)) + AppDivider(Modifier.padding(vertical = 12.dp)) SettingsSwitchRow( title = stringResource(R.string.allow_chat_screenshots), subtitle = stringResource(R.string.allow_chat_screenshots_subtitle), checked = !appState.allowChatScreenshotsInChats, onCheckedChange = { appState.updateAllowChatScreenshotsInChats(!it) }, ) - HorizontalDivider(Modifier.padding(vertical = 12.dp)) + AppDivider(Modifier.padding(vertical = 12.dp)) SettingsSwitchRow( title = stringResource(R.string.telemetry), subtitle = stringResource(R.string.telemetry_settings_subtitle), @@ -135,7 +135,7 @@ internal fun SecurityPrivacyScreen( } }, ) - HorizontalDivider(Modifier.padding(vertical = 12.dp)) + AppDivider(Modifier.padding(vertical = 12.dp)) SettingsSwitchRow( title = stringResource(R.string.audit_logs), subtitle = stringResource(R.string.audit_logs_settings_subtitle), @@ -153,7 +153,7 @@ internal fun SecurityPrivacyScreen( } }, ) - HorizontalDivider(Modifier.padding(vertical = 12.dp)) + AppDivider(Modifier.padding(vertical = 12.dp)) var deleteAuditLogsConfirmOpen by remember { mutableStateOf(false) } Row( Modifier @@ -217,9 +217,9 @@ internal fun SecurityPrivacyScreen( onCheckedChange = { appState.updateDeveloperMode(it) }, ) if (appState.developerMode) { - HorizontalDivider(Modifier.padding(vertical = 12.dp)) + AppDivider(Modifier.padding(vertical = 12.dp)) SettingsRow(stringResource(R.string.diagnostics), stringResource(R.string.diagnostics_settings_subtitle)) { onOpenDiagnostics() } - HorizontalDivider(Modifier.padding(vertical = 12.dp)) + AppDivider(Modifier.padding(vertical = 12.dp)) SettingsSwitchRow( title = stringResource(R.string.streaming_debug), subtitle = stringResource(R.string.streaming_debug_subtitle), diff --git a/app/src/main/java/dev/ipf/whitenoise/android/ui/theme/VisualTokens.kt b/app/src/main/java/dev/ipf/whitenoise/android/ui/theme/VisualTokens.kt new file mode 100644 index 000000000..4101060fc --- /dev/null +++ b/app/src/main/java/dev/ipf/whitenoise/android/ui/theme/VisualTokens.kt @@ -0,0 +1,26 @@ +package dev.ipf.whitenoise.android.ui.theme + +import androidx.compose.material3.HorizontalDivider +import androidx.compose.material3.MaterialTheme +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier + +/** Semantic opacity tokens for black scrims drawn over media. */ +object ScrimAlpha { + const val Light = 0.35f + const val LightEmphasis = 0.4f + const val Medium = 0.45f + const val MediumEmphasis = 0.5f + const val Strong = 0.55f + const val Gradient = 0.6f + const val Heavy = 0.62f +} + +/** App-wide horizontal separator using Material's divider-specific color role. */ +@Composable +fun AppDivider(modifier: Modifier = Modifier) { + HorizontalDivider( + modifier = modifier, + color = MaterialTheme.colorScheme.outlineVariant, + ) +} diff --git a/app/src/test/java/dev/ipf/whitenoise/android/ui/screenshot/MessageBubbleChromeScreenshotTest.kt b/app/src/test/java/dev/ipf/whitenoise/android/ui/screenshot/MessageBubbleChromeScreenshotTest.kt index e193fa398..84f134f57 100644 --- a/app/src/test/java/dev/ipf/whitenoise/android/ui/screenshot/MessageBubbleChromeScreenshotTest.kt +++ b/app/src/test/java/dev/ipf/whitenoise/android/ui/screenshot/MessageBubbleChromeScreenshotTest.kt @@ -18,8 +18,14 @@ import androidx.compose.ui.test.junit4.createComposeRule import androidx.compose.ui.test.onNodeWithTag import androidx.compose.ui.unit.dp import com.github.takahirom.roborazzi.captureRoboImage +import dev.ipf.marmotkit.MarkdownAlignmentFfi +import dev.ipf.marmotkit.MarkdownBlockFfi +import dev.ipf.marmotkit.MarkdownDocumentFfi +import dev.ipf.marmotkit.MarkdownInlineFfi +import dev.ipf.marmotkit.MarkdownTableCellFfi import dev.ipf.whitenoise.android.core.ReplyMediaKind import dev.ipf.whitenoise.android.state.MessageStatus +import dev.ipf.whitenoise.android.ui.MarkdownMessageBody import dev.ipf.whitenoise.android.ui.conversation.messages.MessageInlineFooter import dev.ipf.whitenoise.android.ui.conversation.messages.messageBubbleBorder import dev.ipf.whitenoise.android.ui.conversation.messages.messageBubbleTimestampColor @@ -80,6 +86,30 @@ class MessageBubbleChromeScreenshotTest { .captureRoboImage("src/test/snapshots/message_bubble_chrome_amoled.png") } + @Test + fun bubbleMarkdownDividersLight() { + renderMarkdownDividers(darkTheme = false, amoled = false) + composeRule + .onNodeWithTag(MARKDOWN_TAG) + .captureRoboImage("src/test/snapshots/message_bubble_markdown_dividers_light.png") + } + + @Test + fun bubbleMarkdownDividersDark() { + renderMarkdownDividers(darkTheme = true, amoled = false) + composeRule + .onNodeWithTag(MARKDOWN_TAG) + .captureRoboImage("src/test/snapshots/message_bubble_markdown_dividers_dark.png") + } + + @Test + fun bubbleMarkdownDividersAmoled() { + renderMarkdownDividers(darkTheme = true, amoled = true) + composeRule + .onNodeWithTag(MARKDOWN_TAG) + .captureRoboImage("src/test/snapshots/message_bubble_markdown_dividers_amoled.png") + } + private fun render(darkTheme: Boolean) { composeRule.setContent { WhiteNoiseTheme(darkTheme = darkTheme) { @@ -125,11 +155,76 @@ class MessageBubbleChromeScreenshotTest { } } + private fun renderMarkdownDividers( + darkTheme: Boolean, + amoled: Boolean, + ) { + composeRule.setContent { + WhiteNoiseTheme(darkTheme = darkTheme, amoled = amoled) { + Surface { + Column( + modifier = Modifier.width(360.dp).padding(16.dp).testTag(MARKDOWN_TAG), + verticalArrangement = Arrangement.spacedBy(16.dp), + ) { + MarkdownDividerBubble(mine = false, amoled = amoled) + Row(modifier = Modifier.fillMaxWidth(), horizontalArrangement = Arrangement.End) { + MarkdownDividerBubble(mine = true, amoled = amoled) + } + } + } + } + } + } + private companion object { const val TAG = "bubble-chrome" + const val MARKDOWN_TAG = "bubble-markdown-dividers" + } +} + +@Composable +private fun MarkdownDividerBubble( + mine: Boolean, + amoled: Boolean, +) { + val bubbleColor = + when { + amoled -> Color.Black + mine -> MaterialTheme.colorScheme.primaryContainer + else -> MaterialTheme.colorScheme.surfaceVariant + } + val label = if (mine) "Sent" else "Received" + + Surface( + color = bubbleColor, + shape = RoundedCornerShape(18.dp), + border = messageBubbleBorder(highlighted = false, mine = mine), + tonalElevation = if (mine) 1.dp else 0.dp, + ) { + MarkdownMessageBody( + document = markdownDividerDocument(label), + modifier = Modifier.width(260.dp).padding(horizontal = 14.dp, vertical = 10.dp), + ) } } +private fun markdownDividerDocument(label: String): MarkdownDocumentFfi = + MarkdownDocumentFfi( + blocks = + listOf( + MarkdownBlockFfi.Paragraph(listOf(MarkdownInlineFfi.Text("$label markdown rule"))), + MarkdownBlockFfi.ThematicBreak, + MarkdownBlockFfi.Table( + alignments = listOf(MarkdownAlignmentFfi.NONE, MarkdownAlignmentFfi.NONE), + header = listOf(markdownTableCell("Token"), markdownTableCell("Value")), + rows = listOf(listOf(markdownTableCell("Divider"), markdownTableCell("Visible"))), + ), + ), + truncated = false, + ) + +private fun markdownTableCell(text: String): MarkdownTableCellFfi = MarkdownTableCellFfi(listOf(MarkdownInlineFfi.Text(text))) + @Composable private fun DirectionalBubble( text: String, diff --git a/app/src/test/java/dev/ipf/whitenoise/android/ui/theme/VisualTokensTest.kt b/app/src/test/java/dev/ipf/whitenoise/android/ui/theme/VisualTokensTest.kt new file mode 100644 index 000000000..eacb80117 --- /dev/null +++ b/app/src/test/java/dev/ipf/whitenoise/android/ui/theme/VisualTokensTest.kt @@ -0,0 +1,22 @@ +package dev.ipf.whitenoise.android.ui.theme + +import org.junit.Assert.assertEquals +import org.junit.Test + +class VisualTokensTest { + @Test + fun scrimAlphaTokensPreserveExistingVisualLevels() { + assertEquals( + listOf(0.35f, 0.4f, 0.45f, 0.5f, 0.55f, 0.6f, 0.62f), + listOf( + ScrimAlpha.Light, + ScrimAlpha.LightEmphasis, + ScrimAlpha.Medium, + ScrimAlpha.MediumEmphasis, + ScrimAlpha.Strong, + ScrimAlpha.Gradient, + ScrimAlpha.Heavy, + ), + ) + } +} diff --git a/app/src/test/snapshots/message_bubble_markdown_dividers_amoled.png b/app/src/test/snapshots/message_bubble_markdown_dividers_amoled.png new file mode 100644 index 000000000..64fd131e8 Binary files /dev/null and b/app/src/test/snapshots/message_bubble_markdown_dividers_amoled.png differ diff --git a/app/src/test/snapshots/message_bubble_markdown_dividers_dark.png b/app/src/test/snapshots/message_bubble_markdown_dividers_dark.png new file mode 100644 index 000000000..db32b8f06 Binary files /dev/null and b/app/src/test/snapshots/message_bubble_markdown_dividers_dark.png differ diff --git a/app/src/test/snapshots/message_bubble_markdown_dividers_light.png b/app/src/test/snapshots/message_bubble_markdown_dividers_light.png new file mode 100644 index 000000000..f2af19720 Binary files /dev/null and b/app/src/test/snapshots/message_bubble_markdown_dividers_light.png differ