diff --git a/shared/cache/useCache.ts b/shared/cache/useCache.ts index b13abc11..f515ab61 100644 --- a/shared/cache/useCache.ts +++ b/shared/cache/useCache.ts @@ -10,7 +10,7 @@ import { isValidStr } from '../utils/string-helper'; * 用户缓存 */ export function useCachedUserInfo( - userId: string, + userId: string | null, refetch = false ): UserBaseInfo | Record { const { data } = useQuery( diff --git a/shared/index.tsx b/shared/index.tsx index f53023f4..6fa5b32d 100644 --- a/shared/index.tsx +++ b/shared/index.tsx @@ -61,8 +61,11 @@ export { // redux export { useAppSelector, useAppDispatch } from './redux/hooks/useAppSelector'; +export { useDMConverseList } from './redux/hooks/useConverse'; export { useConverseMessage } from './redux/hooks/useConverseMessage'; +export { useUserId } from './redux/hooks/useUserInfo'; export { userActions } from './redux/slices'; +export type { ChatConverseState } from './redux/slices/chat'; export { setupRedux } from './redux/setup'; export { createStore } from './redux/store'; export type { AppStore, AppDispatch } from './redux/store'; diff --git a/shared/redux/hooks/useConverse.ts b/shared/redux/hooks/useConverse.ts new file mode 100644 index 00000000..2d7fa4c7 --- /dev/null +++ b/shared/redux/hooks/useConverse.ts @@ -0,0 +1,19 @@ +import { useMemo } from 'react'; +import type { ChatConverseState } from '../slices/chat'; +import { useAppSelector } from './useAppSelector'; + +/** + * 获取私信会话列表 + * 并补充一些信息 + */ +export function useDMConverseList(): ChatConverseState[] { + const converses = useAppSelector((state) => state.chat.converses); + + return useMemo( + () => + Object.entries(converses) + .filter(([, info]) => info.type === 'DM') + .map(([, info]) => info), + [converses] + ); +} diff --git a/shared/redux/hooks/useUserInfo.ts b/shared/redux/hooks/useUserInfo.ts new file mode 100644 index 00000000..00d074f1 --- /dev/null +++ b/shared/redux/hooks/useUserInfo.ts @@ -0,0 +1,8 @@ +import { useAppSelector } from './useAppSelector'; + +/** + * 用户基本Id + */ +export function useUserId(): string | undefined { + return useAppSelector((state) => state.user.info?._id); +} diff --git a/shared/redux/slices/chat.ts b/shared/redux/slices/chat.ts index 79d52275..74c3d3af 100644 --- a/shared/redux/slices/chat.ts +++ b/shared/redux/slices/chat.ts @@ -4,7 +4,7 @@ import type { ChatMessage } from '../../model/message'; import _uniqBy from 'lodash/uniqBy'; import _orderBy from 'lodash/orderBy'; -interface ChatConverseState extends ChatConverseInfo { +export interface ChatConverseState extends ChatConverseInfo { messages: ChatMessage[]; } diff --git a/web/src/routes/Main/Content/Personal/Sidebar.tsx b/web/src/routes/Main/Content/Personal/Sidebar.tsx index c1afd26c..f88f7574 100644 --- a/web/src/routes/Main/Content/Personal/Sidebar.tsx +++ b/web/src/routes/Main/Content/Personal/Sidebar.tsx @@ -1,6 +1,8 @@ import React from 'react'; import { Icon } from '@iconify/react'; import { SidebarItem } from '../SidebarItem'; +import { useDMConverseList } from 'pawchat-shared'; +import { SidebarDMItem } from './SidebarDMItem'; const SidebarSection: React.FC<{ action: React.ReactNode; @@ -22,6 +24,8 @@ SidebarSection.displayName = 'SidebarSection'; * 个人面板侧边栏组件 */ export const Sidebar: React.FC = React.memo(() => { + const converseList = useDMConverseList(); + return ( <> { }>私信 - } - to={`/main/personal/converse/${'uuid'}`} - /> + {converseList.map((converse) => { + return ; + })} ); }); diff --git a/web/src/routes/Main/Content/Personal/SidebarDMItem.tsx b/web/src/routes/Main/Content/Personal/SidebarDMItem.tsx new file mode 100644 index 00000000..e457f109 --- /dev/null +++ b/web/src/routes/Main/Content/Personal/SidebarDMItem.tsx @@ -0,0 +1,45 @@ +import { + ChatConverseState, + useCachedUserInfo, + useUserId, +} from 'pawchat-shared'; +import { isValidStr } from 'pawchat-shared/utils/string-helper'; +import React, { useMemo } from 'react'; +import { SidebarItem } from '../SidebarItem'; + +interface SidebarDMItemProps { + converse: ChatConverseState; +} +export const SidebarDMItem: React.FC = React.memo( + (props) => { + const converse = props.converse; + const userId = useUserId(); + const otherMemberId = converse.members.find((m) => m !== userId); + const memberInfo = useCachedUserInfo(otherMemberId ?? null); + const memberSize = converse.members.length; + + const name = useMemo(() => { + if (isValidStr(converse.name)) { + return converse.name; + } + + let name = memberInfo.nickname; + if (memberSize >= 3) { + name += ' 等人的会话'; + } + + return name; + }, [converse.name, memberInfo.nickname, memberSize]); + + return ( + } + to={`/main/personal/converse/${converse._id}`} + /> + ); + } +); +SidebarDMItem.displayName = 'SidebarDMItem';