@@ -222,6 +222,15 @@ type MessageListPropsWithContext = Pick<
222222 * ```
223223 */
224224 setFlatListRef ?: ( ref : FlatListType < LocalMessage > | null ) => void ;
225+ /**
226+ * If true, the message list will be used in a live-streaming scenario.
227+ * This flag is used to make sure that the auto scroll behaves well, if multiple messages are received.
228+ *
229+ * This flag is experimental and is subject to change. Please test thoroughly before using it.
230+ *
231+ * @experimental
232+ */
233+ isLiveStreaming ?: boolean ;
225234 } ;
226235
227236/**
@@ -256,6 +265,7 @@ const MessageListWithContext = (props: MessageListPropsWithContext) => {
256265 InlineUnreadIndicator,
257266 inverted = true ,
258267 isListActive = false ,
268+ isLiveStreaming = false ,
259269 legacyImageViewerSwipeBehaviour,
260270 loadChannelAroundMessage,
261271 loading,
@@ -313,6 +323,7 @@ const MessageListWithContext = (props: MessageListPropsWithContext) => {
313323 */
314324 const { dateSeparatorsRef, messageGroupStylesRef, processedMessageList, rawMessageList } =
315325 useMessageList ( {
326+ isLiveStreaming,
316327 noGroupByUser,
317328 threadList,
318329 } ) ;
@@ -336,12 +347,17 @@ const MessageListWithContext = (props: MessageListPropsWithContext) => {
336347
337348 const minIndexForVisible = Math . min ( 1 , processedMessageList . length ) ;
338349
350+ const autoscrollToTopThreshold = useMemo (
351+ ( ) => ( isLiveStreaming ? 64 : autoscrollToRecent ? 10 : undefined ) ,
352+ [ autoscrollToRecent , isLiveStreaming ] ,
353+ ) ;
354+
339355 const maintainVisibleContentPosition = useMemo (
340356 ( ) => ( {
341- autoscrollToTopThreshold : autoscrollToRecent ? 10 : undefined ,
357+ autoscrollToTopThreshold,
342358 minIndexForVisible,
343359 } ) ,
344- [ autoscrollToRecent , minIndexForVisible ] ,
360+ [ autoscrollToTopThreshold , minIndexForVisible ] ,
345361 ) ;
346362
347363 /**
@@ -652,7 +668,11 @@ const MessageListWithContext = (props: MessageListPropsWithContext) => {
652668 latestNonCurrentMessageBeforeUpdate ?. id === latestCurrentMessageAfterUpdate . id ;
653669 // if didMergeMessageSetsWithNoUpdates=false, we got new messages
654670 // so we should scroll to bottom if we are near the bottom already
655- setAutoscrollToRecent ( ! didMergeMessageSetsWithNoUpdates ) ;
671+ const shouldForceScrollToRecent =
672+ ! didMergeMessageSetsWithNoUpdates ||
673+ processedMessageList . length - messageListLengthBeforeUpdate . current > 0 ;
674+
675+ setAutoscrollToRecent ( shouldForceScrollToRecent ) ;
656676
657677 if ( ! didMergeMessageSetsWithNoUpdates ) {
658678 const shouldScrollToRecentOnNewOwnMessage = shouldScrollToRecentOnNewOwnMessageRef . current ( ) ;
@@ -667,8 +687,7 @@ const MessageListWithContext = (props: MessageListPropsWithContext) => {
667687 } , WAIT_FOR_SCROLL_TIMEOUT ) ; // flatlist might take a bit to update, so a small delay is needed
668688 }
669689 }
670- // eslint-disable-next-line react-hooks/exhaustive-deps
671- } , [ channel , processedMessageList , threadList ] ) ;
690+ } , [ channel , threadList , processedMessageList , shouldScrollToRecentOnNewOwnMessageRef ] ) ;
672691
673692 const goToMessage = useStableCallback ( async ( messageId : string ) => {
674693 const indexOfParentInMessageList = processedMessageList . findIndex (
@@ -1218,7 +1237,10 @@ const MessageListWithContext = (props: MessageListPropsWithContext) => {
12181237 onViewableItemsChanged = { stableOnViewableItemsChanged }
12191238 ref = { refCallback }
12201239 renderItem = { renderItem }
1240+ scrollEventThrottle = { isLiveStreaming ? 16 : undefined }
12211241 showsVerticalScrollIndicator = { false }
1242+ // @ts -expect-error react-native internal
1243+ strictMode = { isLiveStreaming }
12221244 style = { flatListStyle }
12231245 testID = 'message-flat-list'
12241246 viewabilityConfig = { flatListViewabilityConfig }
0 commit comments