|
|
|
@ -0,0 +1,140 @@
|
|
|
|
|
import DynamicSizeList from '@/components/DynamicVirtualizedList/DynamicSizeList';
|
|
|
|
|
import { Divider } from 'antd';
|
|
|
|
|
import React, { useRef } from 'react';
|
|
|
|
|
import AutoSizer from 'react-virtualized-auto-sizer';
|
|
|
|
|
import {
|
|
|
|
|
ChatMessage,
|
|
|
|
|
getMessageTimeDiff,
|
|
|
|
|
shouldShowMessageTime,
|
|
|
|
|
} from 'tailchat-shared';
|
|
|
|
|
import { ChatMessageItem } from './Item';
|
|
|
|
|
|
|
|
|
|
// 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 postListStyle = {
|
|
|
|
|
padding: '14px 0px 7px',
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
const virtListStyles: React.CSSProperties = {
|
|
|
|
|
position: 'absolute',
|
|
|
|
|
bottom: 0,
|
|
|
|
|
maxHeight: '100%',
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
const dynamicListStyle: React.CSSProperties = {}; // TODO
|
|
|
|
|
|
|
|
|
|
interface VirtualizedMessageListProps {
|
|
|
|
|
messages: ChatMessage[];
|
|
|
|
|
}
|
|
|
|
|
export const VirtualizedMessageList: React.FC<VirtualizedMessageListProps> =
|
|
|
|
|
React.memo((props) => {
|
|
|
|
|
const listRef = useRef<DynamicSizeList>(null);
|
|
|
|
|
const postListRef = useRef<any>(null);
|
|
|
|
|
|
|
|
|
|
const onScroll = (info: any) => {
|
|
|
|
|
console.log('onScroll', info);
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
const initScrollToIndex = () => {
|
|
|
|
|
return {
|
|
|
|
|
index: 0,
|
|
|
|
|
position: 'end',
|
|
|
|
|
};
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
const onItemsRendered = ({ visibleStartIndex }: any) => {
|
|
|
|
|
// this.updateFloatingTimestamp(visibleStartIndex);
|
|
|
|
|
console.log('visibleStartIndex', visibleStartIndex);
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
const scrollToFailed = (index: number) => {
|
|
|
|
|
console.log('scrollToFailed', index);
|
|
|
|
|
// if (index === 0) {
|
|
|
|
|
// this.props.actions.changeUnreadChunkTimeStamp('');
|
|
|
|
|
// } else {
|
|
|
|
|
// this.props.actions.changeUnreadChunkTimeStamp(this.props.lastViewedAt);
|
|
|
|
|
// }
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
const renderRow = ({ data, itemId, style }: any) => {
|
|
|
|
|
const index = data.indexOf(itemId);
|
|
|
|
|
const message = props.messages.find((m) => m._id === itemId); // TODO: 这里是因为mattermost的动态列表传的id因此只能这边再用id找回,可以看看是否可以优化
|
|
|
|
|
|
|
|
|
|
if (!message) {
|
|
|
|
|
return <div />;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
let showDate = true;
|
|
|
|
|
let showAvatar = true;
|
|
|
|
|
const messageCreatedAt = new Date(message.createdAt ?? '');
|
|
|
|
|
if (index > 0) {
|
|
|
|
|
// 当不是第一条数据时
|
|
|
|
|
|
|
|
|
|
// 进行时间合并
|
|
|
|
|
const prevMessage = data[index - 1];
|
|
|
|
|
if (
|
|
|
|
|
!shouldShowMessageTime(
|
|
|
|
|
new Date(prevMessage.createdAt ?? ''),
|
|
|
|
|
messageCreatedAt
|
|
|
|
|
)
|
|
|
|
|
) {
|
|
|
|
|
showDate = false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 进行头像合并(在同一时间块下 且发送者为同一人)
|
|
|
|
|
if (showDate === false) {
|
|
|
|
|
showAvatar = prevMessage.author !== message.author;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return (
|
|
|
|
|
<div key={message._id}>
|
|
|
|
|
{showDate && (
|
|
|
|
|
<Divider className="text-sm opacity-40 px-6 font-normal select-none">
|
|
|
|
|
{getMessageTimeDiff(messageCreatedAt)}
|
|
|
|
|
</Divider>
|
|
|
|
|
)}
|
|
|
|
|
<ChatMessageItem showAvatar={showAvatar} payload={message} />
|
|
|
|
|
</div>
|
|
|
|
|
);
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// 初始渲染范围
|
|
|
|
|
const initRangeToRender = [
|
|
|
|
|
props.messages.length - 50,
|
|
|
|
|
props.messages.length - 1,
|
|
|
|
|
];
|
|
|
|
|
|
|
|
|
|
return (
|
|
|
|
|
<AutoSizer>
|
|
|
|
|
{({ height, width }) => (
|
|
|
|
|
<DynamicSizeList
|
|
|
|
|
ref={listRef}
|
|
|
|
|
height={height}
|
|
|
|
|
width={width}
|
|
|
|
|
className="post-list__dynamic"
|
|
|
|
|
itemData={props.messages.map((m) => m._id)}
|
|
|
|
|
overscanCountForward={OVERSCAN_COUNT_FORWARD}
|
|
|
|
|
overscanCountBackward={OVERSCAN_COUNT_BACKWARD}
|
|
|
|
|
onScroll={onScroll}
|
|
|
|
|
initScrollToIndex={initScrollToIndex}
|
|
|
|
|
canLoadMorePosts={() => {}}
|
|
|
|
|
innerRef={postListRef}
|
|
|
|
|
style={{ ...virtListStyles, ...dynamicListStyle }}
|
|
|
|
|
innerListStyle={postListStyle}
|
|
|
|
|
initRangeToRender={initRangeToRender}
|
|
|
|
|
// loaderId={PostListRowListIds.OLDER_MESSAGES_LOADER}
|
|
|
|
|
// correctScrollToBottom={this.props.atLatestPost}
|
|
|
|
|
onItemsRendered={onItemsRendered}
|
|
|
|
|
scrollToFailed={scrollToFailed}
|
|
|
|
|
>
|
|
|
|
|
{renderRow}
|
|
|
|
|
</DynamicSizeList>
|
|
|
|
|
)}
|
|
|
|
|
</AutoSizer>
|
|
|
|
|
);
|
|
|
|
|
});
|
|
|
|
|
VirtualizedMessageList.displayName = 'VirtualizedMessageList';
|