mirror of https://github.com/msgbyte/tailchat
You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
176 lines
4.9 KiB
TypeScript
176 lines
4.9 KiB
TypeScript
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';
|
|
import {
|
|
List,
|
|
CellMeasurer,
|
|
CellMeasurerCache,
|
|
ListRowRenderer,
|
|
InfiniteLoader,
|
|
} from 'react-virtualized';
|
|
|
|
// 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<List>(null);
|
|
// const postListRef = useRef<HTMLDivElement>(null);
|
|
// const [isBottom, setIsBottom] = useState(true);
|
|
// useLockScroll(props.messages, listRef);
|
|
|
|
useEffect(() => {
|
|
listRef.current?.scrollToRow(props.messages.length - 1);
|
|
}, [props.messages]);
|
|
|
|
// 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 rowRenderer: ListRowRenderer = ({ index, key, parent, style }) => {
|
|
// if (key === messageReverseItemId.OLDER_MESSAGES_LOADER) {
|
|
// return (
|
|
// <div key={key} className="text-center text-gray-400">
|
|
// {t('加载中...')}
|
|
// </div>
|
|
// );
|
|
// } else if (key === messageReverseItemId.TEXT_CHANNEL_INTRO) {
|
|
// return (
|
|
// <div key={key} className="text-center text-gray-400">
|
|
// {t('到顶了')}
|
|
// </div>
|
|
// );
|
|
// }
|
|
|
|
return (
|
|
<CellMeasurer
|
|
cache={measurerCache}
|
|
columnIndex={0}
|
|
key={key}
|
|
rowIndex={index}
|
|
parent={parent}
|
|
>
|
|
{({ measure, registerChild }) => (
|
|
<div
|
|
ref={(el) => el && registerChild && registerChild(el)}
|
|
onLoad={measure}
|
|
style={style}
|
|
>
|
|
{buildMessageItemRow(props.messages, props.messages[index]._id)}
|
|
{/* {buildMessageItemRow(props.messages, key)} */}
|
|
</div>
|
|
)}
|
|
</CellMeasurer>
|
|
);
|
|
};
|
|
// const itemData = useMemo(
|
|
// () => [
|
|
// ...props.messages.map((m) => m._id).reverse(),
|
|
// props.hasMoreMessage
|
|
// ? messageReverseItemId.OLDER_MESSAGES_LOADER
|
|
// : messageReverseItemId.TEXT_CHANNEL_INTRO,
|
|
// ],
|
|
// [props.messages, props.hasMoreMessage]
|
|
// );
|
|
|
|
const measurerCache = useMemo(
|
|
() =>
|
|
new CellMeasurerCache({
|
|
fixedWidth: true,
|
|
minHeight: 24,
|
|
}),
|
|
[]
|
|
);
|
|
|
|
return (
|
|
<AutoSizer>
|
|
{({ height, width }) => (
|
|
<List
|
|
ref={listRef}
|
|
height={height}
|
|
width={width}
|
|
overscanRowCount={0}
|
|
rowCount={props.messages.length}
|
|
deferredMeasurementCache={measurerCache}
|
|
rowHeight={measurerCache.rowHeight}
|
|
rowRenderer={rowRenderer}
|
|
onRowsRendered={({ startIndex }) => console.log(startIndex)}
|
|
scrollToIndex={props.messages.length - 1}
|
|
scrollToAlignment="end"
|
|
/>
|
|
)}
|
|
</AutoSizer>
|
|
);
|
|
}
|
|
);
|
|
VirtualizedMessageList.displayName = 'VirtualizedMessageList';
|