From 7a1d288d5a2bf4da430d820c3d8d6658318e9eca Mon Sep 17 00:00:00 2001 From: moonrailgun Date: Tue, 21 Sep 2021 00:12:15 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E5=A2=9E=E5=8A=A0=E5=A5=BD=E5=8F=8B?= =?UTF-8?q?=E9=80=89=E6=8B=A9=E7=BB=84=E4=BB=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 用于创建多人会话 --- web/src/components/FriendPicker.tsx | 100 ++++++++++++++++++ .../components/modals/CreateDMConverse.tsx | 34 ++++++ .../routes/Main/Content/Personal/Sidebar.tsx | 15 ++- 3 files changed, 144 insertions(+), 5 deletions(-) create mode 100644 web/src/components/FriendPicker.tsx create mode 100644 web/src/components/modals/CreateDMConverse.tsx diff --git a/web/src/components/FriendPicker.tsx b/web/src/components/FriendPicker.tsx new file mode 100644 index 00000000..74449aa8 --- /dev/null +++ b/web/src/components/FriendPicker.tsx @@ -0,0 +1,100 @@ +import { Checkbox, Input } from 'antd'; +import React, { useCallback, useState } from 'react'; +import { + getCachedUserInfo, + t, + useAppSelector, + useAsync, +} from 'tailchat-shared'; +import _take from 'lodash/take'; +import _without from 'lodash/without'; +import { Avatar } from './Avatar'; + +interface FriendPickerProps { + /** + * 排除的用户id + * 在选择好友时会进行过滤 + */ + withoutUserIds?: string[]; + + /** + * 是否包含搜索框 + * 默认为 true + */ + withSearch?: boolean; + + selectedIds: string[]; + onChange: (selectedIds: string[]) => void; +} +export const FriendPicker: React.FC = React.memo((props) => { + const { + withoutUserIds = [], + withSearch = true, + selectedIds, + onChange, + } = props; + const [searchValue, setSearchValue] = useState(''); + const friendIds = useAppSelector((state) => + state.user.friends.filter((id) => !withoutUserIds.includes(id)) + ); + + const { value: friendInfoList = [] } = useAsync(() => { + return Promise.all(friendIds.map((id) => getCachedUserInfo(id))); + }, [friendIds.join(',')]); + + const handleSelectUser = useCallback( + (userId: string, isSelected: boolean) => { + if (isSelected === true) { + // 添加 + if (selectedIds.includes(userId)) { + return; + } + + typeof onChange === 'function' && onChange([...selectedIds, userId]); + } else { + // 移除 + typeof onChange === 'function' && + onChange(_without(selectedIds, userId)); + } + }, + [selectedIds, onChange] + ); + + return ( +
+ {withSearch && ( + setSearchValue(e.target.value)} + /> + )} + +
+ {t('已选择')}: {selectedIds.length} +
+ + {_take( + friendInfoList.filter((info) => info.nickname.includes(searchValue)), + 5 + ).map((info) => { + return ( +
+ handleSelectUser(info._id, e.target.checked)} + > +
+ + +
{info.nickname}
+
+
+
+ ); + })} +
+ ); +}); +FriendPicker.displayName = 'FriendPicker'; diff --git a/web/src/components/modals/CreateDMConverse.tsx b/web/src/components/modals/CreateDMConverse.tsx new file mode 100644 index 00000000..9a72fa4b --- /dev/null +++ b/web/src/components/modals/CreateDMConverse.tsx @@ -0,0 +1,34 @@ +import { Button } from 'antd'; +import React, { useState } from 'react'; +import { t } from 'tailchat-shared'; +import { FriendPicker } from '../FriendPicker'; +import { ModalWrapper } from '../Modal'; + +interface CreateDMCOnverseProps { + /** + * 排除的用户id + * 在选择好友时会进行过滤 + */ + withoutUserIds?: string[]; +} +export const CreateDMCOnverse: React.FC = React.memo( + (props) => { + const { withoutUserIds = [] } = props; + const [selectedFriendIds, setSelectedFriendIds] = useState([]); + + return ( + + + +
+ +
+
+ ); + } +); +CreateDMCOnverse.displayName = 'CreateDMCOnverse'; diff --git a/web/src/routes/Main/Content/Personal/Sidebar.tsx b/web/src/routes/Main/Content/Personal/Sidebar.tsx index 6179cf7c..101252e3 100644 --- a/web/src/routes/Main/Content/Personal/Sidebar.tsx +++ b/web/src/routes/Main/Content/Personal/Sidebar.tsx @@ -1,8 +1,11 @@ import React from 'react'; import { Icon } from '@iconify/react'; import { SidebarItem } from '../SidebarItem'; -import { showToasts, t, useDMConverseList } from 'tailchat-shared'; +import { t, useDMConverseList } from 'tailchat-shared'; import { SidebarDMItem } from './SidebarDMItem'; +import { openModal } from '@/components/Modal'; +import { CreateDMCOnverse } from '@/components/modals/CreateDMConverse'; +import DevContainer from '@/components/DevContainer'; const SidebarSection: React.FC<{ action: React.ReactNode; @@ -41,10 +44,12 @@ export const PersonalSidebar: React.FC = React.memo(() => { showToasts('该功能正在开发中')} - /> + + openModal()} + /> + } > {t('私信')}