feat: add message list popover for DM and group

pull/90/head
moonrailgun 2 years ago
parent 693edf2739
commit 704c05e0ec

@ -9,10 +9,11 @@ import {
MessageHelper,
showMessageTime,
useUserInfoList,
UserBaseInfo,
} from 'tailchat-shared';
import { useRenderPluginMessageInterpreter } from './useRenderPluginMessageInterpreter';
import { getMessageRender, pluginMessageExtraParsers } from '@/plugin/common';
import { Divider, Dropdown } from 'antd';
import { Divider, Dropdown, Popover } from 'antd';
import { UserName } from '@/components/UserName';
import clsx from 'clsx';
import { useChatMessageItemAction } from './useChatMessageItemAction';
@ -22,6 +23,8 @@ import { useMessageReactions } from './useMessageReactions';
import { stopPropagation } from '@/utils/dom-helper';
import { AutoFolder, Avatar, Icon } from 'tailchat-design';
import { MessageAckContainer } from './MessageAckContainer';
import { UserPopover } from '@/components/popover/UserPopover';
import _isEmpty from 'lodash/isEmpty';
import './Item.less';
/**
@ -85,7 +88,22 @@ const NormalMessage: React.FC<ChatMessageItemProps> = React.memo((props) => {
{/* 头像 */}
<div className="w-18 mobile:w-14 flex items-start justify-center pt-0.5">
{showAvatar ? (
<Avatar size={40} src={userInfo.avatar} name={userInfo.nickname} />
<Popover
content={
!_isEmpty(userInfo) && (
<UserPopover userInfo={userInfo as UserBaseInfo} />
)
}
placement="top"
trigger="click"
>
<Avatar
className="cursor-pointer"
size={40}
src={userInfo.avatar}
name={userInfo.nickname}
/>
</Popover>
) : (
<div className="hidden group-hover:block opacity-40">
{formatShortTime(payload.createdAt)}

@ -1,5 +1,5 @@
import { Icon } from 'tailchat-design';
import { GroupUserPopover } from '@/components/popover/GroupUserPopover';
import { GroupUserPopover } from '@/components/popover/UserPopover/GroupUserPopover';
import { UserListItem } from '@/components/UserListItem';
import { Divider, Dropdown, Input, MenuProps, Skeleton } from 'antd';
import React, { useMemo } from 'react';
@ -11,9 +11,7 @@ import {
useGroupInfo,
useHasGroupPermission,
UserBaseInfo,
useUserInfoList,
} from 'tailchat-shared';
import _compact from 'lodash/compact';
import { Problem } from '@/components/Problem';
import { useGroupMemberAction } from '@/hooks/useGroupMemberAction';
@ -42,7 +40,6 @@ export const MembersPanel: React.FC<MembersPanelProps> = React.memo((props) => {
setSearchText,
isSearching,
searchResult: filteredGroupMembers,
getMemberHasMute,
generateActionMenu,
} = useGroupMemberAction(groupId);

@ -1,4 +1,3 @@
import { pluginUserExtraInfo } from '@/plugin/common';
import { fetchImagePrimaryColor } from '@/utils/image-helper';
import { Space, Tag } from 'antd';
import React, { useEffect } from 'react';
@ -9,7 +8,8 @@ import {
t,
UserBaseInfo,
} from 'tailchat-shared';
import { UserProfileContainer } from '../UserProfileContainer';
import { UserProfileContainer } from '../../UserProfileContainer';
import { usePluginUserExtraInfo } from './usePluginUserExtraInfo';
export const GroupUserPopover: React.FC<{
userInfo: UserBaseInfo;
@ -19,6 +19,7 @@ export const GroupUserPopover: React.FC<{
const userExtra = userInfo.extra ?? {};
const roleNames = getUserRoleNames(userInfo._id, groupInfo);
const { hideGroupMemberDiscriminator } = getGroupConfigWithInfo(groupInfo);
const pluginUserExtraInfoEl = usePluginUserExtraInfo(userExtra);
useEffect(() => {
if (userInfo.avatar) {
@ -52,27 +53,7 @@ export const GroupUserPopover: React.FC<{
))}
</Space>
<div className="pt-2">
{pluginUserExtraInfo.map((item, i) => {
const Component = item.component?.render;
if (Component) {
// 自定义渲染方式
return (
<Component key={item.name + i} value={userExtra[item.name]} />
);
}
// 默认渲染方式
return (
<div key={item.name + i} className="flex">
<div className="w-1/4 text-gray-500">{item.label}:</div>
<div className="w-3/4">
{userExtra[item.name] ? String(userExtra[item.name]) : ''}
</div>
</div>
);
})}
</div>
<div className="pt-2">{pluginUserExtraInfoEl}</div>
</UserProfileContainer>
</div>
);

@ -0,0 +1,40 @@
import { fetchImagePrimaryColor } from '@/utils/image-helper';
import { Space, Tag } from 'antd';
import React, { useEffect } from 'react';
import { t, UserBaseInfo } from 'tailchat-shared';
import { UserProfileContainer } from '../../UserProfileContainer';
import { usePluginUserExtraInfo } from './usePluginUserExtraInfo';
export const PersonalUserPopover: React.FC<{
userInfo: UserBaseInfo;
}> = React.memo((props) => {
const { userInfo } = props;
const userExtra = userInfo.extra ?? {};
const pluginUserExtraInfoEl = usePluginUserExtraInfo(userExtra);
useEffect(() => {
if (userInfo.avatar) {
fetchImagePrimaryColor(userInfo.avatar).then((rgba) => {
console.log('fetchImagePrimaryColor', rgba);
});
}
}, [userInfo.avatar]);
return (
<div className="w-80 -mx-4 -my-3 bg-inherit">
<UserProfileContainer userInfo={userInfo}>
<div className="text-xl">
<span className="font-semibold">{userInfo.nickname}</span>
<span className="opacity-60 ml-1">#{userInfo.discriminator}</span>
</div>
<Space size={4} wrap={true} className="py-1">
{userInfo.temporary && <Tag color="processing">{t('游客')}</Tag>}
</Space>
<div className="pt-2">{pluginUserExtraInfoEl}</div>
</UserProfileContainer>
</div>
);
});
PersonalUserPopover.displayName = 'PersonalUserPopover';

@ -0,0 +1,23 @@
import { useGroupIdContext } from '@/context/GroupIdContext';
import React from 'react';
import { useGroupInfo, UserBaseInfo } from 'tailchat-shared';
import { GroupUserPopover } from './GroupUserPopover';
import { PersonalUserPopover } from './PersonalUserPopover';
/**
* Common Entry for User Popover
*/
export const UserPopover: React.FC<{
userInfo: UserBaseInfo;
}> = React.memo((props) => {
const groupId = useGroupIdContext();
const groupInfo = useGroupInfo(groupId);
if (groupInfo) {
return <GroupUserPopover userInfo={props.userInfo} groupInfo={groupInfo} />;
}
// TODO
return <PersonalUserPopover userInfo={props.userInfo} />;
});
UserPopover.displayName = 'UserPopover';

@ -0,0 +1,28 @@
import { pluginUserExtraInfo } from '@/plugin/common';
import React from 'react';
export function usePluginUserExtraInfo(
userExtra: Record<string, unknown> = {}
) {
return (
<>
{pluginUserExtraInfo.map((item, i) => {
const Component = item.component?.render;
if (Component) {
// 自定义渲染方式
return <Component key={item.name + i} value={userExtra[item.name]} />;
}
// 默认渲染方式
return (
<div key={item.name + i} className="flex">
<div className="w-1/4 text-gray-500">{item.label}:</div>
<div className="w-3/4">
{userExtra[item.name] ? String(userExtra[item.name]) : ''}
</div>
</div>
);
})}
</>
);
}
Loading…
Cancel
Save