@@ -2,13 +2,15 @@ import React, { useCallback, useEffect, useMemo, useRef, useState } from 'react'
22import {
33 FlatListProps ,
44 FlatList as FlatListType ,
5+ LayoutChangeEvent ,
56 ScrollViewProps ,
67 StyleSheet ,
78 View ,
89 ViewabilityConfig ,
910 ViewToken ,
1011} from 'react-native' ;
1112
13+ import debounce from 'lodash/debounce' ;
1214import type { Channel , Event , LocalMessage , MessageResponse } from 'stream-chat' ;
1315
1416import { useMessageList } from './hooks/useMessageList' ;
@@ -327,8 +329,8 @@ const MessageListWithContext = (props: MessageListPropsWithContext) => {
327329
328330 const renderItem = useCallback (
329331 ( { item : message , index } : { item : LocalMessage ; index : number } ) => {
330- const previousMessage = processedMessageListRef . current [ index + 1 ] ;
331- const nextMessage = processedMessageListRef . current [ index - 1 ] ;
332+ const previousMessage = processedMessageList [ index + 1 ] ;
333+ const nextMessage = processedMessageList [ index - 1 ] ;
332334 return (
333335 < MessageWrapper
334336 message = { message }
@@ -337,7 +339,7 @@ const MessageListWithContext = (props: MessageListPropsWithContext) => {
337339 />
338340 ) ;
339341 } ,
340- [ processedMessageListRef ] ,
342+ [ processedMessageList ] ,
341343 ) ;
342344
343345 const messageListLengthBeforeUpdate = useRef ( 0 ) ;
@@ -1126,6 +1128,44 @@ const MessageListWithContext = (props: MessageListPropsWithContext) => {
11261128 [ additionalFlatListProps ?. contentContainerStyle , contentContainer ] ,
11271129 ) ;
11281130
1131+ const viewportHeightRef = useRef < number > ( undefined ) ;
1132+
1133+ /**
1134+ * This debounced callback makes sure that if the current number of messages do not
1135+ * fill our screen, we load more messages continuously until we cover enough ground.
1136+ */
1137+ const debouncedPrefillMessages = useMemo (
1138+ ( ) =>
1139+ debounce (
1140+ ( viewportHeight : number , contentHeight : number ) => {
1141+ if ( viewportHeight >= contentHeight ) {
1142+ maybeCallOnEndReached ( ) ;
1143+ }
1144+ } ,
1145+ 500 ,
1146+ {
1147+ leading : false ,
1148+ trailing : true ,
1149+ } ,
1150+ ) ,
1151+ [ maybeCallOnEndReached ] ,
1152+ ) ;
1153+
1154+ const onContentSizeChange = useStableCallback ( ( width : number , height : number ) => {
1155+ if ( additionalFlatListProps ?. onContentSizeChange ) {
1156+ additionalFlatListProps . onContentSizeChange ( width , height ) ;
1157+ }
1158+
1159+ debouncedPrefillMessages ( viewportHeightRef . current ?? 0 , height ) ;
1160+ } ) ;
1161+
1162+ const onLayout = useStableCallback ( ( event : LayoutChangeEvent ) => {
1163+ if ( additionalFlatListProps ?. onLayout ) {
1164+ additionalFlatListProps . onLayout ( event ) ;
1165+ }
1166+ viewportHeightRef . current = event . nativeEvent . layout . height ;
1167+ } ) ;
1168+
11291169 if ( ! FlatList ) {
11301170 return null ;
11311171 }
@@ -1168,6 +1208,8 @@ const MessageListWithContext = (props: MessageListPropsWithContext) => {
11681208 */
11691209 maintainVisibleContentPosition = { maintainVisibleContentPosition }
11701210 maxToRenderPerBatch = { 30 }
1211+ onContentSizeChange = { onContentSizeChange }
1212+ onLayout = { onLayout }
11711213 onMomentumScrollEnd = { onUserScrollEvent }
11721214 onScroll = { handleScroll }
11731215 onScrollBeginDrag = { onScrollBeginDrag }
0 commit comments