You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
tailchat/web/src/components/ChatBox/ChatMessageList/useMessageReactions.tsx

64 lines
1.6 KiB
TypeScript

import { ChatMessage, useUsernames } from 'tailchat-shared';
import _groupBy from 'lodash/groupBy';
import _uniqBy from 'lodash/uniqBy';
import { useMemo } from 'react';
import { Emoji } from '@/components/Emoji';
import React from 'react';
import { Tooltip } from 'antd';
interface GroupedReaction {
name: string;
length: number;
users: string[];
}
/**
* 消息反应的用户名
*/
const ReactionItem: React.FC<{ reaction: GroupedReaction }> = React.memo(
(props) => {
const { reaction } = props;
return (
<div className="py-0.5 px-1 bg-black bg-opacity-20 rounded flex">
<Tooltip title={useUsernames(reaction.users)}>
<div>
<Emoji emoji={reaction.name} />
{reaction.length > 1 && <span>{reaction.length}</span>}
</div>
</Tooltip>
</div>
);
}
);
ReactionItem.displayName = 'ReactionItem';
/**
* 消息反应表情渲染
*/
export function useMessageReactions(payload: ChatMessage) {
const reactions = payload.reactions ?? [];
const groupedReactions: GroupedReaction[] = useMemo(() => {
const groups = _groupBy(reactions, 'name');
return Object.keys(groups).map((name) => {
const reactions = _uniqBy(groups[name], 'author');
return {
name,
length: reactions.length,
users: reactions.map((r) => r.author),
};
});
}, [reactions]);
return (
<div className="flex chat-message-reactions gap-1">
{groupedReactions.map((reaction) => (
<ReactionItem key={reaction.name} reaction={reaction} />
))}
</div>
);
}