1173 lines
40 KiB
Plaintext
1173 lines
40 KiB
Plaintext
/*
|
|
* Copyright (c) 2022 NetEase, Inc. All rights reserved.
|
|
* Use of this source code is governed by a MIT license that can be
|
|
* found in the LICENSE file.
|
|
*
|
|
*/
|
|
|
|
import {
|
|
AitModel,
|
|
ChatKitClient,
|
|
ChatRepo,
|
|
collectionTypeOffset,
|
|
ConversationRepo,
|
|
ErrorUtils,
|
|
IMKitConfigCenter,
|
|
LocalConversationRepo,
|
|
StorageRepo,
|
|
YxAitMsg
|
|
} from '@nimkit/chatkit';
|
|
import fs from '@ohos.file.fs';
|
|
import {
|
|
V2NIMAIModelRoleType,
|
|
V2NIMAIUser,
|
|
V2NIMConnectStatus,
|
|
V2NIMDataSyncState,
|
|
V2NIMDataSyncType,
|
|
V2NIMError,
|
|
V2NIMErrorCode,
|
|
V2NIMLoginStatus,
|
|
V2NIMMessage,
|
|
V2NIMMessageAIConfigParams,
|
|
V2NIMMessageAIStatus,
|
|
V2NIMMessageAIStreamStatus,
|
|
V2NIMMessageConfig,
|
|
V2NIMMessageDeletedNotification,
|
|
V2NIMMessageFileAttachment,
|
|
V2NIMMessagePinNotification,
|
|
V2NIMMessagePinState,
|
|
V2NIMMessagePushConfig,
|
|
V2NIMMessageRevokeNotification,
|
|
V2NIMMessageSendingState,
|
|
V2NIMMessageType,
|
|
V2NIMQueryDirection,
|
|
V2NIMSendMessageParams
|
|
} from '@nimsdk/base';
|
|
import { NIMMessageInfo } from '../model/NIMMessageInfo';
|
|
import { ChatInfo } from '../model/ChatInfo';
|
|
import { ChatConst } from '../constants/ChatConst';
|
|
import { BusinessError } from '@kit.BasicServicesKit';
|
|
import { DeviceUtils } from '../common/DeviceUtils';
|
|
import { image } from '@kit.ImageKit';
|
|
import {
|
|
saveLocalRevokeMessage,
|
|
saveLocalRevokeMessageFormOther
|
|
} from '@nimkit/chatkit/src/main/ets/utils/MessageUtils';
|
|
import { ConversationSelectModel } from '@nimkit/chatkit/src/main/ets/model/ConversationSelectModel';
|
|
import { ChatKitConfig } from '../ChatKitConfig';
|
|
import { sceneMap } from '@kit.MapKit';
|
|
import { clearForwardAtMark, createForwardMessageListFileDetail, sendMessageFailedTips } from '../common/MessageHelper';
|
|
import { instanceToPlain } from 'class-transformer';
|
|
import { NECommonUtils, UserUtils } from '@nimkit/common';
|
|
import { HashMap, JSON } from '@kit.ArkTS';
|
|
import { assign } from '@nimsdk/vendor';
|
|
import { BasicConstant, ChatExtModel, preferenceStore } from '@itcast/basic';
|
|
|
|
@ObservedV2
|
|
export class ChatBaseViewModel {
|
|
@Trace static currentViewModel: ChatBaseViewModel | undefined = undefined
|
|
@Trace anchorMsg: NIMMessageInfo | undefined = undefined
|
|
@Trace conversationId: string = ""
|
|
// p2p 会话是对方账号ID,群聊是为群ID teamId
|
|
targetId: string = ""
|
|
@Trace chatInfo: ChatInfo | undefined = undefined
|
|
@Trace selectMsgMap: Map<string, NIMMessageInfo> = new Map()
|
|
@Trace selectMsgCount = 0
|
|
@Trace needScrollToBottom = false
|
|
isLoading = false
|
|
hasMore = false
|
|
hasNew = false
|
|
revokeMsg: NIMMessageInfo | undefined = undefined
|
|
sendingMsgClientId: string = ''
|
|
saveRevokeClientId: string = ''
|
|
hasLoadData = false
|
|
// 网络连接状态
|
|
@Trace networkBroken: boolean = ChatKitClient.connectBroken()
|
|
// 流式 ing 缓存数据
|
|
private streamingMessageMap: HashMap<string, StreamMessage> = new HashMap();
|
|
// 发送消息
|
|
onSendFun = async (message: V2NIMMessage): Promise<void> => {
|
|
if (message.conversationId === this.conversationId) {
|
|
if (message.sendingState == V2NIMMessageSendingState.V2NIM_MESSAGE_SENDING_STATE_SENDING) {
|
|
if (message.messageClientId !== this.sendingMsgClientId) {
|
|
this.sendingMsgClientId = message.messageClientId
|
|
this.chatInfo?.pushMessage(message)
|
|
this.chatInfo?.setReceiveMsg(true)
|
|
}
|
|
|
|
} else {
|
|
let result = this.chatInfo?.updateMessageStatus(message)
|
|
if (!result) {
|
|
this.chatInfo?.setReceiveMsg(true)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
private msgDirection: number = 0
|
|
|
|
setAnchorMessage(msg: NIMMessageInfo | undefined) {
|
|
this.anchorMsg = msg
|
|
}
|
|
|
|
init(conversationId: string, chatInfo: ChatInfo) {
|
|
this.conversationId = conversationId
|
|
this.targetId = ChatKitClient.nim.conversationIdUtil.parseConversationTargetId(conversationId)
|
|
this.chatInfo = chatInfo;
|
|
// 设置当前会话
|
|
ChatKitClient.setCurrentConversationId(this.conversationId)
|
|
// 注册消息接受监听
|
|
ChatRepo.onReceiverMessage(this.onReceiveFun)
|
|
// 注册消息更新监听
|
|
ChatRepo.onReceiveMessagesModified(this.onModifyFun)
|
|
// 注册消息发送监听
|
|
ChatRepo.onSendMessage(this.onSendFun)
|
|
// 注册消息删除监听
|
|
ChatRepo.onDeleteMessage(this.onDeleteFun)
|
|
// 注册消息撤回监听
|
|
ChatRepo.onRevokeMessage(this.onRevokeFun)
|
|
// 注册消息置顶监听
|
|
ChatRepo.onMessagePinNotification(this.onPinFun)
|
|
|
|
// 监听数据同步完成监听
|
|
ChatKitClient.nim.loginService.on('onDataSync', this.onSyncFinishedFun)
|
|
// 长连接状态变更
|
|
ChatKitClient.nim.loginService?.on('onConnectStatus', this.onConnectStatusChange)
|
|
// 登录状态变更
|
|
ChatKitClient.nim.loginService?.on('onLoginStatus', this.onLoginStatusChange)
|
|
|
|
ChatBaseViewModel.currentViewModel = this
|
|
// 清理未读数
|
|
this.clearUnreadCount()
|
|
}
|
|
|
|
onConnectStatusChange = (status: V2NIMConnectStatus) => {
|
|
if (status !== V2NIMConnectStatus.V2NIM_CONNECT_STATUS_CONNECTED) {
|
|
this.networkBroken = true
|
|
}
|
|
}
|
|
onLoginStatusChange = (status: V2NIMLoginStatus) => {
|
|
if (status === V2NIMLoginStatus.V2NIM_LOGIN_STATUS_LOGINED) {
|
|
this.networkBroken = false
|
|
}
|
|
}
|
|
// 处理数据同步完成
|
|
onSyncFinishedFun = (type: V2NIMDataSyncType,
|
|
state: V2NIMDataSyncState,
|
|
error?: V2NIMError) => {
|
|
if (state == V2NIMDataSyncState.V2NIM_DATA_SYNC_STATE_COMPLETED) {
|
|
this.toHandleDataSyncFinished()
|
|
}
|
|
}
|
|
// 接受消息
|
|
onReceiveFun = (messages: V2NIMMessage[]) => {
|
|
if (this.hasNew) {
|
|
return
|
|
}
|
|
let hasNew = false
|
|
let receiveMsg: NIMMessageInfo[] = [];
|
|
for (let i = messages.length - 1; i >= 0; i--) {
|
|
let msg = messages[i];
|
|
if (msg.conversationId == this.conversationId) {
|
|
let msgInfo = this.chatInfo?.pushMessage(msg);
|
|
if (msgInfo !== undefined) {
|
|
receiveMsg.push(msgInfo)
|
|
}
|
|
hasNew = true;
|
|
}
|
|
}
|
|
if (hasNew) {
|
|
this.toHandleReceiveMessage(receiveMsg)
|
|
this.clearUnreadCount()
|
|
this.chatInfo?.setReceiveMsg(true);
|
|
}
|
|
}
|
|
// 更新消息
|
|
onModifyFun = (messages: V2NIMMessage[]) => {
|
|
for (let i = messages.length - 1; i >= 0; i--) {
|
|
let message = messages[i];
|
|
// 流式并且机器人回复消息,走流式展示逻辑
|
|
if (message.aiConfig?.aiStream && message.aiConfig?.aiStatus === V2NIMMessageAIStatus.V2NIM_MESSAGE_AI_STATUS_RESPONSE) {
|
|
this.onModifyFunStream(message)
|
|
} else {
|
|
this.onModifyFunNormal(message)
|
|
}
|
|
}
|
|
}
|
|
|
|
private onModifyFunNormal = (message: V2NIMMessage) => {
|
|
if (this.hasNew) {
|
|
return
|
|
}
|
|
let hasNew = false
|
|
let receiveMsg: NIMMessageInfo[] = [];
|
|
if (message.conversationId == this.conversationId) {
|
|
let msgInfo = this.chatInfo?.pushModifyMessage(message);
|
|
if (msgInfo !== undefined) {
|
|
receiveMsg.push(msgInfo)
|
|
}
|
|
hasNew = true;
|
|
}
|
|
if (hasNew) {
|
|
this.toHandleReceiveMessage(receiveMsg)
|
|
// this.clearUnreadCount() // 更新消息不做 clear 动作
|
|
this.chatInfo?.setReceiveMsg(true);
|
|
}
|
|
}
|
|
|
|
private onModifyFunStream = async (message: V2NIMMessage) => {
|
|
if (message.aiConfig?.aiStreamStatus === V2NIMMessageAIStreamStatus.V2NIM_MESSAGE_AI_STREAM_STATUS_STREAMING) {
|
|
// 检查新老情况
|
|
const messageClientId: string = message.messageClientId
|
|
const oldStreamMessage: StreamMessage | undefined = this.streamingMessageMap.get(messageClientId) // 老的
|
|
const newStreamMessage: StreamMessage = new StreamMessage(message) // 新的
|
|
this.streamingMessageMap.set(messageClientId, newStreamMessage) // 替换成新的
|
|
|
|
// 准备裁切 message.text
|
|
const oldLen = oldStreamMessage?.message?.text?.length ?? 0
|
|
const newLen = newStreamMessage.message?.text?.length ?? 0
|
|
const newStr: string = newStreamMessage.message?.text ?? ''
|
|
const currentIndex: number = newStreamMessage.index
|
|
|
|
// 开始裁切
|
|
for (let i = oldLen; i < newLen; i++) {
|
|
const latestStreaming: StreamMessage | undefined = this.streamingMessageMap.get(messageClientId)
|
|
if (latestStreaming.finish || currentIndex !== latestStreaming.index) {
|
|
break; // finish or index 已经发生了变化,不再更新
|
|
}
|
|
const tmpMessage: V2NIMMessage = assign({}, message)
|
|
const tmpStr: string = newStr.substring(0, i + 1);
|
|
tmpMessage.text = tmpStr
|
|
this.onModifyFunNormal(tmpMessage) // 循环 modify
|
|
// 阻塞 20ms,避免循环过快而回调过快
|
|
await new Promise<void>(resolve => {
|
|
setTimeout(resolve, 20); // 例如,这里设置一个 20 毫秒的延迟。还有优化空间
|
|
});
|
|
}
|
|
} else {
|
|
if (message.aiConfig?.aiStreamStatus === V2NIMMessageAIStreamStatus.V2NIM_MESSAGE_AI_STREAM_STATUS_STOPPED ||
|
|
message.aiConfig?.aiStreamStatus === V2NIMMessageAIStreamStatus.V2NIM_MESSAGE_AI_STREAM_STATUS_UPDATED ||
|
|
message.aiConfig?.aiStreamStatus === V2NIMMessageAIStreamStatus.V2NIM_MESSAGE_AI_STREAM_STATUS_GENERATED ||
|
|
message.aiConfig?.aiStreamStatus === V2NIMMessageAIStreamStatus.V2NIM_MESSAGE_AI_STREAM_STATUS_ABORTED) {
|
|
// finish
|
|
const oldStreaming = this.streamingMessageMap.get(message.messageClientId)
|
|
if (oldStreaming) {
|
|
oldStreaming.finish = true
|
|
} else {
|
|
this.streamingMessageMap.set(message.messageClientId, new StreamMessage(message)) // finished message
|
|
}
|
|
}
|
|
this.onModifyFunNormal(message) // 直接 modify
|
|
}
|
|
}
|
|
|
|
// 删除消息
|
|
onDeleteFun = (messages: V2NIMMessageDeletedNotification[]) => {
|
|
messages.forEach((msg, index, messages) => {
|
|
if (msg.messageRefer.conversationId === this.conversationId) {
|
|
this.removeReplyInfo(msg.messageRefer.messageClientId)
|
|
this.chatInfo?.deleteMessage(msg.messageRefer.messageClientId)
|
|
if (this.selectMsgMap.has(msg.messageRefer.messageClientId)) {
|
|
this.selectMsgMap.delete(msg.messageRefer.messageClientId)
|
|
this.selectMsgCount = this.selectMsgMap.size
|
|
}
|
|
}
|
|
})
|
|
// 等待 1 秒,然后重新拉取一次消息
|
|
if ((this.chatInfo?.msgList.totalCount() ?? 0) <= 0) {
|
|
setTimeout(() => {
|
|
this.getMessageList() // 被删完了消息之后,防止消息空了,重新拉取
|
|
}, 1000)
|
|
}
|
|
}
|
|
// 撤回消息
|
|
onRevokeFun = (messages: V2NIMMessageRevokeNotification[]) => {
|
|
messages.forEach((msg, index, messages) => {
|
|
if (msg.messageRefer.conversationId === this.conversationId) {
|
|
let revokeMsg = this.chatInfo?.getMessage(msg.messageRefer.messageClientId)
|
|
this.removeReplyInfo(msg.messageRefer.messageClientId)
|
|
this.chatInfo?.revokeMessage(msg.messageRefer.messageClientId)
|
|
if (this.selectMsgMap.has(msg.messageRefer.messageClientId)) {
|
|
this.selectMsgMap.delete(msg.messageRefer.messageClientId)
|
|
this.selectMsgCount = this.selectMsgMap.size
|
|
}
|
|
if (this.saveRevokeClientId == revokeMsg?.message.messageServerId) {
|
|
return
|
|
}
|
|
this.saveRevokeClientId = revokeMsg?.message.messageServerId ?? ''
|
|
console.debug('netease viewmodel onRevokeFun revoke message', msg.revokeAccountId,
|
|
msg.messageRefer.messageClientId)
|
|
if (revokeMsg !== undefined && msg.messageRefer.senderId == ChatKitClient.getLoginUserId()) {
|
|
let canEdit =
|
|
!revokeMsg.isReceiveMsg && revokeMsg.message.messageType == V2NIMMessageType.V2NIM_MESSAGE_TYPE_TEXT
|
|
saveLocalRevokeMessage(msg.messageRefer.conversationId, revokeMsg.message, canEdit)
|
|
} else {
|
|
saveLocalRevokeMessageFormOther(msg.messageRefer.conversationId, msg, false)
|
|
}
|
|
}
|
|
})
|
|
}
|
|
// 置顶消息
|
|
onPinFun = ((notification: V2NIMMessagePinNotification) => {
|
|
if (notification.pinState == V2NIMMessagePinState.V2NIM_MESSAGE_PIN_STATE_PINNED) {
|
|
this.chatInfo?.addPinMessage([notification.pin])
|
|
this.needScrollToBottom = true
|
|
|
|
} else if (notification.pinState == V2NIMMessagePinState.V2NIM_MESSAGE_PIN_STATE_UPDATED) {
|
|
this.chatInfo?.addPinMessage([notification.pin])
|
|
this.needScrollToBottom = true
|
|
|
|
} else if (notification.pinState == V2NIMMessagePinState.V2NIM_MESSAGE_PIN_STATE_NOT_PINNED) {
|
|
this.chatInfo?.removePinMessage([notification.pin])
|
|
}
|
|
|
|
})
|
|
|
|
loadAnchorMsg(msg: NIMMessageInfo) {
|
|
this.loadMessageListWithAnchor(msg)
|
|
}
|
|
|
|
// 拉取历史消息
|
|
async getMessageList(): Promise<NIMMessageInfo[]> {
|
|
let hasError = false
|
|
const messageList: V2NIMMessage[] = await ChatRepo.getMessageList({
|
|
'conversationId': this.conversationId,
|
|
'limit': ChatConst.chatMessagePageSize,
|
|
'direction': this.msgDirection,
|
|
'onlyQueryLocal': false,
|
|
'strictMode': true
|
|
}).catch((err: BusinessError) => {
|
|
hasError = true
|
|
return []
|
|
})
|
|
let result: NIMMessageInfo[] = [];
|
|
if (hasError) {
|
|
return result
|
|
}
|
|
// 拉回的消息数据存在误差
|
|
if (messageList.length >= ChatConst.chatMessagePageSize - 10) {
|
|
this.hasMore = true;
|
|
} else {
|
|
this.hasMore = false;
|
|
}
|
|
this.chatInfo?.cleanMessage()
|
|
this.setAnchorMessage(undefined)
|
|
for (let index = messageList.length - 1; index >= 0; index--) {
|
|
let msgInfo = this.chatInfo?.pushMessage(messageList[index]);
|
|
if (msgInfo != undefined) {
|
|
result.push(msgInfo);
|
|
}
|
|
}
|
|
// 修改接受消息标志,如果有新消息则更新接受消息标志,否则列表滚动到底部
|
|
this.chatInfo?.setReceiveMsg(true)
|
|
this.toHandleQueryMessage(result, messageList)
|
|
this.hasLoadData = true
|
|
return result;
|
|
}
|
|
|
|
async loadMessageListWithAnchor(anchorMsg: NIMMessageInfo): Promise<NIMMessageInfo[]> {
|
|
let errorCount = 0
|
|
let result: NIMMessageInfo[] = [];
|
|
const messageBeforList: V2NIMMessage[] = await ChatRepo.getMessageList({
|
|
'conversationId': this.conversationId,
|
|
'anchorMessage': anchorMsg.message,
|
|
'limit': ChatConst.chatMessagePageSize,
|
|
'direction': V2NIMQueryDirection.V2NIM_QUERY_DIRECTION_DESC
|
|
}).catch((err: BusinessError) => {
|
|
errorCount++
|
|
return []
|
|
})
|
|
const messageAfterList: V2NIMMessage[] = await ChatRepo.getMessageList({
|
|
'conversationId': this.conversationId,
|
|
'anchorMessage': anchorMsg.message,
|
|
'limit': ChatConst.chatMessagePageSize,
|
|
'direction': V2NIMQueryDirection.V2NIM_QUERY_DIRECTION_ASC
|
|
}).catch((err: BusinessError) => {
|
|
errorCount++
|
|
return []
|
|
})
|
|
if (errorCount > 1) {
|
|
return result
|
|
}
|
|
this.chatInfo?.cleanMessage()
|
|
if (messageBeforList.length > 0) {
|
|
for (let index = messageBeforList.length - 1; index >= 0; index--) {
|
|
let msgInfo = this.chatInfo?.pushMessage(messageBeforList[index])
|
|
if (msgInfo != undefined) {
|
|
result.push(msgInfo);
|
|
}
|
|
}
|
|
}
|
|
this.chatInfo?.pushMessageInfo(anchorMsg)
|
|
let anchorIndex = this.chatInfo?.msgList.totalCount() ?? 1 - 1
|
|
if (messageAfterList.length > 0) {
|
|
for (let index = 0; index < messageAfterList.length; index++) {
|
|
let msgInfo = this.chatInfo?.pushMessage(messageAfterList[index])
|
|
if (msgInfo != undefined) {
|
|
result.push(msgInfo);
|
|
}
|
|
}
|
|
}
|
|
if (messageAfterList.length > ChatConst.chatMessagePageSize - 5 || this.networkBroken) {
|
|
this.hasNew = true
|
|
} else if (!this.networkBroken) {
|
|
this.hasNew = false;
|
|
}
|
|
// // 修改接受消息标志,如果有新消息则更新接受消息标志,否则列表滚动到底部
|
|
// this.chatInfo?.setReceiveMsg(true)
|
|
this.toHandleQueryMessage(result, messageAfterList)
|
|
if (anchorIndex) {
|
|
this.chatInfo?.setScrollIndex(anchorIndex)
|
|
}
|
|
this.hasLoadData = true
|
|
return result;
|
|
}
|
|
|
|
// 处理接受消息,用于子类进行特殊业务处理
|
|
toHandleReceiveMessage(messages: NIMMessageInfo[]) {
|
|
|
|
}
|
|
|
|
// 处理查询消息,用于子类进行特殊业务处理
|
|
toHandleQueryMessage(messages: NIMMessageInfo[], originMsg: V2NIMMessage[]) {
|
|
|
|
}
|
|
|
|
toHandleDataSyncFinished() {
|
|
|
|
}
|
|
|
|
// 是否有更多消息,分页加载
|
|
canLoadMore(): boolean {
|
|
return this.hasMore && !this.isLoading;
|
|
}
|
|
|
|
// 是否有更多新消息加载,分页加载
|
|
canLoadNext(end: number): boolean {
|
|
return this.hasNew && !this.isLoading && this.chatInfo !== undefined &&
|
|
this.chatInfo.msgList.totalCount() - end < ChatConst.chatMessagePageSize
|
|
}
|
|
|
|
// 拉取历史消息
|
|
async getMoreMessageList(): Promise<NIMMessageInfo[]> {
|
|
let anchorMsg = this.chatInfo?.msgList.getData(0)
|
|
if (this.isLoading || anchorMsg == undefined) {
|
|
return []
|
|
}
|
|
this.isLoading = true;
|
|
let result: NIMMessageInfo[] = [];
|
|
await ChatRepo.getMessageList({
|
|
"anchorMessage": anchorMsg.message,
|
|
"conversationId": this.conversationId,
|
|
"limit": ChatConst.chatMessagePageSize,
|
|
"direction": this.msgDirection,
|
|
}).then((messageList: V2NIMMessage[]) => {
|
|
// SDK 返回消息不太稳定,所以按照更小的值判断是否有下一页
|
|
if (messageList.length >= ChatConst.chatMessagePageSize - 5 || this.networkBroken) {
|
|
this.hasMore = true
|
|
} else {
|
|
this.hasMore = false
|
|
}
|
|
if (this.chatInfo) {
|
|
result = this.chatInfo.unshiftMessage(messageList)
|
|
}
|
|
this.toHandleQueryMessage(result, messageList)
|
|
this.isLoading = false
|
|
}).catch((err: BusinessError) => {
|
|
this.isLoading = false
|
|
if (this.networkBroken) {
|
|
this.hasMore = true
|
|
}
|
|
})
|
|
return result
|
|
}
|
|
|
|
// 拉取历史消息
|
|
async getNewMessageList(): Promise<NIMMessageInfo[]> {
|
|
if (this.isLoading || !this.hasNew) {
|
|
return []
|
|
}
|
|
let anchorMsg = this.chatInfo?.msgList.getData(this.chatInfo?.msgList.totalCount() - 1)
|
|
if (anchorMsg == undefined) {
|
|
return []
|
|
}
|
|
this.isLoading = true;
|
|
let result: NIMMessageInfo[] = [];
|
|
await ChatRepo.getMessageList({
|
|
"anchorMessage": anchorMsg.message,
|
|
"conversationId": this.conversationId,
|
|
"limit": ChatConst.chatMessagePageSize,
|
|
"direction": V2NIMQueryDirection.V2NIM_QUERY_DIRECTION_ASC,
|
|
}).then((messageList: V2NIMMessage[]) => {
|
|
// SDK 返回消息不太稳定,所以按照更小的值判断是否有下一页
|
|
if (messageList.length >= ChatConst.chatMessagePageSize - 10 || this.networkBroken) {
|
|
this.hasNew = true
|
|
} else {
|
|
this.hasNew = false
|
|
}
|
|
console.debug('netease getNewMessageList,lenght:', messageList.length, 'hasNew:', this.hasNew)
|
|
|
|
if (this.chatInfo) {
|
|
for (let index = 0; index < messageList.length; index++) {
|
|
let msgInfo = this.chatInfo.pushMessage(messageList[index])
|
|
result.push(msgInfo)
|
|
}
|
|
}
|
|
this.toHandleQueryMessage(result, messageList)
|
|
this.isLoading = false
|
|
}).catch((err: BusinessError) => {
|
|
this.isLoading = false
|
|
if (this.networkBroken) {
|
|
this.hasNew = true
|
|
} else {
|
|
this.hasNew = false
|
|
}
|
|
})
|
|
return result
|
|
}
|
|
|
|
// 拉取PIN信息
|
|
getPinList() {
|
|
ChatRepo.getPinnedMessageList(this.conversationId).then((pinMessageList) => {
|
|
this.chatInfo?.resetPinMessage(pinMessageList)
|
|
this.needScrollToBottom = true
|
|
})
|
|
}
|
|
|
|
// 删除消息
|
|
deleteMessage(messages: NIMMessageInfo[]) {
|
|
for (const message of messages) {
|
|
ChatRepo.deleteMessage(message.message, undefined, false).then(() => {
|
|
this.removeReplyInfo(message.message.messageClientId)
|
|
}).catch((err: BusinessError) => {
|
|
ErrorUtils.handleErrorToast(err.code)
|
|
});
|
|
}
|
|
}
|
|
|
|
// 批量删除消息
|
|
deleteMessageList(messages: NIMMessageInfo[]) {
|
|
let msgList: V2NIMMessage[] = []
|
|
messages.forEach((msg, index, messages) => {
|
|
msgList.push(msg.message)
|
|
})
|
|
|
|
ChatRepo.deleteMessages(msgList, undefined, false).then(() => {
|
|
messages.forEach((msg) => {
|
|
this.removeReplyInfo(msg.message.messageClientId)
|
|
})
|
|
}).catch((err: BusinessError) => {
|
|
ErrorUtils.handleErrorToast(err.code)
|
|
});
|
|
}
|
|
|
|
// 撤回消息
|
|
revokeMessage(msg: NIMMessageInfo) {
|
|
ChatRepo.revokeMessage(msg.message).then(() => {
|
|
if (msg.isPinMsg && msg.pinInfo) {
|
|
ChatRepo.unpinMessage(msg.pinInfo?.messageRefer)
|
|
}
|
|
this.removeReplyInfo(msg.message.messageClientId)
|
|
}).catch((err: BusinessError) => {
|
|
ErrorUtils.handleErrorToast(err.code)
|
|
console.error(`netease Invoke startAbility failed, code is ${err.code}, message is ${err.message}`);
|
|
});
|
|
}
|
|
|
|
/// 移除被回复信息
|
|
removeReplyInfo(invalidMessageClientId: string) {
|
|
const invalidMessage = this.chatInfo?.getMessage(invalidMessageClientId)
|
|
if (invalidMessage) {
|
|
const invalidIndex = this.chatInfo?.msgList.getMessageList().indexOf(invalidMessage)
|
|
if (invalidIndex) {
|
|
for (let index = invalidIndex; index < (this.chatInfo?.msgList.totalCount() ?? invalidIndex); index++) {
|
|
let message = this.chatInfo?.msgList.getMessageList()[index]
|
|
if (message && message.replyMsg?.message.messageClientId === invalidMessage.message.messageClientId) {
|
|
message.replyMsg = undefined
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// 收藏消息
|
|
collectionMessage(msg: NIMMessageInfo) {
|
|
if (ErrorUtils.checkNetworkAndToast()) {
|
|
let collectionDic: Record<string, Object> = {}
|
|
let message = msg.message
|
|
clearForwardAtMark(message)
|
|
const messageString = ChatKitClient.nim.messageConverter.messageSerialization(message)
|
|
if (messageString) {
|
|
collectionDic["message"] = messageString
|
|
}
|
|
|
|
collectionDic['conversationName'] = this.chatInfo?.conversationName ?? ''
|
|
collectionDic['senderName'] = this.chatInfo?.getChatUserShowName(message) ?? ''
|
|
collectionDic['avatar'] = this.chatInfo?.getChatUserAvatarUrl(message) ?? ''
|
|
|
|
const collectionData = JSON.stringify(collectionDic)
|
|
|
|
ChatRepo.addCollection({
|
|
collectionType: message.messageType.valueOf() + collectionTypeOffset,
|
|
collectionData: collectionData,
|
|
uniqueId: message.messageServerId
|
|
}).catch((err: BusinessError) => {
|
|
ErrorUtils.handleErrorToast(err.code)
|
|
}).finally(() => {
|
|
NECommonUtils.showToast($r('app.string.chat_collection_success'))
|
|
})
|
|
}
|
|
}
|
|
|
|
// PIN消息
|
|
pinMessage(msg: NIMMessageInfo) {
|
|
if (ErrorUtils.checkNetworkAndToast()) {
|
|
ChatRepo.pinMessage(msg.message).catch((err: BusinessError) => {
|
|
if (err.code == V2NIMErrorCode.V2NIM_ERROR_CODE_PIN_ALREADY_EXIST) {
|
|
return
|
|
}
|
|
ErrorUtils.handleErrorToast(err.code)
|
|
})
|
|
}
|
|
}
|
|
|
|
unpinMessage(msg: NIMMessageInfo) {
|
|
if (ErrorUtils.checkNetworkAndToast()) {
|
|
if (msg.isPinMsg) {
|
|
if (msg.pinInfo?.messageRefer !== undefined) {
|
|
ChatRepo.unpinMessage(msg.pinInfo?.messageRefer).catch((err: BusinessError) => {
|
|
if (err.code == V2NIMErrorCode.V2NIM_ERROR_CODE_PIN_NOT_EXIST) {
|
|
return
|
|
}
|
|
ErrorUtils.handleErrorToast(err.code)
|
|
})
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// 清理未读数
|
|
clearUnreadCount() {
|
|
if (IMKitConfigCenter.enableLocalConversation) {
|
|
LocalConversationRepo.clearUnreadCountByIds([this.conversationId])
|
|
} else {
|
|
ConversationRepo.clearUnreadCountByIds([this.conversationId])
|
|
}
|
|
}
|
|
|
|
// 消息发送之前调用,用于配置消息通用参数
|
|
beforeSendMessage(msg: V2NIMMessage){
|
|
// if (ChatKitConfig.messageReadState) {
|
|
// let msgConfig: V2NIMMessageConfig = {
|
|
// readReceiptEnabled: false
|
|
// }
|
|
// msg.messageConfig = msgConfig
|
|
// }
|
|
|
|
return msg
|
|
}
|
|
|
|
// 发送消息并设置发送进度
|
|
sendMessageAndSetProgress(message: V2NIMMessage) {
|
|
this.sendMessage(this.beforeSendMessage(message), undefined, (percentage: number) => {
|
|
let msgInfo = this.chatInfo?.getMessage(message.messageClientId)
|
|
if (msgInfo) {
|
|
let progress = percentage * 100
|
|
msgInfo.setDownloadProgress(progress)
|
|
if (progress >= 100) {
|
|
msgInfo.setDownloadProgress(-1)
|
|
}
|
|
}
|
|
});
|
|
}
|
|
|
|
// 发送文本消息
|
|
async sendTextMessage(text: string, replyMsg?: NIMMessageInfo, aitModel?: AitModel, pushList?: string[]) {
|
|
const message = ChatRepo.createTextMessage(text)
|
|
//设置Ait
|
|
// if (aitModel && aitModel.aitBlocks.size > 0) {
|
|
// let extensionMap: YxAitMsg = {
|
|
// yxAitMsg: aitModel.aitBlocks
|
|
// }
|
|
// let extension = JSON.stringify(instanceToPlain(extensionMap))
|
|
// message.serverExtension = extension
|
|
// }
|
|
|
|
|
|
|
|
//设置推送
|
|
let params: V2NIMSendMessageParams | undefined = undefined
|
|
if (pushList) {
|
|
params = {
|
|
pushConfig: {
|
|
forcePush: true,
|
|
forcePushAccountIds: pushList.length >= 0 ? pushList : undefined
|
|
}
|
|
}
|
|
}
|
|
|
|
// 回复
|
|
if (replyMsg) {
|
|
this.replyMessage(message, replyMsg.message, params)
|
|
return
|
|
}
|
|
|
|
// 设置 AI 配置
|
|
const enableAIStream: boolean = false
|
|
if (enableAIStream) {
|
|
const text: string = message.text ?? '你是谁'
|
|
const aiUsers: V2NIMAIUser[] = await ChatKitClient.nim.aiService!.getAIUserList()
|
|
const ollamaaitest20AIUser: V2NIMAIUser | undefined =
|
|
aiUsers.find((aiUser) => aiUser.accountId === 'ollamaaitest9')
|
|
|
|
const aiParams: V2NIMMessageAIConfigParams = {
|
|
accountId: ollamaaitest20AIUser ? ollamaaitest20AIUser.accountId : (aiUsers.length > 0 ? aiUsers[0].accountId : ''),
|
|
content: {
|
|
msg: text,
|
|
type: 0
|
|
},
|
|
messages: [
|
|
{
|
|
role: V2NIMAIModelRoleType.V2NIM_AI_MODEL_ROLE_TYPE_ASSISTANT,
|
|
msg: text,
|
|
type: 0
|
|
}
|
|
],
|
|
promptVariables: undefined,
|
|
modelConfigParams: {
|
|
prompt: undefined,
|
|
maxTokens: undefined,
|
|
topP: undefined,
|
|
temperature: undefined
|
|
},
|
|
aiStream: true // open aiStream
|
|
}
|
|
|
|
if (typeof params === 'undefined') {
|
|
params = {}
|
|
}
|
|
params.aiConfig = aiParams
|
|
}
|
|
|
|
this.sendMessage(message, params)
|
|
}
|
|
|
|
// 发送位置消息
|
|
async sendLocationMessage(data: sceneMap.LocationChoosingResult) {
|
|
const message = ChatRepo.createLocationMessage(data.location.latitude, data.location.longitude, data.address)
|
|
message.text = data.name
|
|
this.sendMessage(message)
|
|
}
|
|
|
|
/**
|
|
* 发送图片消息
|
|
* @param uri 本地图片地址
|
|
*/
|
|
async sendImageMessage(uri: string) {
|
|
try {
|
|
if (uri.length > 0) {
|
|
let fileType = ""
|
|
const subStrings = uri.split(".");
|
|
if (subStrings.length > 0) {
|
|
fileType = subStrings[subStrings.length - 1];
|
|
}
|
|
// 将文件 拷贝到 临时目录
|
|
const file = await fs.open(uri, fs.OpenMode.READ_ONLY)
|
|
// (以时间戳)生成一个新的文件名
|
|
const fileName = Date.now() + '.' + fileType
|
|
// 通过缓存路径+文件名 拼接出完整的路径
|
|
let fileDir = DeviceUtils.rootDirPath + '/temp/'
|
|
const copyFilePath = fileDir + fileName
|
|
if (!fs.accessSync(fileDir)) {
|
|
await fs.mkdir(fileDir)
|
|
}
|
|
await fs.copyFile(file.fd, copyFilePath)
|
|
const imageSource = image.createImageSource(file.fd);
|
|
let imageInfo = imageSource.getImageInfoSync()
|
|
const message = await ChatRepo.createImageMessage(copyFilePath, file.name, undefined, imageInfo?.size.width,
|
|
imageInfo?.size.height);
|
|
const fn: Function = () => {
|
|
this.sendMessageAndSetProgress(message)
|
|
}
|
|
ChatKitClient.runAfterLoggedIn(fn)
|
|
|
|
await fs.close(file)
|
|
}
|
|
} catch (err) {
|
|
console.log("net ease send image error", err);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* 发送视频消息
|
|
* @param uri 本地视频地址
|
|
* @param duration 视频时长
|
|
* @param width 视频宽度
|
|
* @param height 视频高度
|
|
*/
|
|
async sendVideoMessage(uri: string, duration?: number, width?: number, height?: number, thumbnail?: PixelMap) {
|
|
try {
|
|
let fileType = ""
|
|
const subStrings = uri.split(".");
|
|
if (subStrings.length > 0) {
|
|
fileType = subStrings[subStrings.length - 1];
|
|
}
|
|
// 将文件 拷贝到 临时目录
|
|
const file = await fs.open(uri, fs.OpenMode.READ_ONLY)
|
|
// (以时间戳)生成一个新的文件名
|
|
const fileName = Date.now() + '.' + fileType
|
|
// 通过缓存路径+文件名 拼接出完整的路径
|
|
let fileDir = DeviceUtils.rootDirPath + '/temp/'
|
|
const copyFilePath = fileDir + fileName
|
|
if (!fs.accessSync(fileDir)) {
|
|
await fs.mkdir(fileDir)
|
|
}
|
|
await fs.copyFile(file.fd, copyFilePath)
|
|
const message = await ChatRepo.createVideoMessage(copyFilePath, file.name, undefined, duration, width, height);
|
|
const fn: Function = () => {
|
|
this.sendMessageAndSetProgress(message)
|
|
}
|
|
ChatKitClient.runAfterLoggedIn(fn)
|
|
|
|
await fs.close(file)
|
|
} catch (err) {
|
|
console.log("net ease send video error", err);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* 发送文件消息
|
|
* @param uri 文件地址
|
|
*/
|
|
async sendFileMessage(uri: string) {
|
|
try {
|
|
let fileType = ""
|
|
const subStrings = uri.split(".");
|
|
if (subStrings.length > 0) {
|
|
fileType = subStrings[subStrings.length - 1];
|
|
}
|
|
// 将文件 拷贝到 临时目录
|
|
const file = await fs.open(uri, fs.OpenMode.READ_ONLY)
|
|
// (以时间戳)生成一个新的文件名
|
|
const fileName = Date.now() + '.' + fileType
|
|
// 通过缓存路径+文件名 拼接出完整的路径
|
|
let fileDir = DeviceUtils.rootDirPath + '/temp/'
|
|
const copyFilePath = fileDir + fileName
|
|
if (!fs.accessSync(fileDir)) {
|
|
await fs.mkdir(fileDir)
|
|
}
|
|
await fs.copyFile(file.fd, copyFilePath)
|
|
const message = await ChatRepo.createFileMessage(copyFilePath, file.name);
|
|
this.sendMessage(message, undefined, (percentage: number) => {
|
|
let msgInfo = this.chatInfo?.getMessage(message.messageClientId)
|
|
if (msgInfo !== undefined) {
|
|
let progress = percentage * 100
|
|
msgInfo.setDownloadProgress(progress)
|
|
if (progress >= 100) {
|
|
msgInfo.setDownloadProgress(-1)
|
|
}
|
|
}
|
|
});
|
|
|
|
await fs.close(file)
|
|
} catch (err) {
|
|
console.log("net ease send file error", err);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* 发送语音消息
|
|
* @param uri
|
|
* @param duration 单位 s
|
|
*/
|
|
async sendAudioMessage(uri: string, duration: number) {
|
|
try {
|
|
const message = await ChatRepo.createAudioMessage(uri, undefined, undefined, duration * 1000);
|
|
this.sendMessage(message)
|
|
} catch (err) {
|
|
console.error("net ease send audio message error", err.code, err.message)
|
|
}
|
|
}
|
|
/**
|
|
* 发送自定义消息
|
|
* @param uri
|
|
* @param duration 单位 s
|
|
*/
|
|
async sendCustomMessage(text: string, rawAttachment: string) {
|
|
try {
|
|
const message = await ChatRepo.createCustomMessage(text,rawAttachment);
|
|
this.sendMessage(message)
|
|
} catch (err) {
|
|
console.error("net ease send custom message error"+rawAttachment, err.code, err.message)
|
|
}
|
|
}
|
|
|
|
/**
|
|
* 发送消息
|
|
* @param msg 消息
|
|
* @param params 消息配置参数
|
|
* @param progress 消息发送进度
|
|
*/
|
|
async sendMessage(msg: V2NIMMessage, params?: V2NIMSendMessageParams, progress?: (percentage: number) => void) {
|
|
let extension:ChatExtModel= {
|
|
gdxz_sessionType: preferenceStore.getItemString('gdxz_sessionType'),
|
|
gdxz_consult_uuid: preferenceStore.getItemString('gdxz_consult_uuid')+'',
|
|
gdxz_nickName:await UserUtils.getAvatarName(ChatKitClient.nim.conversationIdUtil.parseConversationTargetId(this.conversationId),'')
|
|
}
|
|
msg.serverExtension =JSON.stringify(extension)
|
|
// Map<String,Integer> p=new HashMap<>();
|
|
// p.put("classification",1);
|
|
// payload.put("vivoField",p);//vivo推送
|
|
// payload.put("apns-collapse-id", "321");//ios需要
|
|
// payload.put("apns-from-id", NimUIKit.getAccount());//ios需要
|
|
// msg.pushConfig = {} as V2NIMMessagePushConfig
|
|
// msg.pushConfig.pushPayload=''
|
|
// 2. 设置推送负载(新增核心代码)
|
|
const pushPayload: Record<string, Record<string,string> | string> = {
|
|
"vivoField": {"classification":"1"},
|
|
"apns-collapse-id": "321",
|
|
"apns-from-id": ChatKitClient.getLoginUserId()
|
|
};
|
|
|
|
if (!msg.pushConfig) {
|
|
msg.pushConfig = {} as V2NIMMessagePushConfig;
|
|
}
|
|
msg.pushConfig.pushPayload = JSON.stringify(pushPayload)
|
|
|
|
ChatRepo.sendMessage(this.beforeSendMessage(msg), this.conversationId!, params, progress)
|
|
.catch((err: BusinessError) => {
|
|
console.error("net ease send message error", err.code, err.message);
|
|
sendMessageFailedTips(msg, err, this.conversationId!)
|
|
})
|
|
}
|
|
|
|
/**
|
|
* 回复消息
|
|
* @param msg 消息
|
|
* @param replyMsg 被回复的消息
|
|
* @param params 消息配置参数
|
|
* @param progress 消息发送进度
|
|
*/
|
|
async replyMessage(msg: V2NIMMessage, replyMsg: V2NIMMessage, params?: V2NIMSendMessageParams,
|
|
progress?: (percentage: number) => void) {
|
|
ChatRepo.replyMessage(this.beforeSendMessage(msg), replyMsg, params, progress)
|
|
.catch((err: BusinessError) => {
|
|
console.error("net ease reply message error", err.code, err.message);
|
|
sendMessageFailedTips(msg, err, this.conversationId!)
|
|
})
|
|
}
|
|
|
|
/**
|
|
* 转发消息
|
|
* @param msg 消息体
|
|
* @param conversationId 转发到某个会话
|
|
* @param params 消息参数
|
|
* @param progress 消息发送进度
|
|
*/
|
|
async sendForwardMessage(msg: V2NIMMessage, conversationId: string, params?: V2NIMSendMessageParams,
|
|
progress?: (percentage: number) => void) {
|
|
ChatRepo.sendMessage(this.beforeSendMessage(msg), conversationId, params, progress)
|
|
.catch((err: BusinessError) => {
|
|
console.error("net ease send message error", err.code, err.message);
|
|
sendMessageFailedTips(msg, err, conversationId)
|
|
})
|
|
}
|
|
|
|
// 消息附件下载
|
|
async downloadAttachment(msg: NIMMessageInfo, path: string) {
|
|
if (msg.message.attachment as V2NIMMessageFileAttachment) {
|
|
let fileAttachment = msg.message.attachment as V2NIMMessageFileAttachment;
|
|
if (fileAttachment.url !== undefined) {
|
|
msg.setDownloadProgress(1)
|
|
try {
|
|
await StorageRepo.downloadFile(fileAttachment.url, path, (progress: number) => {
|
|
if (progress < 100) {
|
|
this.chatInfo?.downloadProgressMap.set(msg.message.messageClientId, progress)
|
|
msg.setDownloadProgress(progress)
|
|
} else {
|
|
if (progress == 100) {
|
|
msg.setDownloadProgress(100)
|
|
}
|
|
msg.setDownloadProgress(-1)
|
|
this.chatInfo?.downloadProgressMap.delete(msg.message.messageClientId)
|
|
}
|
|
}
|
|
)
|
|
} catch (err) {
|
|
console.log('netease downloadAttachment', err)
|
|
msg.setDownloadProgress(-1)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* 【逐条转发】将多个消息转发到多个会话中,并将留言发送到多个会话中
|
|
* @param messages 待转发的消息
|
|
* @param conversationIds 待转发的会话
|
|
* @param leaveText 留言
|
|
*/
|
|
forwardMessage(messages: V2NIMMessage[], conversationIds: ConversationSelectModel[],
|
|
leaveText: string | undefined) {
|
|
|
|
if (ErrorUtils.checkNetworkAndToast()) {
|
|
conversationIds.forEach((conversation) => {
|
|
messages.forEach((message) => {
|
|
const forwardMsg = ChatRepo.createForwardMessage(message)
|
|
try {
|
|
if (forwardMsg && conversation.conversationId) {
|
|
clearForwardAtMark(forwardMsg)
|
|
this.sendForwardMessage(forwardMsg, conversation.conversationId)
|
|
}
|
|
} catch (err) {
|
|
console.error(err)
|
|
}
|
|
})
|
|
|
|
// 发送留言
|
|
if (leaveText && leaveText.length > 0) {
|
|
const leaveMsg = ChatRepo.createTextMessage(leaveText)
|
|
if (leaveMsg && conversation.conversationId) {
|
|
setTimeout(() => {
|
|
ChatRepo.sendMessage(this.beforeSendMessage(leaveMsg), conversation.conversationId!)
|
|
.catch((err: BusinessError) => {
|
|
console.error("net ease send message error", err.code, err.message);
|
|
sendMessageFailedTips(leaveMsg, err, conversation.conversationId!)
|
|
})
|
|
}, 200)
|
|
}
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
/**
|
|
* 将多个消息合并为一条自定义消息
|
|
* @param messages 待合并的消息
|
|
* @param depth 合并转发消息的深度
|
|
*/
|
|
async mergeForwardMessage(messages: NIMMessageInfo[], depth: number): Promise<V2NIMMessage | undefined> {
|
|
// 校验网络
|
|
if (ErrorUtils.checkNetworkAndToast()) {
|
|
// 排序(发送时间正序)
|
|
let sortMessages = messages.sort((m1, m2) => {
|
|
if (m1.message.createTime < m2.message.createTime) {
|
|
return -1
|
|
}
|
|
if (m1.message.createTime > m2.message.createTime) {
|
|
return 1
|
|
}
|
|
return 0
|
|
})
|
|
|
|
let rawMessages = sortMessages.map(msg => msg.message)
|
|
if (this.chatInfo) {
|
|
try {
|
|
return await createForwardMessageListFileDetail(rawMessages, this.chatInfo, depth)
|
|
} catch (err) {
|
|
console.error(err)
|
|
}
|
|
}
|
|
}
|
|
|
|
return undefined
|
|
}
|
|
|
|
resendMessage(msgInfo: NIMMessageInfo) {
|
|
//设置推送
|
|
let params: V2NIMSendMessageParams | undefined = undefined
|
|
let pushList = msgInfo.message.pushConfig?.forcePushAccountIds
|
|
if (pushList) {
|
|
params = {
|
|
pushConfig: {
|
|
forcePush: true,
|
|
forcePushAccountIds: pushList.length >= 0 ? pushList : undefined
|
|
}
|
|
}
|
|
}
|
|
if (msgInfo.isReplyMsg && msgInfo.replyMsg && msgInfo.replyMsg.message) {
|
|
this.replyMessage(msgInfo.message,msgInfo.replyMsg?.message,params)
|
|
}else {
|
|
this.sendMessage(msgInfo.message,params)
|
|
}
|
|
}
|
|
|
|
// 多选数据,添加新的选中消息
|
|
addSelectMessage(msg: NIMMessageInfo) {
|
|
this.selectMsgMap.set(msg.getMessageClientId(), msg)
|
|
this.chatInfo?.getMessage(msg.getMessageClientId())?.setSelected(true)
|
|
this.selectMsgCount = this.selectMsgMap.size
|
|
}
|
|
|
|
// 多选数据,移除选中消息
|
|
removeSelectMessage(msg: NIMMessageInfo) {
|
|
this.selectMsgMap.delete(msg.getMessageClientId())
|
|
this.chatInfo?.getMessage(msg.getMessageClientId())?.setSelected(false)
|
|
this.selectMsgCount = this.selectMsgMap.size
|
|
}
|
|
|
|
// 多选数据,清空所有选中消息
|
|
clearSelectMessage() {
|
|
this.selectMsgMap.forEach((msg) => {
|
|
this.chatInfo?.getMessage(msg.getMessageClientId())?.setSelected(false)
|
|
})
|
|
this.selectMsgMap.clear()
|
|
this.selectMsgCount = this.selectMsgMap.size
|
|
}
|
|
|
|
// 获取多选数据
|
|
getSelectMessageList(): NIMMessageInfo[] {
|
|
return Array.from(this.selectMsgMap.values());
|
|
}
|
|
|
|
// 获取多选数据数量
|
|
getSelectMessageSize(): number {
|
|
return this.selectMsgMap.size;
|
|
}
|
|
|
|
isSelect(msgClientId: string) {
|
|
let result = this.selectMsgMap.has(msgClientId)
|
|
let msg = this.chatInfo?.getMessage(msgClientId)
|
|
console.debug('netease isSelect', msgClientId, result, ',content:', msg?.message.text)
|
|
return result
|
|
}
|
|
|
|
/**
|
|
* 销毁
|
|
*/
|
|
onDestroy(): void {
|
|
ChatRepo.offReceiverMessage(this.onReceiveFun)
|
|
ChatRepo.offReceiveMessagesModified(this.onModifyFun)
|
|
ChatRepo.offSendMessage(this.onSendFun)
|
|
ChatRepo.offDeleteMessage(this.onDeleteFun)
|
|
ChatRepo.offRevokeMessage(this.onRevokeFun)
|
|
ChatRepo.offMessagePinNotification(this.onPinFun)
|
|
ChatKitClient.nim.loginService.off('onDataSync', this.onSyncFinishedFun)
|
|
// 长连接状态变更
|
|
ChatKitClient.nim.loginService?.off('onConnectStatus', this.onConnectStatusChange)
|
|
// 登录状态变更
|
|
ChatKitClient.nim.loginService?.off('onLoginStatus', this.onLoginStatusChange)
|
|
// 清理未读数
|
|
this.clearUnreadCount()
|
|
ChatKitClient.clearCurrentConversationId()
|
|
}
|
|
}
|
|
|
|
|
|
class StreamMessage {
|
|
public message: V2NIMMessage
|
|
public streamingArr: string[]
|
|
public index: number
|
|
public finish: boolean
|
|
|
|
constructor(message: V2NIMMessage) {
|
|
this.message = message
|
|
this.streamingArr = []
|
|
this.index = message.aiConfig?.aiStreamLastChunk?.index ?? 0
|
|
if (message.aiConfig?.aiStreamStatus === V2NIMMessageAIStreamStatus.V2NIM_MESSAGE_AI_STREAM_STATUS_STREAMING ||
|
|
message.aiConfig?.aiStreamStatus === V2NIMMessageAIStreamStatus.V2NIM_MESSAGE_AI_STREAM_STATUS_PLACEHOLDER) {
|
|
this.finish = false // streaming / placeholder 认为还没结束
|
|
} else {
|
|
this.finish = true
|
|
}
|
|
}
|
|
} |