Skip to content

Commit b51f846

Browse files
authored
fix: show UnreadMessagesNotification when MessageList is scrolled to bottom via Element.scrollTo (#2261)
1 parent 5dfa493 commit b51f846

File tree

3 files changed

+29
-10
lines changed

3 files changed

+29
-10
lines changed

src/components/MessageList/MessageList.tsx

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -94,10 +94,6 @@ const MessageListWithContext = <
9494
const loadMoreScrollThreshold = internalInfiniteScrollProps?.threshold || 250;
9595
const currentUserChannelReadState = client.user && read?.[client.user.id];
9696

97-
const { show: showUnreadMessagesNotification } = useUnreadMessagesNotification({
98-
unreadCount: currentUserChannelReadState?.unread_messages,
99-
});
100-
10197
const {
10298
hasNewMessages,
10399
isMessageListScrolledToBottom,
@@ -113,6 +109,11 @@ const MessageListWithContext = <
113109
suppressAutoscroll,
114110
});
115111

112+
const { show: showUnreadMessagesNotification } = useUnreadMessagesNotification({
113+
isMessageListScrolledToBottom,
114+
unreadCount: currentUserChannelReadState?.unread_messages,
115+
});
116+
116117
useMarkRead({
117118
isMessageListScrolledToBottom,
118119
markReadOnScrolledToBottom,

src/components/MessageList/hooks/MessageList/useScrollLocationLogic.tsx

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,14 +37,12 @@ export const useScrollLocationLogic = <
3737
const [isMessageListScrolledToBottom, setIsMessageListScrolledToBottom] = useState(true);
3838
const closeToBottom = useRef(false);
3939
const closeToTop = useRef(false);
40-
const scrollCounter = useRef({ autoScroll: 0, scroll: 0 });
4140

4241
const scrollToBottom = useCallback(() => {
4342
if (!listElement?.scrollTo || hasMoreNewer || suppressAutoscroll) {
4443
return;
4544
}
4645

47-
scrollCounter.current.autoScroll += 1;
4846
listElement.scrollTo({
4947
top: listElement.scrollHeight,
5048
});

src/components/MessageList/hooks/MessageList/useUnreadMessagesNotification.ts

Lines changed: 24 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { useChannelStateContext } from '../../../../context';
2-
import { useEffect, useState } from 'react';
2+
import { useEffect, useRef, useState } from 'react';
33
import { MESSAGE_LIST_MAIN_PANEL_CLASS } from '../../MessageListMainPanel';
44
import { UNREAD_MESSAGE_SEPARATOR_CLASS } from '../../UnreadMessagesSeparator';
55

@@ -10,14 +10,17 @@ const targetIsVisibleInContainer = (element: Element, container: Element) => {
1010
};
1111

1212
export type UseUnreadMessagesNotificationParams = {
13+
isMessageListScrolledToBottom: boolean;
1314
unreadCount?: number;
1415
};
1516

1617
export const useUnreadMessagesNotification = ({
18+
isMessageListScrolledToBottom,
1719
unreadCount,
1820
}: UseUnreadMessagesNotificationParams) => {
1921
const { messages } = useChannelStateContext('UnreadMessagesNotification');
2022
const [show, setShow] = useState(false);
23+
const isScrolledAboveTargetTop = useRef(false);
2124
const intersectionObserverIsSupported = typeof IntersectionObserver !== 'undefined';
2225

2326
useEffect(() => {
@@ -41,9 +44,13 @@ export const useUnreadMessagesNotification = ({
4144
(elements) => {
4245
if (!elements.length) return;
4346
const { boundingClientRect, isIntersecting, rootBounds } = elements[0];
44-
const isScrolledAboveTargetTop =
45-
rootBounds && boundingClientRect && rootBounds.bottom < boundingClientRect.top;
46-
setShow(!isIntersecting && !isScrolledAboveTargetTop);
47+
const isScrolledAboveTargetTopCurrent = !!(
48+
rootBounds &&
49+
boundingClientRect &&
50+
rootBounds.bottom < boundingClientRect.top
51+
);
52+
setShow(!isIntersecting && !isScrolledAboveTargetTopCurrent);
53+
isScrolledAboveTargetTop.current = isScrolledAboveTargetTopCurrent;
4754
},
4855
{ root: msgListPanel },
4956
);
@@ -54,5 +61,18 @@ export const useUnreadMessagesNotification = ({
5461
};
5562
}, [intersectionObserverIsSupported, messages, unreadCount]);
5663

64+
useEffect(() => {
65+
/**
66+
* Handle situation when scrollToBottom is called from another component when the msg list is scrolled above the observed target (unread separator).
67+
* The intersection observer is not triggered when Element.scrollTo() is called. So we end up in a situation when we are scrolled to the bottom
68+
* and at the same time scrolled above the observed target.
69+
*/
70+
71+
if (unreadCount && isMessageListScrolledToBottom && isScrolledAboveTargetTop.current) {
72+
setShow(true);
73+
isScrolledAboveTargetTop.current = false;
74+
}
75+
}, [isMessageListScrolledToBottom, unreadCount]);
76+
5777
return { show: show && intersectionObserverIsSupported };
5878
};

0 commit comments

Comments
 (0)