@onyx-p/imlib-web 2.0.6 → 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 -191
- package/index.umd.js +555 -191
- package/package.json +1 -1
package/index.umd.js
CHANGED
@@ -7747,14 +7747,6 @@
|
|
7747
7747
|
return typeof process !== 'undefined' && typeof process.versions !== 'undefined' && !!process.versions.electron;
|
7748
7748
|
};
|
7749
7749
|
let electronStore = null;
|
7750
|
-
if (isElectron()) {
|
7751
|
-
try {
|
7752
|
-
const Store = require('electron-store');
|
7753
|
-
electronStore = new Store();
|
7754
|
-
} catch (e) {
|
7755
|
-
console.error('Failed to initialize electron-store:', e);
|
7756
|
-
}
|
7757
|
-
}
|
7758
7750
|
const LocalStorageService = {
|
7759
7751
|
get: function (key) {
|
7760
7752
|
if (isElectron() && electronStore) {
|
@@ -20943,6 +20935,548 @@
|
|
20943
20935
|
|
20944
20936
|
const RecallCommandMessage = registerMessageType$1(MessageTypes.RECALL, true, false, false);
|
20945
20937
|
|
20938
|
+
class MessageCache {
|
20939
|
+
static instance;
|
20940
|
+
loadedEndMap = new Map();
|
20941
|
+
db = null;
|
20942
|
+
currentAppKey = '';
|
20943
|
+
currentUserId = '';
|
20944
|
+
APP_INFO_KEY = 'im_app_info';
|
20945
|
+
DB_NAME_PREFIX = 'im_message_cache';
|
20946
|
+
DB_VERSION = 2;
|
20947
|
+
STORE_NAME = 'messages';
|
20948
|
+
DIALOG_STATE_STORE = 'dialogStates';
|
20949
|
+
constructor(appKey, userId) {
|
20950
|
+
this.init(appKey, userId);
|
20951
|
+
}
|
20952
|
+
async init(appKey, userId) {
|
20953
|
+
this.currentAppKey = appKey;
|
20954
|
+
this.currentUserId = userId;
|
20955
|
+
await this.checkAndResetDatabase();
|
20956
|
+
await this.initDatabase();
|
20957
|
+
}
|
20958
|
+
async checkAndResetDatabase() {
|
20959
|
+
const storedInfoStr = LocalStorageService.get(this.APP_INFO_KEY);
|
20960
|
+
if (storedInfoStr) {
|
20961
|
+
try {
|
20962
|
+
const storedInfo = JSON.parse(storedInfoStr);
|
20963
|
+
if (storedInfo.appKey !== this.currentAppKey || storedInfo.userId !== this.currentUserId) {
|
20964
|
+
await this.deleteDatabase();
|
20965
|
+
}
|
20966
|
+
} catch (error) {
|
20967
|
+
console.error('解析存储的AppKey和UserId出错', error);
|
20968
|
+
await this.deleteDatabase();
|
20969
|
+
}
|
20970
|
+
}
|
20971
|
+
LocalStorageService.set(this.APP_INFO_KEY, JSON.stringify({
|
20972
|
+
appKey: this.currentAppKey,
|
20973
|
+
userId: this.currentUserId,
|
20974
|
+
timestamp: Date.now()
|
20975
|
+
}));
|
20976
|
+
}
|
20977
|
+
async deleteDatabase() {
|
20978
|
+
if (this.db) {
|
20979
|
+
this.db.close();
|
20980
|
+
this.db = null;
|
20981
|
+
}
|
20982
|
+
this.loadedEndMap.clear();
|
20983
|
+
return new Promise((resolve, reject) => {
|
20984
|
+
const dbName = this.getDBName();
|
20985
|
+
const deleteRequest = indexedDB.deleteDatabase(dbName);
|
20986
|
+
deleteRequest.onsuccess = () => {
|
20987
|
+
console.log(`数据库 ${dbName} 已成功删除`);
|
20988
|
+
resolve();
|
20989
|
+
};
|
20990
|
+
deleteRequest.onerror = event => {
|
20991
|
+
console.error(`删除数据库 ${dbName} 失败`, event);
|
20992
|
+
resolve();
|
20993
|
+
};
|
20994
|
+
});
|
20995
|
+
}
|
20996
|
+
getDBName() {
|
20997
|
+
return `${this.DB_NAME_PREFIX}_${this.currentAppKey}_${this.currentUserId}`;
|
20998
|
+
}
|
20999
|
+
initDatabase() {
|
21000
|
+
return new Promise((resolve, reject) => {
|
21001
|
+
const dbName = this.getDBName();
|
21002
|
+
const request = indexedDB.open(dbName, this.DB_VERSION);
|
21003
|
+
request.onerror = event => {
|
21004
|
+
console.error('数据库打开失败', event);
|
21005
|
+
reject(new Error('数据库打开失败'));
|
21006
|
+
};
|
21007
|
+
request.onsuccess = event => {
|
21008
|
+
this.db = event.target.result;
|
21009
|
+
this.loadAllDialogStates().then(() => {
|
21010
|
+
resolve();
|
21011
|
+
}).catch(err => {
|
21012
|
+
console.error('加载会话状态失败', err);
|
21013
|
+
resolve();
|
21014
|
+
});
|
21015
|
+
};
|
21016
|
+
request.onupgradeneeded = event => {
|
21017
|
+
const db = event.target.result;
|
21018
|
+
if (!db.objectStoreNames.contains(this.STORE_NAME)) {
|
21019
|
+
const store = db.createObjectStore(this.STORE_NAME, {
|
21020
|
+
keyPath: 'messageUId'
|
21021
|
+
});
|
21022
|
+
store.createIndex('dialogId', 'dialogId', {
|
21023
|
+
unique: false
|
21024
|
+
});
|
21025
|
+
store.createIndex('dialogId_sentTime', ['dialogId', 'sentTime'], {
|
21026
|
+
unique: false
|
21027
|
+
});
|
21028
|
+
store.createIndex('receivedStatus', 'receivedStatus', {
|
21029
|
+
unique: false
|
21030
|
+
});
|
21031
|
+
store.createIndex('burnAfterReadingFlag', 'burnAfterReadingFlag', {
|
21032
|
+
unique: false
|
21033
|
+
});
|
21034
|
+
store.createIndex('dialogId_receivedStatus', ['dialogId', 'receivedStatus'], {
|
21035
|
+
unique: false
|
21036
|
+
});
|
21037
|
+
}
|
21038
|
+
if (!db.objectStoreNames.contains(this.DIALOG_STATE_STORE)) {
|
21039
|
+
db.createObjectStore(this.DIALOG_STATE_STORE, {
|
21040
|
+
keyPath: 'dialogId'
|
21041
|
+
});
|
21042
|
+
}
|
21043
|
+
};
|
21044
|
+
});
|
21045
|
+
}
|
21046
|
+
async loadAllDialogStates() {
|
21047
|
+
if (!this.db) {
|
21048
|
+
return;
|
21049
|
+
}
|
21050
|
+
return new Promise((resolve, reject) => {
|
21051
|
+
const transaction = this.db.transaction(this.DIALOG_STATE_STORE, 'readonly');
|
21052
|
+
const store = transaction.objectStore(this.DIALOG_STATE_STORE);
|
21053
|
+
const request = store.getAll();
|
21054
|
+
request.onsuccess = () => {
|
21055
|
+
const states = request.result;
|
21056
|
+
this.loadedEndMap.clear();
|
21057
|
+
states.forEach(state => {
|
21058
|
+
this.loadedEndMap.set(state.dialogId, state.isEnd);
|
21059
|
+
});
|
21060
|
+
resolve();
|
21061
|
+
};
|
21062
|
+
request.onerror = event => {
|
21063
|
+
reject(new Error('加载会话状态失败'));
|
21064
|
+
};
|
21065
|
+
});
|
21066
|
+
}
|
21067
|
+
async updateDialogState(dialogId, isEnd) {
|
21068
|
+
if (!this.db) {
|
21069
|
+
return;
|
21070
|
+
}
|
21071
|
+
this.loadedEndMap.set(dialogId, isEnd);
|
21072
|
+
return new Promise((resolve, reject) => {
|
21073
|
+
const transaction = this.db.transaction(this.DIALOG_STATE_STORE, 'readwrite');
|
21074
|
+
const store = transaction.objectStore(this.DIALOG_STATE_STORE);
|
21075
|
+
const request = store.put({
|
21076
|
+
dialogId,
|
21077
|
+
isEnd,
|
21078
|
+
updateTime: Date.now()
|
21079
|
+
});
|
21080
|
+
request.onsuccess = () => {
|
21081
|
+
resolve();
|
21082
|
+
};
|
21083
|
+
request.onerror = event => {
|
21084
|
+
console.error('更新会话状态失败', event);
|
21085
|
+
reject(new Error('更新会话状态失败'));
|
21086
|
+
};
|
21087
|
+
});
|
21088
|
+
}
|
21089
|
+
async addMessages(messages, toConversation, isEnd = undefined) {
|
21090
|
+
const dialogId = getFullDialogId(toConversation);
|
21091
|
+
if (isDef(isEnd)) {
|
21092
|
+
await this.updateDialogState(dialogId, isEnd);
|
21093
|
+
}
|
21094
|
+
if (!messages || messages.length === 0 || !this.db) {
|
21095
|
+
return;
|
21096
|
+
}
|
21097
|
+
return new Promise((resolve, reject) => {
|
21098
|
+
const transaction = this.db.transaction(this.STORE_NAME, 'readwrite');
|
21099
|
+
const store = transaction.objectStore(this.STORE_NAME);
|
21100
|
+
messages.forEach(message => {
|
21101
|
+
const messageToStore = {
|
21102
|
+
...message,
|
21103
|
+
dialogId
|
21104
|
+
};
|
21105
|
+
store.put(messageToStore);
|
21106
|
+
});
|
21107
|
+
transaction.oncomplete = () => {
|
21108
|
+
resolve();
|
21109
|
+
};
|
21110
|
+
transaction.onerror = event => {
|
21111
|
+
console.error('添加消息事务失败', event);
|
21112
|
+
reject(new Error('添加消息事务失败'));
|
21113
|
+
};
|
21114
|
+
});
|
21115
|
+
}
|
21116
|
+
async getPreviousMessages(conversation, timestamp = "0", count = 20) {
|
21117
|
+
const dialogId = getFullDialogId(conversation);
|
21118
|
+
if (!this.db) {
|
21119
|
+
return {
|
21120
|
+
messages: [],
|
21121
|
+
hasMore: false
|
21122
|
+
};
|
21123
|
+
}
|
21124
|
+
const isLoaded = await this.getDialogLoadedState(dialogId);
|
21125
|
+
return new Promise((resolve, reject) => {
|
21126
|
+
const transaction = this.db.transaction(this.STORE_NAME, 'readonly');
|
21127
|
+
const store = transaction.objectStore(this.STORE_NAME);
|
21128
|
+
const index = store.index('dialogId_sentTime');
|
21129
|
+
let range;
|
21130
|
+
const direction = 'prev';
|
21131
|
+
if (timestamp === "0") {
|
21132
|
+
range = IDBKeyRange.bound([dialogId, ''], [dialogId, '\uffff']);
|
21133
|
+
} else {
|
21134
|
+
range = IDBKeyRange.bound([dialogId, ''], [dialogId, timestamp]);
|
21135
|
+
}
|
21136
|
+
const messages = [];
|
21137
|
+
let hasMoreMessages = false;
|
21138
|
+
let processedCount = 0;
|
21139
|
+
const countRequest = index.count(range);
|
21140
|
+
countRequest.onsuccess = () => {
|
21141
|
+
const totalCount = countRequest.result;
|
21142
|
+
const cursorRequest = index.openCursor(range, direction);
|
21143
|
+
cursorRequest.onsuccess = event => {
|
21144
|
+
const cursor = event.target.result;
|
21145
|
+
if (cursor) {
|
21146
|
+
if (processedCount < count) {
|
21147
|
+
messages.push(cursor.value);
|
21148
|
+
processedCount++;
|
21149
|
+
cursor.continue();
|
21150
|
+
} else {
|
21151
|
+
hasMoreMessages = true;
|
21152
|
+
finishQuery();
|
21153
|
+
}
|
21154
|
+
} else {
|
21155
|
+
finishQuery();
|
21156
|
+
}
|
21157
|
+
};
|
21158
|
+
function finishQuery() {
|
21159
|
+
messages.sort((a, b) => Long.fromString(a.sentTime).compare(Long.fromString(b.sentTime)));
|
21160
|
+
resolve({
|
21161
|
+
messages,
|
21162
|
+
hasMore: hasMoreMessages || totalCount > count || !isLoaded
|
21163
|
+
});
|
21164
|
+
}
|
21165
|
+
};
|
21166
|
+
transaction.onerror = event => {
|
21167
|
+
console.error('获取消息事务失败', event);
|
21168
|
+
reject(new Error('获取消息事务失败'));
|
21169
|
+
};
|
21170
|
+
});
|
21171
|
+
}
|
21172
|
+
async clearConversationCache(conversation) {
|
21173
|
+
const dialogId = getFullDialogId(conversation);
|
21174
|
+
if (!this.db) {
|
21175
|
+
this.loadedEndMap.set(dialogId, true);
|
21176
|
+
return;
|
21177
|
+
}
|
21178
|
+
const deleteMessagesPromise = new Promise((resolve, reject) => {
|
21179
|
+
const transaction = this.db.transaction(this.STORE_NAME, 'readwrite');
|
21180
|
+
const store = transaction.objectStore(this.STORE_NAME);
|
21181
|
+
const index = store.index('dialogId');
|
21182
|
+
const request = index.openCursor(IDBKeyRange.only(dialogId));
|
21183
|
+
request.onsuccess = event => {
|
21184
|
+
const cursor = event.target.result;
|
21185
|
+
if (cursor) {
|
21186
|
+
cursor.delete();
|
21187
|
+
cursor.continue();
|
21188
|
+
}
|
21189
|
+
};
|
21190
|
+
transaction.oncomplete = () => {
|
21191
|
+
resolve();
|
21192
|
+
};
|
21193
|
+
transaction.onerror = event => {
|
21194
|
+
reject(new Error('清除会话消息失败'));
|
21195
|
+
};
|
21196
|
+
});
|
21197
|
+
await Promise.all([deleteMessagesPromise, this.updateDialogState(dialogId, true)]);
|
21198
|
+
}
|
21199
|
+
async clearAllCache() {
|
21200
|
+
if (!this.db) {
|
21201
|
+
this.loadedEndMap.clear();
|
21202
|
+
return;
|
21203
|
+
}
|
21204
|
+
const clearMessagesPromise = new Promise((resolve, reject) => {
|
21205
|
+
const transaction = this.db.transaction(this.STORE_NAME, 'readwrite');
|
21206
|
+
const store = transaction.objectStore(this.STORE_NAME);
|
21207
|
+
const request = store.clear();
|
21208
|
+
request.onsuccess = () => {
|
21209
|
+
resolve();
|
21210
|
+
};
|
21211
|
+
request.onerror = event => {
|
21212
|
+
reject(new Error('清除所有消息失败'));
|
21213
|
+
};
|
21214
|
+
});
|
21215
|
+
const clearStatesPromise = new Promise((resolve, reject) => {
|
21216
|
+
const transaction = this.db.transaction(this.DIALOG_STATE_STORE, 'readwrite');
|
21217
|
+
const store = transaction.objectStore(this.DIALOG_STATE_STORE);
|
21218
|
+
const request = store.clear();
|
21219
|
+
request.onsuccess = () => {
|
21220
|
+
this.loadedEndMap.clear();
|
21221
|
+
resolve();
|
21222
|
+
};
|
21223
|
+
request.onerror = event => {
|
21224
|
+
reject(new Error('清除所有会话状态失败'));
|
21225
|
+
};
|
21226
|
+
});
|
21227
|
+
await Promise.all([clearMessagesPromise, clearStatesPromise]);
|
21228
|
+
}
|
21229
|
+
async getDialogLoadedState(dialogId) {
|
21230
|
+
if (this.loadedEndMap.has(dialogId)) {
|
21231
|
+
return this.loadedEndMap.get(dialogId);
|
21232
|
+
}
|
21233
|
+
if (!this.db) {
|
21234
|
+
return false;
|
21235
|
+
}
|
21236
|
+
return new Promise((resolve, reject) => {
|
21237
|
+
const transaction = this.db.transaction(this.DIALOG_STATE_STORE, 'readonly');
|
21238
|
+
const store = transaction.objectStore(this.DIALOG_STATE_STORE);
|
21239
|
+
const request = store.get(dialogId);
|
21240
|
+
request.onsuccess = () => {
|
21241
|
+
const state = request.result;
|
21242
|
+
if (state) {
|
21243
|
+
this.loadedEndMap.set(dialogId, state.isEnd);
|
21244
|
+
resolve(state.isEnd);
|
21245
|
+
} else {
|
21246
|
+
resolve(false);
|
21247
|
+
}
|
21248
|
+
};
|
21249
|
+
request.onerror = event => {
|
21250
|
+
resolve(false);
|
21251
|
+
};
|
21252
|
+
});
|
21253
|
+
}
|
21254
|
+
async removeMessagesByUId(messageUIds) {
|
21255
|
+
if (!messageUIds || messageUIds.length === 0 || !this.db) {
|
21256
|
+
return;
|
21257
|
+
}
|
21258
|
+
return new Promise((resolve, reject) => {
|
21259
|
+
const transaction = this.db.transaction(this.STORE_NAME, 'readwrite');
|
21260
|
+
const store = transaction.objectStore(this.STORE_NAME);
|
21261
|
+
let completed = 0;
|
21262
|
+
let hasError = false;
|
21263
|
+
messageUIds.forEach(id => {
|
21264
|
+
const deleteRequest = store.delete(id);
|
21265
|
+
deleteRequest.onsuccess = () => {
|
21266
|
+
completed++;
|
21267
|
+
if (completed === messageUIds.length && !hasError) {
|
21268
|
+
resolve();
|
21269
|
+
}
|
21270
|
+
};
|
21271
|
+
deleteRequest.onerror = event => {
|
21272
|
+
console.error('删除消息失败', id, event);
|
21273
|
+
if (!hasError) {
|
21274
|
+
hasError = true;
|
21275
|
+
reject(new Error('删除消息失败'));
|
21276
|
+
}
|
21277
|
+
};
|
21278
|
+
});
|
21279
|
+
transaction.oncomplete = () => {
|
21280
|
+
if (!hasError) {
|
21281
|
+
resolve();
|
21282
|
+
}
|
21283
|
+
};
|
21284
|
+
transaction.onerror = event => {
|
21285
|
+
reject(new Error('批量删除消息事务失败'));
|
21286
|
+
};
|
21287
|
+
});
|
21288
|
+
}
|
21289
|
+
async updateMessageReceiptStatus(event, type) {
|
21290
|
+
if (!event || !event.messageUIdList || event.messageUIdList.length === 0 || !this.db) {
|
21291
|
+
return;
|
21292
|
+
}
|
21293
|
+
const {
|
21294
|
+
conversation
|
21295
|
+
} = event;
|
21296
|
+
getFullDialogId(conversation);
|
21297
|
+
return new Promise((resolve, reject) => {
|
21298
|
+
const transaction = this.db.transaction(this.STORE_NAME, 'readwrite');
|
21299
|
+
const store = transaction.objectStore(this.STORE_NAME);
|
21300
|
+
new Set(event.messageUIdList);
|
21301
|
+
let completed = 0;
|
21302
|
+
let hasError = false;
|
21303
|
+
event.messageUIdList.forEach(id => {
|
21304
|
+
const getRequest = store.get(id);
|
21305
|
+
getRequest.onsuccess = () => {
|
21306
|
+
const message = getRequest.result;
|
21307
|
+
if (message) {
|
21308
|
+
let needUpdate = false;
|
21309
|
+
if (type === 0 && message.receivedStatus < exports.ReceivedStatus.RECEIVED) {
|
21310
|
+
message.receivedStatus = exports.ReceivedStatus.RECEIVED;
|
21311
|
+
needUpdate = true;
|
21312
|
+
} else if (type === 1 && message.receivedStatus < exports.ReceivedStatus.READ) {
|
21313
|
+
message.receivedStatus = exports.ReceivedStatus.READ;
|
21314
|
+
needUpdate = true;
|
21315
|
+
}
|
21316
|
+
if (needUpdate) {
|
21317
|
+
store.put(message);
|
21318
|
+
}
|
21319
|
+
}
|
21320
|
+
completed++;
|
21321
|
+
if (completed === event.messageUIdList.length && !hasError) {
|
21322
|
+
resolve();
|
21323
|
+
}
|
21324
|
+
};
|
21325
|
+
getRequest.onerror = event => {
|
21326
|
+
if (!hasError) {
|
21327
|
+
hasError = true;
|
21328
|
+
reject(new Error('更新消息状态失败'));
|
21329
|
+
}
|
21330
|
+
};
|
21331
|
+
});
|
21332
|
+
transaction.oncomplete = () => {
|
21333
|
+
if (!hasError) {
|
21334
|
+
resolve();
|
21335
|
+
}
|
21336
|
+
};
|
21337
|
+
transaction.onerror = event => {
|
21338
|
+
reject(new Error('更新消息状态事务失败'));
|
21339
|
+
};
|
21340
|
+
});
|
21341
|
+
}
|
21342
|
+
async clearBurnAfterReadingExpiredMessages(conversation) {
|
21343
|
+
const dialogId = getFullDialogId(conversation);
|
21344
|
+
if (!this.db) {
|
21345
|
+
return [];
|
21346
|
+
}
|
21347
|
+
const currentTime = Date.now();
|
21348
|
+
return new Promise((resolve, reject) => {
|
21349
|
+
const transaction = this.db.transaction(this.STORE_NAME, 'readwrite');
|
21350
|
+
const store = transaction.objectStore(this.STORE_NAME);
|
21351
|
+
const index = store.index('dialogId');
|
21352
|
+
const expiredMessageUIds = [];
|
21353
|
+
const request = index.openCursor(IDBKeyRange.only(dialogId));
|
21354
|
+
request.onsuccess = event => {
|
21355
|
+
const cursor = event.target.result;
|
21356
|
+
if (cursor) {
|
21357
|
+
const message = cursor.value;
|
21358
|
+
if (message.burnAfterReadingFlag) {
|
21359
|
+
const burnTime = message.burnAfterReadingTime || 0;
|
21360
|
+
let isExpired = burnTime === 0;
|
21361
|
+
if (!isExpired && burnTime > 0) {
|
21362
|
+
const sentTimeLong = Long.fromString(message.sentTime);
|
21363
|
+
const currentTimeLong = Long.fromNumber(currentTime);
|
21364
|
+
const burnTimeLong = Long.fromNumber(burnTime);
|
21365
|
+
const expirationTime = sentTimeLong.add(burnTimeLong);
|
21366
|
+
isExpired = currentTimeLong.greaterThan(expirationTime);
|
21367
|
+
}
|
21368
|
+
if (isExpired) {
|
21369
|
+
expiredMessageUIds.push(message.messageUId);
|
21370
|
+
cursor.delete();
|
21371
|
+
}
|
21372
|
+
}
|
21373
|
+
cursor.continue();
|
21374
|
+
} else {
|
21375
|
+
resolve(expiredMessageUIds);
|
21376
|
+
}
|
21377
|
+
};
|
21378
|
+
request.onerror = event => {
|
21379
|
+
console.error('清除过期消息失败', event);
|
21380
|
+
reject(new Error('清除过期消息失败'));
|
21381
|
+
};
|
21382
|
+
});
|
21383
|
+
}
|
21384
|
+
async getMessagesByPage(dialogId, pageSize = 20, cursorPosition = null) {
|
21385
|
+
if (!this.db) {
|
21386
|
+
return {
|
21387
|
+
messages: [],
|
21388
|
+
nextCursor: null
|
21389
|
+
};
|
21390
|
+
}
|
21391
|
+
return new Promise((resolve, reject) => {
|
21392
|
+
const transaction = this.db.transaction(this.STORE_NAME, 'readonly');
|
21393
|
+
const store = transaction.objectStore(this.STORE_NAME);
|
21394
|
+
const index = store.index('dialogId_sentTime');
|
21395
|
+
const range = IDBKeyRange.bound([dialogId, cursorPosition || ''], [dialogId, '\uffff']);
|
21396
|
+
const messages = [];
|
21397
|
+
let nextCursor = null;
|
21398
|
+
let count = 0;
|
21399
|
+
const cursorRequest = index.openCursor(range);
|
21400
|
+
cursorRequest.onsuccess = event => {
|
21401
|
+
const cursor = event.target.result;
|
21402
|
+
if (cursor && count < pageSize) {
|
21403
|
+
messages.push(cursor.value);
|
21404
|
+
count++;
|
21405
|
+
cursor.continue();
|
21406
|
+
} else if (cursor) {
|
21407
|
+
nextCursor = cursor.value.sentTime;
|
21408
|
+
} else {
|
21409
|
+
nextCursor = null;
|
21410
|
+
}
|
21411
|
+
if (!cursor || count >= pageSize) {
|
21412
|
+
resolve({
|
21413
|
+
messages,
|
21414
|
+
nextCursor
|
21415
|
+
});
|
21416
|
+
}
|
21417
|
+
};
|
21418
|
+
cursorRequest.onerror = event => {
|
21419
|
+
reject(new Error('获取分页消息失败'));
|
21420
|
+
};
|
21421
|
+
});
|
21422
|
+
}
|
21423
|
+
async updateMessagesStatus(messageUIds, newStatus) {
|
21424
|
+
if (!this.db || messageUIds.length === 0) {
|
21425
|
+
return;
|
21426
|
+
}
|
21427
|
+
return new Promise((resolve, reject) => {
|
21428
|
+
const transaction = this.db.transaction(this.STORE_NAME, 'readwrite');
|
21429
|
+
const store = transaction.objectStore(this.STORE_NAME);
|
21430
|
+
let completed = 0;
|
21431
|
+
let hasError = false;
|
21432
|
+
messageUIds.forEach(id => {
|
21433
|
+
const getRequest = store.get(id);
|
21434
|
+
getRequest.onsuccess = () => {
|
21435
|
+
const message = getRequest.result;
|
21436
|
+
if (message) {
|
21437
|
+
message.receivedStatus = newStatus;
|
21438
|
+
store.put(message);
|
21439
|
+
}
|
21440
|
+
completed++;
|
21441
|
+
if (completed === messageUIds.length && !hasError) {
|
21442
|
+
resolve();
|
21443
|
+
}
|
21444
|
+
};
|
21445
|
+
getRequest.onerror = event => {
|
21446
|
+
if (!hasError) {
|
21447
|
+
hasError = true;
|
21448
|
+
reject(new Error('更新消息状态失败'));
|
21449
|
+
}
|
21450
|
+
};
|
21451
|
+
});
|
21452
|
+
transaction.oncomplete = () => {
|
21453
|
+
resolve();
|
21454
|
+
};
|
21455
|
+
transaction.onerror = event => {
|
21456
|
+
reject(new Error('批量更新事务失败'));
|
21457
|
+
};
|
21458
|
+
});
|
21459
|
+
}
|
21460
|
+
async changeUser(appKey, userId) {
|
21461
|
+
if (this.currentAppKey === appKey && this.currentUserId === userId) {
|
21462
|
+
return;
|
21463
|
+
}
|
21464
|
+
this.currentAppKey = appKey;
|
21465
|
+
this.currentUserId = userId;
|
21466
|
+
await this.checkAndResetDatabase();
|
21467
|
+
await this.initDatabase();
|
21468
|
+
}
|
21469
|
+
}
|
21470
|
+
let cache;
|
21471
|
+
var MessageCache$1 = {
|
21472
|
+
create(appkey, currentUserId) {
|
21473
|
+
cache = new MessageCache(appkey, currentUserId);
|
21474
|
+
},
|
21475
|
+
get() {
|
21476
|
+
return cache;
|
21477
|
+
}
|
21478
|
+
};
|
21479
|
+
|
20946
21480
|
const DEFAULT_SOCKET_URI = 'wss://imweb.mp.net:6443';
|
20947
21481
|
class LibLoader {
|
20948
21482
|
options;
|
@@ -21031,6 +21565,7 @@
|
|
21031
21565
|
ConversationManager$1.get().destroyed();
|
21032
21566
|
ConversationManager$1.create(this.options.appkey, accountStore.uid.toString(), this.watcher.conversationState);
|
21033
21567
|
MessageReceiptManager$1.create(this.options.appkey, accountStore.uid.toString());
|
21568
|
+
MessageCache$1.create(this.options.appkey, accountStore.uid.toString());
|
21034
21569
|
this.messageLoader?.stop();
|
21035
21570
|
this.messageLoader = new MessageLoader(this.watcher, this.options);
|
21036
21571
|
synchronizeServerTime();
|
@@ -28379,174 +28914,6 @@
|
|
28379
28914
|
return UniqueSentTime;
|
28380
28915
|
}
|
28381
28916
|
|
28382
|
-
class MessageCache {
|
28383
|
-
static instance;
|
28384
|
-
messageCache = new Map();
|
28385
|
-
loadedEndMap = new Map();
|
28386
|
-
maxCacheCount = 1000;
|
28387
|
-
constructor() {}
|
28388
|
-
static get() {
|
28389
|
-
if (!MessageCache.instance) {
|
28390
|
-
MessageCache.instance = new MessageCache();
|
28391
|
-
}
|
28392
|
-
return MessageCache.instance;
|
28393
|
-
}
|
28394
|
-
setMaxCacheCount(count) {
|
28395
|
-
if (count > 0) {
|
28396
|
-
this.maxCacheCount = count;
|
28397
|
-
}
|
28398
|
-
}
|
28399
|
-
addMessages(messages, toConversation, isEnd = undefined) {
|
28400
|
-
const dialogId = getFullDialogId(toConversation);
|
28401
|
-
if (isDef(isEnd)) {
|
28402
|
-
this.loadedEndMap.set(dialogId, isEnd);
|
28403
|
-
}
|
28404
|
-
if (!messages || messages.length === 0) {
|
28405
|
-
return;
|
28406
|
-
}
|
28407
|
-
if (!this.messageCache.has(dialogId)) {
|
28408
|
-
this.messageCache.set(dialogId, []);
|
28409
|
-
}
|
28410
|
-
const cachedMessages = this.messageCache.get(dialogId) || [];
|
28411
|
-
const existingMessageIds = new Set(cachedMessages.map(msg => msg.messageUId));
|
28412
|
-
const newMessages = messages.filter(msg => !existingMessageIds.has(msg.messageUId));
|
28413
|
-
const allMessages = [...cachedMessages, ...newMessages].sort((a, b) => Long.fromString(a.sentTime).compare(Long.fromString(b.sentTime)));
|
28414
|
-
if (allMessages.length > this.maxCacheCount) {
|
28415
|
-
allMessages.splice(0, allMessages.length - this.maxCacheCount);
|
28416
|
-
}
|
28417
|
-
this.messageCache.set(dialogId, allMessages);
|
28418
|
-
}
|
28419
|
-
getPreviousMessages(conversation, timestamp = "0", count = 20) {
|
28420
|
-
const dialogId = getFullDialogId(conversation);
|
28421
|
-
const cachedMessages = this.messageCache.get(dialogId) || [];
|
28422
|
-
if (cachedMessages.length === 0) {
|
28423
|
-
return {
|
28424
|
-
messages: [],
|
28425
|
-
hasMore: !this.loadedEndMap.get(dialogId)
|
28426
|
-
};
|
28427
|
-
}
|
28428
|
-
if (timestamp === "0") {
|
28429
|
-
const messages = cachedMessages.slice(-count);
|
28430
|
-
return {
|
28431
|
-
messages,
|
28432
|
-
hasMore: cachedMessages.length > count || !this.loadedEndMap.get(dialogId)
|
28433
|
-
};
|
28434
|
-
}
|
28435
|
-
const timestampLong = Long.fromString(timestamp);
|
28436
|
-
let endIndex = cachedMessages.length - 1;
|
28437
|
-
while (endIndex >= 0) {
|
28438
|
-
if (Long.fromString(cachedMessages[endIndex].sentTime).lessThanOrEqual(timestampLong)) {
|
28439
|
-
break;
|
28440
|
-
}
|
28441
|
-
endIndex--;
|
28442
|
-
}
|
28443
|
-
if (endIndex < 0) {
|
28444
|
-
return {
|
28445
|
-
messages: [],
|
28446
|
-
hasMore: !this.loadedEndMap.get(dialogId)
|
28447
|
-
};
|
28448
|
-
}
|
28449
|
-
const startIndex = Math.max(0, endIndex - count + 1);
|
28450
|
-
return {
|
28451
|
-
messages: cachedMessages.slice(startIndex, endIndex + 1),
|
28452
|
-
hasMore: startIndex > 0 || !this.loadedEndMap.get(dialogId)
|
28453
|
-
};
|
28454
|
-
}
|
28455
|
-
clearConversationCache(conversation) {
|
28456
|
-
const dialogId = getFullDialogId(conversation);
|
28457
|
-
this.messageCache.delete(dialogId);
|
28458
|
-
this.loadedEndMap.set(dialogId, true);
|
28459
|
-
}
|
28460
|
-
clearAllCache() {
|
28461
|
-
this.messageCache.clear();
|
28462
|
-
this.loadedEndMap.clear();
|
28463
|
-
}
|
28464
|
-
removeMessagesByUId(messageUIds) {
|
28465
|
-
if (!messageUIds || messageUIds.length === 0) {
|
28466
|
-
return;
|
28467
|
-
}
|
28468
|
-
const messageUIdSet = new Set(messageUIds);
|
28469
|
-
this.messageCache.forEach((messages, dialogId) => {
|
28470
|
-
const filteredMessages = messages.filter(msg => !messageUIdSet.has(msg.messageUId));
|
28471
|
-
if (filteredMessages.length !== messages.length) {
|
28472
|
-
this.messageCache.set(dialogId, filteredMessages);
|
28473
|
-
}
|
28474
|
-
});
|
28475
|
-
}
|
28476
|
-
updateMessageReceiptStatus(event, type) {
|
28477
|
-
if (!event || !event.messageUIdList || event.messageUIdList.length === 0) {
|
28478
|
-
return;
|
28479
|
-
}
|
28480
|
-
const {
|
28481
|
-
conversation
|
28482
|
-
} = event;
|
28483
|
-
const dialogId = getFullDialogId(conversation);
|
28484
|
-
const cachedMessages = this.messageCache.get(dialogId);
|
28485
|
-
if (!cachedMessages || cachedMessages.length === 0) {
|
28486
|
-
return;
|
28487
|
-
}
|
28488
|
-
const messageUIdSet = new Set(event.messageUIdList);
|
28489
|
-
let updated = false;
|
28490
|
-
const updatedMessages = cachedMessages.map((message, index) => {
|
28491
|
-
if (messageUIdSet.has(message.messageUId)) {
|
28492
|
-
if (type === 0) {
|
28493
|
-
if (message.receivedStatus < exports.ReceivedStatus.RECEIVED) {
|
28494
|
-
updated = true;
|
28495
|
-
return {
|
28496
|
-
...message,
|
28497
|
-
receivedStatus: exports.ReceivedStatus.RECEIVED
|
28498
|
-
};
|
28499
|
-
}
|
28500
|
-
} else {
|
28501
|
-
if (message.receivedStatus < exports.ReceivedStatus.READ) {
|
28502
|
-
updated = true;
|
28503
|
-
return {
|
28504
|
-
...message,
|
28505
|
-
receivedStatus: exports.ReceivedStatus.READ
|
28506
|
-
};
|
28507
|
-
}
|
28508
|
-
}
|
28509
|
-
}
|
28510
|
-
return message;
|
28511
|
-
});
|
28512
|
-
if (updated) {
|
28513
|
-
this.messageCache.set(dialogId, updatedMessages);
|
28514
|
-
}
|
28515
|
-
}
|
28516
|
-
clearBurnAfterReadingExpiredMessages(conversation) {
|
28517
|
-
const dialogId = getFullDialogId(conversation);
|
28518
|
-
const cachedMessages = this.messageCache.get(dialogId);
|
28519
|
-
if (!cachedMessages || cachedMessages.length === 0) {
|
28520
|
-
return [];
|
28521
|
-
}
|
28522
|
-
const currentTime = Date.now();
|
28523
|
-
const expiredMessageUIds = [];
|
28524
|
-
const remainingMessages = cachedMessages.filter(message => {
|
28525
|
-
if (!message.burnAfterReadingFlag) {
|
28526
|
-
return true;
|
28527
|
-
}
|
28528
|
-
const burnTime = message.burnAfterReadingTime || 0;
|
28529
|
-
if (burnTime === 0) {
|
28530
|
-
expiredMessageUIds.push(message.messageUId);
|
28531
|
-
return false;
|
28532
|
-
}
|
28533
|
-
const sentTimeLong = Long.fromString(message.sentTime);
|
28534
|
-
const currentTimeLong = Long.fromNumber(currentTime);
|
28535
|
-
const burnTimeLong = Long.fromNumber(burnTime);
|
28536
|
-
const expirationTime = sentTimeLong.add(burnTimeLong);
|
28537
|
-
if (currentTimeLong.greaterThan(expirationTime)) {
|
28538
|
-
expiredMessageUIds.push(message.messageUId);
|
28539
|
-
return false;
|
28540
|
-
}
|
28541
|
-
return true;
|
28542
|
-
});
|
28543
|
-
if (remainingMessages.length < cachedMessages.length) {
|
28544
|
-
this.messageCache.set(dialogId, remainingMessages);
|
28545
|
-
}
|
28546
|
-
return expiredMessageUIds;
|
28547
|
-
}
|
28548
|
-
}
|
28549
|
-
|
28550
28917
|
class IMClient extends EventEmitter {
|
28551
28918
|
options;
|
28552
28919
|
static imClient;
|
@@ -28595,7 +28962,7 @@
|
|
28595
28962
|
},
|
28596
28963
|
batchMessage: messages => {
|
28597
28964
|
if (messages.length) {
|
28598
|
-
MessageCache.get()
|
28965
|
+
MessageCache$1.get()?.addMessages(messages, {
|
28599
28966
|
conversationType: messages[0].content,
|
28600
28967
|
targetId: messages[0].targetId
|
28601
28968
|
});
|
@@ -28626,13 +28993,13 @@
|
|
28626
28993
|
});
|
28627
28994
|
},
|
28628
28995
|
onRecall: messageUids => {
|
28629
|
-
MessageCache.get()
|
28996
|
+
MessageCache$1.get()?.removeMessagesByUId(messageUids);
|
28630
28997
|
messageUids.forEach(messageUId => {
|
28631
28998
|
this.emit(exports.Events.RECALL, messageUId);
|
28632
28999
|
});
|
28633
29000
|
},
|
28634
29001
|
onReceiptReceived: (event, type) => {
|
28635
|
-
MessageCache.get()
|
29002
|
+
MessageCache$1.get()?.updateMessageReceiptStatus(event, type);
|
28636
29003
|
if (type === 0) {
|
28637
29004
|
this.emit(exports.Events.ARRIVAL_RECEIPT_RECEIVED, event);
|
28638
29005
|
} else {
|
@@ -28668,7 +29035,7 @@
|
|
28668
29035
|
async recallMsg(conversation, options) {
|
28669
29036
|
const result = await sendRecallMessage(conversation, options);
|
28670
29037
|
if (result.code === exports.ErrorCode.SUCCESS) {
|
28671
|
-
MessageCache.get()
|
29038
|
+
MessageCache$1.get()?.removeMessagesByUId([options.messageUId]);
|
28672
29039
|
}
|
28673
29040
|
return result;
|
28674
29041
|
}
|
@@ -28710,9 +29077,8 @@
|
|
28710
29077
|
});
|
28711
29078
|
}
|
28712
29079
|
async getPreviousHistoryMessages(conversation, timestamp, count = 20) {
|
28713
|
-
|
28714
|
-
const cachedResult = MessageCache.get().getPreviousMessages(conversation, timestamp ?? '0', count);
|
28715
|
-
logger.warn('getPreviousHistoryMessages cachedResult', cachedResult);
|
29080
|
+
debugger;
|
29081
|
+
const cachedResult = await MessageCache$1.get().getPreviousMessages(conversation, timestamp ?? '0', count);
|
28716
29082
|
if (!timestamp && cachedResult.messages.length) {
|
28717
29083
|
ConversationManager$1.get().refreshLatestMessage(conversation, cachedResult.messages[cachedResult.messages.length - 1]);
|
28718
29084
|
}
|
@@ -28731,7 +29097,6 @@
|
|
28731
29097
|
count: count - cachedResult.messages.length,
|
28732
29098
|
order: 0
|
28733
29099
|
});
|
28734
|
-
logger.warn('getPreviousHistoryMessages remotesResult', remotesResult);
|
28735
29100
|
if (remotesResult.code !== exports.ErrorCode.SUCCESS) {
|
28736
29101
|
return remotesResult;
|
28737
29102
|
}
|
@@ -28739,7 +29104,7 @@
|
|
28739
29104
|
if (!remotesTimestamp) {
|
28740
29105
|
ConversationManager$1.get().refreshLatestMessage(conversation, remotesMessages[remotesMessages.length - 1]);
|
28741
29106
|
}
|
28742
|
-
MessageCache.get().addMessages(remotesMessages, conversation, !remotesResult.data.hasMore);
|
29107
|
+
MessageCache$1.get().addMessages(remotesMessages, conversation, !remotesResult.data.hasMore);
|
28743
29108
|
return {
|
28744
29109
|
code: exports.ErrorCode.SUCCESS,
|
28745
29110
|
data: {
|
@@ -28749,11 +29114,11 @@
|
|
28749
29114
|
};
|
28750
29115
|
}
|
28751
29116
|
async deleteRemoteMessage(conversation, list) {
|
28752
|
-
MessageCache.get()
|
29117
|
+
MessageCache$1.get()?.removeMessagesByUId(list.map(e => e.messageUId));
|
28753
29118
|
return deleteMessages$1(getFullDialogId(conversation), list.map(e => e.messageUId)).then(result => result.code);
|
28754
29119
|
}
|
28755
29120
|
async deleteRemoteMessageByTimestamp(conversation, timestamp) {
|
28756
|
-
MessageCache.get()
|
29121
|
+
MessageCache$1.get()?.clearConversationCache(conversation);
|
28757
29122
|
ConversationManager$1.get().clearHistoryMessages(conversation);
|
28758
29123
|
return clearHistoryMessage(getFullDialogId(conversation), timestamp === 0 ? Number.MAX_VALUE : timestamp).then(result => result.code);
|
28759
29124
|
}
|
@@ -28939,7 +29304,7 @@
|
|
28939
29304
|
return conversationObj;
|
28940
29305
|
}
|
28941
29306
|
clearBurnAfterReadingExpiredMessages(conversation) {
|
28942
|
-
return MessageCache.get()
|
29307
|
+
return MessageCache$1.get()?.clearBurnAfterReadingExpiredMessages(conversation) ?? Promise.resolve([]);
|
28943
29308
|
}
|
28944
29309
|
}
|
28945
29310
|
|
@@ -30115,7 +30480,6 @@
|
|
30115
30480
|
assert('conversation', conversation, AssertRules.CONVERSATION, true);
|
30116
30481
|
const paramsStr = 'conversationType:' + conversation.conversationType + ',targetId:' + conversation.targetId;
|
30117
30482
|
logger.debug('get remote history message ->' + paramsStr);
|
30118
|
-
logger.warn('getRemoteHistoryMessages options', options);
|
30119
30483
|
if (isDef(options.timestamp)) {
|
30120
30484
|
options.timestamp = options.timestamp.toString();
|
30121
30485
|
}
|
@@ -30201,11 +30565,11 @@
|
|
30201
30565
|
logger.warn('send message fail ->' + errorCode + ':' + ErrorDesc(errorCode) + ',' + paramsStr);
|
30202
30566
|
}
|
30203
30567
|
};
|
30204
|
-
const clearBurnAfterReadingExpiredMessages = conversation => {
|
30568
|
+
const clearBurnAfterReadingExpiredMessages = async conversation => {
|
30205
30569
|
assert('conversation', conversation, AssertRules.CONVERSATION, true);
|
30206
30570
|
const paramsStr = 'conversationType:' + conversation.conversationType + ',targetId:' + conversation.targetId;
|
30207
30571
|
logger.debug('clear burn after reading expired messages ->' + paramsStr);
|
30208
|
-
const expiredMessageUIds = imClient.clearBurnAfterReadingExpiredMessages(conversation);
|
30572
|
+
const expiredMessageUIds = await imClient.clearBurnAfterReadingExpiredMessages(conversation);
|
30209
30573
|
if (expiredMessageUIds.length > 0) {
|
30210
30574
|
logger.debug(`已清除会话 ${paramsStr} 中的 ${expiredMessageUIds.length} 条阅后即焚过期消息`);
|
30211
30575
|
}
|