@onyx-p/imlib-web 2.0.7 → 2.0.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/index.esm.js +555 -187
- package/index.umd.js +555 -187
- package/package.json +1 -1
package/index.esm.js
CHANGED
@@ -7741,14 +7741,6 @@ const isElectron = () => {
|
|
7741
7741
|
return typeof process !== 'undefined' && typeof process.versions !== 'undefined' && !!process.versions.electron;
|
7742
7742
|
};
|
7743
7743
|
let electronStore = null;
|
7744
|
-
if (isElectron()) {
|
7745
|
-
try {
|
7746
|
-
const Store = require('electron-store');
|
7747
|
-
electronStore = new Store();
|
7748
|
-
} catch (e) {
|
7749
|
-
console.error('Failed to initialize electron-store:', e);
|
7750
|
-
}
|
7751
|
-
}
|
7752
7744
|
const LocalStorageService = {
|
7753
7745
|
get: function (key) {
|
7754
7746
|
if (isElectron() && electronStore) {
|
@@ -20937,6 +20929,548 @@ const GroupCloseBurnAfterReadingMessage = registerMessageType$1(NotiMessageTypes
|
|
20937
20929
|
|
20938
20930
|
const RecallCommandMessage = registerMessageType$1(MessageTypes.RECALL, true, false, false);
|
20939
20931
|
|
20932
|
+
class MessageCache {
|
20933
|
+
static instance;
|
20934
|
+
loadedEndMap = new Map();
|
20935
|
+
db = null;
|
20936
|
+
currentAppKey = '';
|
20937
|
+
currentUserId = '';
|
20938
|
+
APP_INFO_KEY = 'im_app_info';
|
20939
|
+
DB_NAME_PREFIX = 'im_message_cache';
|
20940
|
+
DB_VERSION = 2;
|
20941
|
+
STORE_NAME = 'messages';
|
20942
|
+
DIALOG_STATE_STORE = 'dialogStates';
|
20943
|
+
constructor(appKey, userId) {
|
20944
|
+
this.init(appKey, userId);
|
20945
|
+
}
|
20946
|
+
async init(appKey, userId) {
|
20947
|
+
this.currentAppKey = appKey;
|
20948
|
+
this.currentUserId = userId;
|
20949
|
+
await this.checkAndResetDatabase();
|
20950
|
+
await this.initDatabase();
|
20951
|
+
}
|
20952
|
+
async checkAndResetDatabase() {
|
20953
|
+
const storedInfoStr = LocalStorageService.get(this.APP_INFO_KEY);
|
20954
|
+
if (storedInfoStr) {
|
20955
|
+
try {
|
20956
|
+
const storedInfo = JSON.parse(storedInfoStr);
|
20957
|
+
if (storedInfo.appKey !== this.currentAppKey || storedInfo.userId !== this.currentUserId) {
|
20958
|
+
await this.deleteDatabase();
|
20959
|
+
}
|
20960
|
+
} catch (error) {
|
20961
|
+
console.error('解析存储的AppKey和UserId出错', error);
|
20962
|
+
await this.deleteDatabase();
|
20963
|
+
}
|
20964
|
+
}
|
20965
|
+
LocalStorageService.set(this.APP_INFO_KEY, JSON.stringify({
|
20966
|
+
appKey: this.currentAppKey,
|
20967
|
+
userId: this.currentUserId,
|
20968
|
+
timestamp: Date.now()
|
20969
|
+
}));
|
20970
|
+
}
|
20971
|
+
async deleteDatabase() {
|
20972
|
+
if (this.db) {
|
20973
|
+
this.db.close();
|
20974
|
+
this.db = null;
|
20975
|
+
}
|
20976
|
+
this.loadedEndMap.clear();
|
20977
|
+
return new Promise((resolve, reject) => {
|
20978
|
+
const dbName = this.getDBName();
|
20979
|
+
const deleteRequest = indexedDB.deleteDatabase(dbName);
|
20980
|
+
deleteRequest.onsuccess = () => {
|
20981
|
+
console.log(`数据库 ${dbName} 已成功删除`);
|
20982
|
+
resolve();
|
20983
|
+
};
|
20984
|
+
deleteRequest.onerror = event => {
|
20985
|
+
console.error(`删除数据库 ${dbName} 失败`, event);
|
20986
|
+
resolve();
|
20987
|
+
};
|
20988
|
+
});
|
20989
|
+
}
|
20990
|
+
getDBName() {
|
20991
|
+
return `${this.DB_NAME_PREFIX}_${this.currentAppKey}_${this.currentUserId}`;
|
20992
|
+
}
|
20993
|
+
initDatabase() {
|
20994
|
+
return new Promise((resolve, reject) => {
|
20995
|
+
const dbName = this.getDBName();
|
20996
|
+
const request = indexedDB.open(dbName, this.DB_VERSION);
|
20997
|
+
request.onerror = event => {
|
20998
|
+
console.error('数据库打开失败', event);
|
20999
|
+
reject(new Error('数据库打开失败'));
|
21000
|
+
};
|
21001
|
+
request.onsuccess = event => {
|
21002
|
+
this.db = event.target.result;
|
21003
|
+
this.loadAllDialogStates().then(() => {
|
21004
|
+
resolve();
|
21005
|
+
}).catch(err => {
|
21006
|
+
console.error('加载会话状态失败', err);
|
21007
|
+
resolve();
|
21008
|
+
});
|
21009
|
+
};
|
21010
|
+
request.onupgradeneeded = event => {
|
21011
|
+
const db = event.target.result;
|
21012
|
+
if (!db.objectStoreNames.contains(this.STORE_NAME)) {
|
21013
|
+
const store = db.createObjectStore(this.STORE_NAME, {
|
21014
|
+
keyPath: 'messageUId'
|
21015
|
+
});
|
21016
|
+
store.createIndex('dialogId', 'dialogId', {
|
21017
|
+
unique: false
|
21018
|
+
});
|
21019
|
+
store.createIndex('dialogId_sentTime', ['dialogId', 'sentTime'], {
|
21020
|
+
unique: false
|
21021
|
+
});
|
21022
|
+
store.createIndex('receivedStatus', 'receivedStatus', {
|
21023
|
+
unique: false
|
21024
|
+
});
|
21025
|
+
store.createIndex('burnAfterReadingFlag', 'burnAfterReadingFlag', {
|
21026
|
+
unique: false
|
21027
|
+
});
|
21028
|
+
store.createIndex('dialogId_receivedStatus', ['dialogId', 'receivedStatus'], {
|
21029
|
+
unique: false
|
21030
|
+
});
|
21031
|
+
}
|
21032
|
+
if (!db.objectStoreNames.contains(this.DIALOG_STATE_STORE)) {
|
21033
|
+
db.createObjectStore(this.DIALOG_STATE_STORE, {
|
21034
|
+
keyPath: 'dialogId'
|
21035
|
+
});
|
21036
|
+
}
|
21037
|
+
};
|
21038
|
+
});
|
21039
|
+
}
|
21040
|
+
async loadAllDialogStates() {
|
21041
|
+
if (!this.db) {
|
21042
|
+
return;
|
21043
|
+
}
|
21044
|
+
return new Promise((resolve, reject) => {
|
21045
|
+
const transaction = this.db.transaction(this.DIALOG_STATE_STORE, 'readonly');
|
21046
|
+
const store = transaction.objectStore(this.DIALOG_STATE_STORE);
|
21047
|
+
const request = store.getAll();
|
21048
|
+
request.onsuccess = () => {
|
21049
|
+
const states = request.result;
|
21050
|
+
this.loadedEndMap.clear();
|
21051
|
+
states.forEach(state => {
|
21052
|
+
this.loadedEndMap.set(state.dialogId, state.isEnd);
|
21053
|
+
});
|
21054
|
+
resolve();
|
21055
|
+
};
|
21056
|
+
request.onerror = event => {
|
21057
|
+
reject(new Error('加载会话状态失败'));
|
21058
|
+
};
|
21059
|
+
});
|
21060
|
+
}
|
21061
|
+
async updateDialogState(dialogId, isEnd) {
|
21062
|
+
if (!this.db) {
|
21063
|
+
return;
|
21064
|
+
}
|
21065
|
+
this.loadedEndMap.set(dialogId, isEnd);
|
21066
|
+
return new Promise((resolve, reject) => {
|
21067
|
+
const transaction = this.db.transaction(this.DIALOG_STATE_STORE, 'readwrite');
|
21068
|
+
const store = transaction.objectStore(this.DIALOG_STATE_STORE);
|
21069
|
+
const request = store.put({
|
21070
|
+
dialogId,
|
21071
|
+
isEnd,
|
21072
|
+
updateTime: Date.now()
|
21073
|
+
});
|
21074
|
+
request.onsuccess = () => {
|
21075
|
+
resolve();
|
21076
|
+
};
|
21077
|
+
request.onerror = event => {
|
21078
|
+
console.error('更新会话状态失败', event);
|
21079
|
+
reject(new Error('更新会话状态失败'));
|
21080
|
+
};
|
21081
|
+
});
|
21082
|
+
}
|
21083
|
+
async addMessages(messages, toConversation, isEnd = undefined) {
|
21084
|
+
const dialogId = getFullDialogId(toConversation);
|
21085
|
+
if (isDef(isEnd)) {
|
21086
|
+
await this.updateDialogState(dialogId, isEnd);
|
21087
|
+
}
|
21088
|
+
if (!messages || messages.length === 0 || !this.db) {
|
21089
|
+
return;
|
21090
|
+
}
|
21091
|
+
return new Promise((resolve, reject) => {
|
21092
|
+
const transaction = this.db.transaction(this.STORE_NAME, 'readwrite');
|
21093
|
+
const store = transaction.objectStore(this.STORE_NAME);
|
21094
|
+
messages.forEach(message => {
|
21095
|
+
const messageToStore = {
|
21096
|
+
...message,
|
21097
|
+
dialogId
|
21098
|
+
};
|
21099
|
+
store.put(messageToStore);
|
21100
|
+
});
|
21101
|
+
transaction.oncomplete = () => {
|
21102
|
+
resolve();
|
21103
|
+
};
|
21104
|
+
transaction.onerror = event => {
|
21105
|
+
console.error('添加消息事务失败', event);
|
21106
|
+
reject(new Error('添加消息事务失败'));
|
21107
|
+
};
|
21108
|
+
});
|
21109
|
+
}
|
21110
|
+
async getPreviousMessages(conversation, timestamp = "0", count = 20) {
|
21111
|
+
const dialogId = getFullDialogId(conversation);
|
21112
|
+
if (!this.db) {
|
21113
|
+
return {
|
21114
|
+
messages: [],
|
21115
|
+
hasMore: false
|
21116
|
+
};
|
21117
|
+
}
|
21118
|
+
const isLoaded = await this.getDialogLoadedState(dialogId);
|
21119
|
+
return new Promise((resolve, reject) => {
|
21120
|
+
const transaction = this.db.transaction(this.STORE_NAME, 'readonly');
|
21121
|
+
const store = transaction.objectStore(this.STORE_NAME);
|
21122
|
+
const index = store.index('dialogId_sentTime');
|
21123
|
+
let range;
|
21124
|
+
const direction = 'prev';
|
21125
|
+
if (timestamp === "0") {
|
21126
|
+
range = IDBKeyRange.bound([dialogId, ''], [dialogId, '\uffff']);
|
21127
|
+
} else {
|
21128
|
+
range = IDBKeyRange.bound([dialogId, ''], [dialogId, timestamp]);
|
21129
|
+
}
|
21130
|
+
const messages = [];
|
21131
|
+
let hasMoreMessages = false;
|
21132
|
+
let processedCount = 0;
|
21133
|
+
const countRequest = index.count(range);
|
21134
|
+
countRequest.onsuccess = () => {
|
21135
|
+
const totalCount = countRequest.result;
|
21136
|
+
const cursorRequest = index.openCursor(range, direction);
|
21137
|
+
cursorRequest.onsuccess = event => {
|
21138
|
+
const cursor = event.target.result;
|
21139
|
+
if (cursor) {
|
21140
|
+
if (processedCount < count) {
|
21141
|
+
messages.push(cursor.value);
|
21142
|
+
processedCount++;
|
21143
|
+
cursor.continue();
|
21144
|
+
} else {
|
21145
|
+
hasMoreMessages = true;
|
21146
|
+
finishQuery();
|
21147
|
+
}
|
21148
|
+
} else {
|
21149
|
+
finishQuery();
|
21150
|
+
}
|
21151
|
+
};
|
21152
|
+
function finishQuery() {
|
21153
|
+
messages.sort((a, b) => Long.fromString(a.sentTime).compare(Long.fromString(b.sentTime)));
|
21154
|
+
resolve({
|
21155
|
+
messages,
|
21156
|
+
hasMore: hasMoreMessages || totalCount > count || !isLoaded
|
21157
|
+
});
|
21158
|
+
}
|
21159
|
+
};
|
21160
|
+
transaction.onerror = event => {
|
21161
|
+
console.error('获取消息事务失败', event);
|
21162
|
+
reject(new Error('获取消息事务失败'));
|
21163
|
+
};
|
21164
|
+
});
|
21165
|
+
}
|
21166
|
+
async clearConversationCache(conversation) {
|
21167
|
+
const dialogId = getFullDialogId(conversation);
|
21168
|
+
if (!this.db) {
|
21169
|
+
this.loadedEndMap.set(dialogId, true);
|
21170
|
+
return;
|
21171
|
+
}
|
21172
|
+
const deleteMessagesPromise = new Promise((resolve, reject) => {
|
21173
|
+
const transaction = this.db.transaction(this.STORE_NAME, 'readwrite');
|
21174
|
+
const store = transaction.objectStore(this.STORE_NAME);
|
21175
|
+
const index = store.index('dialogId');
|
21176
|
+
const request = index.openCursor(IDBKeyRange.only(dialogId));
|
21177
|
+
request.onsuccess = event => {
|
21178
|
+
const cursor = event.target.result;
|
21179
|
+
if (cursor) {
|
21180
|
+
cursor.delete();
|
21181
|
+
cursor.continue();
|
21182
|
+
}
|
21183
|
+
};
|
21184
|
+
transaction.oncomplete = () => {
|
21185
|
+
resolve();
|
21186
|
+
};
|
21187
|
+
transaction.onerror = event => {
|
21188
|
+
reject(new Error('清除会话消息失败'));
|
21189
|
+
};
|
21190
|
+
});
|
21191
|
+
await Promise.all([deleteMessagesPromise, this.updateDialogState(dialogId, true)]);
|
21192
|
+
}
|
21193
|
+
async clearAllCache() {
|
21194
|
+
if (!this.db) {
|
21195
|
+
this.loadedEndMap.clear();
|
21196
|
+
return;
|
21197
|
+
}
|
21198
|
+
const clearMessagesPromise = new Promise((resolve, reject) => {
|
21199
|
+
const transaction = this.db.transaction(this.STORE_NAME, 'readwrite');
|
21200
|
+
const store = transaction.objectStore(this.STORE_NAME);
|
21201
|
+
const request = store.clear();
|
21202
|
+
request.onsuccess = () => {
|
21203
|
+
resolve();
|
21204
|
+
};
|
21205
|
+
request.onerror = event => {
|
21206
|
+
reject(new Error('清除所有消息失败'));
|
21207
|
+
};
|
21208
|
+
});
|
21209
|
+
const clearStatesPromise = new Promise((resolve, reject) => {
|
21210
|
+
const transaction = this.db.transaction(this.DIALOG_STATE_STORE, 'readwrite');
|
21211
|
+
const store = transaction.objectStore(this.DIALOG_STATE_STORE);
|
21212
|
+
const request = store.clear();
|
21213
|
+
request.onsuccess = () => {
|
21214
|
+
this.loadedEndMap.clear();
|
21215
|
+
resolve();
|
21216
|
+
};
|
21217
|
+
request.onerror = event => {
|
21218
|
+
reject(new Error('清除所有会话状态失败'));
|
21219
|
+
};
|
21220
|
+
});
|
21221
|
+
await Promise.all([clearMessagesPromise, clearStatesPromise]);
|
21222
|
+
}
|
21223
|
+
async getDialogLoadedState(dialogId) {
|
21224
|
+
if (this.loadedEndMap.has(dialogId)) {
|
21225
|
+
return this.loadedEndMap.get(dialogId);
|
21226
|
+
}
|
21227
|
+
if (!this.db) {
|
21228
|
+
return false;
|
21229
|
+
}
|
21230
|
+
return new Promise((resolve, reject) => {
|
21231
|
+
const transaction = this.db.transaction(this.DIALOG_STATE_STORE, 'readonly');
|
21232
|
+
const store = transaction.objectStore(this.DIALOG_STATE_STORE);
|
21233
|
+
const request = store.get(dialogId);
|
21234
|
+
request.onsuccess = () => {
|
21235
|
+
const state = request.result;
|
21236
|
+
if (state) {
|
21237
|
+
this.loadedEndMap.set(dialogId, state.isEnd);
|
21238
|
+
resolve(state.isEnd);
|
21239
|
+
} else {
|
21240
|
+
resolve(false);
|
21241
|
+
}
|
21242
|
+
};
|
21243
|
+
request.onerror = event => {
|
21244
|
+
resolve(false);
|
21245
|
+
};
|
21246
|
+
});
|
21247
|
+
}
|
21248
|
+
async removeMessagesByUId(messageUIds) {
|
21249
|
+
if (!messageUIds || messageUIds.length === 0 || !this.db) {
|
21250
|
+
return;
|
21251
|
+
}
|
21252
|
+
return new Promise((resolve, reject) => {
|
21253
|
+
const transaction = this.db.transaction(this.STORE_NAME, 'readwrite');
|
21254
|
+
const store = transaction.objectStore(this.STORE_NAME);
|
21255
|
+
let completed = 0;
|
21256
|
+
let hasError = false;
|
21257
|
+
messageUIds.forEach(id => {
|
21258
|
+
const deleteRequest = store.delete(id);
|
21259
|
+
deleteRequest.onsuccess = () => {
|
21260
|
+
completed++;
|
21261
|
+
if (completed === messageUIds.length && !hasError) {
|
21262
|
+
resolve();
|
21263
|
+
}
|
21264
|
+
};
|
21265
|
+
deleteRequest.onerror = event => {
|
21266
|
+
console.error('删除消息失败', id, event);
|
21267
|
+
if (!hasError) {
|
21268
|
+
hasError = true;
|
21269
|
+
reject(new Error('删除消息失败'));
|
21270
|
+
}
|
21271
|
+
};
|
21272
|
+
});
|
21273
|
+
transaction.oncomplete = () => {
|
21274
|
+
if (!hasError) {
|
21275
|
+
resolve();
|
21276
|
+
}
|
21277
|
+
};
|
21278
|
+
transaction.onerror = event => {
|
21279
|
+
reject(new Error('批量删除消息事务失败'));
|
21280
|
+
};
|
21281
|
+
});
|
21282
|
+
}
|
21283
|
+
async updateMessageReceiptStatus(event, type) {
|
21284
|
+
if (!event || !event.messageUIdList || event.messageUIdList.length === 0 || !this.db) {
|
21285
|
+
return;
|
21286
|
+
}
|
21287
|
+
const {
|
21288
|
+
conversation
|
21289
|
+
} = event;
|
21290
|
+
getFullDialogId(conversation);
|
21291
|
+
return new Promise((resolve, reject) => {
|
21292
|
+
const transaction = this.db.transaction(this.STORE_NAME, 'readwrite');
|
21293
|
+
const store = transaction.objectStore(this.STORE_NAME);
|
21294
|
+
new Set(event.messageUIdList);
|
21295
|
+
let completed = 0;
|
21296
|
+
let hasError = false;
|
21297
|
+
event.messageUIdList.forEach(id => {
|
21298
|
+
const getRequest = store.get(id);
|
21299
|
+
getRequest.onsuccess = () => {
|
21300
|
+
const message = getRequest.result;
|
21301
|
+
if (message) {
|
21302
|
+
let needUpdate = false;
|
21303
|
+
if (type === 0 && message.receivedStatus < ReceivedStatus.RECEIVED) {
|
21304
|
+
message.receivedStatus = ReceivedStatus.RECEIVED;
|
21305
|
+
needUpdate = true;
|
21306
|
+
} else if (type === 1 && message.receivedStatus < ReceivedStatus.READ) {
|
21307
|
+
message.receivedStatus = ReceivedStatus.READ;
|
21308
|
+
needUpdate = true;
|
21309
|
+
}
|
21310
|
+
if (needUpdate) {
|
21311
|
+
store.put(message);
|
21312
|
+
}
|
21313
|
+
}
|
21314
|
+
completed++;
|
21315
|
+
if (completed === event.messageUIdList.length && !hasError) {
|
21316
|
+
resolve();
|
21317
|
+
}
|
21318
|
+
};
|
21319
|
+
getRequest.onerror = event => {
|
21320
|
+
if (!hasError) {
|
21321
|
+
hasError = true;
|
21322
|
+
reject(new Error('更新消息状态失败'));
|
21323
|
+
}
|
21324
|
+
};
|
21325
|
+
});
|
21326
|
+
transaction.oncomplete = () => {
|
21327
|
+
if (!hasError) {
|
21328
|
+
resolve();
|
21329
|
+
}
|
21330
|
+
};
|
21331
|
+
transaction.onerror = event => {
|
21332
|
+
reject(new Error('更新消息状态事务失败'));
|
21333
|
+
};
|
21334
|
+
});
|
21335
|
+
}
|
21336
|
+
async clearBurnAfterReadingExpiredMessages(conversation) {
|
21337
|
+
const dialogId = getFullDialogId(conversation);
|
21338
|
+
if (!this.db) {
|
21339
|
+
return [];
|
21340
|
+
}
|
21341
|
+
const currentTime = Date.now();
|
21342
|
+
return new Promise((resolve, reject) => {
|
21343
|
+
const transaction = this.db.transaction(this.STORE_NAME, 'readwrite');
|
21344
|
+
const store = transaction.objectStore(this.STORE_NAME);
|
21345
|
+
const index = store.index('dialogId');
|
21346
|
+
const expiredMessageUIds = [];
|
21347
|
+
const request = index.openCursor(IDBKeyRange.only(dialogId));
|
21348
|
+
request.onsuccess = event => {
|
21349
|
+
const cursor = event.target.result;
|
21350
|
+
if (cursor) {
|
21351
|
+
const message = cursor.value;
|
21352
|
+
if (message.burnAfterReadingFlag) {
|
21353
|
+
const burnTime = message.burnAfterReadingTime || 0;
|
21354
|
+
let isExpired = burnTime === 0;
|
21355
|
+
if (!isExpired && burnTime > 0) {
|
21356
|
+
const sentTimeLong = Long.fromString(message.sentTime);
|
21357
|
+
const currentTimeLong = Long.fromNumber(currentTime);
|
21358
|
+
const burnTimeLong = Long.fromNumber(burnTime);
|
21359
|
+
const expirationTime = sentTimeLong.add(burnTimeLong);
|
21360
|
+
isExpired = currentTimeLong.greaterThan(expirationTime);
|
21361
|
+
}
|
21362
|
+
if (isExpired) {
|
21363
|
+
expiredMessageUIds.push(message.messageUId);
|
21364
|
+
cursor.delete();
|
21365
|
+
}
|
21366
|
+
}
|
21367
|
+
cursor.continue();
|
21368
|
+
} else {
|
21369
|
+
resolve(expiredMessageUIds);
|
21370
|
+
}
|
21371
|
+
};
|
21372
|
+
request.onerror = event => {
|
21373
|
+
console.error('清除过期消息失败', event);
|
21374
|
+
reject(new Error('清除过期消息失败'));
|
21375
|
+
};
|
21376
|
+
});
|
21377
|
+
}
|
21378
|
+
async getMessagesByPage(dialogId, pageSize = 20, cursorPosition = null) {
|
21379
|
+
if (!this.db) {
|
21380
|
+
return {
|
21381
|
+
messages: [],
|
21382
|
+
nextCursor: null
|
21383
|
+
};
|
21384
|
+
}
|
21385
|
+
return new Promise((resolve, reject) => {
|
21386
|
+
const transaction = this.db.transaction(this.STORE_NAME, 'readonly');
|
21387
|
+
const store = transaction.objectStore(this.STORE_NAME);
|
21388
|
+
const index = store.index('dialogId_sentTime');
|
21389
|
+
const range = IDBKeyRange.bound([dialogId, cursorPosition || ''], [dialogId, '\uffff']);
|
21390
|
+
const messages = [];
|
21391
|
+
let nextCursor = null;
|
21392
|
+
let count = 0;
|
21393
|
+
const cursorRequest = index.openCursor(range);
|
21394
|
+
cursorRequest.onsuccess = event => {
|
21395
|
+
const cursor = event.target.result;
|
21396
|
+
if (cursor && count < pageSize) {
|
21397
|
+
messages.push(cursor.value);
|
21398
|
+
count++;
|
21399
|
+
cursor.continue();
|
21400
|
+
} else if (cursor) {
|
21401
|
+
nextCursor = cursor.value.sentTime;
|
21402
|
+
} else {
|
21403
|
+
nextCursor = null;
|
21404
|
+
}
|
21405
|
+
if (!cursor || count >= pageSize) {
|
21406
|
+
resolve({
|
21407
|
+
messages,
|
21408
|
+
nextCursor
|
21409
|
+
});
|
21410
|
+
}
|
21411
|
+
};
|
21412
|
+
cursorRequest.onerror = event => {
|
21413
|
+
reject(new Error('获取分页消息失败'));
|
21414
|
+
};
|
21415
|
+
});
|
21416
|
+
}
|
21417
|
+
async updateMessagesStatus(messageUIds, newStatus) {
|
21418
|
+
if (!this.db || messageUIds.length === 0) {
|
21419
|
+
return;
|
21420
|
+
}
|
21421
|
+
return new Promise((resolve, reject) => {
|
21422
|
+
const transaction = this.db.transaction(this.STORE_NAME, 'readwrite');
|
21423
|
+
const store = transaction.objectStore(this.STORE_NAME);
|
21424
|
+
let completed = 0;
|
21425
|
+
let hasError = false;
|
21426
|
+
messageUIds.forEach(id => {
|
21427
|
+
const getRequest = store.get(id);
|
21428
|
+
getRequest.onsuccess = () => {
|
21429
|
+
const message = getRequest.result;
|
21430
|
+
if (message) {
|
21431
|
+
message.receivedStatus = newStatus;
|
21432
|
+
store.put(message);
|
21433
|
+
}
|
21434
|
+
completed++;
|
21435
|
+
if (completed === messageUIds.length && !hasError) {
|
21436
|
+
resolve();
|
21437
|
+
}
|
21438
|
+
};
|
21439
|
+
getRequest.onerror = event => {
|
21440
|
+
if (!hasError) {
|
21441
|
+
hasError = true;
|
21442
|
+
reject(new Error('更新消息状态失败'));
|
21443
|
+
}
|
21444
|
+
};
|
21445
|
+
});
|
21446
|
+
transaction.oncomplete = () => {
|
21447
|
+
resolve();
|
21448
|
+
};
|
21449
|
+
transaction.onerror = event => {
|
21450
|
+
reject(new Error('批量更新事务失败'));
|
21451
|
+
};
|
21452
|
+
});
|
21453
|
+
}
|
21454
|
+
async changeUser(appKey, userId) {
|
21455
|
+
if (this.currentAppKey === appKey && this.currentUserId === userId) {
|
21456
|
+
return;
|
21457
|
+
}
|
21458
|
+
this.currentAppKey = appKey;
|
21459
|
+
this.currentUserId = userId;
|
21460
|
+
await this.checkAndResetDatabase();
|
21461
|
+
await this.initDatabase();
|
21462
|
+
}
|
21463
|
+
}
|
21464
|
+
let cache;
|
21465
|
+
var MessageCache$1 = {
|
21466
|
+
create(appkey, currentUserId) {
|
21467
|
+
cache = new MessageCache(appkey, currentUserId);
|
21468
|
+
},
|
21469
|
+
get() {
|
21470
|
+
return cache;
|
21471
|
+
}
|
21472
|
+
};
|
21473
|
+
|
20940
21474
|
const DEFAULT_SOCKET_URI = 'wss://imweb.mp.net:6443';
|
20941
21475
|
class LibLoader {
|
20942
21476
|
options;
|
@@ -21025,6 +21559,7 @@ class LibLoader {
|
|
21025
21559
|
ConversationManager$1.get().destroyed();
|
21026
21560
|
ConversationManager$1.create(this.options.appkey, accountStore.uid.toString(), this.watcher.conversationState);
|
21027
21561
|
MessageReceiptManager$1.create(this.options.appkey, accountStore.uid.toString());
|
21562
|
+
MessageCache$1.create(this.options.appkey, accountStore.uid.toString());
|
21028
21563
|
this.messageLoader?.stop();
|
21029
21564
|
this.messageLoader = new MessageLoader(this.watcher, this.options);
|
21030
21565
|
synchronizeServerTime();
|
@@ -28373,174 +28908,6 @@ function getMessageSentTime() {
|
|
28373
28908
|
return UniqueSentTime;
|
28374
28909
|
}
|
28375
28910
|
|
28376
|
-
class MessageCache {
|
28377
|
-
static instance;
|
28378
|
-
messageCache = new Map();
|
28379
|
-
loadedEndMap = new Map();
|
28380
|
-
maxCacheCount = 1000;
|
28381
|
-
constructor() {}
|
28382
|
-
static get() {
|
28383
|
-
if (!MessageCache.instance) {
|
28384
|
-
MessageCache.instance = new MessageCache();
|
28385
|
-
}
|
28386
|
-
return MessageCache.instance;
|
28387
|
-
}
|
28388
|
-
setMaxCacheCount(count) {
|
28389
|
-
if (count > 0) {
|
28390
|
-
this.maxCacheCount = count;
|
28391
|
-
}
|
28392
|
-
}
|
28393
|
-
addMessages(messages, toConversation, isEnd = undefined) {
|
28394
|
-
const dialogId = getFullDialogId(toConversation);
|
28395
|
-
if (isDef(isEnd)) {
|
28396
|
-
this.loadedEndMap.set(dialogId, isEnd);
|
28397
|
-
}
|
28398
|
-
if (!messages || messages.length === 0) {
|
28399
|
-
return;
|
28400
|
-
}
|
28401
|
-
if (!this.messageCache.has(dialogId)) {
|
28402
|
-
this.messageCache.set(dialogId, []);
|
28403
|
-
}
|
28404
|
-
const cachedMessages = this.messageCache.get(dialogId) || [];
|
28405
|
-
const existingMessageIds = new Set(cachedMessages.map(msg => msg.messageUId));
|
28406
|
-
const newMessages = messages.filter(msg => !existingMessageIds.has(msg.messageUId));
|
28407
|
-
const allMessages = [...cachedMessages, ...newMessages].sort((a, b) => Long.fromString(a.sentTime).compare(Long.fromString(b.sentTime)));
|
28408
|
-
if (allMessages.length > this.maxCacheCount) {
|
28409
|
-
allMessages.splice(0, allMessages.length - this.maxCacheCount);
|
28410
|
-
}
|
28411
|
-
this.messageCache.set(dialogId, allMessages);
|
28412
|
-
}
|
28413
|
-
getPreviousMessages(conversation, timestamp = "0", count = 20) {
|
28414
|
-
const dialogId = getFullDialogId(conversation);
|
28415
|
-
const cachedMessages = this.messageCache.get(dialogId) || [];
|
28416
|
-
if (cachedMessages.length === 0) {
|
28417
|
-
return {
|
28418
|
-
messages: [],
|
28419
|
-
hasMore: !this.loadedEndMap.get(dialogId)
|
28420
|
-
};
|
28421
|
-
}
|
28422
|
-
if (timestamp === "0") {
|
28423
|
-
const messages = cachedMessages.slice(-count);
|
28424
|
-
return {
|
28425
|
-
messages,
|
28426
|
-
hasMore: cachedMessages.length > count || !this.loadedEndMap.get(dialogId)
|
28427
|
-
};
|
28428
|
-
}
|
28429
|
-
const timestampLong = Long.fromString(timestamp);
|
28430
|
-
let endIndex = cachedMessages.length - 1;
|
28431
|
-
while (endIndex >= 0) {
|
28432
|
-
if (Long.fromString(cachedMessages[endIndex].sentTime).lessThanOrEqual(timestampLong)) {
|
28433
|
-
break;
|
28434
|
-
}
|
28435
|
-
endIndex--;
|
28436
|
-
}
|
28437
|
-
if (endIndex < 0) {
|
28438
|
-
return {
|
28439
|
-
messages: [],
|
28440
|
-
hasMore: !this.loadedEndMap.get(dialogId)
|
28441
|
-
};
|
28442
|
-
}
|
28443
|
-
const startIndex = Math.max(0, endIndex - count + 1);
|
28444
|
-
return {
|
28445
|
-
messages: cachedMessages.slice(startIndex, endIndex + 1),
|
28446
|
-
hasMore: startIndex > 0 || !this.loadedEndMap.get(dialogId)
|
28447
|
-
};
|
28448
|
-
}
|
28449
|
-
clearConversationCache(conversation) {
|
28450
|
-
const dialogId = getFullDialogId(conversation);
|
28451
|
-
this.messageCache.delete(dialogId);
|
28452
|
-
this.loadedEndMap.set(dialogId, true);
|
28453
|
-
}
|
28454
|
-
clearAllCache() {
|
28455
|
-
this.messageCache.clear();
|
28456
|
-
this.loadedEndMap.clear();
|
28457
|
-
}
|
28458
|
-
removeMessagesByUId(messageUIds) {
|
28459
|
-
if (!messageUIds || messageUIds.length === 0) {
|
28460
|
-
return;
|
28461
|
-
}
|
28462
|
-
const messageUIdSet = new Set(messageUIds);
|
28463
|
-
this.messageCache.forEach((messages, dialogId) => {
|
28464
|
-
const filteredMessages = messages.filter(msg => !messageUIdSet.has(msg.messageUId));
|
28465
|
-
if (filteredMessages.length !== messages.length) {
|
28466
|
-
this.messageCache.set(dialogId, filteredMessages);
|
28467
|
-
}
|
28468
|
-
});
|
28469
|
-
}
|
28470
|
-
updateMessageReceiptStatus(event, type) {
|
28471
|
-
if (!event || !event.messageUIdList || event.messageUIdList.length === 0) {
|
28472
|
-
return;
|
28473
|
-
}
|
28474
|
-
const {
|
28475
|
-
conversation
|
28476
|
-
} = event;
|
28477
|
-
const dialogId = getFullDialogId(conversation);
|
28478
|
-
const cachedMessages = this.messageCache.get(dialogId);
|
28479
|
-
if (!cachedMessages || cachedMessages.length === 0) {
|
28480
|
-
return;
|
28481
|
-
}
|
28482
|
-
const messageUIdSet = new Set(event.messageUIdList);
|
28483
|
-
let updated = false;
|
28484
|
-
const updatedMessages = cachedMessages.map((message, index) => {
|
28485
|
-
if (messageUIdSet.has(message.messageUId)) {
|
28486
|
-
if (type === 0) {
|
28487
|
-
if (message.receivedStatus < ReceivedStatus.RECEIVED) {
|
28488
|
-
updated = true;
|
28489
|
-
return {
|
28490
|
-
...message,
|
28491
|
-
receivedStatus: ReceivedStatus.RECEIVED
|
28492
|
-
};
|
28493
|
-
}
|
28494
|
-
} else {
|
28495
|
-
if (message.receivedStatus < ReceivedStatus.READ) {
|
28496
|
-
updated = true;
|
28497
|
-
return {
|
28498
|
-
...message,
|
28499
|
-
receivedStatus: ReceivedStatus.READ
|
28500
|
-
};
|
28501
|
-
}
|
28502
|
-
}
|
28503
|
-
}
|
28504
|
-
return message;
|
28505
|
-
});
|
28506
|
-
if (updated) {
|
28507
|
-
this.messageCache.set(dialogId, updatedMessages);
|
28508
|
-
}
|
28509
|
-
}
|
28510
|
-
clearBurnAfterReadingExpiredMessages(conversation) {
|
28511
|
-
const dialogId = getFullDialogId(conversation);
|
28512
|
-
const cachedMessages = this.messageCache.get(dialogId);
|
28513
|
-
if (!cachedMessages || cachedMessages.length === 0) {
|
28514
|
-
return [];
|
28515
|
-
}
|
28516
|
-
const currentTime = Date.now();
|
28517
|
-
const expiredMessageUIds = [];
|
28518
|
-
const remainingMessages = cachedMessages.filter(message => {
|
28519
|
-
if (!message.burnAfterReadingFlag) {
|
28520
|
-
return true;
|
28521
|
-
}
|
28522
|
-
const burnTime = message.burnAfterReadingTime || 0;
|
28523
|
-
if (burnTime === 0) {
|
28524
|
-
expiredMessageUIds.push(message.messageUId);
|
28525
|
-
return false;
|
28526
|
-
}
|
28527
|
-
const sentTimeLong = Long.fromString(message.sentTime);
|
28528
|
-
const currentTimeLong = Long.fromNumber(currentTime);
|
28529
|
-
const burnTimeLong = Long.fromNumber(burnTime);
|
28530
|
-
const expirationTime = sentTimeLong.add(burnTimeLong);
|
28531
|
-
if (currentTimeLong.greaterThan(expirationTime)) {
|
28532
|
-
expiredMessageUIds.push(message.messageUId);
|
28533
|
-
return false;
|
28534
|
-
}
|
28535
|
-
return true;
|
28536
|
-
});
|
28537
|
-
if (remainingMessages.length < cachedMessages.length) {
|
28538
|
-
this.messageCache.set(dialogId, remainingMessages);
|
28539
|
-
}
|
28540
|
-
return expiredMessageUIds;
|
28541
|
-
}
|
28542
|
-
}
|
28543
|
-
|
28544
28911
|
class IMClient extends EventEmitter {
|
28545
28912
|
options;
|
28546
28913
|
static imClient;
|
@@ -28589,7 +28956,7 @@ class IMClient extends EventEmitter {
|
|
28589
28956
|
},
|
28590
28957
|
batchMessage: messages => {
|
28591
28958
|
if (messages.length) {
|
28592
|
-
MessageCache.get()
|
28959
|
+
MessageCache$1.get()?.addMessages(messages, {
|
28593
28960
|
conversationType: messages[0].content,
|
28594
28961
|
targetId: messages[0].targetId
|
28595
28962
|
});
|
@@ -28620,13 +28987,13 @@ class IMClient extends EventEmitter {
|
|
28620
28987
|
});
|
28621
28988
|
},
|
28622
28989
|
onRecall: messageUids => {
|
28623
|
-
MessageCache.get()
|
28990
|
+
MessageCache$1.get()?.removeMessagesByUId(messageUids);
|
28624
28991
|
messageUids.forEach(messageUId => {
|
28625
28992
|
this.emit(Events.RECALL, messageUId);
|
28626
28993
|
});
|
28627
28994
|
},
|
28628
28995
|
onReceiptReceived: (event, type) => {
|
28629
|
-
MessageCache.get()
|
28996
|
+
MessageCache$1.get()?.updateMessageReceiptStatus(event, type);
|
28630
28997
|
if (type === 0) {
|
28631
28998
|
this.emit(Events.ARRIVAL_RECEIPT_RECEIVED, event);
|
28632
28999
|
} else {
|
@@ -28662,7 +29029,7 @@ class IMClient extends EventEmitter {
|
|
28662
29029
|
async recallMsg(conversation, options) {
|
28663
29030
|
const result = await sendRecallMessage(conversation, options);
|
28664
29031
|
if (result.code === ErrorCode.SUCCESS) {
|
28665
|
-
MessageCache.get()
|
29032
|
+
MessageCache$1.get()?.removeMessagesByUId([options.messageUId]);
|
28666
29033
|
}
|
28667
29034
|
return result;
|
28668
29035
|
}
|
@@ -28704,7 +29071,8 @@ class IMClient extends EventEmitter {
|
|
28704
29071
|
});
|
28705
29072
|
}
|
28706
29073
|
async getPreviousHistoryMessages(conversation, timestamp, count = 20) {
|
28707
|
-
|
29074
|
+
debugger;
|
29075
|
+
const cachedResult = await MessageCache$1.get().getPreviousMessages(conversation, timestamp ?? '0', count);
|
28708
29076
|
if (!timestamp && cachedResult.messages.length) {
|
28709
29077
|
ConversationManager$1.get().refreshLatestMessage(conversation, cachedResult.messages[cachedResult.messages.length - 1]);
|
28710
29078
|
}
|
@@ -28730,7 +29098,7 @@ class IMClient extends EventEmitter {
|
|
28730
29098
|
if (!remotesTimestamp) {
|
28731
29099
|
ConversationManager$1.get().refreshLatestMessage(conversation, remotesMessages[remotesMessages.length - 1]);
|
28732
29100
|
}
|
28733
|
-
MessageCache.get().addMessages(remotesMessages, conversation, !remotesResult.data.hasMore);
|
29101
|
+
MessageCache$1.get().addMessages(remotesMessages, conversation, !remotesResult.data.hasMore);
|
28734
29102
|
return {
|
28735
29103
|
code: ErrorCode.SUCCESS,
|
28736
29104
|
data: {
|
@@ -28740,11 +29108,11 @@ class IMClient extends EventEmitter {
|
|
28740
29108
|
};
|
28741
29109
|
}
|
28742
29110
|
async deleteRemoteMessage(conversation, list) {
|
28743
|
-
MessageCache.get()
|
29111
|
+
MessageCache$1.get()?.removeMessagesByUId(list.map(e => e.messageUId));
|
28744
29112
|
return deleteMessages$1(getFullDialogId(conversation), list.map(e => e.messageUId)).then(result => result.code);
|
28745
29113
|
}
|
28746
29114
|
async deleteRemoteMessageByTimestamp(conversation, timestamp) {
|
28747
|
-
MessageCache.get()
|
29115
|
+
MessageCache$1.get()?.clearConversationCache(conversation);
|
28748
29116
|
ConversationManager$1.get().clearHistoryMessages(conversation);
|
28749
29117
|
return clearHistoryMessage(getFullDialogId(conversation), timestamp === 0 ? Number.MAX_VALUE : timestamp).then(result => result.code);
|
28750
29118
|
}
|
@@ -28930,7 +29298,7 @@ class IMClient extends EventEmitter {
|
|
28930
29298
|
return conversationObj;
|
28931
29299
|
}
|
28932
29300
|
clearBurnAfterReadingExpiredMessages(conversation) {
|
28933
|
-
return MessageCache.get()
|
29301
|
+
return MessageCache$1.get()?.clearBurnAfterReadingExpiredMessages(conversation) ?? Promise.resolve([]);
|
28934
29302
|
}
|
28935
29303
|
}
|
28936
29304
|
|
@@ -30191,11 +30559,11 @@ const _logSendError = (conversation, errorCode) => {
|
|
30191
30559
|
logger.warn('send message fail ->' + errorCode + ':' + ErrorDesc(errorCode) + ',' + paramsStr);
|
30192
30560
|
}
|
30193
30561
|
};
|
30194
|
-
const clearBurnAfterReadingExpiredMessages = conversation => {
|
30562
|
+
const clearBurnAfterReadingExpiredMessages = async conversation => {
|
30195
30563
|
assert('conversation', conversation, AssertRules.CONVERSATION, true);
|
30196
30564
|
const paramsStr = 'conversationType:' + conversation.conversationType + ',targetId:' + conversation.targetId;
|
30197
30565
|
logger.debug('clear burn after reading expired messages ->' + paramsStr);
|
30198
|
-
const expiredMessageUIds = imClient.clearBurnAfterReadingExpiredMessages(conversation);
|
30566
|
+
const expiredMessageUIds = await imClient.clearBurnAfterReadingExpiredMessages(conversation);
|
30199
30567
|
if (expiredMessageUIds.length > 0) {
|
30200
30568
|
logger.debug(`已清除会话 ${paramsStr} 中的 ${expiredMessageUIds.length} 条阅后即焚过期消息`);
|
30201
30569
|
}
|