Skip to content

Commit f962540

Browse files
committed
fiX: message list scroll settime outs
1 parent 850b2da commit f962540

File tree

2 files changed

+48
-38
lines changed

2 files changed

+48
-38
lines changed

package/src/components/Channel/Channel.tsx

Lines changed: 14 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -806,6 +806,7 @@ const ChannelWithContext = <
806806
let listener: ReturnType<typeof channel.on>;
807807
const initChannel = async () => {
808808
setLastRead(new Date());
809+
const unreadCount = channel.countUnread();
809810
if (!channel || !shouldSyncChannel || channel.offlineMode) return;
810811
let errored = false;
811812

@@ -835,18 +836,22 @@ const ChannelWithContext = <
835836
} else if (
836837
initialScrollToFirstUnreadMessage &&
837838
client.user &&
838-
channel.countUnread() > scrollToFirstUnreadThreshold
839+
unreadCount > scrollToFirstUnreadThreshold
839840
) {
840-
// eslint-disable-next-line @typescript-eslint/no-unused-vars
841-
const { user, ...ownReadState } = channel.state.read[client.user.id];
842-
await loadChannelAtFirstUnreadMessage({
843-
channelUnreadState: ownReadState,
844-
setChannelUnreadState,
845-
setTargetedMessage,
846-
});
841+
try {
842+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
843+
const { user, ...ownReadState } = channel.state.read[client.user.id];
844+
await loadChannelAtFirstUnreadMessage({
845+
channelUnreadState: ownReadState,
846+
setChannelUnreadState,
847+
setTargetedMessage,
848+
});
849+
} catch (error) {
850+
console.warn('Error loading channel at first unread message:', error);
851+
}
847852
}
848853

849-
if (channel.countUnread() > 0 && markReadOnMount) {
854+
if (unreadCount > 0 && markReadOnMount) {
850855
await markRead({ updateChannelUnreadState: false });
851856
}
852857

package/src/components/MessageList/MessageList.tsx

Lines changed: 34 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,9 @@ import { ThreadContextValue, useThreadContext } from '../../contexts/threadConte
5555

5656
import { DefaultStreamChatGenerics, FileTypes } from '../../types/types';
5757

58-
const WAIT_FOR_SCROLL_TIMEOUT = 150;
58+
// This is just to make sure that the scrolling happens in a different task queue.
59+
// TODO: Think if we really need this and strive to remove it if we can.
60+
const WAIT_FOR_SCROLL_TIMEOUT = 0;
5961
const MAX_RETRIES_AFTER_SCROLL_FAILURE = 10;
6062
const styles = StyleSheet.create({
6163
container: {
@@ -579,6 +581,34 @@ const MessageListWithContext = <
579581
// eslint-disable-next-line react-hooks/exhaustive-deps
580582
}, [rawMessageList, threadList]);
581583

584+
const goToMessage = async (messageId: string) => {
585+
const indexOfParentInMessageList = processedMessageList.findIndex(
586+
(message) => message?.id === messageId,
587+
);
588+
try {
589+
if (indexOfParentInMessageList === -1) {
590+
await loadChannelAroundMessage({ messageId });
591+
return;
592+
} else {
593+
if (!flatListRef.current) return;
594+
clearTimeout(failScrollTimeoutId.current);
595+
scrollToIndexFailedRetryCountRef.current = 0;
596+
// keep track of this messageId, so that we dont scroll to again in useEffect for targeted message change
597+
messageIdLastScrolledToRef.current = messageId;
598+
setTargetedMessage(messageId);
599+
// now scroll to it with animated=true
600+
flatListRef.current.scrollToIndex({
601+
animated: true,
602+
index: indexOfParentInMessageList,
603+
viewPosition: 0.5, // try to place message in the center of the screen
604+
});
605+
return;
606+
}
607+
} catch (e) {
608+
console.warn('Error while scrolling to message', e);
609+
}
610+
};
611+
582612
/**
583613
* Check if a messageId needs to be scrolled to after list loads, and scroll to it
584614
* Note: This effect fires on every list change with a small debounce so that scrolling isnt abrupted by an immediate rerender
@@ -602,7 +632,7 @@ const MessageListWithContext = <
602632
scrollToIndexFailedRetryCountRef.current = 0;
603633
// now scroll to it
604634
flatListRef.current.scrollToIndex({
605-
animated: false,
635+
animated: true,
606636
index: indexOfParentInMessageList,
607637
viewPosition: 0.5, // try to place message in the center of the screen
608638
});
@@ -841,6 +871,7 @@ const MessageListWithContext = <
841871
await reloadChannel();
842872
} else if (flatListRef.current) {
843873
flatListRef.current.scrollToOffset({
874+
animated: true,
844875
offset: 0,
845876
});
846877
}
@@ -856,16 +887,12 @@ const MessageListWithContext = <
856887
// We got a failure as we tried to scroll to an item that was outside the render length
857888
if (!flatListRef.current) return;
858889
// we don't know the actual size of all items but we can see the average, so scroll to the closest offset
859-
flatListRef.current.scrollToOffset({
860-
animated: false,
861-
offset: info.averageItemLength * info.index,
862-
});
863890
// since we used only an average offset... we won't go to the center of the item yet
864891
// with a little delay to wait for scroll to offset to complete, we can then scroll to the index
865892
failScrollTimeoutId.current = setTimeout(() => {
866893
try {
867894
flatListRef.current?.scrollToIndex({
868-
animated: false,
895+
animated: true,
869896
index: info.index,
870897
viewPosition: 0.5, // try to place message in the center of the screen
871898
});
@@ -896,28 +923,6 @@ const MessageListWithContext = <
896923
// this onScrollToIndexFailed will be called again
897924
});
898925

899-
const goToMessage = async (messageId: string) => {
900-
const indexOfParentInMessageList = processedMessageList.findIndex(
901-
(message) => message?.id === messageId,
902-
);
903-
if (indexOfParentInMessageList !== -1 && flatListRef.current) {
904-
clearTimeout(failScrollTimeoutId.current);
905-
scrollToIndexFailedRetryCountRef.current = 0;
906-
// keep track of this messageId, so that we dont scroll to again in useEffect for targeted message change
907-
messageIdLastScrolledToRef.current = messageId;
908-
setTargetedMessage(messageId);
909-
// now scroll to it with animated=true (in useEffect animated=false is used)
910-
flatListRef.current.scrollToIndex({
911-
animated: true,
912-
index: indexOfParentInMessageList,
913-
viewPosition: 0.5, // try to place message in the center of the screen
914-
});
915-
return;
916-
}
917-
// the message we want was not loaded yet, so lets load it
918-
await loadChannelAroundMessage({ messageId });
919-
};
920-
921926
const messagesWithImages =
922927
legacyImageViewerSwipeBehaviour &&
923928
processedMessageList.filter((message) => {

0 commit comments

Comments
 (0)