@@ -78,7 +78,11 @@ export type MessageContentPropsWithContext = Pick<
7878 | 'FileAttachmentGroup'
7979 | 'Gallery'
8080 | 'isAttachmentEqual'
81+ | 'MessageContentBottomView'
82+ | 'MessageContentLeadingView'
8183 | 'MessageLocation'
84+ | 'MessageContentTrailingView'
85+ | 'MessageContentTopView'
8286 | 'myMessageTheme'
8387 | 'Reply'
8488 | 'StreamingMessageView'
@@ -128,8 +132,12 @@ const MessageContentWithContext = (props: MessageContentPropsWithContext) => {
128132 isVeryLastMessage,
129133 message,
130134 messageContentOrder,
135+ MessageContentBottomView,
136+ MessageContentLeadingView,
131137 messageGroupedSingleOrBottom = false ,
132138 MessageLocation,
139+ MessageContentTrailingView,
140+ MessageContentTopView,
133141 noBorder,
134142 onLongPress,
135143 onPress,
@@ -227,6 +235,83 @@ const MessageContentWithContext = (props: MessageContentPropsWithContext) => {
227235 } ;
228236
229237 const { setNativeScrollability } = useMessageListItemContext ( ) ;
238+ const hasContentSideViews = ! ! ( MessageContentLeadingView || MessageContentTrailingView ) ;
239+
240+ const contentBody = (
241+ < >
242+ < View
243+ style = { [
244+ {
245+ gap : primitives . spacingXs ,
246+ paddingTop : hidePaddingTop ? 0 : primitives . spacingXs ,
247+ paddingHorizontal : hidePaddingHorizontal ? 0 : primitives . spacingXs ,
248+ paddingBottom : hidePaddingBottom ? 0 : primitives . spacingXs ,
249+ } ,
250+ contentContainer ,
251+ ] }
252+ >
253+ { messageContentOrder . map ( ( messageContentType , messageContentOrderIndex ) => {
254+ switch ( messageContentType ) {
255+ case 'quoted_reply' :
256+ return (
257+ message . quoted_message && (
258+ < View
259+ key = { `quoted_reply_${ messageContentOrderIndex } ` }
260+ style = { [ styles . replyContainer , replyContainer ] }
261+ >
262+ < Reply mode = 'reply' styles = { replyStyles } />
263+ </ View >
264+ )
265+ ) ;
266+ case 'attachments' :
267+ return otherAttachments . map ( ( attachment , attachmentIndex ) => (
268+ < Attachment attachment = { attachment } key = { `${ message . id } -${ attachmentIndex } ` } />
269+ ) ) ;
270+ case 'files' :
271+ return (
272+ < FileAttachmentGroup key = { `file_attachment_group_${ messageContentOrderIndex } ` } />
273+ ) ;
274+ case 'gallery' :
275+ return (
276+ < View key = { `gallery_${ messageContentOrderIndex } ` } style = { styles . galleryContainer } >
277+ < Gallery />
278+ </ View >
279+ ) ;
280+ case 'poll' : {
281+ const pollId = message . poll_id ;
282+ const poll = pollId && client . polls . fromState ( pollId ) ;
283+ return pollId && poll ? (
284+ < Poll
285+ key = { `poll_${ message . poll_id } ` }
286+ message = { message }
287+ poll = { poll }
288+ PollContent = { PollContentOverride }
289+ />
290+ ) : null ;
291+ }
292+ case 'location' :
293+ return MessageLocation ? (
294+ < MessageLocation
295+ key = { `message_location_${ messageContentOrderIndex } ` }
296+ message = { message }
297+ />
298+ ) : null ;
299+ case 'ai_text' :
300+ return isAIGenerated ? (
301+ < StreamingMessageView
302+ key = { `ai_message_text_container_${ messageContentOrderIndex } ` }
303+ />
304+ ) : null ;
305+ default :
306+ return null ;
307+ }
308+ } ) }
309+ </ View >
310+ { ( otherAttachments . length && otherAttachments [ 0 ] . actions ) || isAIGenerated ? null : (
311+ < MessageTextContainer />
312+ ) }
313+ </ >
314+ ) ;
230315
231316 return (
232317 < Pressable
@@ -284,82 +369,17 @@ const MessageContentWithContext = (props: MessageContentPropsWithContext) => {
284369 ] }
285370 testID = 'message-content-wrapper'
286371 >
287- < View
288- style = { [
289- {
290- gap : primitives . spacingXs ,
291- paddingTop : hidePaddingTop ? 0 : primitives . spacingXs ,
292- paddingHorizontal : hidePaddingHorizontal ? 0 : primitives . spacingXs ,
293- paddingBottom : hidePaddingBottom ? 0 : primitives . spacingXs ,
294- } ,
295- contentContainer ,
296- ] }
297- >
298- { messageContentOrder . map ( ( messageContentType , messageContentOrderIndex ) => {
299- switch ( messageContentType ) {
300- case 'quoted_reply' :
301- return (
302- message . quoted_message && (
303- < View
304- key = { `quoted_reply_${ messageContentOrderIndex } ` }
305- style = { [ styles . replyContainer , replyContainer ] }
306- >
307- < Reply mode = 'reply' styles = { replyStyles } />
308- </ View >
309- )
310- ) ;
311- case 'attachments' :
312- return otherAttachments . map ( ( attachment , attachmentIndex ) => (
313- < Attachment attachment = { attachment } key = { `${ message . id } -${ attachmentIndex } ` } />
314- ) ) ;
315- case 'files' :
316- return (
317- < FileAttachmentGroup
318- key = { `file_attachment_group_${ messageContentOrderIndex } ` }
319- />
320- ) ;
321- case 'gallery' :
322- return (
323- < View
324- key = { `gallery_${ messageContentOrderIndex } ` }
325- style = { styles . galleryContainer }
326- >
327- < Gallery />
328- </ View >
329- ) ;
330- case 'poll' : {
331- const pollId = message . poll_id ;
332- const poll = pollId && client . polls . fromState ( pollId ) ;
333- return pollId && poll ? (
334- < Poll
335- key = { `poll_${ message . poll_id } ` }
336- message = { message }
337- poll = { poll }
338- PollContent = { PollContentOverride }
339- />
340- ) : null ;
341- }
342- case 'location' :
343- return MessageLocation ? (
344- < MessageLocation
345- key = { `message_location_${ messageContentOrderIndex } ` }
346- message = { message }
347- />
348- ) : null ;
349- case 'ai_text' :
350- return isAIGenerated ? (
351- < StreamingMessageView
352- key = { `ai_message_text_container_${ messageContentOrderIndex } ` }
353- />
354- ) : null ;
355- default :
356- return null ;
357- }
358- } ) }
359- </ View >
360- { ( otherAttachments . length && otherAttachments [ 0 ] . actions ) || isAIGenerated ? null : (
361- < MessageTextContainer />
372+ { MessageContentTopView ? < MessageContentTopView /> : null }
373+ { hasContentSideViews ? (
374+ < View style = { styles . contentRow } >
375+ { MessageContentLeadingView ? < MessageContentLeadingView /> : null }
376+ < View style = { styles . contentBody } > { contentBody } </ View >
377+ { MessageContentTrailingView ? < MessageContentTrailingView /> : null }
378+ </ View >
379+ ) : (
380+ contentBody
362381 ) }
382+ { MessageContentBottomView ? < MessageContentBottomView /> : null }
363383 </ View >
364384 </ View >
365385 </ Pressable >
@@ -550,7 +570,11 @@ export const MessageContent = (props: MessageContentProps) => {
550570 FileAttachmentGroup,
551571 Gallery,
552572 isAttachmentEqual,
573+ MessageContentBottomView,
574+ MessageContentLeadingView,
553575 MessageLocation,
576+ MessageContentTrailingView,
577+ MessageContentTopView,
554578 myMessageTheme,
555579 Reply,
556580 StreamingMessageView,
@@ -604,7 +628,11 @@ export const MessageContent = (props: MessageContentProps) => {
604628 isMyMessage,
605629 message,
606630 messageContentOrder,
631+ MessageContentBottomView,
632+ MessageContentLeadingView,
607633 MessageLocation,
634+ MessageContentTrailingView,
635+ MessageContentTopView,
608636 myMessageTheme,
609637 onLongPress,
610638 onPress,
@@ -633,6 +661,13 @@ const styles = StyleSheet.create({
633661 borderTopRightRadius : components . messageBubbleRadiusGroupBottom ,
634662 overflow : 'hidden' ,
635663 } ,
664+ contentBody : {
665+ flexShrink : 1 ,
666+ minWidth : 0 ,
667+ } ,
668+ contentRow : {
669+ flexDirection : 'row' ,
670+ } ,
636671 leftAlignContent : {
637672 justifyContent : 'flex-start' ,
638673 } ,
0 commit comments