@@ -15,10 +15,15 @@ import androidx.compose.ui.geometry.Offset
1515import androidx.compose.ui.graphics.BlendMode
1616import androidx.compose.ui.graphics.Brush
1717import androidx.compose.ui.graphics.Color
18+ import androidx.compose.ui.semantics.semantics
19+ import androidx.compose.ui.semantics.text
20+ import androidx.compose.ui.text.AnnotatedString
1821import androidx.compose.ui.text.style.TextAlign
1922import androidx.compose.ui.unit.dp
2023import com.agui.example.chatapp.ui.screens.chat.DisplayMessage
2124import com.agui.example.chatapp.ui.screens.chat.MessageRole
25+ import com.halilibo.richtext.commonmark.Markdown
26+ import com.halilibo.richtext.ui.material3.RichText
2227import kotlinx.datetime.Instant
2328import kotlinx.datetime.TimeZone
2429import kotlinx.datetime.toLocalDateTime
@@ -34,6 +39,14 @@ fun MessageBubble(
3439 val isToolCall = message.role == MessageRole .TOOL_CALL
3540 val isStepInfo = message.role == MessageRole .STEP_INFO
3641 val isEphemeral = message.ephemeralGroupId != null
42+ val messageTextColor = when {
43+ isUser -> MaterialTheme .colorScheme.onPrimary
44+ isError -> MaterialTheme .colorScheme.onError
45+ isSystem -> MaterialTheme .colorScheme.onTertiary
46+ isToolCall -> MaterialTheme .colorScheme.onSecondaryContainer
47+ isStepInfo -> MaterialTheme .colorScheme.onTertiaryContainer
48+ else -> MaterialTheme .colorScheme.onSurfaceVariant
49+ }
3750
3851 // Enhanced fade-in animation
3952 val animatedAlpha = remember(message.id) { Animatable (0f ) }
@@ -94,12 +107,7 @@ fun MessageBubble(
94107 Text (
95108 text = message.content,
96109 style = MaterialTheme .typography.bodyLarge,
97- color = when {
98- isUser -> MaterialTheme .colorScheme.onPrimary
99- isError -> MaterialTheme .colorScheme.onError
100- isSystem -> MaterialTheme .colorScheme.onTertiary
101- else -> MaterialTheme .colorScheme.onSurfaceVariant
102- }
110+ color = messageTextColor
103111 )
104112 CircularProgressIndicator (
105113 modifier = Modifier .size(12 .dp),
@@ -126,14 +134,7 @@ fun MessageBubble(
126134 label = " textShimmer"
127135 )
128136
129- val textColor = when {
130- isUser -> MaterialTheme .colorScheme.onPrimary
131- isError -> MaterialTheme .colorScheme.onError
132- isSystem -> MaterialTheme .colorScheme.onTertiary
133- isToolCall -> MaterialTheme .colorScheme.onSecondaryContainer
134- isStepInfo -> MaterialTheme .colorScheme.onTertiaryContainer
135- else -> MaterialTheme .colorScheme.onSurfaceVariant
136- }
137+ val textColor = messageTextColor
137138
138139 Box {
139140 Text (
@@ -163,18 +164,17 @@ fun MessageBubble(
163164 }
164165 } else {
165166 // Regular text for non-ephemeral messages
166- Text (
167- text = message.content,
168- style = MaterialTheme .typography.bodyLarge,
169- color = when {
170- isUser -> MaterialTheme .colorScheme.onPrimary
171- isError -> MaterialTheme .colorScheme.onError
172- isSystem -> MaterialTheme .colorScheme.onTertiary
173- isToolCall -> MaterialTheme .colorScheme.onSecondaryContainer
174- isStepInfo -> MaterialTheme .colorScheme.onTertiaryContainer
175- else -> MaterialTheme .colorScheme.onSurfaceVariant
167+ ProvideTextStyle (MaterialTheme .typography.bodyLarge) {
168+ CompositionLocalProvider (LocalContentColor provides messageTextColor) {
169+ RichText (
170+ modifier = Modifier
171+ .fillMaxWidth()
172+ .semantics { text = AnnotatedString (message.content) }
173+ ) {
174+ Markdown (message.content)
175+ }
176176 }
177- )
177+ }
178178 }
179179 }
180180
@@ -203,4 +203,4 @@ private fun formatTimestamp(timestamp: Long): String {
203203 val instant = Instant .fromEpochMilliseconds(timestamp)
204204 val localDateTime = instant.toLocalDateTime(TimeZone .currentSystemDefault())
205205 return " ${localDateTime.hour.toString().padStart(2 , ' 0' )} :${localDateTime.minute.toString().padStart(2 , ' 0' )} "
206- }
206+ }
0 commit comments