From fc3d9ae06f8bacfb44dfa4f28da7916c139db361 Mon Sep 17 00:00:00 2001 From: moonrailgun Date: Thu, 22 Jul 2021 11:39:10 +0800 Subject: [PATCH] =?UTF-8?q?refactor(shared):=20=E7=BE=A4=E7=BB=84=E5=88=97?= =?UTF-8?q?=E8=A1=A8=E8=8E=B7=E5=8F=96=E4=B8=8E=E5=B1=95=E7=A4=BA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- shared/index.tsx | 1 + shared/model/group.ts | 25 ++++++++++++ shared/redux/setup.ts | 10 ++++- shared/redux/slices/group.ts | 30 ++++++++++++++ shared/redux/slices/index.ts | 3 ++ web/src/routes/Main/Navbar/GroupNav.tsx | 39 +++++++++++++++++++ web/src/routes/Main/Navbar/NavItem.tsx | 19 +++++++++ .../Main/{Navbar.tsx => Navbar/index.tsx} | 32 +++------------ 8 files changed, 130 insertions(+), 29 deletions(-) create mode 100644 shared/model/group.ts create mode 100644 shared/redux/slices/group.ts create mode 100644 web/src/routes/Main/Navbar/GroupNav.tsx create mode 100644 web/src/routes/Main/Navbar/NavItem.tsx rename web/src/routes/Main/{Navbar.tsx => Navbar/index.tsx} (52%) diff --git a/shared/index.tsx b/shared/index.tsx index 67583231..9e89f133 100644 --- a/shared/index.tsx +++ b/shared/index.tsx @@ -51,6 +51,7 @@ export { denyFriendRequest, } from './model/friend'; export type { FriendRequest } from './model/friend'; +export type { GroupInfo } from './model/group'; export type { ChatMessage } from './model/message'; export type { UserBaseInfo, UserLoginInfo } from './model/user'; export { diff --git a/shared/model/group.ts b/shared/model/group.ts new file mode 100644 index 00000000..be2514fc --- /dev/null +++ b/shared/model/group.ts @@ -0,0 +1,25 @@ +export enum GroupPanelType { + TEXT = 0, + GROUP = 1, +} + +export interface GroupMember { + role: string; // 角色 + userId: string; +} + +export interface GroupPanel { + id: string; // 在群组中唯一 + name: string; + parentId?: string; + type: GroupPanelType; +} + +export interface GroupInfo { + _id: string; + name: string; + avatar?: string; + creator: string; + members: GroupMember[]; + panels: GroupPanel[]; +} diff --git a/shared/redux/setup.ts b/shared/redux/setup.ts index 89c4a082..a023e995 100644 --- a/shared/redux/setup.ts +++ b/shared/redux/setup.ts @@ -1,12 +1,14 @@ import type { AppStore } from './store'; import type { AppSocket } from '../api/socket'; -import { chatActions, userActions } from './slices'; +import { chatActions, groupActions, userActions } from './slices'; import type { FriendRequest } from '../model/friend'; import type { UserDMList } from '../model/user'; import { getCachedConverseInfo } from '../cache/cache'; +import type { GroupInfo } from '../model/group'; /** - * 初始化Redux 上下文 + * 初始化 Redux 上下文 + * 该文件用于处理远程数据与本地 Redux 状态的交互 */ export function setupRedux(socket: AppSocket, store: AppStore) { initial(socket, store); @@ -37,6 +39,10 @@ function initial(socket: AppSocket, store: AppStore) { store.dispatch(chatActions.setConverseInfo(converse)); }); }); + + socket.request('group.getUserGroups').then((groups) => { + store.dispatch(groupActions.appendGroups(groups)); + }); } /** diff --git a/shared/redux/slices/group.ts b/shared/redux/slices/group.ts new file mode 100644 index 00000000..ecd12680 --- /dev/null +++ b/shared/redux/slices/group.ts @@ -0,0 +1,30 @@ +import { createSlice, PayloadAction } from '@reduxjs/toolkit'; +import type { GroupInfo } from '../../model/group'; + +interface GroupState { + groups: Record; +} + +const initialState: GroupState = { + groups: {}, +}; + +const groupSlice = createSlice({ + name: 'group', + initialState, + reducers: { + appendGroups(state, action: PayloadAction) { + const groups = action.payload; + + for (const group of groups) { + state.groups[group._id] = { + ...state.groups[group._id], + ...group, + }; + } + }, + }, +}); + +export const groupActions = groupSlice.actions; +export const groupReducer = groupSlice.reducer; diff --git a/shared/redux/slices/index.ts b/shared/redux/slices/index.ts index cdf7a9e5..ba464a56 100644 --- a/shared/redux/slices/index.ts +++ b/shared/redux/slices/index.ts @@ -1,13 +1,16 @@ import { combineReducers } from '@reduxjs/toolkit'; import { userReducer } from './user'; import { chatReducer } from './chat'; +import { groupReducer } from './group'; export const appReducer = combineReducers({ user: userReducer, chat: chatReducer, + group: groupReducer, }); export type AppState = ReturnType; export { userActions } from './user'; export { chatActions } from './chat'; +export { groupActions } from './group'; diff --git a/web/src/routes/Main/Navbar/GroupNav.tsx b/web/src/routes/Main/Navbar/GroupNav.tsx new file mode 100644 index 00000000..05392c0c --- /dev/null +++ b/web/src/routes/Main/Navbar/GroupNav.tsx @@ -0,0 +1,39 @@ +import { Avatar } from '@/components/Avatar'; +import { Icon } from '@iconify/react'; +import React, { useMemo } from 'react'; +import { GroupInfo, useAppSelector } from 'tailchat-shared'; +import { NavbarNavItem } from './NavItem'; + +function useGroups(): GroupInfo[] { + const groups = useAppSelector((state) => state.group.groups); + return useMemo( + () => Object.entries(groups).map(([_, group]) => group), + [groups] + ); +} + +export const GroupNav: React.FC = React.memo(() => { + const groups = useGroups(); + + return ( +
+ {Array.isArray(groups) && + groups.map((group) => ( + + + + ))} + + {/* 创建群组 */} + + + +
+ ); +}); +GroupNav.displayName = 'GroupNav'; diff --git a/web/src/routes/Main/Navbar/NavItem.tsx b/web/src/routes/Main/Navbar/NavItem.tsx new file mode 100644 index 00000000..c61c0de8 --- /dev/null +++ b/web/src/routes/Main/Navbar/NavItem.tsx @@ -0,0 +1,19 @@ +import type { ClassValue } from 'clsx'; +import clsx from 'clsx'; +import React from 'react'; + +export const NavbarNavItem: React.FC<{ + className?: ClassValue; +}> = React.memo((props) => { + return ( +
+ {props.children} +
+ ); +}); +NavbarNavItem.displayName = 'NavbarNavItem'; diff --git a/web/src/routes/Main/Navbar.tsx b/web/src/routes/Main/Navbar/index.tsx similarity index 52% rename from web/src/routes/Main/Navbar.tsx rename to web/src/routes/Main/Navbar/index.tsx index e24fd3a3..fc0ddce4 100644 --- a/web/src/routes/Main/Navbar.tsx +++ b/web/src/routes/Main/Navbar/index.tsx @@ -1,24 +1,9 @@ import React from 'react'; import { useAppSelector } from 'tailchat-shared'; import { Icon } from '@iconify/react'; -import clsx, { ClassValue } from 'clsx'; -import { Avatar } from '../../components/Avatar'; - -const NavbarNavItem: React.FC<{ - className?: ClassValue; -}> = React.memo((props) => { - return ( -
- {props.children} -
- ); -}); -NavbarNavItem.displayName = 'NavbarNavItem'; +import { Avatar } from '@/components/Avatar'; +import { NavbarNavItem } from './NavItem'; +import { GroupNav } from './GroupNav'; /** * 导航栏组件 @@ -39,15 +24,8 @@ export const Navbar: React.FC = React.memo(() => { />
-
- - - - - - - -
+ +