diff --git a/web/src/components/ChatBox/ChatMessageList/Item.tsx b/web/src/components/ChatBox/ChatMessageList/Item.tsx index a61c547b..227adcfc 100644 --- a/web/src/components/ChatBox/ChatMessageList/Item.tsx +++ b/web/src/components/ChatBox/ChatMessageList/Item.tsx @@ -2,6 +2,8 @@ import React, { useMemo } from 'react'; import { ChatMessage, formatShortTime, + getMessageTimeDiff, + shouldShowMessageTime, SYSTEM_USERID, t, useCachedUserInfo, @@ -11,7 +13,7 @@ import { Avatar } from '@/components/Avatar'; import { useRenderPluginMessageInterpreter } from './useRenderPluginMessageInterpreter'; import { getMessageRender } from '@/plugin/common'; import { Icon } from '@iconify/react'; -import { Dropdown, Menu } from 'antd'; +import { Divider, Dropdown, Menu } from 'antd'; import { MessageHelper } from 'tailchat-shared'; import { UserName } from '@/components/UserName'; import './item.less'; @@ -128,13 +130,64 @@ interface ChatMessageItemProps { showAvatar: boolean; payload: ChatMessage; } -export const ChatMessageItem: React.FC = React.memo( - (props) => { - if (props.payload.author === SYSTEM_USERID) { - return ; +const ChatMessageItem: React.FC = React.memo((props) => { + if (props.payload.author === SYSTEM_USERID) { + return ; + } + + return ; +}); +ChatMessageItem.displayName = 'ChatMessageItem'; + +function findMessageIndexWithId( + messages: ChatMessage[], + messageId: string +): number { + return messages.findIndex((m) => m._id === messageId); +} + +/** + * 构造聊天项 + */ +export function buildItemRow(messages: ChatMessage[], messageId: string) { + const index = findMessageIndexWithId(messages, messageId); // TODO: 这里是因为mattermost的动态列表传的id因此只能这边再用id找回,可以看看是否可以优化 + if (index === -1) { + return
; + } + + const message = messages[index]; + + let showDate = true; + let showAvatar = true; + const messageCreatedAt = new Date(message.createdAt ?? ''); + if (index > 0) { + // 当不是第一条数据时 + + // 进行时间合并 + const prevMessage = messages[index - 1]; + if ( + !shouldShowMessageTime( + new Date(prevMessage.createdAt ?? ''), + messageCreatedAt + ) + ) { + showDate = false; } - return ; + // 进行头像合并(在同一时间块下 且发送者为同一人) + if (showDate === false) { + showAvatar = prevMessage.author !== message.author; + } } -); -ChatMessageItem.displayName = 'ChatMessageItem'; + + return ( +
+ {showDate && ( + + {getMessageTimeDiff(messageCreatedAt)} + + )} + +
+ ); +} diff --git a/web/src/components/ChatBox/ChatMessageList/VirtualizedList.tsx b/web/src/components/ChatBox/ChatMessageList/VirtualizedList.tsx index c216a55d..5ae0f8cc 100644 --- a/web/src/components/ChatBox/ChatMessageList/VirtualizedList.tsx +++ b/web/src/components/ChatBox/ChatMessageList/VirtualizedList.tsx @@ -3,7 +3,6 @@ import { DynamicSizeRenderInfo, OnScrollInfo, } from '@/components/DynamicVirtualizedList/DynamicSizeList'; -import { Divider } from 'antd'; import React, { useEffect, useLayoutEffect, @@ -12,16 +11,10 @@ import React, { useState, } from 'react'; import AutoSizer from 'react-virtualized-auto-sizer'; -import { - ChatMessage, - getMessageTimeDiff, - shouldShowMessageTime, - t, - usePrevious, - useUpdateRef, -} from 'tailchat-shared'; +import { ChatMessage, t, usePrevious, useUpdateRef } from 'tailchat-shared'; import { messageReverseItemId } from './const'; -import { ChatMessageItem } from './Item'; +import { buildItemRow } 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 @@ -41,22 +34,8 @@ const virtListStyles: React.CSSProperties = { const dynamicListStyle: React.CSSProperties = {}; // TODO -function findMessageIndexWithId( - messages: ChatMessage[], - messageId: string -): number { - return messages.findIndex((m) => m._id === messageId); -} - -export interface VirtualizedMessageListProps { - messages: ChatMessage[]; - isLoadingMore: boolean; - hasMoreMessage: boolean; - onUpdateReadedMessage: (lastMessageId: string) => void; - onLoadMore: () => void; -} -export const VirtualizedMessageList: React.FC = - React.memo((props) => { +export const VirtualizedMessageList: React.FC = React.memo( + (props) => { const listRef = useRef(null); const postListRef = useRef(null); const [isBottom, setIsBottom] = useState(true); @@ -135,47 +114,7 @@ export const VirtualizedMessageList: React.FC = ); } - const messages = props.messages; - const index = findMessageIndexWithId(messages, itemId); // TODO: 这里是因为mattermost的动态列表传的id因此只能这边再用id找回,可以看看是否可以优化 - if (index === -1) { - return
; - } - - const message = messages[index]; - - let showDate = true; - let showAvatar = true; - const messageCreatedAt = new Date(message.createdAt ?? ''); - if (index > 0) { - // 当不是第一条数据时 - - // 进行时间合并 - const prevMessage = messages[index - 1]; - if ( - !shouldShowMessageTime( - new Date(prevMessage.createdAt ?? ''), - messageCreatedAt - ) - ) { - showDate = false; - } - - // 进行头像合并(在同一时间块下 且发送者为同一人) - if (showDate === false) { - showAvatar = prevMessage.author !== message.author; - } - } - - return ( -
- {showDate && ( - - {getMessageTimeDiff(messageCreatedAt)} - - )} - -
- ); + return buildItemRow(props.messages, itemId); }; // 初始渲染范围 @@ -215,7 +154,8 @@ export const VirtualizedMessageList: React.FC = )} ); - }); + } +); VirtualizedMessageList.displayName = 'VirtualizedMessageList'; /** diff --git a/web/src/components/ChatBox/ChatMessageList/index.tsx b/web/src/components/ChatBox/ChatMessageList/index.tsx index 0a39e868..1dc9ad70 100644 --- a/web/src/components/ChatBox/ChatMessageList/index.tsx +++ b/web/src/components/ChatBox/ChatMessageList/index.tsx @@ -1,15 +1,14 @@ import React from 'react'; -import { - VirtualizedMessageList, - VirtualizedMessageListProps, -} from './VirtualizedList'; +import type { MessageListProps } from './types'; +import { VirtualizedMessageList } from './VirtualizedList'; -export const ChatMessageList: React.FC = - React.memo((props) => { +export const ChatMessageList: React.FC = React.memo( + (props) => { return (
); - }); + } +); ChatMessageList.displayName = 'ChatMessageList'; diff --git a/web/src/components/ChatBox/ChatMessageList/types.ts b/web/src/components/ChatBox/ChatMessageList/types.ts new file mode 100644 index 00000000..bce18d78 --- /dev/null +++ b/web/src/components/ChatBox/ChatMessageList/types.ts @@ -0,0 +1,9 @@ +import type { ChatMessage } from 'tailchat-shared'; + +export interface MessageListProps { + messages: ChatMessage[]; + isLoadingMore: boolean; + hasMoreMessage: boolean; + onUpdateReadedMessage: (lastMessageId: string) => void; + onLoadMore: () => void; +}