refactor: scroll to bottom while new msg coming in

This commit is contained in:
Tristan Yang
2023-03-07 22:45:16 +08:00
parent 69595bec3c
commit d9343ec795
5 changed files with 59 additions and 25 deletions
+43 -14
View File
@@ -1,8 +1,8 @@
import { useEffect, useRef } from 'react';
import { memo, useEffect, useRef } from 'react';
import { useTranslation } from 'react-i18next';
import { NavLink, useLocation } from 'react-router-dom';
import { useDebounce } from 'rooks';
import { ViewportList } from 'react-viewport-list';
import { ViewportList, ViewportListRef } from 'react-viewport-list';
import { useReadMessageMutation } from '../../../app/services/message';
import { useAppSelector } from '../../../app/store';
@@ -14,9 +14,9 @@ type Props = {
context: "user" | "channel",
id: number
}
const triggerScrollHeight = 400;
const MessageFeed = ({ context, id }: Props) => {
// const listRef = useRef<ViewportListRef | null>(null);
const listRef = useRef<ViewportListRef | null>(null);
const ref = useRef<HTMLDivElement | null>(
null,
);
@@ -41,17 +41,45 @@ const MessageFeed = ({ context, id }: Props) => {
messageData: store.message || {}
};
});
// useEffect(() => {
// // 滚动到记忆位置
// if (listRef && listRef.current) {
// listRef.current.scrollToIndex({ index: 5 });
// }
// }, [context, id]);
useEffect(() => {
// 上下文有变动,则滚动到底部
console.log("listRef", listRef);
if (listRef && listRef.current) {
const list = listRef.current;
ref.current?.classList.remove("scroll-smooth");
list.scrollToIndex({
index: Number.POSITIVE_INFINITY
});
setTimeout(() => {
// tricky
ref.current?.classList.add("scroll-smooth");
}, 150);
}
}, [context, id]);
useEffect(() => {
// 需要检测滚动位置,如果距离底部超过阈值,则不滚到底部
if (ref && ref.current) {
const container = ref.current;
const { scrollHeight, scrollTop, offsetHeight } = container;
const deltaNum = scrollHeight - scrollTop - offsetHeight;
console.log("delta", deltaNum);
if (deltaNum < triggerScrollHeight) {
// scroll to bottom
container.scrollTop = container.scrollHeight;
}
}
}, [mids]);
const handleMessageListChange = (data: [number, number]) => {
const [first, last] = data;
console.log("index changed", data);
};
const readIndex = context == "channel" ? footprint.readChannels[id] : Number.POSITIVE_INFINITY;
const isEmptyList = !mids || mids.length == 0;
return (
<article ref={ref} id={`VOCECHAT_FEED_${context}_${id}`} className="w-full h-full px-1 md:px-4 py-4.5 overflow-x-hidden overflow-y-scroll will-change-contents">
<article ref={ref} id={`VOCECHAT_FEED_${context}_${id}`} className="w-full h-full px-1 md:px-4 py-4.5 overflow-x-hidden overflow-y-scroll scroll-smooth will-change-contents">
{context == "channel" && <div className="pt-14 px-1 md:px-0 flex flex-col items-start gap-2">
<h2 className="font-bold text-4xl dark:text-white">{t("welcome_channel", { name: data?.name })}</h2>
<p className="text-gray-600 dark:text-gray-300">{t("welcome_desc", { name: data?.name })} </p>
@@ -63,11 +91,12 @@ const MessageFeed = ({ context, id }: Props) => {
)}
</div>}
{isEmptyList ? null : <ViewportList
onViewportIndexesChange={handleMessageListChange}
overscan={10}
// itemSize={100}
initialPrerender={50}
initialPrerender={30}
scrollThreshold={2000}
// ref={listRef}
ref={listRef}
viewportRef={ref}
items={mids}
>
@@ -92,4 +121,4 @@ const MessageFeed = ({ context, id }: Props) => {
);
};
export default MessageFeed;
export default memo(MessageFeed);