Skip to content

Commit

Permalink
feat: add search friend feature #157
Browse files Browse the repository at this point in the history
include can search by nickname
  • Loading branch information
moonrailgun committed Nov 13, 2023
1 parent de63236 commit a7fe82e
Show file tree
Hide file tree
Showing 9 changed files with 89 additions and 71 deletions.
34 changes: 2 additions & 32 deletions client/shared/cache/useCache.ts
Original file line number Diff line number Diff line change
@@ -1,38 +1,8 @@
import { useQueries, useQuery, useQueryClient } from '@tanstack/react-query';
import {
fetchUserInfo,
getUserOnlineStatus,
UserBaseInfo,
} from '../model/user';
import { isValidStr } from '../utils/string-helper';
import { useQuery, useQueryClient } from '@tanstack/react-query';
import { getUserOnlineStatus } from '../model/user';

export { useQuery, useQueryClient };

/**
* 用户缓存
*/
export function useCachedUserInfo(
userId: string | null,
refetch = false
): UserBaseInfo | Record<string, never> {
const { data } = useQuery(
['user', userId],
() => {
if (!isValidStr(userId)) {
return {};
}

return fetchUserInfo(userId);
},
{
staleTime: 2 * 60 * 60 * 1000, // 缓存2小时
refetchOnMount: refetch ? 'always' : true,
}
);

return data ?? {};
}

/**
* 用户登录状态
*/
Expand Down
19 changes: 19 additions & 0 deletions client/shared/hooks/model/useUserInfo.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import { getCachedUserInfo } from '../../cache/cache';
import type { UserBaseInfo } from '../../model/user';
import { useAsync } from '../useAsync';

/**
* 用户信息
*/
export function useCachedUserInfo(
userId: string,
refetch = false
): UserBaseInfo | Record<string, never> {
const { value: userInfo = {} } = useAsync(async () => {
const users = getCachedUserInfo(userId, refetch);

return users;
}, [userId, refetch]);

return userInfo;
}
33 changes: 33 additions & 0 deletions client/shared/hooks/useSearch.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
import { useMemo, useState } from 'react';
import { useFriendNicknameMap } from '../redux/hooks/useFriendNickname';
import type { UserBaseInfo } from 'tailchat-types';

export interface UseSearchOptions<T> {
dataSource: T[];
Expand All @@ -21,3 +23,34 @@ export function useSearch<T>(options: UseSearchOptions<T>) {
searchResult,
};
}

/**
* 用于搜索用户的封装函数
*/
export function useUserSearch(userInfos: UserBaseInfo[]) {
const friendNicknameMap = useFriendNicknameMap();

const { searchText, setSearchText, isSearching, searchResult } = useSearch({
dataSource: userInfos,
filterFn: (item, searchText) => {
if (friendNicknameMap[item._id]) {
if (friendNicknameMap[item._id].includes(searchText)) {
return true;
}
}

if (item.nickname.includes(searchText)) {
return true;
}

return false;
},
});

return {
searchText,
setSearchText,
isSearching,
searchResult,
};
}
10 changes: 7 additions & 3 deletions client/shared/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ export {
getCachedRegistryPlugins,
getCachedUserSettings,
} from './cache/cache';
export { useCachedUserInfo, useCachedOnlineStatus } from './cache/useCache';
export { useCachedOnlineStatus } from './cache/useCache';

// components
export { buildPortal, DefaultEventEmitter } from './components/Portal';
Expand Down Expand Up @@ -61,6 +61,7 @@ export { useLanguage } from './i18n/language';
export { createUseStorageState } from './hooks/factory/createUseStorageState';
export { useAvailableServices } from './hooks/model/useAvailableServices';
export { useMessageNotifyEventFilter } from './hooks/model/useMessageNotifyEventFilter';
export { useCachedUserInfo } from './hooks/model/useUserInfo';
export { useUserInfoList } from './hooks/model/useUserInfoList';
export { useUsernames } from './hooks/model/useUsernames';
export {
Expand All @@ -82,7 +83,7 @@ export { useMemoizedFn } from './hooks/useMemoizedFn';
export { useMountedState } from './hooks/useMountedState';
export { usePrevious } from './hooks/usePrevious';
export { useRafState } from './hooks/useRafState';
export { useSearch } from './hooks/useSearch';
export { useSearch, useUserSearch } from './hooks/useSearch';
export { useShallowObject } from './hooks/useShallowObject';
export { useUpdateRef } from './hooks/useUpdateRef';
export { useWatch } from './hooks/useWatch';
Expand Down Expand Up @@ -197,7 +198,10 @@ export { useDMConverseList } from './redux/hooks/useConverse';
export { useConverseAck } from './redux/hooks/useConverseAck';
export { useConverseMessage } from './redux/hooks/useConverseMessage';
export { useDMConverseName } from './redux/hooks/useDMConverseName';
export { useFriendNickname } from './redux/hooks/useFriendNickname';
export {
useFriendNickname,
useFriendNicknameMap,
} from './redux/hooks/useFriendNickname';
export {
useGroupInfo,
useGroupMemberIds,
Expand Down
13 changes: 2 additions & 11 deletions client/shared/model/user.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,18 +11,9 @@ import _uniq from 'lodash/uniq';
import _flatten from 'lodash/flatten';
import _zipObject from 'lodash/zipObject';
import { t } from '../i18n';
import type { UserBaseInfo } from 'tailchat-types';

export interface UserBaseInfo {
_id: string;
email: string;
nickname: string;
discriminator: string;
avatar: string | null;
temporary: boolean;
emailVerified: boolean;
banned: boolean;
extra?: Record<string, unknown>;
}
export type { UserBaseInfo };

export interface UserLoginInfo extends UserBaseInfo {
token: string;
Expand Down
2 changes: 1 addition & 1 deletion client/web/src/components/Panel/group/TextPanel.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ import {
GroupPanelType,
useHasGroupPanelPermission,
} from 'tailchat-shared';
import { useFriendNicknameMap } from 'tailchat-shared/redux/hooks/useFriendNickname';
import { useFriendNicknameMap } from 'tailchat-shared';
import { MembersPanel } from './MembersPanel';
import { GroupPanelContainer } from './shared/GroupPanelContainer';
import { MessageSearchPanel } from '../common/MessageSearch';
Expand Down
22 changes: 3 additions & 19 deletions client/web/src/hooks/useGroupMemberAction.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,9 @@ import {
useGroupMemberInfos,
useHasGroupPermission,
UserBaseInfo,
useSearch,
useUserSearch,
} from 'tailchat-shared';
import _compact from 'lodash/compact';
import { useFriendNicknameMap } from 'tailchat-shared/redux/hooks/useFriendNickname';

/**
* 群组成员管理相关操作
Expand All @@ -26,7 +25,6 @@ export function useGroupMemberAction(groupId: string) {
const members = groupInfo?.members ?? [];
const roles = groupInfo?.roles ?? [];
const userInfos = useGroupMemberInfos(groupId);
const friendNicknameMap = useFriendNicknameMap();
const [allowManageUser, allowManageRoles] = useHasGroupPermission(groupId, [
PERMISSION.core.manageUser,
PERMISSION.core.manageRoles,
Expand All @@ -37,22 +35,8 @@ export function useGroupMemberAction(groupId: string) {
userInfos
);

const { searchText, setSearchText, isSearching, searchResult } = useSearch({
dataSource: userInfos,
filterFn: (item, searchText) => {
if (friendNicknameMap[item._id]) {
if (friendNicknameMap[item._id].includes(searchText)) {
return true;
}
}

if (item.nickname.includes(searchText)) {
return true;
}

return false;
},
});
const { searchText, setSearchText, isSearching, searchResult } =
useUserSearch(userInfos);

/**
* 移除用户
Expand Down
26 changes: 21 additions & 5 deletions client/web/src/routes/Main/Content/Personal/Friends/FriendList.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import React, { useCallback } from 'react';
import React, { useCallback, useMemo, useState } from 'react';
import {
createDMConverse,
isValidStr,
Expand All @@ -12,15 +12,18 @@ import {
useAsyncRequest,
useEvent,
useGlobalConfigStore,
useUserInfoList,
useUserSearch,
userActions,
} from 'tailchat-shared';
import { UserListItem } from '@/components/UserListItem';
import { IconBtn } from '@/components/IconBtn';
import { Button, Dropdown, Tooltip } from 'antd';
import { Button, Dropdown, Input, Tooltip } from 'antd';
import { useNavigate } from 'react-router';
import { Problem } from '@/components/Problem';
import { closeModal, openModal } from '@/components/Modal';
import { SetFriendNickname } from '@/components/modals/SetFriendNickname';
import { Icon } from 'tailchat-design';

/**
* 好友列表
Expand All @@ -29,6 +32,9 @@ export const FriendList: React.FC<{
onSwitchToAddFriend: () => void;
}> = React.memo((props) => {
const friends = useAppSelector((state) => state.user.friends);
const friendIds = useMemo(() => friends.map((f) => f.id), [friends]);
const userInfos = useUserInfoList(friendIds);
const { searchText, setSearchText, searchResult } = useUserSearch(userInfos);
const navigate = useNavigate();
const dispatch = useAppDispatch();
const disableAddFriend = useGlobalConfigStore(
Expand Down Expand Up @@ -91,11 +97,21 @@ export const FriendList: React.FC<{
return (
<div className="py-2.5 px-5">
<div>{t('好友列表')}</div>

<Input
className="my-2"
placeholder={t('搜索好友')}
size="large"
prefix={<Icon fontSize={20} color="grey" icon="mdi:magnify" />}
value={searchText}
onChange={(e) => setSearchText(e.target.value)}
/>

<div>
{friends.map((item) => (
{searchResult.map((item) => (
<UserListItem
key={item.id}
userId={item.id}
key={item._id}
userId={item._id}
actions={[
<Tooltip key="message" title={t('发送消息')}>
<div>
Expand Down
1 change: 1 addition & 0 deletions packages/types/src/model/user.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ export interface UserBaseInfo {
temporary: boolean;
type: UserType;
emailVerified: boolean;
banned: boolean;
extra?: Record<string, unknown>;
}

Expand Down

0 comments on commit a7fe82e

Please sign in to comment.