227 lines
9.7 KiB
TypeScript
227 lines
9.7 KiB
TypeScript
import type { Conversation, Message } from '@tencentcloud/lite-chat/basic';
|
|
import TUIBase from '../tui-base';
|
|
import type { ITUIConversationService } from '../interface/service';
|
|
import { StoreName, ERROR_CODE_ENGINE, ERROR_MSG_ENGINE } from '../const';
|
|
import { isUndefined } from '../utils/common-utils';
|
|
import ConversationModel from '../model/conversation';
|
|
|
|
export default class TUIConversationService extends TUIBase implements ITUIConversationService {
|
|
static instance: TUIConversationService;
|
|
private serv: string;
|
|
constructor() {
|
|
super();
|
|
this.serv = 'TUIConversationService';
|
|
}
|
|
|
|
/**
|
|
* 获取 TUIConversationService 实例
|
|
*/
|
|
static getInstance() {
|
|
if (!TUIConversationService.instance) {
|
|
TUIConversationService.instance = new TUIConversationService();
|
|
}
|
|
return TUIConversationService.instance;
|
|
}
|
|
|
|
public init() {
|
|
const chatEngine = this.getEngine();
|
|
chatEngine.eventCenter.addEvent(chatEngine.EVENT.CONVERSATION_LIST_UPDATED, this.onConversationListUpdated.bind(this));
|
|
chatEngine.eventCenter.addEvent(chatEngine.EVENT.TOTAL_UNREAD_MESSAGE_COUNT_UPDATED, this.onTotalUnreadCountUpdated.bind(this));
|
|
chatEngine.eventCenter.addEvent(chatEngine.EVENT.MESSAGE_RECEIVED, this.onMessageReceived.bind(this));
|
|
this.getConversationInitData();
|
|
}
|
|
|
|
private onConversationListUpdated(conversationList: Conversation[]) {
|
|
const tmpConversationList = this.filterSystemConversation(conversationList);
|
|
this.getEngine().TUIStore.update(StoreName.CONV, 'conversationList', tmpConversationList);
|
|
this.updateCurrentConversation();
|
|
}
|
|
|
|
private onTotalUnreadCountUpdated(totalUnreadCount: number) {
|
|
this.getEngine().TUIStore.update(StoreName.CONV, 'totalUnreadCount', totalUnreadCount);
|
|
}
|
|
|
|
private onMessageReceived(messageList: Message[]) {
|
|
const chatEngine = this.getEngine();
|
|
const conversationList = this.getEngine().TUIStore.getData(StoreName.CONV, 'conversationList');
|
|
let toBeUpdated = false;
|
|
for (let i = 0; i < messageList.length; i++) {
|
|
if (messageList[i].type !== chatEngine.TYPES.MSG_GRP_SYS_NOTICE) {
|
|
continue;
|
|
}
|
|
const { operationType } = messageList[i].payload;
|
|
const conversationID = `GROUP${messageList[i].to}`;
|
|
const condition1 = (operationType === 4 || operationType === 5 || operationType === 8); // 群成员被踢(operationType=4)、群组被解散(operationType=5)、主动退群(operationType=8)
|
|
const condition2 = (operationType === 2 || operationType === 6 || operationType === 7); // 主动加群(operationType=2)、创建群组(operationType=6)、被邀请进群(operationType=7)
|
|
if (condition1 || condition2) {
|
|
for (let j = 0; j < conversationList.length; j++) {
|
|
// C2C 会话直接跳过,节省循环执行时间
|
|
if (conversationList[j].type === chatEngine.TYPES.CONV_C2C) {
|
|
continue;
|
|
}
|
|
if (conversationList[j].conversationID === conversationID) {
|
|
if (condition1) {
|
|
this.getEngine().TUIStore.update(StoreName.CONV, 'operationTypeMap', { conversationID, operationType });
|
|
toBeUpdated = true;
|
|
break;
|
|
}
|
|
// 当前登录生命周期内,主动退群、解散群组、被踢后,再次主动加群、创建群组、被邀请进群时需要重置 operationType 为 0
|
|
if (condition2 && conversationList[j].operationType > 0) {
|
|
this.getEngine().TUIStore.update(StoreName.CONV, 'operationTypeMap', { conversationID, operationType: 0 });
|
|
toBeUpdated = true;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
if (toBeUpdated) {
|
|
this.getEngine().TUIStore.update(StoreName.CONV, 'conversationList', conversationList);
|
|
const currentConversationID = this.getEngine().TUIStore.getData(StoreName.CONV, 'currentConversationID') || '';
|
|
const currentConversation = this.findConversation(currentConversationID);
|
|
if (currentConversation) {
|
|
this.getEngine().TUIStore.update(StoreName.CONV, 'currentConversation', currentConversation);
|
|
}
|
|
}
|
|
}
|
|
|
|
// 解决 TUIChatEngine 含 UI集成通过 TUILogin 登录时注册 Chat SDK 事件时机后置问题
|
|
private getConversationInitData() {
|
|
const chatEngine = this.getEngine();
|
|
// TUIChatEngine 无 UI 集成时不需要执行此逻辑
|
|
if (!chatEngine.chat.isReady()) {
|
|
return;
|
|
}
|
|
chatEngine.chat.getConversationList().then((imResponse: any) => {
|
|
const { conversationList, isSyncCompleted } = imResponse.data;
|
|
console.log(`${this.serv}.init, getConversationList count:${conversationList.length} isSyncCompleted:${isSyncCompleted}`);
|
|
if (conversationList.length > 0) {
|
|
this.onConversationListUpdated(conversationList);
|
|
const totalUnreadCount: number = chatEngine.chat.getTotalUnreadMessageCount();
|
|
this.onTotalUnreadCountUpdated(totalUnreadCount);
|
|
}
|
|
});
|
|
}
|
|
|
|
public async switchConversation(conversationID: string) {
|
|
const logTxt = `${this.serv}.switchConversation`;
|
|
const chatEngine = this.getEngine();
|
|
if (!conversationID) {
|
|
chatEngine.TUIStore.reset(StoreName.CHAT, ['messageList', 'isCompleted', 'nextReqMessageID']);
|
|
chatEngine.TUIStore.update(StoreName.CONV, 'currentConversationID', '');
|
|
chatEngine.TUIStore.update(StoreName.CONV, 'currentConversation', null);
|
|
console.log(`${logTxt} conversationID is empty, conversationID:${conversationID}`);
|
|
return Promise.resolve({});
|
|
}
|
|
if (!conversationID.startsWith(chatEngine.TYPES.CONV_C2C) && !conversationID.startsWith(chatEngine.TYPES.CONV_GROUP)) {
|
|
console.warn(`${logTxt} conversationID is invalid, conversationID:${conversationID}`);
|
|
return Promise.reject({
|
|
code: ERROR_CODE_ENGINE.INVALID_CONV_ID,
|
|
message: ERROR_MSG_ENGINE.INVALID_CONV_ID,
|
|
});
|
|
}
|
|
const enableAutoMessageRead = chatEngine.TUIStore.getData(StoreName.APP, 'enableAutoMessageRead');
|
|
const currentConversationID = chatEngine.TUIStore.getData(StoreName.CONV, 'currentConversationID');
|
|
if (currentConversationID && currentConversationID === conversationID) {
|
|
if (enableAutoMessageRead) {
|
|
this.setMessageRead(currentConversationID);
|
|
}
|
|
console.warn(`${logTxt} please check conversationID, conversationID:${conversationID}`);
|
|
return Promise.resolve({
|
|
code: ERROR_CODE_ENGINE.CONV_ID_SAME,
|
|
message: ERROR_MSG_ENGINE.CONV_ID_SAME,
|
|
});
|
|
}
|
|
|
|
// 需要切换的目标会话
|
|
const targetConversation: any = await this.getConversationModel(conversationID);
|
|
if (isUndefined(targetConversation)) {
|
|
console.warn(`${logTxt} target conversation is not exist, conversationID:${conversationID}`);
|
|
return Promise.reject({
|
|
code: ERROR_CODE_ENGINE.CONV_NOT_EXIST,
|
|
message: ERROR_MSG_ENGINE.CONV_NOT_EXIST,
|
|
});
|
|
}
|
|
if (enableAutoMessageRead) {
|
|
if (currentConversationID) {
|
|
this.setMessageRead(currentConversationID);
|
|
}
|
|
if (conversationID) {
|
|
this.setMessageRead(conversationID);
|
|
}
|
|
}
|
|
chatEngine.TUIStore.reset(StoreName.CHAT, ['messageList', 'isCompleted', 'nextReqMessageID']);
|
|
chatEngine.TUIStore.update(StoreName.CONV, 'currentConversationID', conversationID);
|
|
chatEngine.TUIStore.update(StoreName.CONV, 'currentConversation', targetConversation);
|
|
return Promise.resolve(targetConversation);
|
|
}
|
|
|
|
private async getConversationModel(conversationID: string) {
|
|
let conversationModel: any = this.findConversation(conversationID);
|
|
if (isUndefined(conversationModel)) {
|
|
try {
|
|
const res: any = await this.getConversationProfile(conversationID);
|
|
if (res.data && res.data.conversation) {
|
|
conversationModel = new ConversationModel(res.data.conversation);
|
|
}
|
|
} catch (error) {
|
|
conversationModel = undefined;
|
|
}
|
|
}
|
|
return conversationModel;
|
|
}
|
|
|
|
private findConversation(conversationID: string) {
|
|
let conversation: any;
|
|
const conversationList = this.getEngine().TUIStore.getData(StoreName.CONV, 'conversationList');
|
|
for (let i = 0; i < conversationList.length; i++) {
|
|
if (conversationList[i].conversationID === conversationID) {
|
|
conversation = conversationList[i];
|
|
break;
|
|
}
|
|
}
|
|
return conversation;
|
|
}
|
|
|
|
private updateCurrentConversation() {
|
|
const chatEngine = this.getEngine();
|
|
const currentConversationID: string = chatEngine.TUIStore.getData(StoreName.CONV, 'currentConversationID');
|
|
const currentConversation = this.findConversation(currentConversationID);
|
|
// 更新当前会话
|
|
if (currentConversation) {
|
|
chatEngine.TUIStore.update(StoreName.CONV, 'currentConversation', currentConversation);
|
|
}
|
|
}
|
|
|
|
public getConversationList() {
|
|
return this.getEngine().chat.getConversationList();
|
|
}
|
|
|
|
public getConversationProfile(conversationID: string) {
|
|
return this.getEngine().chat.getConversationProfile(conversationID);
|
|
}
|
|
|
|
public clearHistoryMessage(conversationID: string) {
|
|
return this.getEngine().chat.clearHistoryMessage(conversationID).then((imResponse: any) => {
|
|
this.getEngine().TUIStore.update(StoreName.CHAT, 'messageList', []);
|
|
this.getEngine().TUIStore.update(StoreName.CHAT, 'nextReqMessageID', '');
|
|
this.getEngine().TUIStore.update(StoreName.CHAT, 'isCompleted', true);
|
|
return imResponse;
|
|
});
|
|
}
|
|
|
|
public setMessageRead(conversationID: string) {
|
|
return this.getEngine().chat.setMessageRead({ conversationID });
|
|
}
|
|
|
|
/**
|
|
* 过滤系统会话
|
|
* @param {Array<any>} list SDK 更新下来的会话列表数据
|
|
*/
|
|
private filterSystemConversation(list: any[]) {
|
|
const toBeUpdatedList = list.filter(conversation => conversation.type !== this.getEngine().TYPES.CONV_SYSTEM);
|
|
return toBeUpdatedList;
|
|
}
|
|
|
|
}
|