diff --git a/shared/index.tsx b/shared/index.tsx index 6fa5b32d..c1b63e70 100644 --- a/shared/index.tsx +++ b/shared/index.tsx @@ -71,5 +71,10 @@ export { createStore } from './redux/store'; export type { AppStore, AppDispatch } from './redux/store'; // utils -export { getTextColorHex } from './utils/string-helper'; +export { + shouldShowMessageTime, + getMessageTimeDiff, + formatShortTime, +} from './utils/date-helper'; export { isBrowser, isNavigator } from './utils/environment'; +export { getTextColorHex } from './utils/string-helper'; diff --git a/shared/utils/date-helper.ts b/shared/utils/date-helper.ts index bca659df..5ca0eaf4 100644 --- a/shared/utils/date-helper.ts +++ b/shared/utils/date-helper.ts @@ -12,7 +12,7 @@ dayjs.locale('zh-cn'); /** * 是否为当天 */ -export function isToday(date: Date): boolean { +export function isToday(date: dayjs.ConfigType): boolean { return dayjs(date).isSame(dayjs(), 'd'); } @@ -22,9 +22,24 @@ export function isToday(date: Date): boolean { export function getMessageTimeDiff(input: Date): string { const date = dayjs(input); - if (isToday(input)) { + if (isToday(date)) { return date.fromNow(); } else { return date.format('YYYY-MM-DD HH:mm:ss'); } } + +/** + * 是否应该显示消息时间 + * 间隔时间大于十五分钟则显示 + */ +export function shouldShowMessageTime(date1: Date, date2: Date): boolean { + return Math.abs(date1.valueOf() - date2.valueOf()) > 15 * 60 * 1000; +} + +/** + * 格式化为 小时:分钟 + */ +export function formatShortTime(date: dayjs.ConfigType): string { + return dayjs(date).format('HH:mm'); +} diff --git a/web/src/components/ChatBox/ChatMessageList/Item.tsx b/web/src/components/ChatBox/ChatMessageList/Item.tsx index 1a83e555..f440dec7 100644 --- a/web/src/components/ChatBox/ChatMessageList/Item.tsx +++ b/web/src/components/ChatBox/ChatMessageList/Item.tsx @@ -1,5 +1,11 @@ import React from 'react'; -import { ChatMessage, useCachedUserInfo } from 'pawchat-shared'; +import { + ChatMessage, + formatShortTime, + useCachedUserInfo, +} from 'pawchat-shared'; +import { Avatar } from '@/components/Avatar'; +import clsx from 'clsx'; interface ChatMessageItemProps { showAvatar: boolean; @@ -11,8 +17,23 @@ export const ChatMessageItem: React.FC = React.memo( const userInfo = useCachedUserInfo(payload.author ?? ''); return ( -
- {userInfo.nickname}: {payload.content} +
+
+ {showAvatar ? ( + + ) : ( +
+ {formatShortTime(payload.createdAt)} +
+ )} +
+
+ {showAvatar &&
{userInfo.nickname}
} + +
{payload.content}
+
); } diff --git a/web/src/components/ChatBox/ChatMessageList/index.tsx b/web/src/components/ChatBox/ChatMessageList/index.tsx index 62a6625a..3093157c 100644 --- a/web/src/components/ChatBox/ChatMessageList/index.tsx +++ b/web/src/components/ChatBox/ChatMessageList/index.tsx @@ -1,6 +1,11 @@ import React from 'react'; -import type { ChatMessage } from 'pawchat-shared'; +import { + ChatMessage, + getMessageTimeDiff, + shouldShowMessageTime, +} from 'pawchat-shared'; import { ChatMessageItem } from './Item'; +import { Divider } from 'antd'; interface ChatMessageListProps { messages: ChatMessage[]; @@ -9,13 +14,41 @@ export const ChatMessageList: React.FC = React.memo( (props) => { return (
- {props.messages.map((message) => ( - - ))} + {props.messages.map((message, index, arr) => { + let showDate = true; + let showAvatar = true; + const messageCreatedAt = new Date(message.createdAt ?? ''); + if (index > 0) { + // 当不是第一条数据时 + + // 进行时间合并 + const prevMessage = arr[index - 1]; + if ( + !shouldShowMessageTime( + new Date(prevMessage.createdAt ?? ''), + messageCreatedAt + ) + ) { + showDate = false; + } + + // 进行头像合并(在同一时间块下) + if (showDate === false) { + showAvatar = prevMessage.author !== message.author; + } + } + + return ( +
+ {showDate && ( + + {getMessageTimeDiff(messageCreatedAt)} + + )} + +
+ ); + })}
); }