import TUIChatEngine, { TUIChatService, TUIStore, StoreName, TUITranslateService, IConversationModel, SendMessageParams, } from '@tencentcloud/chat-uikit-engine'; import { Toast, TOAST_TYPE } from '../../common/Toast/index'; import { isEnabledMessageReadReceiptGlobal } from '../utils/utils'; import { ITipTapEditorContent } from '../../../interface'; import { enableSampleTaskStatus } from '../../../utils/enableSampleTaskStatus'; import OfflinePushInfoManager, { IOfflinePushInfoCreateParams } from '../offlinePushInfoManager/index'; export const sendMessageErrorCodeMap: Map = new Map([ [3123, '文本包含本地审核拦截词'], [4004, '图片消息失败,无效的图片格式'], [4005, '文件消息失败,禁止发送违规封禁的文件'], [7004, '文件不存在,请检查文件路径是否正确'], [7005, '文件大小超出了限制,如果上传文件,最大限制是100MB'], [8001, '消息长度超出限制,消息长度不要超过12K'], [80001, '消息或者资料中文本存在敏感内容,发送失败'], [80004, '消息中图片存在敏感内容,发送失败'], ]); export const createOfflinePushInfo = (conversation: IConversationModel) => { const androidInfo = { sound: 'private_ring.mp3', XiaoMiChannelID: 'high_custom_1', OPPOChannelID: 'tuikit', }; const apnsInfo = { sound: '01.caf', image: 'https://web.sdk.qcloud.com/im/demo/latest/faviconnew.png', }; const userInfo = TUIStore.getData(StoreName.USER, 'userProfile'); const entity = { sender: conversation.type === TUIChatEngine.TYPES.CONV_GROUP ? conversation.groupProfile?.groupID : userInfo.userID, nickName: userInfo.nick, chatType: conversation.type === TUIChatEngine.TYPES.CONV_GROUP ? 2 : 1, version: 1, action: 1, }; return { extension: JSON.stringify({ entity }), androidInfo, apnsInfo, }; }; /** * This function only processes five message types: Text/TextAt/Image/Video/File * @param messageList * @param currentConversation */ export const sendMessages = async ( messageList: ITipTapEditorContent[], currentConversation: IConversationModel, ) => { // In case of messageJumping, the sent message is automatically cleared and returns to the bottom if (TUIStore.getData(StoreName.CHAT, 'messageSource')) { TUIStore.update(StoreName.CHAT, 'messageSource', undefined); } messageList?.forEach(async (content: ITipTapEditorContent) => { try { const options: SendMessageParams = { to: currentConversation?.groupProfile?.groupID || currentConversation?.userProfile?.userID, conversationType: currentConversation?.type as any, payload: {}, needReadReceipt: isEnabledMessageReadReceiptGlobal(), }; // handle message typing let textMessageContent; const sendMessageOptions = { offlinePushInfo: {}, }; const offlinePushInfoCreateParams: IOfflinePushInfoCreateParams = { conversation: currentConversation, payload: content.payload, messageType: '', }; switch (content?.type) { case 'text': textMessageContent = JSON.parse(JSON.stringify(content.payload?.text)); // Do not send empty messages if (!textMessageContent) { break; } options.payload = { text: textMessageContent, }; offlinePushInfoCreateParams.messageType = TUIChatEngine.TYPES.MSG_TEXT; sendMessageOptions.offlinePushInfo = OfflinePushInfoManager.create(offlinePushInfoCreateParams); if (content.payload?.atUserList) { options.payload.atUserList = content.payload.atUserList; await TUIChatService.sendTextAtMessage(options, sendMessageOptions); } else { await TUIChatService.sendTextMessage(options, sendMessageOptions); } break; case 'image': options.payload = { file: content.payload?.file, }; offlinePushInfoCreateParams.messageType = TUIChatEngine.TYPES.MSG_IMAGE; sendMessageOptions.offlinePushInfo = OfflinePushInfoManager.create(offlinePushInfoCreateParams); await TUIChatService.sendImageMessage(options, sendMessageOptions); break; case 'video': options.payload = { file: content.payload?.file, }; offlinePushInfoCreateParams.messageType = TUIChatEngine.TYPES.MSG_VIDEO; sendMessageOptions.offlinePushInfo = OfflinePushInfoManager.create(offlinePushInfoCreateParams); await TUIChatService.sendVideoMessage(options, sendMessageOptions); break; case 'file': options.payload = { file: content.payload?.file, }; offlinePushInfoCreateParams.messageType = TUIChatEngine.TYPES.MSG_FILE; sendMessageOptions.offlinePushInfo = OfflinePushInfoManager.create(offlinePushInfoCreateParams); await TUIChatService.sendFileMessage(options, sendMessageOptions); break; default: break; } enableSampleTaskStatus('sendMessage'); } catch (error: any) { Toast({ message: sendMessageErrorCodeMap.get(error?.code) ? TUITranslateService.t(`TUIChat.${sendMessageErrorCodeMap.get(error.code) as string}`) : error?.message, type: TOAST_TYPE.ERROR, }); // If the message fails to be sent and the message is a reference message, clear the reference message information if (TUIStore.getData(StoreName.CHAT, 'quoteMessage')) { TUIStore.update(StoreName.CHAT, 'quoteMessage', {}); } } }); }; export const handleMessageWithTyping = (cloudCustomData: any) => { if (!cloudCustomData) { cloudCustomData = {}; } cloudCustomData.messageFeature = { needTyping: 1, version: 1, }; return cloudCustomData; }; export const sendTyping = (inputContentEmpty: boolean, inputBlur: boolean) => { if (!inputContentEmpty && !inputBlur) { TUIChatService.enterTypingState(); } else { TUIChatService.leaveTypingState(); } };