@onyx-p/imlib-web 2.0.7 → 2.0.9

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.
Files changed (3) hide show
  1. package/index.esm.js +614 -187
  2. package/index.umd.js +614 -187
  3. 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,607 @@
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
+ encryptKey = {
20950
+ key: ''
20951
+ };
20952
+ SALT_PREFIX = 'im_message_cache_salt_prefix';
20953
+ SALT_SUFFIX = 'im_message_cache_salt_suffix';
20954
+ constructor(appKey, userId) {
20955
+ this.generateEncryptKey(appKey, userId);
20956
+ this.init(appKey, userId);
20957
+ }
20958
+ generateEncryptKey(appKey, userId) {
20959
+ const saltedInput = `${this.SALT_PREFIX}${appKey}_${userId}${this.SALT_SUFFIX}`;
20960
+ const keyMaterial = CryptoJS.SHA256(saltedInput).toString();
20961
+ const iv = keyMaterial.substring(0, 16);
20962
+ const key = keyMaterial.substring(16, 48);
20963
+ const additionalSalt = CryptoJS.SHA256(`${iv}:${this.SALT_PREFIX}:${userId}:${appKey}`).toString().substring(0, 8);
20964
+ const finalKey = CryptoJS.PBKDF2(key, additionalSalt, {
20965
+ keySize: 256 / 32,
20966
+ iterations: 1000,
20967
+ hasher: CryptoJS.algo.SHA256
20968
+ }).toString();
20969
+ this.encryptKey = {
20970
+ key: finalKey.substring(0, 32),
20971
+ iv: iv
20972
+ };
20973
+ }
20974
+ async init(appKey, userId) {
20975
+ this.currentAppKey = appKey;
20976
+ this.currentUserId = userId;
20977
+ await this.checkAndResetDatabase();
20978
+ await this.initDatabase();
20979
+ }
20980
+ async checkAndResetDatabase() {
20981
+ const storedInfoStr = LocalStorageService.get(this.APP_INFO_KEY);
20982
+ if (storedInfoStr) {
20983
+ try {
20984
+ const storedInfo = JSON.parse(storedInfoStr);
20985
+ if (storedInfo.appKey !== this.currentAppKey || storedInfo.userId !== this.currentUserId) {
20986
+ await this.deleteDatabase();
20987
+ }
20988
+ } catch (error) {
20989
+ console.error('解析存储的AppKey和UserId出错', error);
20990
+ await this.deleteDatabase();
20991
+ }
20992
+ }
20993
+ LocalStorageService.set(this.APP_INFO_KEY, JSON.stringify({
20994
+ appKey: this.currentAppKey,
20995
+ userId: this.currentUserId,
20996
+ timestamp: Date.now()
20997
+ }));
20998
+ }
20999
+ async deleteDatabase() {
21000
+ if (this.db) {
21001
+ this.db.close();
21002
+ this.db = null;
21003
+ }
21004
+ this.loadedEndMap.clear();
21005
+ return new Promise((resolve, reject) => {
21006
+ const dbName = this.getDBName();
21007
+ const deleteRequest = indexedDB.deleteDatabase(dbName);
21008
+ deleteRequest.onsuccess = () => {
21009
+ console.log(`数据库 ${dbName} 已成功删除`);
21010
+ resolve();
21011
+ };
21012
+ deleteRequest.onerror = event => {
21013
+ console.error(`删除数据库 ${dbName} 失败`, event);
21014
+ resolve();
21015
+ };
21016
+ });
21017
+ }
21018
+ getDBName() {
21019
+ return `${this.DB_NAME_PREFIX}_${this.currentAppKey}_${this.currentUserId}`;
21020
+ }
21021
+ initDatabase() {
21022
+ return new Promise((resolve, reject) => {
21023
+ const dbName = this.getDBName();
21024
+ const request = indexedDB.open(dbName, this.DB_VERSION);
21025
+ request.onerror = event => {
21026
+ console.error('数据库打开失败', event);
21027
+ reject(new Error('数据库打开失败'));
21028
+ };
21029
+ request.onsuccess = event => {
21030
+ this.db = event.target.result;
21031
+ this.loadAllDialogStates().then(() => {
21032
+ resolve();
21033
+ }).catch(err => {
21034
+ console.error('加载会话状态失败', err);
21035
+ resolve();
21036
+ });
21037
+ };
21038
+ request.onupgradeneeded = event => {
21039
+ const db = event.target.result;
21040
+ if (!db.objectStoreNames.contains(this.STORE_NAME)) {
21041
+ const store = db.createObjectStore(this.STORE_NAME, {
21042
+ keyPath: 'messageUId'
21043
+ });
21044
+ store.createIndex('dialogId', 'dialogId', {
21045
+ unique: false
21046
+ });
21047
+ store.createIndex('dialogId_sentTime', ['dialogId', 'sentTime'], {
21048
+ unique: false
21049
+ });
21050
+ store.createIndex('receivedStatus', 'receivedStatus', {
21051
+ unique: false
21052
+ });
21053
+ store.createIndex('burnAfterReadingFlag', 'burnAfterReadingFlag', {
21054
+ unique: false
21055
+ });
21056
+ store.createIndex('dialogId_receivedStatus', ['dialogId', 'receivedStatus'], {
21057
+ unique: false
21058
+ });
21059
+ }
21060
+ if (!db.objectStoreNames.contains(this.DIALOG_STATE_STORE)) {
21061
+ db.createObjectStore(this.DIALOG_STATE_STORE, {
21062
+ keyPath: 'dialogId'
21063
+ });
21064
+ }
21065
+ };
21066
+ });
21067
+ }
21068
+ async loadAllDialogStates() {
21069
+ if (!this.db) {
21070
+ return;
21071
+ }
21072
+ return new Promise((resolve, reject) => {
21073
+ const transaction = this.db.transaction(this.DIALOG_STATE_STORE, 'readonly');
21074
+ const store = transaction.objectStore(this.DIALOG_STATE_STORE);
21075
+ const request = store.getAll();
21076
+ request.onsuccess = () => {
21077
+ const states = request.result;
21078
+ this.loadedEndMap.clear();
21079
+ states.forEach(state => {
21080
+ this.loadedEndMap.set(state.dialogId, state.isEnd);
21081
+ });
21082
+ resolve();
21083
+ };
21084
+ request.onerror = event => {
21085
+ reject(new Error('加载会话状态失败'));
21086
+ };
21087
+ });
21088
+ }
21089
+ async updateDialogState(dialogId, isEnd) {
21090
+ if (!this.db) {
21091
+ return;
21092
+ }
21093
+ this.loadedEndMap.set(dialogId, isEnd);
21094
+ return new Promise((resolve, reject) => {
21095
+ const transaction = this.db.transaction(this.DIALOG_STATE_STORE, 'readwrite');
21096
+ const store = transaction.objectStore(this.DIALOG_STATE_STORE);
21097
+ const request = store.put({
21098
+ dialogId,
21099
+ isEnd,
21100
+ updateTime: Date.now()
21101
+ });
21102
+ request.onsuccess = () => {
21103
+ resolve();
21104
+ };
21105
+ request.onerror = event => {
21106
+ console.error('更新会话状态失败', event);
21107
+ reject(new Error('更新会话状态失败'));
21108
+ };
21109
+ });
21110
+ }
21111
+ encryptContent(content) {
21112
+ if (!content) return '';
21113
+ try {
21114
+ const contentStr = JSON.stringify(content);
21115
+ return aes256Encrypt(contentStr, this.encryptKey);
21116
+ } catch (error) {
21117
+ console.error('加密消息内容失败', error);
21118
+ return '';
21119
+ }
21120
+ }
21121
+ decryptContent(encryptedHex) {
21122
+ if (!encryptedHex) {
21123
+ return null;
21124
+ }
21125
+ try {
21126
+ const decryptedStr = aes256Decrypt(encryptedHex, this.encryptKey);
21127
+ return JSON.parse(decryptedStr);
21128
+ } catch (error) {
21129
+ console.error('解密消息内容失败', error);
21130
+ return null;
21131
+ }
21132
+ }
21133
+ async addMessages(messages, toConversation, isEnd = undefined) {
21134
+ const dialogId = getFullDialogId(toConversation);
21135
+ if (isDef(isEnd)) {
21136
+ await this.updateDialogState(dialogId, isEnd);
21137
+ }
21138
+ if (!messages || messages.length === 0 || !this.db) {
21139
+ return;
21140
+ }
21141
+ return new Promise((resolve, reject) => {
21142
+ const transaction = this.db.transaction(this.STORE_NAME, 'readwrite');
21143
+ const store = transaction.objectStore(this.STORE_NAME);
21144
+ messages.forEach(message => {
21145
+ const messageToStore = {
21146
+ ...message,
21147
+ dialogId
21148
+ };
21149
+ if (messageToStore.content) {
21150
+ const encryptedContent = this.encryptContent(messageToStore.content);
21151
+ messageToStore.content = encryptedContent;
21152
+ }
21153
+ store.put(messageToStore);
21154
+ });
21155
+ transaction.oncomplete = () => {
21156
+ resolve();
21157
+ };
21158
+ transaction.onerror = event => {
21159
+ console.error('添加消息事务失败', event);
21160
+ reject(new Error('添加消息事务失败'));
21161
+ };
21162
+ });
21163
+ }
21164
+ async getPreviousMessages(conversation, timestamp = "0", count = 20) {
21165
+ const dialogId = getFullDialogId(conversation);
21166
+ if (!this.db) {
21167
+ return {
21168
+ messages: [],
21169
+ hasMore: false
21170
+ };
21171
+ }
21172
+ const isLoaded = await this.getDialogLoadedState(dialogId);
21173
+ return new Promise((resolve, reject) => {
21174
+ const transaction = this.db.transaction(this.STORE_NAME, 'readonly');
21175
+ const store = transaction.objectStore(this.STORE_NAME);
21176
+ const index = store.index('dialogId_sentTime');
21177
+ let range;
21178
+ const direction = 'prev';
21179
+ if (timestamp === "0") {
21180
+ range = IDBKeyRange.bound([dialogId, ''], [dialogId, '\uffff']);
21181
+ } else {
21182
+ range = IDBKeyRange.bound([dialogId, ''], [dialogId, timestamp]);
21183
+ }
21184
+ const messages = [];
21185
+ let hasMoreMessages = false;
21186
+ let processedCount = 0;
21187
+ const countRequest = index.count(range);
21188
+ countRequest.onsuccess = () => {
21189
+ const totalCount = countRequest.result;
21190
+ const cursorRequest = index.openCursor(range, direction);
21191
+ cursorRequest.onsuccess = event => {
21192
+ const cursor = event.target.result;
21193
+ if (cursor) {
21194
+ if (processedCount < count) {
21195
+ const message = {
21196
+ ...cursor.value
21197
+ };
21198
+ if (typeof message.content === 'string' && message.content) {
21199
+ try {
21200
+ message.content = this.decryptContent(message.content);
21201
+ } catch (error) {
21202
+ console.error('解密消息内容失败', error);
21203
+ message.content = null;
21204
+ }
21205
+ }
21206
+ messages.push(message);
21207
+ processedCount++;
21208
+ cursor.continue();
21209
+ } else {
21210
+ hasMoreMessages = true;
21211
+ finishQuery();
21212
+ }
21213
+ } else {
21214
+ finishQuery();
21215
+ }
21216
+ };
21217
+ const finishQuery = () => {
21218
+ messages.sort((a, b) => Long.fromString(a.sentTime).compare(Long.fromString(b.sentTime)));
21219
+ resolve({
21220
+ messages,
21221
+ hasMore: hasMoreMessages || totalCount > count || !isLoaded
21222
+ });
21223
+ };
21224
+ };
21225
+ transaction.onerror = event => {
21226
+ console.error('获取消息事务失败', event);
21227
+ reject(new Error('获取消息事务失败'));
21228
+ };
21229
+ });
21230
+ }
21231
+ async clearConversationCache(conversation) {
21232
+ const dialogId = getFullDialogId(conversation);
21233
+ if (!this.db) {
21234
+ this.loadedEndMap.set(dialogId, true);
21235
+ return;
21236
+ }
21237
+ const deleteMessagesPromise = new Promise((resolve, reject) => {
21238
+ const transaction = this.db.transaction(this.STORE_NAME, 'readwrite');
21239
+ const store = transaction.objectStore(this.STORE_NAME);
21240
+ const index = store.index('dialogId');
21241
+ const request = index.openCursor(IDBKeyRange.only(dialogId));
21242
+ request.onsuccess = event => {
21243
+ const cursor = event.target.result;
21244
+ if (cursor) {
21245
+ cursor.delete();
21246
+ cursor.continue();
21247
+ }
21248
+ };
21249
+ transaction.oncomplete = () => {
21250
+ resolve();
21251
+ };
21252
+ transaction.onerror = event => {
21253
+ reject(new Error('清除会话消息失败'));
21254
+ };
21255
+ });
21256
+ await Promise.all([deleteMessagesPromise, this.updateDialogState(dialogId, true)]);
21257
+ }
21258
+ async clearAllCache() {
21259
+ if (!this.db) {
21260
+ this.loadedEndMap.clear();
21261
+ return;
21262
+ }
21263
+ const clearMessagesPromise = new Promise((resolve, reject) => {
21264
+ const transaction = this.db.transaction(this.STORE_NAME, 'readwrite');
21265
+ const store = transaction.objectStore(this.STORE_NAME);
21266
+ const request = store.clear();
21267
+ request.onsuccess = () => {
21268
+ resolve();
21269
+ };
21270
+ request.onerror = event => {
21271
+ reject(new Error('清除所有消息失败'));
21272
+ };
21273
+ });
21274
+ const clearStatesPromise = new Promise((resolve, reject) => {
21275
+ const transaction = this.db.transaction(this.DIALOG_STATE_STORE, 'readwrite');
21276
+ const store = transaction.objectStore(this.DIALOG_STATE_STORE);
21277
+ const request = store.clear();
21278
+ request.onsuccess = () => {
21279
+ this.loadedEndMap.clear();
21280
+ resolve();
21281
+ };
21282
+ request.onerror = event => {
21283
+ reject(new Error('清除所有会话状态失败'));
21284
+ };
21285
+ });
21286
+ await Promise.all([clearMessagesPromise, clearStatesPromise]);
21287
+ }
21288
+ async getDialogLoadedState(dialogId) {
21289
+ if (this.loadedEndMap.has(dialogId)) {
21290
+ return this.loadedEndMap.get(dialogId);
21291
+ }
21292
+ if (!this.db) {
21293
+ return false;
21294
+ }
21295
+ return new Promise((resolve, reject) => {
21296
+ const transaction = this.db.transaction(this.DIALOG_STATE_STORE, 'readonly');
21297
+ const store = transaction.objectStore(this.DIALOG_STATE_STORE);
21298
+ const request = store.get(dialogId);
21299
+ request.onsuccess = () => {
21300
+ const state = request.result;
21301
+ if (state) {
21302
+ this.loadedEndMap.set(dialogId, state.isEnd);
21303
+ resolve(state.isEnd);
21304
+ } else {
21305
+ resolve(false);
21306
+ }
21307
+ };
21308
+ request.onerror = event => {
21309
+ resolve(false);
21310
+ };
21311
+ });
21312
+ }
21313
+ async removeMessagesByUId(messageUIds) {
21314
+ if (!messageUIds || messageUIds.length === 0 || !this.db) {
21315
+ return;
21316
+ }
21317
+ return new Promise((resolve, reject) => {
21318
+ const transaction = this.db.transaction(this.STORE_NAME, 'readwrite');
21319
+ const store = transaction.objectStore(this.STORE_NAME);
21320
+ let completed = 0;
21321
+ let hasError = false;
21322
+ messageUIds.forEach(id => {
21323
+ const deleteRequest = store.delete(id);
21324
+ deleteRequest.onsuccess = () => {
21325
+ completed++;
21326
+ if (completed === messageUIds.length && !hasError) {
21327
+ resolve();
21328
+ }
21329
+ };
21330
+ deleteRequest.onerror = event => {
21331
+ console.error('删除消息失败', id, event);
21332
+ if (!hasError) {
21333
+ hasError = true;
21334
+ reject(new Error('删除消息失败'));
21335
+ }
21336
+ };
21337
+ });
21338
+ transaction.oncomplete = () => {
21339
+ if (!hasError) {
21340
+ resolve();
21341
+ }
21342
+ };
21343
+ transaction.onerror = event => {
21344
+ reject(new Error('批量删除消息事务失败'));
21345
+ };
21346
+ });
21347
+ }
21348
+ async updateMessageReceiptStatus(event, type) {
21349
+ if (!event || !event.messageUIdList || event.messageUIdList.length === 0 || !this.db) {
21350
+ return;
21351
+ }
21352
+ const {
21353
+ conversation
21354
+ } = event;
21355
+ getFullDialogId(conversation);
21356
+ return new Promise((resolve, reject) => {
21357
+ const transaction = this.db.transaction(this.STORE_NAME, 'readwrite');
21358
+ const store = transaction.objectStore(this.STORE_NAME);
21359
+ let completed = 0;
21360
+ let hasError = false;
21361
+ event.messageUIdList.forEach(id => {
21362
+ const getRequest = store.get(id);
21363
+ getRequest.onsuccess = () => {
21364
+ const message = getRequest.result;
21365
+ if (message) {
21366
+ let needUpdate = false;
21367
+ if (type === 0 && message.receivedStatus < exports.ReceivedStatus.RECEIVED) {
21368
+ message.receivedStatus = exports.ReceivedStatus.RECEIVED;
21369
+ needUpdate = true;
21370
+ } else if (type === 1 && message.receivedStatus < exports.ReceivedStatus.READ) {
21371
+ message.receivedStatus = exports.ReceivedStatus.READ;
21372
+ needUpdate = true;
21373
+ }
21374
+ if (needUpdate) {
21375
+ store.put(message);
21376
+ }
21377
+ }
21378
+ completed++;
21379
+ if (completed === event.messageUIdList.length && !hasError) {
21380
+ resolve();
21381
+ }
21382
+ };
21383
+ getRequest.onerror = event => {
21384
+ if (!hasError) {
21385
+ hasError = true;
21386
+ reject(new Error('更新消息状态失败'));
21387
+ }
21388
+ };
21389
+ });
21390
+ transaction.oncomplete = () => {
21391
+ if (!hasError) {
21392
+ resolve();
21393
+ }
21394
+ };
21395
+ transaction.onerror = event => {
21396
+ reject(new Error('更新消息状态事务失败'));
21397
+ };
21398
+ });
21399
+ }
21400
+ async clearBurnAfterReadingExpiredMessages(conversation) {
21401
+ const dialogId = getFullDialogId(conversation);
21402
+ if (!this.db) {
21403
+ return [];
21404
+ }
21405
+ const currentTime = Date.now();
21406
+ return new Promise((resolve, reject) => {
21407
+ const transaction = this.db.transaction(this.STORE_NAME, 'readwrite');
21408
+ const store = transaction.objectStore(this.STORE_NAME);
21409
+ const index = store.index('dialogId');
21410
+ const expiredMessageUIds = [];
21411
+ const request = index.openCursor(IDBKeyRange.only(dialogId));
21412
+ request.onsuccess = event => {
21413
+ const cursor = event.target.result;
21414
+ if (cursor) {
21415
+ const message = cursor.value;
21416
+ if (message.burnAfterReadingFlag) {
21417
+ const burnTime = message.burnAfterReadingTime || 0;
21418
+ let isExpired = burnTime === 0;
21419
+ if (!isExpired && burnTime > 0) {
21420
+ const sentTimeLong = Long.fromString(message.sentTime);
21421
+ const currentTimeLong = Long.fromNumber(currentTime);
21422
+ const burnTimeLong = Long.fromNumber(burnTime);
21423
+ const expirationTime = sentTimeLong.add(burnTimeLong);
21424
+ isExpired = currentTimeLong.greaterThan(expirationTime);
21425
+ }
21426
+ if (isExpired) {
21427
+ expiredMessageUIds.push(message.messageUId);
21428
+ cursor.delete();
21429
+ }
21430
+ }
21431
+ cursor.continue();
21432
+ } else {
21433
+ resolve(expiredMessageUIds);
21434
+ }
21435
+ };
21436
+ request.onerror = event => {
21437
+ console.error('清除过期消息失败', event);
21438
+ reject(new Error('清除过期消息失败'));
21439
+ };
21440
+ });
21441
+ }
21442
+ async getMessagesByPage(dialogId, pageSize = 20, cursorPosition = null) {
21443
+ if (!this.db) {
21444
+ return {
21445
+ messages: [],
21446
+ nextCursor: null
21447
+ };
21448
+ }
21449
+ return new Promise((resolve, reject) => {
21450
+ const transaction = this.db.transaction(this.STORE_NAME, 'readonly');
21451
+ const store = transaction.objectStore(this.STORE_NAME);
21452
+ const index = store.index('dialogId_sentTime');
21453
+ const range = IDBKeyRange.bound([dialogId, cursorPosition || ''], [dialogId, '\uffff']);
21454
+ const messages = [];
21455
+ let nextCursor = null;
21456
+ let count = 0;
21457
+ const cursorRequest = index.openCursor(range);
21458
+ cursorRequest.onsuccess = event => {
21459
+ const cursor = event.target.result;
21460
+ if (cursor && count < pageSize) {
21461
+ messages.push(cursor.value);
21462
+ count++;
21463
+ cursor.continue();
21464
+ } else if (cursor) {
21465
+ nextCursor = cursor.value.sentTime;
21466
+ } else {
21467
+ nextCursor = null;
21468
+ }
21469
+ if (!cursor || count >= pageSize) {
21470
+ resolve({
21471
+ messages,
21472
+ nextCursor
21473
+ });
21474
+ }
21475
+ };
21476
+ cursorRequest.onerror = event => {
21477
+ reject(new Error('获取分页消息失败'));
21478
+ };
21479
+ });
21480
+ }
21481
+ async updateMessagesStatus(messageUIds, newStatus) {
21482
+ if (!this.db || messageUIds.length === 0) {
21483
+ return;
21484
+ }
21485
+ return new Promise((resolve, reject) => {
21486
+ const transaction = this.db.transaction(this.STORE_NAME, 'readwrite');
21487
+ const store = transaction.objectStore(this.STORE_NAME);
21488
+ let completed = 0;
21489
+ let hasError = false;
21490
+ messageUIds.forEach(id => {
21491
+ const getRequest = store.get(id);
21492
+ getRequest.onsuccess = () => {
21493
+ const message = getRequest.result;
21494
+ if (message) {
21495
+ message.receivedStatus = newStatus;
21496
+ store.put(message);
21497
+ }
21498
+ completed++;
21499
+ if (completed === messageUIds.length && !hasError) {
21500
+ resolve();
21501
+ }
21502
+ };
21503
+ getRequest.onerror = event => {
21504
+ if (!hasError) {
21505
+ hasError = true;
21506
+ reject(new Error('更新消息状态失败'));
21507
+ }
21508
+ };
21509
+ });
21510
+ transaction.oncomplete = () => {
21511
+ resolve();
21512
+ };
21513
+ transaction.onerror = event => {
21514
+ reject(new Error('批量更新事务失败'));
21515
+ };
21516
+ });
21517
+ }
21518
+ async changeUser(appKey, userId) {
21519
+ if (this.currentAppKey === appKey && this.currentUserId === userId) {
21520
+ return;
21521
+ }
21522
+ this.currentAppKey = appKey;
21523
+ this.currentUserId = userId;
21524
+ this.generateEncryptKey(appKey, userId);
21525
+ await this.checkAndResetDatabase();
21526
+ await this.initDatabase();
21527
+ }
21528
+ }
21529
+ let cache;
21530
+ var MessageCache$1 = {
21531
+ create(appkey, currentUserId) {
21532
+ cache = new MessageCache(appkey, currentUserId);
21533
+ },
21534
+ get() {
21535
+ return cache;
21536
+ }
21537
+ };
21538
+
20946
21539
  const DEFAULT_SOCKET_URI = 'wss://imweb.mp.net:6443';
20947
21540
  class LibLoader {
20948
21541
  options;
@@ -21031,6 +21624,7 @@
21031
21624
  ConversationManager$1.get().destroyed();
21032
21625
  ConversationManager$1.create(this.options.appkey, accountStore.uid.toString(), this.watcher.conversationState);
21033
21626
  MessageReceiptManager$1.create(this.options.appkey, accountStore.uid.toString());
21627
+ MessageCache$1.create(this.options.appkey, accountStore.uid.toString());
21034
21628
  this.messageLoader?.stop();
21035
21629
  this.messageLoader = new MessageLoader(this.watcher, this.options);
21036
21630
  synchronizeServerTime();
@@ -28379,174 +28973,6 @@
28379
28973
  return UniqueSentTime;
28380
28974
  }
28381
28975
 
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
28976
  class IMClient extends EventEmitter {
28551
28977
  options;
28552
28978
  static imClient;
@@ -28595,7 +29021,7 @@
28595
29021
  },
28596
29022
  batchMessage: messages => {
28597
29023
  if (messages.length) {
28598
- MessageCache.get().addMessages(messages, {
29024
+ MessageCache$1.get()?.addMessages(messages, {
28599
29025
  conversationType: messages[0].content,
28600
29026
  targetId: messages[0].targetId
28601
29027
  });
@@ -28626,13 +29052,13 @@
28626
29052
  });
28627
29053
  },
28628
29054
  onRecall: messageUids => {
28629
- MessageCache.get().removeMessagesByUId(messageUids);
29055
+ MessageCache$1.get()?.removeMessagesByUId(messageUids);
28630
29056
  messageUids.forEach(messageUId => {
28631
29057
  this.emit(exports.Events.RECALL, messageUId);
28632
29058
  });
28633
29059
  },
28634
29060
  onReceiptReceived: (event, type) => {
28635
- MessageCache.get().updateMessageReceiptStatus(event, type);
29061
+ MessageCache$1.get()?.updateMessageReceiptStatus(event, type);
28636
29062
  if (type === 0) {
28637
29063
  this.emit(exports.Events.ARRIVAL_RECEIPT_RECEIVED, event);
28638
29064
  } else {
@@ -28668,7 +29094,7 @@
28668
29094
  async recallMsg(conversation, options) {
28669
29095
  const result = await sendRecallMessage(conversation, options);
28670
29096
  if (result.code === exports.ErrorCode.SUCCESS) {
28671
- MessageCache.get().removeMessagesByUId([options.messageUId]);
29097
+ MessageCache$1.get()?.removeMessagesByUId([options.messageUId]);
28672
29098
  }
28673
29099
  return result;
28674
29100
  }
@@ -28710,7 +29136,8 @@
28710
29136
  });
28711
29137
  }
28712
29138
  async getPreviousHistoryMessages(conversation, timestamp, count = 20) {
28713
- const cachedResult = MessageCache.get().getPreviousMessages(conversation, timestamp ?? '0', count);
29139
+ debugger;
29140
+ const cachedResult = await MessageCache$1.get().getPreviousMessages(conversation, timestamp ?? '0', count);
28714
29141
  if (!timestamp && cachedResult.messages.length) {
28715
29142
  ConversationManager$1.get().refreshLatestMessage(conversation, cachedResult.messages[cachedResult.messages.length - 1]);
28716
29143
  }
@@ -28736,7 +29163,7 @@
28736
29163
  if (!remotesTimestamp) {
28737
29164
  ConversationManager$1.get().refreshLatestMessage(conversation, remotesMessages[remotesMessages.length - 1]);
28738
29165
  }
28739
- MessageCache.get().addMessages(remotesMessages, conversation, !remotesResult.data.hasMore);
29166
+ MessageCache$1.get().addMessages(remotesMessages, conversation, !remotesResult.data.hasMore);
28740
29167
  return {
28741
29168
  code: exports.ErrorCode.SUCCESS,
28742
29169
  data: {
@@ -28746,11 +29173,11 @@
28746
29173
  };
28747
29174
  }
28748
29175
  async deleteRemoteMessage(conversation, list) {
28749
- MessageCache.get().removeMessagesByUId(list.map(e => e.messageUId));
29176
+ MessageCache$1.get()?.removeMessagesByUId(list.map(e => e.messageUId));
28750
29177
  return deleteMessages$1(getFullDialogId(conversation), list.map(e => e.messageUId)).then(result => result.code);
28751
29178
  }
28752
29179
  async deleteRemoteMessageByTimestamp(conversation, timestamp) {
28753
- MessageCache.get().clearConversationCache(conversation);
29180
+ MessageCache$1.get()?.clearConversationCache(conversation);
28754
29181
  ConversationManager$1.get().clearHistoryMessages(conversation);
28755
29182
  return clearHistoryMessage(getFullDialogId(conversation), timestamp === 0 ? Number.MAX_VALUE : timestamp).then(result => result.code);
28756
29183
  }
@@ -28936,7 +29363,7 @@
28936
29363
  return conversationObj;
28937
29364
  }
28938
29365
  clearBurnAfterReadingExpiredMessages(conversation) {
28939
- return MessageCache.get().clearBurnAfterReadingExpiredMessages(conversation);
29366
+ return MessageCache$1.get()?.clearBurnAfterReadingExpiredMessages(conversation) ?? Promise.resolve([]);
28940
29367
  }
28941
29368
  }
28942
29369
 
@@ -30197,11 +30624,11 @@
30197
30624
  logger.warn('send message fail ->' + errorCode + ':' + ErrorDesc(errorCode) + ',' + paramsStr);
30198
30625
  }
30199
30626
  };
30200
- const clearBurnAfterReadingExpiredMessages = conversation => {
30627
+ const clearBurnAfterReadingExpiredMessages = async conversation => {
30201
30628
  assert('conversation', conversation, AssertRules.CONVERSATION, true);
30202
30629
  const paramsStr = 'conversationType:' + conversation.conversationType + ',targetId:' + conversation.targetId;
30203
30630
  logger.debug('clear burn after reading expired messages ->' + paramsStr);
30204
- const expiredMessageUIds = imClient.clearBurnAfterReadingExpiredMessages(conversation);
30631
+ const expiredMessageUIds = await imClient.clearBurnAfterReadingExpiredMessages(conversation);
30205
30632
  if (expiredMessageUIds.length > 0) {
30206
30633
  logger.debug(`已清除会话 ${paramsStr} 中的 ${expiredMessageUIds.length} 条阅后即焚过期消息`);
30207
30634
  }