@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.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,607 @@ 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
+ encryptKey = {
20944
+ key: ''
20945
+ };
20946
+ SALT_PREFIX = 'im_message_cache_salt_prefix';
20947
+ SALT_SUFFIX = 'im_message_cache_salt_suffix';
20948
+ constructor(appKey, userId) {
20949
+ this.generateEncryptKey(appKey, userId);
20950
+ this.init(appKey, userId);
20951
+ }
20952
+ generateEncryptKey(appKey, userId) {
20953
+ const saltedInput = `${this.SALT_PREFIX}${appKey}_${userId}${this.SALT_SUFFIX}`;
20954
+ const keyMaterial = CryptoJS.SHA256(saltedInput).toString();
20955
+ const iv = keyMaterial.substring(0, 16);
20956
+ const key = keyMaterial.substring(16, 48);
20957
+ const additionalSalt = CryptoJS.SHA256(`${iv}:${this.SALT_PREFIX}:${userId}:${appKey}`).toString().substring(0, 8);
20958
+ const finalKey = CryptoJS.PBKDF2(key, additionalSalt, {
20959
+ keySize: 256 / 32,
20960
+ iterations: 1000,
20961
+ hasher: CryptoJS.algo.SHA256
20962
+ }).toString();
20963
+ this.encryptKey = {
20964
+ key: finalKey.substring(0, 32),
20965
+ iv: iv
20966
+ };
20967
+ }
20968
+ async init(appKey, userId) {
20969
+ this.currentAppKey = appKey;
20970
+ this.currentUserId = userId;
20971
+ await this.checkAndResetDatabase();
20972
+ await this.initDatabase();
20973
+ }
20974
+ async checkAndResetDatabase() {
20975
+ const storedInfoStr = LocalStorageService.get(this.APP_INFO_KEY);
20976
+ if (storedInfoStr) {
20977
+ try {
20978
+ const storedInfo = JSON.parse(storedInfoStr);
20979
+ if (storedInfo.appKey !== this.currentAppKey || storedInfo.userId !== this.currentUserId) {
20980
+ await this.deleteDatabase();
20981
+ }
20982
+ } catch (error) {
20983
+ console.error('解析存储的AppKey和UserId出错', error);
20984
+ await this.deleteDatabase();
20985
+ }
20986
+ }
20987
+ LocalStorageService.set(this.APP_INFO_KEY, JSON.stringify({
20988
+ appKey: this.currentAppKey,
20989
+ userId: this.currentUserId,
20990
+ timestamp: Date.now()
20991
+ }));
20992
+ }
20993
+ async deleteDatabase() {
20994
+ if (this.db) {
20995
+ this.db.close();
20996
+ this.db = null;
20997
+ }
20998
+ this.loadedEndMap.clear();
20999
+ return new Promise((resolve, reject) => {
21000
+ const dbName = this.getDBName();
21001
+ const deleteRequest = indexedDB.deleteDatabase(dbName);
21002
+ deleteRequest.onsuccess = () => {
21003
+ console.log(`数据库 ${dbName} 已成功删除`);
21004
+ resolve();
21005
+ };
21006
+ deleteRequest.onerror = event => {
21007
+ console.error(`删除数据库 ${dbName} 失败`, event);
21008
+ resolve();
21009
+ };
21010
+ });
21011
+ }
21012
+ getDBName() {
21013
+ return `${this.DB_NAME_PREFIX}_${this.currentAppKey}_${this.currentUserId}`;
21014
+ }
21015
+ initDatabase() {
21016
+ return new Promise((resolve, reject) => {
21017
+ const dbName = this.getDBName();
21018
+ const request = indexedDB.open(dbName, this.DB_VERSION);
21019
+ request.onerror = event => {
21020
+ console.error('数据库打开失败', event);
21021
+ reject(new Error('数据库打开失败'));
21022
+ };
21023
+ request.onsuccess = event => {
21024
+ this.db = event.target.result;
21025
+ this.loadAllDialogStates().then(() => {
21026
+ resolve();
21027
+ }).catch(err => {
21028
+ console.error('加载会话状态失败', err);
21029
+ resolve();
21030
+ });
21031
+ };
21032
+ request.onupgradeneeded = event => {
21033
+ const db = event.target.result;
21034
+ if (!db.objectStoreNames.contains(this.STORE_NAME)) {
21035
+ const store = db.createObjectStore(this.STORE_NAME, {
21036
+ keyPath: 'messageUId'
21037
+ });
21038
+ store.createIndex('dialogId', 'dialogId', {
21039
+ unique: false
21040
+ });
21041
+ store.createIndex('dialogId_sentTime', ['dialogId', 'sentTime'], {
21042
+ unique: false
21043
+ });
21044
+ store.createIndex('receivedStatus', 'receivedStatus', {
21045
+ unique: false
21046
+ });
21047
+ store.createIndex('burnAfterReadingFlag', 'burnAfterReadingFlag', {
21048
+ unique: false
21049
+ });
21050
+ store.createIndex('dialogId_receivedStatus', ['dialogId', 'receivedStatus'], {
21051
+ unique: false
21052
+ });
21053
+ }
21054
+ if (!db.objectStoreNames.contains(this.DIALOG_STATE_STORE)) {
21055
+ db.createObjectStore(this.DIALOG_STATE_STORE, {
21056
+ keyPath: 'dialogId'
21057
+ });
21058
+ }
21059
+ };
21060
+ });
21061
+ }
21062
+ async loadAllDialogStates() {
21063
+ if (!this.db) {
21064
+ return;
21065
+ }
21066
+ return new Promise((resolve, reject) => {
21067
+ const transaction = this.db.transaction(this.DIALOG_STATE_STORE, 'readonly');
21068
+ const store = transaction.objectStore(this.DIALOG_STATE_STORE);
21069
+ const request = store.getAll();
21070
+ request.onsuccess = () => {
21071
+ const states = request.result;
21072
+ this.loadedEndMap.clear();
21073
+ states.forEach(state => {
21074
+ this.loadedEndMap.set(state.dialogId, state.isEnd);
21075
+ });
21076
+ resolve();
21077
+ };
21078
+ request.onerror = event => {
21079
+ reject(new Error('加载会话状态失败'));
21080
+ };
21081
+ });
21082
+ }
21083
+ async updateDialogState(dialogId, isEnd) {
21084
+ if (!this.db) {
21085
+ return;
21086
+ }
21087
+ this.loadedEndMap.set(dialogId, isEnd);
21088
+ return new Promise((resolve, reject) => {
21089
+ const transaction = this.db.transaction(this.DIALOG_STATE_STORE, 'readwrite');
21090
+ const store = transaction.objectStore(this.DIALOG_STATE_STORE);
21091
+ const request = store.put({
21092
+ dialogId,
21093
+ isEnd,
21094
+ updateTime: Date.now()
21095
+ });
21096
+ request.onsuccess = () => {
21097
+ resolve();
21098
+ };
21099
+ request.onerror = event => {
21100
+ console.error('更新会话状态失败', event);
21101
+ reject(new Error('更新会话状态失败'));
21102
+ };
21103
+ });
21104
+ }
21105
+ encryptContent(content) {
21106
+ if (!content) return '';
21107
+ try {
21108
+ const contentStr = JSON.stringify(content);
21109
+ return aes256Encrypt(contentStr, this.encryptKey);
21110
+ } catch (error) {
21111
+ console.error('加密消息内容失败', error);
21112
+ return '';
21113
+ }
21114
+ }
21115
+ decryptContent(encryptedHex) {
21116
+ if (!encryptedHex) {
21117
+ return null;
21118
+ }
21119
+ try {
21120
+ const decryptedStr = aes256Decrypt(encryptedHex, this.encryptKey);
21121
+ return JSON.parse(decryptedStr);
21122
+ } catch (error) {
21123
+ console.error('解密消息内容失败', error);
21124
+ return null;
21125
+ }
21126
+ }
21127
+ async addMessages(messages, toConversation, isEnd = undefined) {
21128
+ const dialogId = getFullDialogId(toConversation);
21129
+ if (isDef(isEnd)) {
21130
+ await this.updateDialogState(dialogId, isEnd);
21131
+ }
21132
+ if (!messages || messages.length === 0 || !this.db) {
21133
+ return;
21134
+ }
21135
+ return new Promise((resolve, reject) => {
21136
+ const transaction = this.db.transaction(this.STORE_NAME, 'readwrite');
21137
+ const store = transaction.objectStore(this.STORE_NAME);
21138
+ messages.forEach(message => {
21139
+ const messageToStore = {
21140
+ ...message,
21141
+ dialogId
21142
+ };
21143
+ if (messageToStore.content) {
21144
+ const encryptedContent = this.encryptContent(messageToStore.content);
21145
+ messageToStore.content = encryptedContent;
21146
+ }
21147
+ store.put(messageToStore);
21148
+ });
21149
+ transaction.oncomplete = () => {
21150
+ resolve();
21151
+ };
21152
+ transaction.onerror = event => {
21153
+ console.error('添加消息事务失败', event);
21154
+ reject(new Error('添加消息事务失败'));
21155
+ };
21156
+ });
21157
+ }
21158
+ async getPreviousMessages(conversation, timestamp = "0", count = 20) {
21159
+ const dialogId = getFullDialogId(conversation);
21160
+ if (!this.db) {
21161
+ return {
21162
+ messages: [],
21163
+ hasMore: false
21164
+ };
21165
+ }
21166
+ const isLoaded = await this.getDialogLoadedState(dialogId);
21167
+ return new Promise((resolve, reject) => {
21168
+ const transaction = this.db.transaction(this.STORE_NAME, 'readonly');
21169
+ const store = transaction.objectStore(this.STORE_NAME);
21170
+ const index = store.index('dialogId_sentTime');
21171
+ let range;
21172
+ const direction = 'prev';
21173
+ if (timestamp === "0") {
21174
+ range = IDBKeyRange.bound([dialogId, ''], [dialogId, '\uffff']);
21175
+ } else {
21176
+ range = IDBKeyRange.bound([dialogId, ''], [dialogId, timestamp]);
21177
+ }
21178
+ const messages = [];
21179
+ let hasMoreMessages = false;
21180
+ let processedCount = 0;
21181
+ const countRequest = index.count(range);
21182
+ countRequest.onsuccess = () => {
21183
+ const totalCount = countRequest.result;
21184
+ const cursorRequest = index.openCursor(range, direction);
21185
+ cursorRequest.onsuccess = event => {
21186
+ const cursor = event.target.result;
21187
+ if (cursor) {
21188
+ if (processedCount < count) {
21189
+ const message = {
21190
+ ...cursor.value
21191
+ };
21192
+ if (typeof message.content === 'string' && message.content) {
21193
+ try {
21194
+ message.content = this.decryptContent(message.content);
21195
+ } catch (error) {
21196
+ console.error('解密消息内容失败', error);
21197
+ message.content = null;
21198
+ }
21199
+ }
21200
+ messages.push(message);
21201
+ processedCount++;
21202
+ cursor.continue();
21203
+ } else {
21204
+ hasMoreMessages = true;
21205
+ finishQuery();
21206
+ }
21207
+ } else {
21208
+ finishQuery();
21209
+ }
21210
+ };
21211
+ const finishQuery = () => {
21212
+ messages.sort((a, b) => Long.fromString(a.sentTime).compare(Long.fromString(b.sentTime)));
21213
+ resolve({
21214
+ messages,
21215
+ hasMore: hasMoreMessages || totalCount > count || !isLoaded
21216
+ });
21217
+ };
21218
+ };
21219
+ transaction.onerror = event => {
21220
+ console.error('获取消息事务失败', event);
21221
+ reject(new Error('获取消息事务失败'));
21222
+ };
21223
+ });
21224
+ }
21225
+ async clearConversationCache(conversation) {
21226
+ const dialogId = getFullDialogId(conversation);
21227
+ if (!this.db) {
21228
+ this.loadedEndMap.set(dialogId, true);
21229
+ return;
21230
+ }
21231
+ const deleteMessagesPromise = new Promise((resolve, reject) => {
21232
+ const transaction = this.db.transaction(this.STORE_NAME, 'readwrite');
21233
+ const store = transaction.objectStore(this.STORE_NAME);
21234
+ const index = store.index('dialogId');
21235
+ const request = index.openCursor(IDBKeyRange.only(dialogId));
21236
+ request.onsuccess = event => {
21237
+ const cursor = event.target.result;
21238
+ if (cursor) {
21239
+ cursor.delete();
21240
+ cursor.continue();
21241
+ }
21242
+ };
21243
+ transaction.oncomplete = () => {
21244
+ resolve();
21245
+ };
21246
+ transaction.onerror = event => {
21247
+ reject(new Error('清除会话消息失败'));
21248
+ };
21249
+ });
21250
+ await Promise.all([deleteMessagesPromise, this.updateDialogState(dialogId, true)]);
21251
+ }
21252
+ async clearAllCache() {
21253
+ if (!this.db) {
21254
+ this.loadedEndMap.clear();
21255
+ return;
21256
+ }
21257
+ const clearMessagesPromise = new Promise((resolve, reject) => {
21258
+ const transaction = this.db.transaction(this.STORE_NAME, 'readwrite');
21259
+ const store = transaction.objectStore(this.STORE_NAME);
21260
+ const request = store.clear();
21261
+ request.onsuccess = () => {
21262
+ resolve();
21263
+ };
21264
+ request.onerror = event => {
21265
+ reject(new Error('清除所有消息失败'));
21266
+ };
21267
+ });
21268
+ const clearStatesPromise = new Promise((resolve, reject) => {
21269
+ const transaction = this.db.transaction(this.DIALOG_STATE_STORE, 'readwrite');
21270
+ const store = transaction.objectStore(this.DIALOG_STATE_STORE);
21271
+ const request = store.clear();
21272
+ request.onsuccess = () => {
21273
+ this.loadedEndMap.clear();
21274
+ resolve();
21275
+ };
21276
+ request.onerror = event => {
21277
+ reject(new Error('清除所有会话状态失败'));
21278
+ };
21279
+ });
21280
+ await Promise.all([clearMessagesPromise, clearStatesPromise]);
21281
+ }
21282
+ async getDialogLoadedState(dialogId) {
21283
+ if (this.loadedEndMap.has(dialogId)) {
21284
+ return this.loadedEndMap.get(dialogId);
21285
+ }
21286
+ if (!this.db) {
21287
+ return false;
21288
+ }
21289
+ return new Promise((resolve, reject) => {
21290
+ const transaction = this.db.transaction(this.DIALOG_STATE_STORE, 'readonly');
21291
+ const store = transaction.objectStore(this.DIALOG_STATE_STORE);
21292
+ const request = store.get(dialogId);
21293
+ request.onsuccess = () => {
21294
+ const state = request.result;
21295
+ if (state) {
21296
+ this.loadedEndMap.set(dialogId, state.isEnd);
21297
+ resolve(state.isEnd);
21298
+ } else {
21299
+ resolve(false);
21300
+ }
21301
+ };
21302
+ request.onerror = event => {
21303
+ resolve(false);
21304
+ };
21305
+ });
21306
+ }
21307
+ async removeMessagesByUId(messageUIds) {
21308
+ if (!messageUIds || messageUIds.length === 0 || !this.db) {
21309
+ return;
21310
+ }
21311
+ return new Promise((resolve, reject) => {
21312
+ const transaction = this.db.transaction(this.STORE_NAME, 'readwrite');
21313
+ const store = transaction.objectStore(this.STORE_NAME);
21314
+ let completed = 0;
21315
+ let hasError = false;
21316
+ messageUIds.forEach(id => {
21317
+ const deleteRequest = store.delete(id);
21318
+ deleteRequest.onsuccess = () => {
21319
+ completed++;
21320
+ if (completed === messageUIds.length && !hasError) {
21321
+ resolve();
21322
+ }
21323
+ };
21324
+ deleteRequest.onerror = event => {
21325
+ console.error('删除消息失败', id, 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 updateMessageReceiptStatus(event, type) {
21343
+ if (!event || !event.messageUIdList || event.messageUIdList.length === 0 || !this.db) {
21344
+ return;
21345
+ }
21346
+ const {
21347
+ conversation
21348
+ } = event;
21349
+ getFullDialogId(conversation);
21350
+ return new Promise((resolve, reject) => {
21351
+ const transaction = this.db.transaction(this.STORE_NAME, 'readwrite');
21352
+ const store = transaction.objectStore(this.STORE_NAME);
21353
+ let completed = 0;
21354
+ let hasError = false;
21355
+ event.messageUIdList.forEach(id => {
21356
+ const getRequest = store.get(id);
21357
+ getRequest.onsuccess = () => {
21358
+ const message = getRequest.result;
21359
+ if (message) {
21360
+ let needUpdate = false;
21361
+ if (type === 0 && message.receivedStatus < ReceivedStatus.RECEIVED) {
21362
+ message.receivedStatus = ReceivedStatus.RECEIVED;
21363
+ needUpdate = true;
21364
+ } else if (type === 1 && message.receivedStatus < ReceivedStatus.READ) {
21365
+ message.receivedStatus = ReceivedStatus.READ;
21366
+ needUpdate = true;
21367
+ }
21368
+ if (needUpdate) {
21369
+ store.put(message);
21370
+ }
21371
+ }
21372
+ completed++;
21373
+ if (completed === event.messageUIdList.length && !hasError) {
21374
+ resolve();
21375
+ }
21376
+ };
21377
+ getRequest.onerror = event => {
21378
+ if (!hasError) {
21379
+ hasError = true;
21380
+ reject(new Error('更新消息状态失败'));
21381
+ }
21382
+ };
21383
+ });
21384
+ transaction.oncomplete = () => {
21385
+ if (!hasError) {
21386
+ resolve();
21387
+ }
21388
+ };
21389
+ transaction.onerror = event => {
21390
+ reject(new Error('更新消息状态事务失败'));
21391
+ };
21392
+ });
21393
+ }
21394
+ async clearBurnAfterReadingExpiredMessages(conversation) {
21395
+ const dialogId = getFullDialogId(conversation);
21396
+ if (!this.db) {
21397
+ return [];
21398
+ }
21399
+ const currentTime = Date.now();
21400
+ return new Promise((resolve, reject) => {
21401
+ const transaction = this.db.transaction(this.STORE_NAME, 'readwrite');
21402
+ const store = transaction.objectStore(this.STORE_NAME);
21403
+ const index = store.index('dialogId');
21404
+ const expiredMessageUIds = [];
21405
+ const request = index.openCursor(IDBKeyRange.only(dialogId));
21406
+ request.onsuccess = event => {
21407
+ const cursor = event.target.result;
21408
+ if (cursor) {
21409
+ const message = cursor.value;
21410
+ if (message.burnAfterReadingFlag) {
21411
+ const burnTime = message.burnAfterReadingTime || 0;
21412
+ let isExpired = burnTime === 0;
21413
+ if (!isExpired && burnTime > 0) {
21414
+ const sentTimeLong = Long.fromString(message.sentTime);
21415
+ const currentTimeLong = Long.fromNumber(currentTime);
21416
+ const burnTimeLong = Long.fromNumber(burnTime);
21417
+ const expirationTime = sentTimeLong.add(burnTimeLong);
21418
+ isExpired = currentTimeLong.greaterThan(expirationTime);
21419
+ }
21420
+ if (isExpired) {
21421
+ expiredMessageUIds.push(message.messageUId);
21422
+ cursor.delete();
21423
+ }
21424
+ }
21425
+ cursor.continue();
21426
+ } else {
21427
+ resolve(expiredMessageUIds);
21428
+ }
21429
+ };
21430
+ request.onerror = event => {
21431
+ console.error('清除过期消息失败', event);
21432
+ reject(new Error('清除过期消息失败'));
21433
+ };
21434
+ });
21435
+ }
21436
+ async getMessagesByPage(dialogId, pageSize = 20, cursorPosition = null) {
21437
+ if (!this.db) {
21438
+ return {
21439
+ messages: [],
21440
+ nextCursor: null
21441
+ };
21442
+ }
21443
+ return new Promise((resolve, reject) => {
21444
+ const transaction = this.db.transaction(this.STORE_NAME, 'readonly');
21445
+ const store = transaction.objectStore(this.STORE_NAME);
21446
+ const index = store.index('dialogId_sentTime');
21447
+ const range = IDBKeyRange.bound([dialogId, cursorPosition || ''], [dialogId, '\uffff']);
21448
+ const messages = [];
21449
+ let nextCursor = null;
21450
+ let count = 0;
21451
+ const cursorRequest = index.openCursor(range);
21452
+ cursorRequest.onsuccess = event => {
21453
+ const cursor = event.target.result;
21454
+ if (cursor && count < pageSize) {
21455
+ messages.push(cursor.value);
21456
+ count++;
21457
+ cursor.continue();
21458
+ } else if (cursor) {
21459
+ nextCursor = cursor.value.sentTime;
21460
+ } else {
21461
+ nextCursor = null;
21462
+ }
21463
+ if (!cursor || count >= pageSize) {
21464
+ resolve({
21465
+ messages,
21466
+ nextCursor
21467
+ });
21468
+ }
21469
+ };
21470
+ cursorRequest.onerror = event => {
21471
+ reject(new Error('获取分页消息失败'));
21472
+ };
21473
+ });
21474
+ }
21475
+ async updateMessagesStatus(messageUIds, newStatus) {
21476
+ if (!this.db || messageUIds.length === 0) {
21477
+ return;
21478
+ }
21479
+ return new Promise((resolve, reject) => {
21480
+ const transaction = this.db.transaction(this.STORE_NAME, 'readwrite');
21481
+ const store = transaction.objectStore(this.STORE_NAME);
21482
+ let completed = 0;
21483
+ let hasError = false;
21484
+ messageUIds.forEach(id => {
21485
+ const getRequest = store.get(id);
21486
+ getRequest.onsuccess = () => {
21487
+ const message = getRequest.result;
21488
+ if (message) {
21489
+ message.receivedStatus = newStatus;
21490
+ store.put(message);
21491
+ }
21492
+ completed++;
21493
+ if (completed === messageUIds.length && !hasError) {
21494
+ resolve();
21495
+ }
21496
+ };
21497
+ getRequest.onerror = event => {
21498
+ if (!hasError) {
21499
+ hasError = true;
21500
+ reject(new Error('更新消息状态失败'));
21501
+ }
21502
+ };
21503
+ });
21504
+ transaction.oncomplete = () => {
21505
+ resolve();
21506
+ };
21507
+ transaction.onerror = event => {
21508
+ reject(new Error('批量更新事务失败'));
21509
+ };
21510
+ });
21511
+ }
21512
+ async changeUser(appKey, userId) {
21513
+ if (this.currentAppKey === appKey && this.currentUserId === userId) {
21514
+ return;
21515
+ }
21516
+ this.currentAppKey = appKey;
21517
+ this.currentUserId = userId;
21518
+ this.generateEncryptKey(appKey, userId);
21519
+ await this.checkAndResetDatabase();
21520
+ await this.initDatabase();
21521
+ }
21522
+ }
21523
+ let cache;
21524
+ var MessageCache$1 = {
21525
+ create(appkey, currentUserId) {
21526
+ cache = new MessageCache(appkey, currentUserId);
21527
+ },
21528
+ get() {
21529
+ return cache;
21530
+ }
21531
+ };
21532
+
20940
21533
  const DEFAULT_SOCKET_URI = 'wss://imweb.mp.net:6443';
20941
21534
  class LibLoader {
20942
21535
  options;
@@ -21025,6 +21618,7 @@ class LibLoader {
21025
21618
  ConversationManager$1.get().destroyed();
21026
21619
  ConversationManager$1.create(this.options.appkey, accountStore.uid.toString(), this.watcher.conversationState);
21027
21620
  MessageReceiptManager$1.create(this.options.appkey, accountStore.uid.toString());
21621
+ MessageCache$1.create(this.options.appkey, accountStore.uid.toString());
21028
21622
  this.messageLoader?.stop();
21029
21623
  this.messageLoader = new MessageLoader(this.watcher, this.options);
21030
21624
  synchronizeServerTime();
@@ -28373,174 +28967,6 @@ function getMessageSentTime() {
28373
28967
  return UniqueSentTime;
28374
28968
  }
28375
28969
 
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
28970
  class IMClient extends EventEmitter {
28545
28971
  options;
28546
28972
  static imClient;
@@ -28589,7 +29015,7 @@ class IMClient extends EventEmitter {
28589
29015
  },
28590
29016
  batchMessage: messages => {
28591
29017
  if (messages.length) {
28592
- MessageCache.get().addMessages(messages, {
29018
+ MessageCache$1.get()?.addMessages(messages, {
28593
29019
  conversationType: messages[0].content,
28594
29020
  targetId: messages[0].targetId
28595
29021
  });
@@ -28620,13 +29046,13 @@ class IMClient extends EventEmitter {
28620
29046
  });
28621
29047
  },
28622
29048
  onRecall: messageUids => {
28623
- MessageCache.get().removeMessagesByUId(messageUids);
29049
+ MessageCache$1.get()?.removeMessagesByUId(messageUids);
28624
29050
  messageUids.forEach(messageUId => {
28625
29051
  this.emit(Events.RECALL, messageUId);
28626
29052
  });
28627
29053
  },
28628
29054
  onReceiptReceived: (event, type) => {
28629
- MessageCache.get().updateMessageReceiptStatus(event, type);
29055
+ MessageCache$1.get()?.updateMessageReceiptStatus(event, type);
28630
29056
  if (type === 0) {
28631
29057
  this.emit(Events.ARRIVAL_RECEIPT_RECEIVED, event);
28632
29058
  } else {
@@ -28662,7 +29088,7 @@ class IMClient extends EventEmitter {
28662
29088
  async recallMsg(conversation, options) {
28663
29089
  const result = await sendRecallMessage(conversation, options);
28664
29090
  if (result.code === ErrorCode.SUCCESS) {
28665
- MessageCache.get().removeMessagesByUId([options.messageUId]);
29091
+ MessageCache$1.get()?.removeMessagesByUId([options.messageUId]);
28666
29092
  }
28667
29093
  return result;
28668
29094
  }
@@ -28704,7 +29130,8 @@ class IMClient extends EventEmitter {
28704
29130
  });
28705
29131
  }
28706
29132
  async getPreviousHistoryMessages(conversation, timestamp, count = 20) {
28707
- const cachedResult = MessageCache.get().getPreviousMessages(conversation, timestamp ?? '0', count);
29133
+ debugger;
29134
+ const cachedResult = await MessageCache$1.get().getPreviousMessages(conversation, timestamp ?? '0', count);
28708
29135
  if (!timestamp && cachedResult.messages.length) {
28709
29136
  ConversationManager$1.get().refreshLatestMessage(conversation, cachedResult.messages[cachedResult.messages.length - 1]);
28710
29137
  }
@@ -28730,7 +29157,7 @@ class IMClient extends EventEmitter {
28730
29157
  if (!remotesTimestamp) {
28731
29158
  ConversationManager$1.get().refreshLatestMessage(conversation, remotesMessages[remotesMessages.length - 1]);
28732
29159
  }
28733
- MessageCache.get().addMessages(remotesMessages, conversation, !remotesResult.data.hasMore);
29160
+ MessageCache$1.get().addMessages(remotesMessages, conversation, !remotesResult.data.hasMore);
28734
29161
  return {
28735
29162
  code: ErrorCode.SUCCESS,
28736
29163
  data: {
@@ -28740,11 +29167,11 @@ class IMClient extends EventEmitter {
28740
29167
  };
28741
29168
  }
28742
29169
  async deleteRemoteMessage(conversation, list) {
28743
- MessageCache.get().removeMessagesByUId(list.map(e => e.messageUId));
29170
+ MessageCache$1.get()?.removeMessagesByUId(list.map(e => e.messageUId));
28744
29171
  return deleteMessages$1(getFullDialogId(conversation), list.map(e => e.messageUId)).then(result => result.code);
28745
29172
  }
28746
29173
  async deleteRemoteMessageByTimestamp(conversation, timestamp) {
28747
- MessageCache.get().clearConversationCache(conversation);
29174
+ MessageCache$1.get()?.clearConversationCache(conversation);
28748
29175
  ConversationManager$1.get().clearHistoryMessages(conversation);
28749
29176
  return clearHistoryMessage(getFullDialogId(conversation), timestamp === 0 ? Number.MAX_VALUE : timestamp).then(result => result.code);
28750
29177
  }
@@ -28930,7 +29357,7 @@ class IMClient extends EventEmitter {
28930
29357
  return conversationObj;
28931
29358
  }
28932
29359
  clearBurnAfterReadingExpiredMessages(conversation) {
28933
- return MessageCache.get().clearBurnAfterReadingExpiredMessages(conversation);
29360
+ return MessageCache$1.get()?.clearBurnAfterReadingExpiredMessages(conversation) ?? Promise.resolve([]);
28934
29361
  }
28935
29362
  }
28936
29363
 
@@ -30191,11 +30618,11 @@ const _logSendError = (conversation, errorCode) => {
30191
30618
  logger.warn('send message fail ->' + errorCode + ':' + ErrorDesc(errorCode) + ',' + paramsStr);
30192
30619
  }
30193
30620
  };
30194
- const clearBurnAfterReadingExpiredMessages = conversation => {
30621
+ const clearBurnAfterReadingExpiredMessages = async conversation => {
30195
30622
  assert('conversation', conversation, AssertRules.CONVERSATION, true);
30196
30623
  const paramsStr = 'conversationType:' + conversation.conversationType + ',targetId:' + conversation.targetId;
30197
30624
  logger.debug('clear burn after reading expired messages ->' + paramsStr);
30198
- const expiredMessageUIds = imClient.clearBurnAfterReadingExpiredMessages(conversation);
30625
+ const expiredMessageUIds = await imClient.clearBurnAfterReadingExpiredMessages(conversation);
30199
30626
  if (expiredMessageUIds.length > 0) {
30200
30627
  logger.debug(`已清除会话 ${paramsStr} 中的 ${expiredMessageUIds.length} 条阅后即焚过期消息`);
30201
30628
  }