diff --git a/web/plugins/com.msgbyte.bbcode/src/bbcode/serialize.ts b/web/plugins/com.msgbyte.bbcode/src/bbcode/serialize.ts index 0ece6e87..cc501733 100644 --- a/web/plugins/com.msgbyte.bbcode/src/bbcode/serialize.ts +++ b/web/plugins/com.msgbyte.bbcode/src/bbcode/serialize.ts @@ -12,11 +12,17 @@ function bbcodeNodeToPlainText(node: AstNode): string { } else { if (node.tag === 'img') { return '[图片]'; - } else { - return (node.content ?? []) - .map((sub) => bbcodeNodeToPlainText(sub)) - .join(''); } + if (node.tag === 'emoji') { + return `:${node.content.join('')}:`; + } + if (node.tag === 'at') { + return `@${node.content.join('')}`; + } + + return (node.content ?? []) + .map((sub) => bbcodeNodeToPlainText(sub)) + .join(''); } } diff --git a/web/plugins/com.msgbyte.bbcode/src/index.tsx b/web/plugins/com.msgbyte.bbcode/src/index.tsx index e5cda518..1bff6efb 100644 --- a/web/plugins/com.msgbyte.bbcode/src/index.tsx +++ b/web/plugins/com.msgbyte.bbcode/src/index.tsx @@ -6,6 +6,10 @@ import { } from '@capital/common'; const BBCode = Loadable(() => import('./render')); +let serialize: (bbcode: string) => string; +import('./bbcode/serialize').then((module) => { + serialize = module.bbcodeToPlainText; +}); regMessageRender((message) => { return ; @@ -22,6 +26,7 @@ regMessageTextDecorators(() => ({ }, mention: (userId, userName) => `[at=${userId}]${userName}[/at]`, emoji: (emojiCode) => `[emoji]${stripColons(emojiCode)}[/emoji]`, + serialize: (plain: string) => (serialize ? serialize(plain) : plain), })); /** diff --git a/web/src/components/ChatBox/ChatMessageList/useChatMessageItemAction.tsx b/web/src/components/ChatBox/ChatMessageList/useChatMessageItemAction.tsx index af76af54..cf400f46 100644 --- a/web/src/components/ChatBox/ChatMessageList/useChatMessageItemAction.tsx +++ b/web/src/components/ChatBox/ChatMessageList/useChatMessageItemAction.tsx @@ -1,6 +1,6 @@ import { Icon } from '@/components/Icon'; import { Menu } from 'antd'; -import React from 'react'; +import React, { useCallback } from 'react'; import { ChatMessage, deleteMessage, @@ -13,6 +13,8 @@ import { useUserInfo, } from 'tailchat-shared'; import { openReconfirmModalP } from '@/components/Modal'; +import copy from 'copy-to-clipboard'; +import { getMessageTextDecorators } from '@/plugin/common'; /** * 消息的会话操作 @@ -25,6 +27,10 @@ export function useChatMessageItemAction( const groupInfo = useGroupInfoContext(); const userInfo = useUserInfo(); + const handleCopy = useCallback(() => { + copy(getMessageTextDecorators().serialize(payload.content)); + }, [payload.content]); + const [, handleRecallMessage] = useAsyncRequest(async () => { if (await openReconfirmModalP()) { await recallMessage(payload._id); @@ -42,6 +48,14 @@ export function useChatMessageItemAction( return ( + } + onClick={handleCopy} + > + {t('复制')} + + {context.hasContext && ( ) => plain, mention: (userId: string, userName: string) => `@${userName}`, emoji: (emojiCode: string) => emojiCode, + serialize: (plain: string) => plain, }; const [_getMessageTextDecorators, regMessageTextDecorators] = buildRegFn< () => Partial