From 5be90cf852fa2c440a270245b16fc2ea7085bf91 Mon Sep 17 00:00:00 2001 From: moonrailgun Date: Thu, 11 Nov 2021 11:35:14 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E5=A2=9E=E5=8A=A0=E6=B6=88=E6=81=AF?= =?UTF-8?q?=E6=92=A4=E5=9B=9E=E6=93=8D=E4=BD=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- shared/i18n/langs/en-US/translation.json | 2 + shared/i18n/langs/zh-CN/translation.json | 2 + shared/index.tsx | 1 + shared/model/message.ts | 14 +++++ shared/model/user.ts | 17 ++++++ .../ChatBox/ChatMessageList/Item.tsx | 52 ++++++++++++++++++- 6 files changed, 86 insertions(+), 2 deletions(-) diff --git a/shared/i18n/langs/en-US/translation.json b/shared/i18n/langs/en-US/translation.json index 440bf1da..c358fa62 100644 --- a/shared/i18n/langs/en-US/translation.json +++ b/shared/i18n/langs/en-US/translation.json @@ -23,6 +23,7 @@ "k2ec4966c": "Selected {{num}} items", "k3172297b": "This feature is not yet open", "k31a9d6a3": "The connect to the server is broken", + "k323b5cc7": "Recall", "k34b5e3ab": "Send Message", "k34e357ee": "Group Summary", "k35abe359": "Lobby", @@ -147,6 +148,7 @@ "kd4216b7b": "Create Link", "kd4ff36fa": "Search Friends", "kd637a30": "Group Invite Service", + "kd983a61a": "{{nickname}} recall a message", "kda0e155e": "Create multiplayer converse", "kda67b115": "Unknown panel type", "kdb57357d": "Connection failed", diff --git a/shared/i18n/langs/zh-CN/translation.json b/shared/i18n/langs/zh-CN/translation.json index b391a1d8..29f852eb 100644 --- a/shared/i18n/langs/zh-CN/translation.json +++ b/shared/i18n/langs/zh-CN/translation.json @@ -23,6 +23,7 @@ "k2ec4966c": "已选择 {{num}} 项", "k3172297b": "该功能暂未开放", "k31a9d6a3": "与服务器的链接已断开", + "k323b5cc7": "撤回", "k34b5e3ab": "发送消息", "k34e357ee": "群组概述", "k35abe359": "大厅", @@ -147,6 +148,7 @@ "kd4216b7b": "创建链接", "kd4ff36fa": "查找好友", "kd637a30": "群组邀请服务", + "kd983a61a": "{{nickname}} 撤回了一条消息", "kda0e155e": "创建多人会话", "kda67b115": "未知的面板类型", "kdb57357d": "连接失败", diff --git a/shared/index.tsx b/shared/index.tsx index 4c9b7d59..6648754c 100644 --- a/shared/index.tsx +++ b/shared/index.tsx @@ -102,6 +102,7 @@ export { deleteGroupPanel, } from './model/group'; export type { GroupPanel, GroupInfo, GroupBasicInfo } from './model/group'; +export { recallMessage } from './model/message'; export type { ChatMessage } from './model/message'; export type { PluginManifest } from './model/plugin'; export type { UserBaseInfo, UserLoginInfo } from './model/user'; diff --git a/shared/model/message.ts b/shared/model/message.ts index 4f7c89e8..90ad8c08 100644 --- a/shared/model/message.ts +++ b/shared/model/message.ts @@ -13,6 +13,8 @@ export interface ChatMessage { reactions?: any[]; + hasRecall?: boolean; + meta?: Record; createdAt?: string; @@ -61,6 +63,18 @@ export async function sendMessage( return data; } +/** + * 撤回消息 + * @param messageId 消息ID + */ +export async function recallMessage(messageId: string): Promise { + const { data } = await request.post('/api/chat/message/recallMessage', { + messageId, + }); + + return data; +} + /** * 基于会话id获取会话最后一条消息的id */ diff --git a/shared/model/user.ts b/shared/model/user.ts index b62341b4..4eb9f0e4 100644 --- a/shared/model/user.ts +++ b/shared/model/user.ts @@ -1,5 +1,6 @@ import { request } from '../api/request'; import { buildCachedRequest } from '../cache/utils'; +import { SYSTEM_USERID } from '../utils/consts'; export interface UserBaseInfo { _id: string; @@ -15,6 +16,18 @@ export interface UserLoginInfo extends UserBaseInfo { createdAt: string; } +// 内置用户信息 +const builtinUserInfo: Record = { + [SYSTEM_USERID]: { + _id: SYSTEM_USERID, + email: 'admin@msgbyte.com', + nickname: '系统', + discriminator: '0000', + avatar: null, + temporary: false, + }, +}; + /** * 用户私信列表 */ @@ -119,6 +132,10 @@ export async function searchUserWithUniqueName( * @param userId 用户ID */ export async function fetchUserInfo(userId: string): Promise { + if (builtinUserInfo[userId]) { + return builtinUserInfo[userId]; + } + const { data } = await request.get('/api/user/getUserInfo', { params: { userId, diff --git a/web/src/components/ChatBox/ChatMessageList/Item.tsx b/web/src/components/ChatBox/ChatMessageList/Item.tsx index 74e1a8b3..ecbe194e 100644 --- a/web/src/components/ChatBox/ChatMessageList/Item.tsx +++ b/web/src/components/ChatBox/ChatMessageList/Item.tsx @@ -8,13 +8,17 @@ import { t, useCachedUserInfo, useChatBoxContext, + MessageHelper, + recallMessage, + useAsync, + getCachedUserInfo, + useAsyncRequest, } from 'tailchat-shared'; import { Avatar } from '@/components/Avatar'; import { useRenderPluginMessageInterpreter } from './useRenderPluginMessageInterpreter'; import { getMessageRender } from '@/plugin/common'; import { Icon } from '@iconify/react'; import { Divider, Dropdown, Menu } from 'antd'; -import { MessageHelper } from 'tailchat-shared'; import { UserName } from '@/components/UserName'; import './item.less'; @@ -24,6 +28,10 @@ import './item.less'; function useChatMessageItemAction(payload: ChatMessage): React.ReactElement { const context = useChatBoxContext(); + const [, handleRecallMessage] = useAsyncRequest(() => { + return recallMessage(payload._id); + }, [payload._id]); + return ( {context.hasContext && ( @@ -31,6 +39,9 @@ function useChatMessageItemAction(payload: ChatMessage): React.ReactElement { {t('回复')} )} + + {t('撤回')} + ); } @@ -126,13 +137,50 @@ const SystemMessage: React.FC = React.memo( ); SystemMessage.displayName = 'SystemMessage'; +/** + * 带userId => nickname异步解析的SystemMessage 组件 + */ +const SystemMessageWithNickname: React.FC< + ChatMessageItemProps & { + userIds: string[]; + overwritePayload: (nicknameList: string[]) => ChatMessage; + } +> = React.memo((props) => { + const { value: nicknameList = [] } = useAsync(() => { + return Promise.all( + props.userIds.map((userId) => + getCachedUserInfo(userId).then((u) => u.nickname) + ) + ); + }, [props.userIds.join(',')]); + + return ( + + ); +}); +SystemMessageWithNickname.displayName = 'SystemMessageWithNickname'; + interface ChatMessageItemProps { showAvatar: boolean; payload: ChatMessage; } const ChatMessageItem: React.FC = React.memo((props) => { - if (props.payload.author === SYSTEM_USERID) { + const payload = props.payload; + if (payload.author === SYSTEM_USERID) { return ; + } else if (payload.hasRecall === true) { + return ( + ({ + ...payload, + content: t('{{nickname}} 撤回了一条消息', { + nickname: nickname[0] ?? '', + }), + })} + /> + ); } return ;