refactor: 将群组用户操作相关的逻辑单独抽象成一个hooks方便复用

pull/70/head
moonrailgun 2 years ago
parent b44ccfd762
commit 7645300bda

@ -1,93 +1,26 @@
import { Icon } from 'tailchat-design'; import { Icon } from 'tailchat-design';
import { openReconfirmModalP } from '@/components/Modal';
import { GroupUserPopover } from '@/components/popover/GroupUserPopover'; import { GroupUserPopover } from '@/components/popover/GroupUserPopover';
import { UserListItem } from '@/components/UserListItem'; import { UserListItem } from '@/components/UserListItem';
import { Divider, Dropdown, Input, MenuProps, Skeleton } from 'antd'; import { Divider, Dropdown, Input, MenuProps, Skeleton } from 'antd';
import React, { useMemo } from 'react'; import React, { useMemo } from 'react';
import { import {
formatFullTime,
getGroupConfigWithInfo, getGroupConfigWithInfo,
GroupMember,
humanizeMsDuration,
model,
PERMISSION, PERMISSION,
showToasts,
t, t,
useAsyncRequest,
useCachedOnlineStatus, useCachedOnlineStatus,
useGroupInfo, useGroupInfo,
useHasGroupPermission, useHasGroupPermission,
UserBaseInfo, UserBaseInfo,
useSearch,
useUserInfoList, useUserInfoList,
} from 'tailchat-shared'; } from 'tailchat-shared';
import _compact from 'lodash/compact'; import _compact from 'lodash/compact';
import { Problem } from '@/components/Problem'; import { Problem } from '@/components/Problem';
import { useGroupMemberAction } from '@/hooks/useGroupMemberAction';
interface MembersPanelProps { interface MembersPanelProps {
groupId: string; groupId: string;
} }
function getMembersHasMute(members: GroupMember[], userId: string): boolean {
const member = members.find((m) => m.userId === userId);
if (!member || !member.muteUntil) {
return false;
}
const muteUntil = member.muteUntil;
return new Date(muteUntil).valueOf() > new Date().valueOf();
}
/**
*
*/
function useMemberMuteAction(
groupId: string,
userInfoList: model.user.UserBaseInfo[]
) {
/**
*
*/
const [, handleMuteMember] = useAsyncRequest(
async (memberId: string, ms: number) => {
const memberInfo = userInfoList.find((m) => m._id === memberId);
if (!memberInfo) {
throw new Error(t('没有找到用户'));
}
if (
await openReconfirmModalP({
title: t('确定要禁言 {{name}} 么', { name: memberInfo.nickname }),
content: t('禁言 {{length}}, 预计到 {{until}} 为止', {
length: humanizeMsDuration(ms),
until: formatFullTime(new Date().valueOf() + ms),
}),
})
) {
await model.group.muteGroupMember(groupId, memberId, ms);
showToasts(t('操作成功'), 'success');
}
},
[groupId, userInfoList]
);
/**
*
*/
const [, handleUnmuteMember] = useAsyncRequest(
async (memberId: string) => {
await model.group.muteGroupMember(groupId, memberId, -1);
showToasts(t('操作成功'), 'success');
},
[groupId]
);
return { handleMuteMember, handleUnmuteMember };
}
/** /**
* *
*/ */
@ -109,10 +42,11 @@ export const MembersPanel: React.FC<MembersPanelProps> = React.memo((props) => {
setSearchText, setSearchText,
isSearching, isSearching,
searchResult: filteredGroupMembers, searchResult: filteredGroupMembers,
} = useSearch({ getMemberHasMute,
dataSource: userInfoList, handleMuteMember,
filterFn: (item, searchText) => item.nickname.includes(searchText), handleUnmuteMember,
}); handleRemoveGroupMember,
} = useGroupMemberAction(groupId);
const groupedMembers = useMemo(() => { const groupedMembers = useMemo(() => {
const online: UserBaseInfo[] = []; const online: UserBaseInfo[] = [];
@ -132,27 +66,6 @@ export const MembersPanel: React.FC<MembersPanelProps> = React.memo((props) => {
}; };
}, [userInfoList, membersOnlineStatus]); }, [userInfoList, membersOnlineStatus]);
const { handleMuteMember, handleUnmuteMember } = useMemberMuteAction(
groupId,
userInfoList
);
/**
*
*/
const [, handleRemoveGroupMember] = useAsyncRequest(
async (memberId: string) => {
const confirm = await openReconfirmModalP({
title: t('确认要将该用户移出群组么'),
});
if (confirm) {
await model.group.deleteGroupMember(groupId, memberId);
showToasts(t('操作成功'), 'success');
}
},
[groupId]
);
if (!groupInfo) { if (!groupInfo) {
return <Problem />; return <Problem />;
} }
@ -162,7 +75,7 @@ export const MembersPanel: React.FC<MembersPanelProps> = React.memo((props) => {
} }
const renderUser = (member: UserBaseInfo) => { const renderUser = (member: UserBaseInfo) => {
const hasMute = getMembersHasMute(members, member._id); const hasMute = getMemberHasMute(member._id);
if (allowManageUser) { if (allowManageUser) {
const muteItems: MenuProps['items'] = hasMute const muteItems: MenuProps['items'] = hasMute

@ -14,6 +14,7 @@ import { GroupRole } from './Role';
import { GroupSummary } from './Summary'; import { GroupSummary } from './Summary';
import _compact from 'lodash/compact'; import _compact from 'lodash/compact';
import { GroupConfig } from './Config'; import { GroupConfig } from './Config';
import { GroupMember } from './Member';
interface SettingsViewProps { interface SettingsViewProps {
groupId: string; groupId: string;
@ -31,11 +32,13 @@ export const GroupDetail: React.FC<SettingsViewProps> = React.memo((props) => {
); );
const [ const [
allowManageConfig, allowManageConfig,
allowManageUser,
allowManagePanel, allowManagePanel,
allowManageInvite, allowManageInvite,
allowManageRoles, allowManageRoles,
] = useHasGroupPermission(groupId, [ ] = useHasGroupPermission(groupId, [
PERMISSION.core.groupConfig, PERMISSION.core.groupConfig,
PERMISSION.core.manageUser,
PERMISSION.core.managePanel, PERMISSION.core.managePanel,
PERMISSION.core.manageInvite, PERMISSION.core.manageInvite,
PERMISSION.core.manageRoles, PERMISSION.core.manageRoles,
@ -58,6 +61,11 @@ export const GroupDetail: React.FC<SettingsViewProps> = React.memo((props) => {
title: t('配置'), title: t('配置'),
content: <GroupConfig groupId={groupId} />, content: <GroupConfig groupId={groupId} />,
}, },
allowManageUser && {
type: 'item',
title: t('成员'),
content: <GroupMember groupId={groupId} />,
},
allowManagePanel && { allowManagePanel && {
type: 'item', type: 'item',
title: t('面板'), title: t('面板'),

@ -0,0 +1,127 @@
import { openReconfirmModalP } from '@/components/Modal';
import { useCallback } from 'react';
import {
formatFullTime,
humanizeMsDuration,
model,
showSuccessToasts,
t,
useAsyncRequest,
useGroupInfo,
useGroupMemberInfos,
useMemoizedFn,
useSearch,
} from 'tailchat-shared';
/**
*
*/
export function useGroupMemberAction(groupId: string) {
const groupInfo = useGroupInfo(groupId);
const members = groupInfo?.members ?? [];
const userInfos = useGroupMemberInfos(groupId);
const { handleMuteMember, handleUnmuteMember } = useMemberMuteAction(
groupId,
userInfos
);
const { searchText, setSearchText, isSearching, searchResult } = useSearch({
dataSource: userInfos,
filterFn: (item, searchText) => item.nickname.includes(searchText),
});
/**
*
*/
const [, handleRemoveGroupMember] = useAsyncRequest(
async (memberId: string) => {
const confirm = await openReconfirmModalP({
title: t('确认要将该用户移出群组么'),
});
if (confirm) {
await model.group.deleteGroupMember(groupId, memberId);
showSuccessToasts();
}
},
[groupId]
);
const getMemberHasMute = useCallback(
(userId: string): boolean => {
const member = members.find((m) => m.userId === userId);
if (!member || !member.muteUntil) {
return false;
}
const muteUntil = member.muteUntil;
return new Date(muteUntil).valueOf() > new Date().valueOf();
},
[members]
);
return {
// 搜索相关
searchText,
setSearchText,
isSearching,
searchResult,
getMemberHasMute,
// 用户操作
handleMuteMember,
handleUnmuteMember,
handleRemoveGroupMember,
};
}
/**
*
*/
function useMemberMuteAction(
groupId: string,
userInfoList: model.user.UserBaseInfo[]
) {
/**
*
*/
const [, handleMuteMember] = useAsyncRequest(
async (memberId: string, ms: number) => {
const memberInfo = userInfoList.find((m) => m._id === memberId);
if (!memberInfo) {
throw new Error(t('没有找到用户'));
}
if (
await openReconfirmModalP({
title: t('确定要禁言 {{name}} 么', { name: memberInfo.nickname }),
content: t('禁言 {{length}}, 预计到 {{until}} 为止', {
length: humanizeMsDuration(ms),
until: formatFullTime(new Date().valueOf() + ms),
}),
})
) {
await model.group.muteGroupMember(groupId, memberId, ms);
showSuccessToasts();
}
},
[groupId, userInfoList]
);
/**
*
*/
const [, handleUnmuteMember] = useAsyncRequest(
async (memberId: string) => {
await model.group.muteGroupMember(groupId, memberId, -1);
showSuccessToasts();
},
[groupId]
);
return { handleMuteMember, handleUnmuteMember };
}
Loading…
Cancel
Save