@@ -43,9 +43,22 @@ import com.adobe.marketing.mobile.concierge.ui.components.suggestions.PromptSugg
4343import com.adobe.marketing.mobile.concierge.ui.state.ChatMessage
4444import com.adobe.marketing.mobile.concierge.ui.state.FeedbackEvent
4545import com.adobe.marketing.mobile.concierge.ui.state.MessageContent
46+ import com.adobe.marketing.mobile.concierge.ui.theme.ChatMessageAlignment
4647import com.adobe.marketing.mobile.concierge.ui.theme.ConciergeStyles
4748import com.adobe.marketing.mobile.concierge.ui.theme.ConciergeTheme
4849
50+ /* *
51+ * Maps a [ChatMessageAlignment] to the Compose [Modifier] that produces the correct
52+ * horizontal alignment for a bot message card. The pattern is consistent across all
53+ * render functions: [fillMaxWidth] reserves the full layout slot so the list is stable,
54+ * and [wrapContentWidth] then shrinks the card to its content and anchors it.
55+ */
56+ private fun ChatMessageAlignment.toModifier (): Modifier = when (this ) {
57+ ChatMessageAlignment .CENTER -> Modifier .fillMaxWidth().wrapContentWidth(Alignment .CenterHorizontally )
58+ ChatMessageAlignment .END -> Modifier .fillMaxWidth().wrapContentWidth(Alignment .End )
59+ ChatMessageAlignment .START -> Modifier .fillMaxWidth()
60+ }
61+
4962/* *
5063 * Component that displays a single chat message.
5164 */
@@ -109,12 +122,15 @@ private fun RenderTextMessage(
109122 val thinkingStyle = ConciergeStyles .thinkingAnimationStyle
110123 val isThinking = message.isThinking
111124 val companyIconName = if (! message.isFromUser) ConciergeTheme .tokens?.assets?.icons?.company?.takeIf { it.isNotEmpty() } else null
125+ val messageAlignment = ConciergeTheme .behavior?.chat?.messageAlignment ? : ChatMessageAlignment .START
112126
113127 if (companyIconName != null ) {
114128 RenderTextMessageWithIcon (
115129 message = message,
116130 companyIconName = companyIconName,
131+ isThinking = isThinking,
117132 style = style,
133+ thinkingStyle = thinkingStyle,
118134 onFeedback = onFeedback,
119135 onSuggestionClick = onSuggestionClick,
120136 handleLink = handleLink,
@@ -132,8 +148,8 @@ private fun RenderTextMessage(
132148 .then(
133149 when {
134150 message.isFromUser -> Modifier .fillMaxWidth().wrapContentWidth(Alignment .End )
135- isThinking -> Modifier
136- else -> Modifier .fillMaxWidth ()
151+ isThinking -> Modifier .fillMaxWidth().wrapContentWidth( Alignment . Start )
152+ else -> messageAlignment.toModifier ()
137153 }
138154 )
139155 .padding(style.padding),
@@ -198,7 +214,9 @@ private fun RenderTextMessage(
198214private fun RenderTextMessageWithIcon (
199215 message : ChatMessage ,
200216 companyIconName : String ,
217+ isThinking : Boolean ,
201218 style : ConciergeStyles .MessageBubbleStyle ,
219+ thinkingStyle : ConciergeStyles .ThinkingAnimationStyle ,
202220 onFeedback : (FeedbackEvent ) -> Unit ,
203221 onSuggestionClick : (String ) -> Unit ,
204222 handleLink : (String ) -> Unit ,
@@ -230,6 +248,9 @@ private fun RenderTextMessageWithIcon(
230248 Card (
231249 modifier = Modifier
232250 .fillMaxWidth()
251+ .then(
252+ if (isThinking) Modifier .wrapContentWidth(Alignment .Start ) else Modifier
253+ )
233254 .padding(
234255 top = style.padding,
235256 bottom = style.padding,
@@ -239,22 +260,28 @@ private fun RenderTextMessageWithIcon(
239260 containerColor = style.botMessageBackgroundColor
240261 ),
241262 elevation = CardDefaults .cardElevation(defaultElevation = style.elevation),
242- shape = style.shape
263+ shape = if (isThinking) thinkingStyle.bubbleShape else style.shape
243264 ) {
244265 Box (
245266 modifier = Modifier .padding(
246- top = style.innerPadding,
247- bottom = style.innerPadding,
248- end = style.innerPadding
267+ if (isThinking) thinkingStyle.bubblePadding else PaddingValues (
268+ top = style.innerPadding,
269+ bottom = style.innerPadding,
270+ end = style.innerPadding
271+ )
249272 )
250273 ) {
251- Column (modifier = Modifier .fillMaxWidth()) {
252- AgentResponseContent (
253- message = message,
254- handleLink = handleLink,
255- onFeedback = onFeedback,
256- feedbackState = feedbackState
257- )
274+ if (isThinking) {
275+ ConciergeThinking ()
276+ } else {
277+ Column (modifier = Modifier .fillMaxWidth()) {
278+ AgentResponseContent (
279+ message = message,
280+ handleLink = handleLink,
281+ onFeedback = onFeedback,
282+ feedbackState = feedbackState
283+ )
284+ }
258285 }
259286 }
260287 }
@@ -282,13 +309,14 @@ private fun RenderMixedMessage(
282309) {
283310 val style = ConciergeStyles .messageBubbleStyle
284311 val content = message.content as MessageContent .Mixed
312+ val messageAlignment = ConciergeTheme .behavior?.chat?.messageAlignment ? : ChatMessageAlignment .START
285313
286314 Column (
287315 modifier = Modifier .fillMaxWidth()
288316 ) {
289317 Card (
290318 modifier = Modifier
291- .fillMaxWidth( )
319+ .then(messageAlignment.toModifier() )
292320 .padding(style.padding),
293321 colors = CardDefaults .cardColors(
294322 containerColor = style.botMessageBackgroundColor
0 commit comments