You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
623 lines
19 KiB
623 lines
19 KiB
import { defineStore } from 'pinia';
|
|
import { MESSAGE_TYPE, MESSAGE_STATUS } from '@/common/enums.js';
|
|
import useFriendStore from './friendStore.js';
|
|
import useGroupStore from './groupStore.js';
|
|
import useUserStore from './userStore';
|
|
import { i18n } from '@/main.js'
|
|
|
|
let cacheChats = [];
|
|
export default defineStore('chatStore', {
|
|
state: () => {
|
|
return {
|
|
chats: [],
|
|
privateMsgMaxId: 0,
|
|
groupMsgMaxId: 0,
|
|
loading: false
|
|
}
|
|
},
|
|
actions: {
|
|
initChats(chatsData) {
|
|
cacheChats = [];
|
|
this.chats = [];
|
|
for (let chat of chatsData.chats) {
|
|
chat.stored = false;
|
|
cacheChats.push(JSON.parse(JSON.stringify(chat)));
|
|
if (this.chats.length < 15) {
|
|
this.chats.push(chat);
|
|
}
|
|
}
|
|
this.privateMsgMaxId = chatsData.privateMsgMaxId || 0;
|
|
this.groupMsgMaxId = chatsData.groupMsgMaxId || 0;
|
|
},
|
|
|
|
// 未知客服触发:全量合并所有旧客服到新客服
|
|
forceMergeAllOldCustomerToNew(newKfId) {
|
|
const userStore = useUserStore();
|
|
const uid = userStore.userInfo.id;
|
|
const prefix = `chats-app-${uid}-PRIVATE-`;
|
|
const rootKey = `chats-app-${uid}`;
|
|
|
|
const allKeys = uni.getStorageInfoSync().keys;
|
|
const oldKeys = allKeys.filter(k =>
|
|
k.startsWith(prefix) &&
|
|
!k.endsWith('-hot') &&
|
|
!k.includes(`-${newKfId}`)
|
|
);
|
|
|
|
if (oldKeys.length === 0) return;
|
|
|
|
let newChat = this.findChatByFriend(newKfId);
|
|
if (!newChat) {
|
|
newChat = {
|
|
targetId: newKfId,
|
|
type: "PRIVATE",
|
|
messages: [],
|
|
unreadCount: 0,
|
|
lastContent: "",
|
|
lastSendTime: 0,
|
|
hotMinIdx: 0,
|
|
readedMessageIdx: 0,
|
|
atMe: false,
|
|
atAll: false,
|
|
stored: false
|
|
};
|
|
this.chats.unshift(newChat);
|
|
}
|
|
|
|
// 读取每一个旧客服 【冷+热完整消息】
|
|
let allOldMessages = [];
|
|
oldKeys.forEach(oldKey => {
|
|
const oldCold = uni.getStorageSync(oldKey);
|
|
const oldHot = uni.getStorageSync(oldKey + "-hot");
|
|
// 旧客服完整消息:冷历史 + 热新消息
|
|
const oldFullMsg = [...(oldCold?.messages || []), ...(oldHot?.messages || [])];
|
|
allOldMessages = [...oldFullMsg, ...allOldMessages];
|
|
|
|
// 合并完成后才删除旧缓存,绝不提前删!
|
|
uni.removeStorageSync(oldKey);
|
|
uni.removeStorageSync(oldKey + "-hot");
|
|
});
|
|
|
|
newChat.messages = [...allOldMessages, ...newChat.messages];
|
|
|
|
// 根缓存只保留最新客服
|
|
const root = uni.getStorageSync(rootKey);
|
|
if (root) {
|
|
root.chatKeys = [`${prefix}${newKfId}`];
|
|
uni.setStorageSync(rootKey, root);
|
|
}
|
|
|
|
newChat.stored = false;
|
|
// 按照原生冷热规则拆分保存
|
|
this.saveToStorage(true);
|
|
},
|
|
|
|
openChat(chatInfo) {
|
|
let chats = this.curChats;
|
|
let chat = null;
|
|
for (let idx in chats) {
|
|
if (chats[idx].type == chatInfo.type &&
|
|
chats[idx].targetId === chatInfo.targetId) {
|
|
chat = chats[idx];
|
|
this.moveTop(idx)
|
|
break;
|
|
}
|
|
}
|
|
if (chat == null) {
|
|
chat = {
|
|
targetId: chatInfo.targetId,
|
|
type: chatInfo.type,
|
|
showName: chatInfo.showName,
|
|
headImage: chatInfo.headImage,
|
|
isDnd: chatInfo.isDnd,
|
|
lastContent: "",
|
|
lastSendTime: new Date().getTime(),
|
|
unreadCount: 0,
|
|
hotMinIdx: 0,
|
|
readedMessageIdx: 0,
|
|
messages: [],
|
|
atMe: false,
|
|
atAll: false,
|
|
stored: false
|
|
};
|
|
chats.unshift(chat);
|
|
this.saveToStorage();
|
|
}
|
|
},
|
|
activeChat(idx) {
|
|
let chats = this.curChats;
|
|
if (idx >= 0) {
|
|
chats[idx].unreadCount = 0;
|
|
}
|
|
},
|
|
resetUnreadCount(chatInfo) {
|
|
let chats = this.curChats;
|
|
for (let idx in chats) {
|
|
if (chats[idx].type == chatInfo.type &&
|
|
chats[idx].targetId == chatInfo.targetId) {
|
|
chats[idx].unreadCount = 0;
|
|
chats[idx].atMe = false;
|
|
chats[idx].atAll = false;
|
|
chats[idx].stored = false;
|
|
this.saveToStorage();
|
|
}
|
|
}
|
|
},
|
|
readedMessage(pos) {
|
|
let chat = this.findChatByFriend(pos.friendId);
|
|
if (!chat) return;
|
|
for (let idx = chat.readedMessageIdx; idx < chat.messages.length; idx++) {
|
|
let m = chat.messages[idx];
|
|
if (m.id && m.selfSend && m.status < MESSAGE_STATUS.RECALL) {
|
|
if (!pos.maxId || m.id <= pos.maxId) {
|
|
m.status = MESSAGE_STATUS.READED
|
|
chat.readedMessageIdx = idx;
|
|
chat.stored = false;
|
|
}
|
|
}
|
|
}
|
|
if (!chat.stored) {
|
|
this.saveToStorage();
|
|
}
|
|
},
|
|
cleanMessage(idx) {
|
|
let chat = this.curChats[idx];
|
|
chat.lastContent = '';
|
|
chat.hotMinIdx = 0;
|
|
chat.unreadCount = 0;
|
|
chat.atMe = false;
|
|
chat.atAll = false;
|
|
chat.stored = false
|
|
chat.messages = [];
|
|
this.saveToStorage(true);
|
|
},
|
|
removeChat(idx) {
|
|
let chats = this.curChats;
|
|
chats[idx].delete = true;
|
|
chats[idx].stored = false;
|
|
this.saveToStorage();
|
|
},
|
|
removePrivateChat(userId) {
|
|
let chats = this.curChats;
|
|
for (let idx in chats) {
|
|
if (chats[idx].type == 'PRIVATE' &&
|
|
chats[idx].targetId == userId) {
|
|
this.removeChat(idx);
|
|
}
|
|
}
|
|
},
|
|
removeGroupChat(groupId) {
|
|
let chats = this.curChats;
|
|
for (let idx in chats) {
|
|
if (chats[idx].type == 'GROUP' &&
|
|
chats[idx].targetId == groupId) {
|
|
this.removeChat(idx);
|
|
}
|
|
}
|
|
},
|
|
moveTop(idx) {
|
|
if (this.loading) {
|
|
return;
|
|
}
|
|
let chats = this.curChats;
|
|
if (idx > 0) {
|
|
let chat = chats[idx];
|
|
chats.splice(idx, 1);
|
|
chats.unshift(chat);
|
|
chat.lastSendTime = new Date().getTime();
|
|
chat.stored = false;
|
|
this.saveToStorage();
|
|
}
|
|
},
|
|
insertMessage(msgInfo, chatInfo) {
|
|
const t = i18n.global.t;
|
|
let type = chatInfo.type;
|
|
if (msgInfo.id && type == "PRIVATE" && msgInfo.id > this.privateMsgMaxId) {
|
|
this.privateMsgMaxId = msgInfo.id;
|
|
}
|
|
if (msgInfo.id && type == "GROUP" && msgInfo.id > this.groupMsgMaxId) {
|
|
this.groupMsgMaxId = msgInfo.id;
|
|
}
|
|
let chat = this.findChat(chatInfo);
|
|
let message = this.findMessage(chat, msgInfo);
|
|
if (message) {
|
|
const msgIndex = chat.messages.findIndex(m =>
|
|
(m.id && m.id === msgInfo.id) ||
|
|
(m.tmpId && m.tmpId === msgInfo.tmpId)
|
|
);
|
|
if (msgIndex !== -1) {
|
|
const updatedMessage = { ...message, ...msgInfo };
|
|
chat.messages.splice(msgIndex, 1, updatedMessage);
|
|
}
|
|
chat.stored = false;
|
|
this.saveToStorage();
|
|
return;
|
|
}
|
|
if (msgInfo.type == MESSAGE_TYPE.IMAGE) {
|
|
chat.lastContent = t('chat.image');
|
|
} else if (msgInfo.type == MESSAGE_TYPE.FILE) {
|
|
chat.lastContent = t('chat.file');
|
|
} else if (msgInfo.type == MESSAGE_TYPE.AUDIO) {
|
|
chat.lastContent = t('chat.voice');
|
|
} else if (msgInfo.type == MESSAGE_TYPE.ACT_RT_VOICE) {
|
|
chat.lastContent = t('chat.voiceCall');
|
|
} else if (msgInfo.type == MESSAGE_TYPE.ACT_RT_VIDEO) {
|
|
chat.lastContent = t('chat.videoCall');
|
|
} else if (msgInfo.type == MESSAGE_TYPE.TEXT ||
|
|
msgInfo.type == MESSAGE_TYPE.RECALL ||
|
|
msgInfo.type == MESSAGE_TYPE.TIP_TEXT) {
|
|
chat.lastContent = msgInfo.content;
|
|
}
|
|
|
|
chat.lastSendTime = msgInfo.sendTime;
|
|
chat.sendNickName = msgInfo.sendNickName;
|
|
if (!msgInfo.selfSend && msgInfo.status != MESSAGE_STATUS.READED &&
|
|
msgInfo.status != MESSAGE_STATUS.RECALL && msgInfo.type != MESSAGE_TYPE.TIP_TEXT) {
|
|
chat.unreadCount++;
|
|
}
|
|
if (!msgInfo.selfSend && chat.type == "GROUP" && msgInfo.atUserIds &&
|
|
msgInfo.status != MESSAGE_STATUS.READED) {
|
|
const userStore = useUserStore();
|
|
let userId = userStore.userInfo.id;
|
|
if (msgInfo.atUserIds.indexOf(userId) >= 0) {
|
|
chat.atMe = true;
|
|
}
|
|
if (msgInfo.atUserIds.indexOf(-1) >= 0) {
|
|
chat.atAll = true;
|
|
}
|
|
}
|
|
if (!chat.lastTimeTip || (chat.lastTimeTip < msgInfo.sendTime - 600 * 1000)) {
|
|
chat.messages.push({
|
|
sendTime: msgInfo.sendTime,
|
|
type: MESSAGE_TYPE.TIP_TIME,
|
|
});
|
|
chat.lastTimeTip = msgInfo.sendTime;
|
|
}
|
|
chat.messages.push(msgInfo);
|
|
chat.stored = false;
|
|
this.saveToStorage();
|
|
},
|
|
updateMessage(msgInfo, chatInfo) {
|
|
let chat = this.findChat(chatInfo);
|
|
let message = this.findMessage(chat, msgInfo);
|
|
if (message) {
|
|
Object.assign(message, msgInfo);
|
|
chat.stored = false;
|
|
this.saveToStorage();
|
|
}
|
|
},
|
|
deleteMessage(msgInfo, chatInfo) {
|
|
let isColdMessage = false;
|
|
let chat = this.findChat(chatInfo);
|
|
let delIdx = -1;
|
|
for (let idx in chat.messages) {
|
|
if (chat.messages[idx].id && chat.messages[idx].id == msgInfo.id) {
|
|
delIdx = idx;
|
|
break;
|
|
}
|
|
if (chat.messages[idx].tmpId && chat.messages[idx].tmpId == msgInfo.tmpId) {
|
|
delIdx = idx;
|
|
break;
|
|
}
|
|
}
|
|
if (delIdx >= 0) {
|
|
chat.messages.splice(delIdx, 1);
|
|
if (delIdx < chat.hotMinIdx) {
|
|
isColdMessage = true;
|
|
chat.hotMinIdx--;
|
|
}
|
|
if (delIdx < chat.readedMessageIdx) {
|
|
chat.readedMessageIdx--;
|
|
}
|
|
chat.stored = false;
|
|
this.saveToStorage(isColdMessage);
|
|
}
|
|
},
|
|
|
|
recallMessage(msgInfo, chatInfo) {
|
|
const t = i18n.global.t;
|
|
let chat = this.findChat(chatInfo);
|
|
if (!chat) return;
|
|
let isColdMessage = false;
|
|
let id = msgInfo.content;
|
|
let name = msgInfo.selfSend ? t('chat.you') : (chat.type == 'PRIVATE' ? t('chat.other') : msgInfo.sendNickName);
|
|
for (let idx in chat.messages) {
|
|
let m = chat.messages[idx];
|
|
if (m.id && m.id == id) {
|
|
m.status = MESSAGE_STATUS.RECALL;
|
|
m.content = `${name}${t('chat.recalledMessage')}`;
|
|
m.type = MESSAGE_TYPE.TIP_TEXT
|
|
chat.lastContent = m.content;
|
|
chat.lastSendTime = msgInfo.sendTime;
|
|
chat.sendNickName = '';
|
|
if (!msgInfo.selfSend && msgInfo.status != MESSAGE_STATUS.READED) {
|
|
chat.unreadCount++;
|
|
}
|
|
isColdMessage = idx < chat.hotMinIdx;
|
|
}
|
|
if (m.quoteMessage && m.quoteMessage.id == msgInfo.id) {
|
|
m.quoteMessage.content = t('chat.quoteRecalled');
|
|
m.quoteMessage.status = MESSAGE_STATUS.RECALL;
|
|
m.quoteMessage.type = MESSAGE_TYPE.TIP_TEXT
|
|
}
|
|
}
|
|
chat.stored = false;
|
|
this.saveToStorage(isColdMessage);
|
|
},
|
|
|
|
updateChatFromFriend(friend) {
|
|
let chat = this.findChatByFriend(friend.id)
|
|
if (chat && (chat.headImage != friend.headImage ||
|
|
chat.showName != friend.nickName)) {
|
|
chat.headImage = friend.headImage;
|
|
chat.showName = friend.nickName;
|
|
chat.stored = false;
|
|
this.saveToStorage();
|
|
}
|
|
},
|
|
updateChatFromUser(user) {
|
|
let chat = this.findChatByFriend(user.id);
|
|
if (chat && (chat.headImage != user.headImageThumb ||
|
|
chat.showName != user.nickName)) {
|
|
chat.headImage = user.headImageThumb;
|
|
chat.showName = user.nickName;
|
|
chat.stored = false;
|
|
this.saveToStorage();
|
|
}
|
|
},
|
|
updateChatFromGroup(group) {
|
|
let chat = this.findChatByGroup(group.id);
|
|
if (chat && (chat.headImage != group.headImageThumb ||
|
|
chat.showName != group.showGroupName)) {
|
|
chat.headImage = group.headImageThumb;
|
|
chat.showName = group.showGroupName;
|
|
chat.stored = false;
|
|
this.saveToStorage();
|
|
}
|
|
},
|
|
setLoading(loading) {
|
|
this.loading = loading;
|
|
},
|
|
setDnd(chatInfo, isDnd) {
|
|
let chat = this.findChat(chatInfo);
|
|
if (chat) {
|
|
chat.isDnd = isDnd;
|
|
}
|
|
},
|
|
refreshChats() {
|
|
let chats = cacheChats || this.chats;
|
|
const friendStore = useFriendStore();
|
|
const groupStore = useGroupStore();
|
|
chats.forEach(chat => {
|
|
if (chat.type == 'PRIVATE') {
|
|
let friend = friendStore.findFriend(chat.targetId);
|
|
if (friend) {
|
|
chat.isDnd = friend.isDnd
|
|
}
|
|
} else if (chat.type == 'GROUP') {
|
|
let group = groupStore.findGroup(chat.targetId);
|
|
if (group) {
|
|
chat.isDnd = group.isDnd
|
|
}
|
|
}
|
|
})
|
|
chats.sort((chat1, chat2) => chat2.lastSendTime - chat1.lastSendTime);
|
|
const storageInfo = uni.getStorageInfoSync();
|
|
if (storageInfo && storageInfo.currentSize > 3000) {
|
|
this.cleanOtherUserCache();
|
|
}
|
|
this.fliterMessage(chats, 3000, 500);
|
|
chats.forEach(chat => {
|
|
// 原生规则:所有消息默认都放入热缓存,hotMinIdx归0
|
|
chat.hotMinIdx = 0;
|
|
chat.stored = false;
|
|
});
|
|
this.chats = chats;
|
|
cacheChats = null;
|
|
this.saveToStorage(true);
|
|
},
|
|
fliterMessage(chats, maxTotalSize, maxPerChatSize) {
|
|
let remainTotalSize = 0;
|
|
chats.forEach(chat => {
|
|
if (chat.messages.length > maxPerChatSize) {
|
|
let idx = chat.messages.length - maxPerChatSize;
|
|
chat.messages = chat.messages.slice(idx);
|
|
}
|
|
remainTotalSize += chat.messages.length;
|
|
})
|
|
if (remainTotalSize > maxTotalSize) {
|
|
this.fliterMessage(chats, maxTotalSize, maxPerChatSize / 2);
|
|
}
|
|
},
|
|
cleanOtherUserCache() {
|
|
const userStore = useUserStore();
|
|
const userId = userStore.userInfo.id;
|
|
const prefix = "chats-app-" + userId;
|
|
const res = uni.getStorageInfoSync();
|
|
res.keys.forEach(key => {
|
|
if (key.startsWith("chats-app") && !key.startsWith(prefix)) {
|
|
uni.removeStorageSync(key);
|
|
}
|
|
})
|
|
},
|
|
|
|
saveToStorage(withColdMessage) {
|
|
if (this.loading) {
|
|
return;
|
|
}
|
|
const userStore = useUserStore();
|
|
let userId = userStore.userInfo.id;
|
|
let rootKey = "chats-app-" + userId;
|
|
let chatKeys = [];
|
|
const keepHotCount = 300; // 原生热缓存保留条数
|
|
|
|
this.chats.forEach((chat) => {
|
|
let chatKey = `${rootKey}-${chat.type}-${chat.targetId}`
|
|
if (!chat.stored) {
|
|
if (chat.delete) {
|
|
uni.removeStorageSync(chatKey);
|
|
uni.removeStorageSync(chatKey + '-hot');
|
|
} else {
|
|
// 原生标准切割:hotMinIdx = 总消息长度 - 最新300条
|
|
const totalMsgLen = chat.messages.length;
|
|
chat.hotMinIdx = Math.max(0, totalMsgLen - keepHotCount);
|
|
// cold:前面所有久远历史消息
|
|
const coldMsg = chat.messages.slice(0, chat.hotMinIdx);
|
|
// hot:后面最新的300条消息(所有新发消息全在这里!)
|
|
const hotMsg = chat.messages.slice(chat.hotMinIdx);
|
|
|
|
// 写入冷缓存
|
|
if (withColdMessage) {
|
|
let coldChat = { ...chat, messages: coldMsg };
|
|
uni.setStorageSync(chatKey, coldChat);
|
|
}
|
|
// 写入热缓存(新发消息100%保存)
|
|
let hotChat = { ...chat, messages: hotMsg };
|
|
uni.setStorageSync(chatKey + '-hot', hotChat);
|
|
}
|
|
chat.stored = true;
|
|
}
|
|
if (!chat.delete) {
|
|
chatKeys.push(chatKey);
|
|
}
|
|
})
|
|
|
|
// 更新根会话列表
|
|
let chatsData = {
|
|
privateMsgMaxId: this.privateMsgMaxId,
|
|
groupMsgMaxId: this.groupMsgMaxId,
|
|
chatKeys: chatKeys
|
|
}
|
|
uni.setStorageSync(rootKey, chatsData)
|
|
this.chats = this.chats.filter(chat => !chat.delete)
|
|
},
|
|
|
|
clear(state) {
|
|
cacheChats = [];
|
|
this.chats = [];
|
|
this.privateMsgMaxId = 0;
|
|
this.groupMsgMaxId = 0;
|
|
this.loadingPrivateMsg = false;
|
|
this.loadingGroupMsg = false;
|
|
},
|
|
loadChat() {
|
|
return new Promise((resolve, reject) => {
|
|
let userStore = useUserStore();
|
|
let userId = userStore.userInfo.id;
|
|
const rootCacheKey = `chats-app-${userId}`;
|
|
let chatsData = uni.getStorageSync(rootCacheKey);
|
|
|
|
// 安全处理:没有数据直接返回
|
|
if (!chatsData) {
|
|
chatsData = {
|
|
privateMsgMaxId: 0,
|
|
groupMsgMaxId: 0,
|
|
chatKeys: []
|
|
};
|
|
}
|
|
|
|
// 安全处理:chatKeys 必须是数组
|
|
if (!chatsData.chatKeys || !Array.isArray(chatsData.chatKeys)) {
|
|
chatsData.chatKeys = [];
|
|
}
|
|
|
|
uni.removeStorageSync("currentActiveCustomerId");
|
|
|
|
let finalChats = [];
|
|
chatsData.chatKeys.forEach(key => {
|
|
try {
|
|
const coldChat = uni.getStorageSync(key) || {};
|
|
const hotChat = uni.getStorageSync(key + "-hot") || {};
|
|
|
|
// 修复发送中状态
|
|
if (hotChat.messages && Array.isArray(hotChat.messages)) {
|
|
hotChat.messages.forEach(msg => {
|
|
if (msg.status === MESSAGE_STATUS.SENDING) {
|
|
msg.status = MESSAGE_STATUS.FAILED;
|
|
}
|
|
});
|
|
}
|
|
|
|
// 消息合并(绝对安全)
|
|
const coldMsg = Array.isArray(coldChat.messages) ? coldChat.messages : [];
|
|
const hotMsg = Array.isArray(hotChat.messages) ? hotChat.messages : [];
|
|
const fullMsg = [...coldMsg, ...hotMsg];
|
|
|
|
let chat = { ...coldChat, ...hotChat };
|
|
chat.messages = fullMsg;
|
|
chat.hotMinIdx = coldMsg.length;
|
|
chat.readedMessageIdx = chat.readedMessageIdx || 0;
|
|
|
|
finalChats.push(chat);
|
|
} catch (e) {}
|
|
});
|
|
|
|
chatsData.chats = finalChats;
|
|
this.initChats(chatsData);
|
|
resolve();
|
|
});
|
|
},
|
|
},
|
|
getters: {
|
|
curChats: (state) => {
|
|
if (cacheChats && state.loading) {
|
|
return cacheChats;
|
|
}
|
|
return state.chats;
|
|
},
|
|
findChatIdx: (state) => (chat) => {
|
|
let chats = state.curChats;
|
|
for (let idx in chats) {
|
|
if (chats[idx].type == chat.type &&
|
|
chats[idx].targetId === chat.targetId) {
|
|
chat = state.chats[idx];
|
|
return idx;
|
|
}
|
|
}
|
|
},
|
|
findChat: (state) => (chat) => {
|
|
let chats = state.curChats;
|
|
let idx = state.findChatIdx(chat);
|
|
return chats[idx];
|
|
},
|
|
findChatByFriend: (state) => (fid) => {
|
|
return state.curChats.find(chat => chat.type == 'PRIVATE' &&
|
|
chat.targetId == fid)
|
|
},
|
|
findChatByGroup: (state) => (gid) => {
|
|
return state.curChats.find(chat => chat.type == 'GROUP' &&
|
|
chat.targetId == gid)
|
|
},
|
|
findMessage: (state) => (chat, msgInfo) => {
|
|
if (!chat) {
|
|
return null;
|
|
}
|
|
if (msgInfo.id) {
|
|
for (let idx = chat.messages.length - 1; idx >= 0; idx--) {
|
|
let m = chat.messages[idx];
|
|
if (m.id && msgInfo.id == m.id) {
|
|
return m;
|
|
}
|
|
if (m.id && m.id < msgInfo.id) {
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
if (msgInfo.selfSend && msgInfo.tmpId) {
|
|
for (let idx = chat.messages.length - 1; idx >= 0; idx--) {
|
|
let m = chat.messages[idx];
|
|
if (!m.selfSend || !m.tmpId) {
|
|
continue;
|
|
}
|
|
if (msgInfo.tmpId == m.tmpId) {
|
|
return m;
|
|
}
|
|
if (m.tmpId && m.tmpId < msgInfo.tmpId) {
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
return null;
|
|
}
|
|
}
|
|
})
|