mirror of https://github.com/msgbyte/tailchat
refactor: 移除弃用的虚拟列表组件
parent
0793490bc6
commit
971691bc82
@ -1,185 +0,0 @@
|
|||||||
import {
|
|
||||||
DynamicSizeList,
|
|
||||||
DynamicSizeRenderInfo,
|
|
||||||
OnScrollInfo,
|
|
||||||
} from '@/components/DynamicVirtualizedList/DynamicSizeList';
|
|
||||||
import React, {
|
|
||||||
useEffect,
|
|
||||||
useLayoutEffect,
|
|
||||||
useMemo,
|
|
||||||
useRef,
|
|
||||||
useState,
|
|
||||||
} from 'react';
|
|
||||||
import AutoSizer from 'react-virtualized-auto-sizer';
|
|
||||||
import { ChatMessage, t, usePrevious, useUpdateRef } from 'tailchat-shared';
|
|
||||||
import { messageReverseItemId } from './const';
|
|
||||||
import { buildMessageItemRow } from './Item';
|
|
||||||
import type { MessageListProps } from './types';
|
|
||||||
|
|
||||||
// Reference: https://github.com/mattermost/mattermost-webapp/blob/master/components/post_view/post_list_virtualized/post_list_virtualized.jsx
|
|
||||||
|
|
||||||
const OVERSCAN_COUNT_BACKWARD = 80;
|
|
||||||
const OVERSCAN_COUNT_FORWARD = 80;
|
|
||||||
const HEIGHT_TRIGGER_FOR_MORE_POSTS = 200; // 触发加载更多的方法
|
|
||||||
|
|
||||||
const postListStyle = {
|
|
||||||
padding: '14px 0px 7px',
|
|
||||||
};
|
|
||||||
|
|
||||||
const virtListStyles: React.CSSProperties = {
|
|
||||||
position: 'absolute',
|
|
||||||
bottom: 0,
|
|
||||||
maxHeight: '100%',
|
|
||||||
};
|
|
||||||
|
|
||||||
const dynamicListStyle: React.CSSProperties = {}; // TODO
|
|
||||||
|
|
||||||
export const VirtualizedMessageList: React.FC<MessageListProps> = React.memo(
|
|
||||||
(props) => {
|
|
||||||
const listRef = useRef<DynamicSizeList>(null);
|
|
||||||
const postListRef = useRef<HTMLDivElement>(null);
|
|
||||||
const [isBottom, setIsBottom] = useState(true);
|
|
||||||
useLockScroll(props.messages, listRef);
|
|
||||||
|
|
||||||
const handleScroll = (info: OnScrollInfo) => {
|
|
||||||
const {
|
|
||||||
clientHeight,
|
|
||||||
scrollOffset,
|
|
||||||
scrollHeight,
|
|
||||||
scrollDirection,
|
|
||||||
scrollUpdateWasRequested,
|
|
||||||
} = info;
|
|
||||||
if (scrollHeight <= 0) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const didUserScrollBackwards =
|
|
||||||
scrollDirection === 'backward' && !scrollUpdateWasRequested;
|
|
||||||
const isOffsetWithInRange = scrollOffset < HEIGHT_TRIGGER_FOR_MORE_POSTS;
|
|
||||||
|
|
||||||
if (
|
|
||||||
didUserScrollBackwards &&
|
|
||||||
isOffsetWithInRange &&
|
|
||||||
!props.isLoadingMore
|
|
||||||
) {
|
|
||||||
// 加载更多历史信息
|
|
||||||
props.onLoadMore();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (clientHeight + scrollOffset === scrollHeight) {
|
|
||||||
// 当前滚动条位于底部
|
|
||||||
setIsBottom(true);
|
|
||||||
props.onUpdateReadedMessage(
|
|
||||||
props.messages[props.messages.length - 1]._id
|
|
||||||
);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const onUpdateReadedMessageRef = useUpdateRef(props.onUpdateReadedMessage);
|
|
||||||
useEffect(() => {
|
|
||||||
if (props.messages.length === 0) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (postListRef.current?.scrollTop === 0) {
|
|
||||||
// 当前列表在最低
|
|
||||||
onUpdateReadedMessageRef.current(
|
|
||||||
props.messages[props.messages.length - 1]._id
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}, [props.messages.length]);
|
|
||||||
|
|
||||||
const initScrollToIndex = () => {
|
|
||||||
return {
|
|
||||||
index: 0,
|
|
||||||
position: 'end' as const,
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 渲染列表元素
|
|
||||||
*/
|
|
||||||
const renderRow = ({ itemId }: DynamicSizeRenderInfo) => {
|
|
||||||
if (itemId === messageReverseItemId.OLDER_MESSAGES_LOADER) {
|
|
||||||
return (
|
|
||||||
<div key={itemId} className="text-center text-gray-400">
|
|
||||||
{t('加载中...')}
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
} else if (itemId === messageReverseItemId.TEXT_CHANNEL_INTRO) {
|
|
||||||
return (
|
|
||||||
<div key={itemId} className="text-center text-gray-400">
|
|
||||||
{t('到顶了')}
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
return buildMessageItemRow(props.messages, itemId);
|
|
||||||
};
|
|
||||||
|
|
||||||
// 初始渲染范围
|
|
||||||
const initRangeToRender = useMemo(() => [0, props.messages.length], []);
|
|
||||||
|
|
||||||
const itemData = useMemo(
|
|
||||||
() => [
|
|
||||||
...props.messages.map((m) => m._id).reverse(),
|
|
||||||
props.hasMoreMessage
|
|
||||||
? messageReverseItemId.OLDER_MESSAGES_LOADER
|
|
||||||
: messageReverseItemId.TEXT_CHANNEL_INTRO,
|
|
||||||
],
|
|
||||||
[props.messages, props.hasMoreMessage]
|
|
||||||
);
|
|
||||||
|
|
||||||
return (
|
|
||||||
<AutoSizer>
|
|
||||||
{({ height, width }) => (
|
|
||||||
<DynamicSizeList
|
|
||||||
ref={listRef}
|
|
||||||
height={height}
|
|
||||||
width={width}
|
|
||||||
itemData={itemData}
|
|
||||||
renderItem={renderRow}
|
|
||||||
overscanCountForward={OVERSCAN_COUNT_FORWARD}
|
|
||||||
overscanCountBackward={OVERSCAN_COUNT_BACKWARD}
|
|
||||||
onScroll={handleScroll}
|
|
||||||
initScrollToIndex={initScrollToIndex}
|
|
||||||
canLoadMorePosts={() => {}}
|
|
||||||
innerRef={postListRef}
|
|
||||||
style={{ ...virtListStyles, ...dynamicListStyle }}
|
|
||||||
innerListStyle={postListStyle}
|
|
||||||
initRangeToRender={initRangeToRender}
|
|
||||||
loaderId={messageReverseItemId.OLDER_MESSAGES_LOADER}
|
|
||||||
correctScrollToBottom={isBottom}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
</AutoSizer>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
);
|
|
||||||
VirtualizedMessageList.displayName = 'VirtualizedMessageList';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 当增加历史信息时锁定滚动条位置
|
|
||||||
*/
|
|
||||||
function useLockScroll(
|
|
||||||
messages: ChatMessage[],
|
|
||||||
listRef: React.RefObject<DynamicSizeList>
|
|
||||||
) {
|
|
||||||
const previousMessages = usePrevious(messages);
|
|
||||||
const previousScrollHeight = usePrevious(
|
|
||||||
listRef.current?._outerRef?.scrollHeight
|
|
||||||
);
|
|
||||||
useLayoutEffect(() => {
|
|
||||||
if (previousMessages && messages[0]._id !== previousMessages[0]._id) {
|
|
||||||
// 增加了历史消息
|
|
||||||
if (listRef.current?._outerRef) {
|
|
||||||
// 能够拿到容器
|
|
||||||
listRef.current.scrollTo(
|
|
||||||
listRef.current._outerRef.scrollTop +
|
|
||||||
listRef.current._outerRef.scrollHeight -
|
|
||||||
(previousScrollHeight || 0)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}, [messages.length, previousMessages?.length]);
|
|
||||||
}
|
|
Loading…
Reference in New Issue