1- import React , { useCallback } from 'react' ;
1+ import React from 'react' ;
22import { SCROLL_BUFFER } from '../../utils/consts' ;
3- import { useDebounce } from '../useDebounce' ;
3+ import { useThrottleCallback } from '../useThrottleCallback' ;
4+ import { isAboutSame } from '../../modules/Channel/context/utils' ;
5+ import { usePreservedCallback } from '@sendbird/uikit-tools' ;
46
5- const DELAY = 500 ;
7+ const DELAY = 100 ;
68
79export interface UseHandleOnScrollCallbackProps {
810 hasMore : boolean ;
@@ -13,7 +15,10 @@ export interface UseHandleOnScrollCallbackProps {
1315 setIsScrolled ?: React . Dispatch < React . SetStateAction < boolean > > ;
1416}
1517
16- export function calcScrollBottom ( scrollHeight : number , scrollTop : number ) : number {
18+ export function calcScrollBottom (
19+ scrollHeight : number ,
20+ scrollTop : number ,
21+ ) : number {
1722 return scrollHeight - scrollTop ;
1823}
1924
@@ -24,17 +29,11 @@ export function useHandleOnScrollCallback({
2429 scrollRef,
2530 setShowScrollDownButton,
2631} : UseHandleOnScrollCallbackProps ) : ( ) => void {
27- const scrollCb = useCallback ( ( ) => {
28- const element = scrollRef ?. current ;
29- if ( element == null ) {
30- return ;
31- }
3232
33- const {
34- scrollTop,
35- scrollHeight,
36- clientHeight,
37- } = element ;
33+ const scrollCb = usePreservedCallback ( ( ) => {
34+ const element = scrollRef ?. current ;
35+ if ( element == null ) return ;
36+ const { scrollTop, scrollHeight, clientHeight } = element ;
3837 // https://sendbird.atlassian.net/browse/SBISSUE-11759
3938 // the edge case where channel is inside a page that already has scroll
4039 // scrollintoView will move the whole page, which we dont want
@@ -44,24 +43,29 @@ export function useHandleOnScrollCallback({
4443 if ( typeof setShowScrollDownButton === 'function' ) {
4544 setShowScrollDownButton ( scrollHeight > scrollTop + clientHeight + 1 ) ;
4645 }
47- if ( hasMore && scrollTop < SCROLL_BUFFER ) {
46+
47+ // Load previous messages
48+ // 1. check if hasMore(hasPrevious) and reached to top
49+ // 2. load previous messages (onScroll)
50+ // 3. maintain scroll position (sets the scroll position to the bottom of the new messages)
51+ if ( hasMore && isAboutSame ( scrollTop , 0 , SCROLL_BUFFER ) ) {
4852 onScroll ( ( ) => {
49- // sets the scroll position to the bottom of the new messages
50- element . scrollTop = element . scrollHeight - scrollBottom ;
53+ const messagesAreAddedToView = element . scrollHeight > scrollHeight ;
54+ if ( messagesAreAddedToView ) element . scrollTop = element . scrollHeight - scrollBottom ;
5155 } ) ;
5256 }
53- if ( hasNext ) {
57+
58+ // Load next messages
59+ // 1. check if hasNext and reached to bottom
60+ // 2. load next messages (onScroll)
61+ // 3. maintain scroll position (sets the scroll position to the top of the new messages)
62+ if ( hasNext && isAboutSame ( clientHeight + scrollTop , scrollHeight , SCROLL_BUFFER ) ) {
5463 onScroll ( ( ) => {
55- // sets the scroll position to the top of the new messages
56- element . scrollTop = scrollTop - ( scrollHeight - element . scrollHeight ) ;
64+ const messagesAreAddedToView = element . scrollHeight > scrollHeight ;
65+ if ( messagesAreAddedToView ) element . scrollTop = scrollTop ;
5766 } ) ;
5867 }
59- } , [
60- setShowScrollDownButton ,
61- hasMore ,
62- onScroll ,
63- scrollRef ,
64- ] ) ;
68+ } ) ;
6569
66- return useDebounce ( scrollCb , DELAY ) ;
70+ return useThrottleCallback ( scrollCb , DELAY , { trailing : true } ) ;
6771}
0 commit comments