Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 26 additions & 0 deletions src/hooks/useDebounce.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import { useEffect, useRef } from 'react';

export function useDebounce<T extends(...args: any[]) => void>(callback: T, delay: number): T {
const timeoutRef = useRef<ReturnType<typeof setTimeout> | null>(null);

useEffect(() => {
// Cleanup the timeout on unmount
return () => {
if (timeoutRef.current) {
clearTimeout(timeoutRef.current);
}
};
}, []);

function debounceFunction(...args: Parameters<T>) {
if (timeoutRef.current) {
clearTimeout(timeoutRef.current);
}

timeoutRef.current = setTimeout(() => {
callback(...args);
}, delay);
}

return debounceFunction as T;
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
import { renderHook } from '@testing-library/react';
import { useHandleOnScrollCallback, calcScrollBottom } from '../index';

jest.useFakeTimers();

const SAFE_DELAY = 1000;

const prepareMockParams = ({
scrollTop = 0,
scrollHeight = 0,
Expand Down Expand Up @@ -39,6 +43,8 @@ describe('useHandleOnScrollCallback', () => {
const handleOnScroll = result.current;
handleOnScroll();

jest.advanceTimersByTime(SAFE_DELAY);

// assert
expect(params.setShowScrollDownButton).toHaveBeenCalledWith(true);
});
Expand All @@ -52,6 +58,8 @@ describe('useHandleOnScrollCallback', () => {
const handleOnScroll = result.current;
handleOnScroll();

jest.advanceTimersByTime(SAFE_DELAY);

// assert
expect(params.setShowScrollDownButton).toHaveBeenCalledWith(false);
expect(params.onScroll).not.toHaveBeenCalled();
Expand All @@ -67,6 +75,8 @@ describe('useHandleOnScrollCallback', () => {
const handleOnScroll = result.current;
handleOnScroll();

jest.advanceTimersByTime(SAFE_DELAY);

// assert
expect(params.onScroll).not.toHaveBeenCalled();
});
Expand Down Expand Up @@ -103,6 +113,8 @@ describe('useHandleOnScrollCallback', () => {
const handleOnScroll = result.current;
handleOnScroll();

jest.advanceTimersByTime(SAFE_DELAY);

// assert
expect(params.onScroll).toHaveBeenCalled();
expect(element.scrollTop).toEqual(newScrollHeight);
Expand Down
22 changes: 16 additions & 6 deletions src/hooks/useHandleOnScrollCallback/index.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,13 @@
import React, { useCallback } from 'react';
import { SCROLL_BUFFER } from '../../utils/consts';
import { useDebounce } from '../useDebounce';

const DELAY = 500;

export interface UseHandleOnScrollCallbackProps {
hasMore: boolean;
onScroll(fn: () => void): void;
hasNext?: boolean;
onScroll(callback: () => void): void;
scrollRef: React.RefObject<HTMLDivElement>;
setShowScrollDownButton?: React.Dispatch<React.SetStateAction<boolean>>;
}
Expand All @@ -14,11 +18,12 @@ export function calcScrollBottom(scrollHeight: number, scrollTop: number): numbe

export function useHandleOnScrollCallback({
hasMore,
hasNext,
onScroll,
scrollRef,
setShowScrollDownButton,
}: UseHandleOnScrollCallbackProps): () => void {
return useCallback(() => {
const scrollCb = useCallback(() => {
const element = scrollRef?.current;
if (element == null) {
return;
Expand All @@ -38,19 +43,24 @@ export function useHandleOnScrollCallback({
if (typeof setShowScrollDownButton === 'function') {
setShowScrollDownButton(scrollHeight > scrollTop + clientHeight + 1);
}
if (!hasMore) {
return;
}
if (scrollTop < SCROLL_BUFFER) {
if (hasMore && scrollTop < SCROLL_BUFFER) {
onScroll(() => {
// sets the scroll position to the bottom of the new messages
element.scrollTop = element.scrollHeight - scrollBottom;
});
}
if (hasNext) {
onScroll(() => {
// sets the scroll position to the top of the new messages
element.scrollTop = scrollTop - (scrollHeight - element.scrollHeight);
Comment on lines +54 to +55
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh, this is what I wanted to do 👍

});
}
}, [
setShowScrollDownButton,
hasMore,
onScroll,
scrollRef,
]);

return useDebounce(scrollCb, DELAY);
}
17 changes: 16 additions & 1 deletion src/modules/Channel/components/MessageList/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -36,11 +36,13 @@ const MessageList: React.FC<MessageListProps> = ({
const {
allMessages,
hasMorePrev,
hasMoreNext,
setInitialTimeStamp,
setAnimatedMessageId,
setHighLightedMessageId,
isMessageGroupingEnabled,
scrollRef,
onScrollCallback,
onScrollDownCallback,
messagesDispatcher,
messageActionTypes,
Expand Down Expand Up @@ -70,7 +72,19 @@ const MessageList: React.FC<MessageListProps> = ({
scrollHeight,
} = element;

if (isAboutSame(clientHeight + scrollTop, scrollHeight, SCROLL_BUFFER)) {
if (isAboutSame(scrollTop, 0, SCROLL_BUFFER)) {
onScrollCallback((messages) => {
if (messages) {
try {
//
} catch (error) {
//
}
}
});
}

if (isAboutSame(clientHeight + scrollTop, scrollHeight, SCROLL_BUFFER) && hasMoreNext) {
onScrollDownCallback(([messages]) => {
if (messages) {
try {
Expand Down Expand Up @@ -116,6 +130,7 @@ const MessageList: React.FC<MessageListProps> = ({

const handleOnScroll = useHandleOnScrollCallback({
hasMore: hasMorePrev,
hasNext: hasMoreNext,
Comment on lines 132 to +133
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you leave a comment here?
like

// TODO: rename these two props, hasMore & hasNext

Copy link
Contributor

@HoonBaek HoonBaek May 19, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nah, let's do not that for now, I can make a fix after release

onScroll,
scrollRef,
});
Expand Down