From 69a50f8fcdecac3568390e1f714d7398dbb6bb9d Mon Sep 17 00:00:00 2001 From: Danil Nikolaev Date: Mon, 15 Dec 2025 23:01:38 +0300 Subject: [PATCH] Refactor: Encapsulate MessageBubble colors This commit refactors the `MessageBubble` composable by extracting the color logic into a private `messageBubbleColors` function. This function returns an immutable `MessageBubbleColors` data class, which holds the container, content, and reply container colors. This change cleans up the main composable, improves readability, and centralizes color definitions for both incoming and outgoing messages. Additionally, the background color logic for attachments has been simplified to make it transparent for media types like stickers and videos. --- .../presentation/MessageBubble.kt | 74 ++++++++++--------- 1 file changed, 41 insertions(+), 33 deletions(-) diff --git a/feature/messageshistory/src/main/kotlin/dev/meloda/fast/messageshistory/presentation/MessageBubble.kt b/feature/messageshistory/src/main/kotlin/dev/meloda/fast/messageshistory/presentation/MessageBubble.kt index 2ace12a4..11a8fa72 100644 --- a/feature/messageshistory/src/main/kotlin/dev/meloda/fast/messageshistory/presentation/MessageBubble.kt +++ b/feature/messageshistory/src/main/kotlin/dev/meloda/fast/messageshistory/presentation/MessageBubble.kt @@ -16,6 +16,7 @@ import androidx.compose.material3.MaterialTheme import androidx.compose.material3.surfaceColorAtElevation import androidx.compose.runtime.Composable import androidx.compose.runtime.CompositionLocalProvider +import androidx.compose.runtime.Immutable import androidx.compose.runtime.derivedStateOf import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableIntStateOf @@ -68,22 +69,7 @@ fun MessageBubble( val currentOnLongClick by rememberUpdatedState(onLongClick) val theme = LocalThemeConfig.current - val backgroundColor = if (!isOut) { - MaterialTheme.colorScheme.surfaceColorAtElevation(2.dp) - } else { - MaterialTheme.colorScheme.primaryContainer - } - val replyBackgroundColor = if (!isOut) { - MaterialTheme.colorScheme.primaryContainer - } else { - MaterialTheme.colorScheme.inversePrimary - } - - val contentColor = if (!isOut) { - MaterialTheme.colorScheme.onSurface - } else { - MaterialTheme.colorScheme.onPrimaryContainer - } + val colors = messageBubbleColors(isOut = isOut) val shouldShowBubble = !text.isNullOrEmpty() @@ -117,7 +103,7 @@ fun MessageBubble( label = "dateContainerWidth" ) - CompositionLocalProvider(LocalContentColor provides contentColor) { + CompositionLocalProvider(LocalContentColor provides colors.content) { Column( modifier = modifier .wrapContentWidth() @@ -140,8 +126,8 @@ fun MessageBubble( onClick = onReplyClick, title = replyTitle, summary = replySummary, - backgroundColor = backgroundColor, - innerBackgroundColor = replyBackgroundColor + backgroundColor = colors.container, + innerBackgroundColor = colors.replyContainer ) } @@ -163,7 +149,7 @@ fun MessageBubble( bottomEnd = if (attachments != null) 0.dp else 24.dp ) ) - .background(backgroundColor) + .background(colors.container) .padding( start = 8.dp, end = 8.dp, @@ -204,6 +190,15 @@ fun MessageBubble( } if (attachments != null) { + val firstAttachment = attachments.firstOrNull() + val isMediaAttachment = firstAttachment is VkStickerDomain || + firstAttachment is VkVideoMessageDomain + val attachmentBackgroundColor = if (isMediaAttachment) { + Color.Transparent + } else { + colors.container + } + Box( modifier = Modifier .onGloballyPositioned { @@ -218,18 +213,7 @@ fun MessageBubble( topEnd = 0.dp ) ) - .background( - backgroundColor.copy( - alpha = if ((attachments.firstOrNull()?.javaClass - ?: Nothing::class.java) - in listOf( - VkStickerDomain::class.java, - VkVideoMessageDomain::class.java - ) - ) 0f - else 1f - ) - ) + .background(attachmentBackgroundColor) ) { Attachments( modifier = Modifier, @@ -241,7 +225,7 @@ fun MessageBubble( val dateStatusBackground = if (theme.darkMode) Color.Black.copy(alpha = 0.5f) else Color.White.copy(alpha = 0.5f) - CompositionLocalProvider(LocalContentColor provides contentColor) { + CompositionLocalProvider(LocalContentColor provides colors.content) { DateStatus( modifier = Modifier .align(Alignment.BottomEnd) @@ -266,6 +250,30 @@ fun MessageBubble( } } +@Immutable +private data class MessageBubbleColors( + val container: Color, + val content: Color, + val replyContainer: Color, +) + +@Composable +private fun messageBubbleColors(isOut: Boolean): MessageBubbleColors { + return if (isOut) { + MessageBubbleColors( + container = MaterialTheme.colorScheme.primaryContainer, + content = MaterialTheme.colorScheme.onPrimaryContainer, + replyContainer = MaterialTheme.colorScheme.inversePrimary + ) + } else { + MessageBubbleColors( + container = MaterialTheme.colorScheme.surfaceColorAtElevation(2.dp), + content = MaterialTheme.colorScheme.onSurface, + replyContainer = MaterialTheme.colorScheme.primaryContainer + ) + } +} + @Preview @Composable private fun Bubble() {