@onyx-p/imlib-web 2.3.3 → 2.3.5

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 +468 -482
  2. package/index.umd.js +468 -482
  3. package/package.json +1 -1
package/index.esm.js CHANGED
@@ -20722,295 +20722,6 @@ function getCurrentMessageId() {
20722
20722
  return lastMessageId;
20723
20723
  }
20724
20724
 
20725
- class MessageLoader {
20726
- watcher;
20727
- pullingMsg = false;
20728
- letterbox;
20729
- serverMsgSeqno = Long.ZERO;
20730
- pullOfflineFinished = false;
20731
- intervalTimer;
20732
- retryTimer;
20733
- latestSyncTimestamp = 0;
20734
- started = false;
20735
- constructor(watcher, options) {
20736
- this.watcher = watcher;
20737
- this.letterbox = new Letterbox(options.appkey, accountStore.uid.toString());
20738
- }
20739
- start() {
20740
- this.started = true;
20741
- this.pullOfflineFinished = false;
20742
- this.startPullInterval();
20743
- }
20744
- stop() {
20745
- this.started = false;
20746
- this.stopPullInterval();
20747
- this.cancelRetryTask();
20748
- }
20749
- syncMsg(seqno) {
20750
- this.serverMsgSeqno = seqno;
20751
- this.pullMsg();
20752
- }
20753
- startPullInterval() {
20754
- this.stopPullInterval();
20755
- const d = 3 * 60 * 1000;
20756
- this.intervalTimer = setInterval(() => {
20757
- if (Date.now() - this.latestSyncTimestamp >= d) {
20758
- this.pullMsg();
20759
- }
20760
- }, 30000);
20761
- this.latestSyncTimestamp = Date.now();
20762
- this.pullMsg();
20763
- }
20764
- stopPullInterval() {
20765
- if (this.intervalTimer) {
20766
- clearInterval(this.intervalTimer);
20767
- this.intervalTimer = null;
20768
- }
20769
- }
20770
- try2RePullMsg() {
20771
- this.retryTimer = setTimeout(() => {
20772
- this.retryTimer = null;
20773
- this.pullMsg();
20774
- }, 1000);
20775
- }
20776
- cancelRetryTask() {
20777
- if (this.retryTimer) {
20778
- clearTimeout(this.retryTimer);
20779
- this.retryTimer = null;
20780
- }
20781
- }
20782
- async pullMsg() {
20783
- if (this.pullingMsg) {
20784
- return;
20785
- }
20786
- if (!this.started) {
20787
- return;
20788
- }
20789
- this.cancelRetryTask();
20790
- this.pullingMsg = true;
20791
- const inboxTime = this.letterbox.getInboxOffset();
20792
- logger.info(`pullMsg -> time: ${inboxTime}`);
20793
- this.latestSyncTimestamp = Date.now();
20794
- const {
20795
- code,
20796
- data
20797
- } = await getNewMessages(inboxTime, 60);
20798
- if (code !== ErrorCode.SUCCESS) {
20799
- logger.warn('pullMsg failed -> code:', code);
20800
- this.pullingMsg = false;
20801
- if (LibLoader.loader?.getConnectionStatus() == ConnectionStatus.CONNECTED) {
20802
- this.try2RePullMsg();
20803
- }
20804
- return;
20805
- }
20806
- const {
20807
- offset,
20808
- seqno,
20809
- msg
20810
- } = data;
20811
- const cons = Object.keys(msg).map(dialogId => {
20812
- const conversationType = extractConversationType(Long.fromString(dialogId));
20813
- return {
20814
- conversationType,
20815
- targetId: dialogId
20816
- };
20817
- });
20818
- await ConversationManager$1.get().loadConvsationsIfNotExist(cons);
20819
- serverMessageParser.parse(msg, (done, outputMsgs) => {
20820
- const messages = [];
20821
- const recallMessageIndexes = [];
20822
- const isOffLineMessage = !this.pullOfflineFinished;
20823
- outputMsgs.forEach((l, dialogId) => {
20824
- let messageList = [];
20825
- l.forEach(m => {
20826
- if (m.messageType === MessageTypes.RECALL && RecallMessageStore.has(m.content.messageUId)) {
20827
- RecallMessageStore.remove(m.content.messageUId);
20828
- } else {
20829
- m.isOffLineMessage = isOffLineMessage;
20830
- if (!m.messageId || m.messageId > getCurrentMessageId()) {
20831
- m.messageId = generateNewMessageId();
20832
- }
20833
- ConversationManager$1.get().setConversationCacheByMessage(m);
20834
- messageList.push(m);
20835
- if (m.messageType === MessageTypes.RECALL) {
20836
- recallMessageIndexes.push(messageList.length - 1);
20837
- }
20838
- }
20839
- if ([NotiMessageTypes.PRIVATE_OPEN_BURNAFTERREADING, NotiMessageTypes.GROUP_OPEN_BURNAFTERREADING, NotiMessageTypes.PRIVATE_CLOSE_BURNAFTERREADING, NotiMessageTypes.GROUP_CLOSE_BURNAFTERREADING].includes(m.messageType)) {
20840
- this.handleBurnAfterReadingMessage(m);
20841
- }
20842
- });
20843
- let recallMessageUIds = [];
20844
- let deletedMessageIndexes = [];
20845
- for (let i = recallMessageIndexes.length - 1; i >= 0; i--) {
20846
- const index = recallMessageIndexes[i];
20847
- const recallMessage = messageList[index];
20848
- const recallContent = recallMessage.content;
20849
- const messageIndex = messageList.findIndex(m => m.messageUId === recallContent.messageUId);
20850
- if (messageIndex !== -1) {
20851
- deletedMessageIndexes.push(messageIndex);
20852
- } else {
20853
- recallMessageUIds.push(recallContent.messageUId);
20854
- deletedMessageIndexes.push(index);
20855
- }
20856
- }
20857
- messageList = messageList.filter((m, index) => !deletedMessageIndexes.includes(index));
20858
- messages.push(...messageList);
20859
- if (this.isExistPersistedMessage(messageList)) {
20860
- splitFullDialog(dialogId);
20861
- }
20862
- if (recallMessageUIds.length) {
20863
- this.watcher.onRecall?.(recallMessageUIds);
20864
- }
20865
- });
20866
- let normalMessages = this.handleReceiptMessages(messages);
20867
- if (normalMessages.length) {
20868
- this.watcher.batchMessage?.(normalMessages);
20869
- MessageReceiptManager$1.get()?.sendArrivalReceipts(normalMessages);
20870
- }
20871
- if (done) {
20872
- let seqNo_long;
20873
- if (seqno) {
20874
- if (Long.isLong(seqno)) {
20875
- seqNo_long = seqno;
20876
- } else if (typeof seqno === 'string') {
20877
- seqNo_long = Long.fromString(seqno);
20878
- } else if (typeof seqno === 'number') {
20879
- seqNo_long = Long.fromNumber(seqno);
20880
- }
20881
- }
20882
- if (seqNo_long && Long.isLong(seqNo_long) && seqNo_long.ge(this.serverMsgSeqno)) {
20883
- this.serverMsgSeqno = seqNo_long;
20884
- }
20885
- const isFinished = this.serverMsgSeqno.lessThanOrEqual(offset);
20886
- logger.info(`pullMsg success -> syncTime: ${offset}, finished: ${isFinished}`);
20887
- this.letterbox?.setInboxOffset(offset);
20888
- this.pullingMsg = false;
20889
- if (isFinished && !this.pullOfflineFinished) {
20890
- this.pullOfflineFinished = true;
20891
- this.watcher.pullFinished && this.watcher.pullFinished();
20892
- }
20893
- if (!isFinished) {
20894
- this.pullMsg();
20895
- }
20896
- }
20897
- });
20898
- }
20899
- handleBurnAfterReadingMessage(message) {
20900
- const content = message.content;
20901
- const conversationType = message.conversationType;
20902
- const targetId = message.targetId;
20903
- const {
20904
- templateId,
20905
- burnAfterReadingTime
20906
- } = content;
20907
- const burnAfterReadingFlag = templateId === 60010010 || templateId === 60010011;
20908
- ConversationManager$1.get().addStatus({
20909
- conversationType,
20910
- targetId,
20911
- burnAfterReadingFlag: burnAfterReadingFlag,
20912
- burnAfterReadingTime: burnAfterReadingFlag ? burnAfterReadingTime : null
20913
- }, true);
20914
- }
20915
- handleReceiptMessages(messages) {
20916
- try {
20917
- const normalMessages = [];
20918
- const receiptnotificationMessages = [];
20919
- messages.forEach(msg => {
20920
- if (msg.messageType === NotiMessageTypes.GROUP_ARRIVAL_RECEIPT || msg.messageType === NotiMessageTypes.GROUP_READ_RECEIPT || msg.messageType === NotiMessageTypes.PRIVATE_ARRIVAL_RECEIPT || msg.messageType === NotiMessageTypes.PRIVATE_READ_RECEIPT) {
20921
- receiptnotificationMessages.push(msg);
20922
- } else {
20923
- normalMessages.push(msg);
20924
- }
20925
- });
20926
- const sentMessages = normalMessages.filter(m => m.messageDirection === MessageDirection.SEND);
20927
- receiptnotificationMessages.forEach(notiMsg => {
20928
- const notiContent = notiMsg.content;
20929
- const isArrivalReceipt = notiMsg.messageType === NotiMessageTypes.GROUP_ARRIVAL_RECEIPT || notiMsg.messageType === NotiMessageTypes.PRIVATE_ARRIVAL_RECEIPT;
20930
- sentMessages.forEach(msg => {
20931
- if (notiContent.msgIdList.includes(msg.messageUId)) {
20932
- if (isArrivalReceipt) {
20933
- msg.receivedStatus = ReceivedStatus.RECEIVED;
20934
- } else {
20935
- msg.receivedStatus = ReceivedStatus.READ;
20936
- }
20937
- }
20938
- });
20939
- this.watcher.onReceiptReceived?.({
20940
- conversation: {
20941
- conversationType: notiMsg.conversationType,
20942
- targetId: notiMsg.targetId
20943
- },
20944
- messageUIdList: notiContent.msgIdList.map(id => id.toString())
20945
- }, notiMsg.messageType === NotiMessageTypes.GROUP_ARRIVAL_RECEIPT || notiMsg.messageType === NotiMessageTypes.PRIVATE_ARRIVAL_RECEIPT ? 0 : 1);
20946
- });
20947
- return normalMessages;
20948
- } catch (error) {
20949
- logger.error('handleReceiptMessages error', error);
20950
- return [];
20951
- }
20952
- }
20953
- isExistPersistedMessage(messageList) {
20954
- return messageList.some(m => m.isPersited);
20955
- }
20956
- }
20957
-
20958
- class BaseMessage {
20959
- messageType;
20960
- content;
20961
- isPersited;
20962
- isCounted;
20963
- isStatusMessage;
20964
- constructor(messageType, content, isPersited = true, isCounted = true, isStatusMessage = false) {
20965
- this.messageType = messageType;
20966
- this.content = content;
20967
- if (isStatusMessage) {
20968
- this.isPersited = false;
20969
- this.isCounted = false;
20970
- } else {
20971
- this.isPersited = isPersited;
20972
- this.isCounted = isCounted;
20973
- }
20974
- this.isStatusMessage = isStatusMessage;
20975
- }
20976
- }
20977
- const registerMessageType$1 = (messageType, isPersited, isCounted, isStatusMessage) => {
20978
- const defined = function (content) {
20979
- return new BaseMessage(messageType, content, isPersited, isCounted, isStatusMessage);
20980
- };
20981
- return defined;
20982
- };
20983
-
20984
- const TextMessage = registerMessageType$1(MessageTypes.TEXT, true, true, false);
20985
-
20986
- const ImageMessage = registerMessageType$1(MessageTypes.IMAGE, true, true, false);
20987
-
20988
- const GIFMessage = registerMessageType$1(MessageTypes.GIF, true, true, false);
20989
-
20990
- const VoiceMessage = registerMessageType$1(MessageTypes.AUDIO, true, true, false);
20991
-
20992
- const FileMessage = registerMessageType$1(MessageTypes.FILE, true, true, false);
20993
-
20994
- const VideoMessage = registerMessageType$1(MessageTypes.VIDEO, true, true, false);
20995
-
20996
- let LocationMessage = registerMessageType$1(MessageTypes.LOCATION, true, true, false);
20997
- let ChatRecordMessage = registerMessageType$1(MessageTypes.CHAT_RECORD, true, true, false);
20998
- let ContactMessage = registerMessageType$1(MessageTypes.CONTACT, true, true, false);
20999
- let InvitationMessage = registerMessageType$1(MessageTypes.GROUP_INVITATION, true, true, false);
21000
- let RedEnvelopeMessage = registerMessageType$1(MessageTypes.REDPACKET, true, true, false);
21001
- let TransferMessage = registerMessageType$1(MessageTypes.TRANSFER, true, true, false);
21002
-
21003
- const GroupArrivalReceiptMessage = registerMessageType$1(NotiMessageTypes.GROUP_ARRIVAL_RECEIPT, false, false, true);
21004
- const GroupReadReceiptMessage = registerMessageType$1(NotiMessageTypes.GROUP_READ_RECEIPT, false, false, true);
21005
- const PrivateArrivalReceiptMessage = registerMessageType$1(NotiMessageTypes.PRIVATE_ARRIVAL_RECEIPT, false, false, true);
21006
- const PrivateReadReceiptMessage = registerMessageType$1(NotiMessageTypes.PRIVATE_READ_RECEIPT, false, false, true);
21007
- const PrivateOpenBurnAfterReadingMessage = registerMessageType$1(NotiMessageTypes.PRIVATE_OPEN_BURNAFTERREADING, false, false, true);
21008
- const PrivateCloseBurnAfterReadingMessage = registerMessageType$1(NotiMessageTypes.PRIVATE_CLOSE_BURNAFTERREADING, false, false, true);
21009
- const GroupOpenBurnAfterReadingMessage = registerMessageType$1(NotiMessageTypes.GROUP_OPEN_BURNAFTERREADING, false, false, true);
21010
- const GroupCloseBurnAfterReadingMessage = registerMessageType$1(NotiMessageTypes.GROUP_CLOSE_BURNAFTERREADING, false, false, true);
21011
-
21012
- const RecallCommandMessage = registerMessageType$1(MessageTypes.RECALL, true, false, false);
21013
-
21014
20725
  class MessageCache {
21015
20726
  loadedEndMap = new Map();
21016
20727
  db = null;
@@ -21080,11 +20791,11 @@ class MessageCache {
21080
20791
  const dbName = this.getDBName();
21081
20792
  const deleteRequest = indexedDB.deleteDatabase(dbName);
21082
20793
  deleteRequest.onsuccess = () => {
21083
- logger.info(`数据库 ${dbName} 已成功删除`);
20794
+ logger.info(`Database ${dbName} successfully deleted`);
21084
20795
  resolve();
21085
20796
  };
21086
20797
  deleteRequest.onerror = event => {
21087
- logger.error(`删除数据库 ${dbName} 失败`, event);
20798
+ logger.error(`Failed to delete database ${dbName}`, event);
21088
20799
  resolve();
21089
20800
  };
21090
20801
  });
@@ -21097,8 +20808,8 @@ class MessageCache {
21097
20808
  const dbName = this.getDBName();
21098
20809
  const request = indexedDB.open(dbName, this.DB_VERSION);
21099
20810
  request.onerror = event => {
21100
- logger.error('数据库打开失败', event);
21101
- reject(new Error('数据库打开失败'));
20811
+ logger.error('Failed to open database', event);
20812
+ reject(new Error('Failed to open database'));
21102
20813
  };
21103
20814
  request.onsuccess = event => {
21104
20815
  this.db = event.target.result;
@@ -21203,7 +20914,7 @@ class MessageCache {
21203
20914
  const decryptedStr = aes256Decrypt(encryptedHex, this.encryptKey);
21204
20915
  return JSON.parse(decryptedStr);
21205
20916
  } catch (error) {
21206
- logger.error('解密消息内容失败', error);
20917
+ logger.error('Failed to decrypt message content', error);
21207
20918
  return null;
21208
20919
  }
21209
20920
  }
@@ -21233,8 +20944,8 @@ class MessageCache {
21233
20944
  resolve();
21234
20945
  };
21235
20946
  transaction.onerror = event => {
21236
- logger.error('添加消息事务失败', event);
21237
- reject(new Error('添加消息事务失败'));
20947
+ logger.error('Add message transaction failed', event);
20948
+ reject(new Error('Add message transaction failed'));
21238
20949
  };
21239
20950
  });
21240
20951
  }
@@ -21276,7 +20987,7 @@ class MessageCache {
21276
20987
  try {
21277
20988
  message.content = this.decryptContent(message.content);
21278
20989
  } catch (error) {
21279
- logger.error('解密消息内容失败', error);
20990
+ logger.error('Failed to decrypt message content', error);
21280
20991
  message.content = null;
21281
20992
  }
21282
20993
  }
@@ -21300,8 +21011,8 @@ class MessageCache {
21300
21011
  };
21301
21012
  };
21302
21013
  transaction.onerror = event => {
21303
- logger.error('获取消息事务失败', event);
21304
- reject(new Error('获取消息事务失败'));
21014
+ logger.error('Get message transaction failed', event);
21015
+ reject(new Error('Get message transaction failed'));
21305
21016
  };
21306
21017
  });
21307
21018
  }
@@ -21391,87 +21102,44 @@ class MessageCache {
21391
21102
  if (!messageUIds || messageUIds.length === 0 || !this.db) {
21392
21103
  return;
21393
21104
  }
21394
- return new Promise((resolve, reject) => {
21395
- const transaction = this.db.transaction(this.STORE_NAME, 'readwrite');
21396
- const store = transaction.objectStore(this.STORE_NAME);
21397
- let completed = 0;
21398
- let hasError = false;
21399
- messageUIds.forEach(id => {
21400
- const deleteRequest = store.delete(id);
21401
- deleteRequest.onsuccess = () => {
21402
- completed++;
21403
- if (completed === messageUIds.length && !hasError) {
21404
- resolve();
21405
- }
21406
- };
21407
- deleteRequest.onerror = event => {
21408
- logger.error('删除消息失败', id, event);
21409
- if (!hasError) {
21410
- hasError = true;
21411
- reject(new Error('删除消息失败'));
21412
- }
21413
- };
21414
- });
21415
- transaction.oncomplete = () => {
21416
- if (!hasError) {
21417
- resolve();
21105
+ const transaction = this.db.transaction(this.STORE_NAME, 'readwrite');
21106
+ const store = transaction.objectStore(this.STORE_NAME);
21107
+ const index = store.index('messageUId');
21108
+ messageUIds.forEach(messageUId => {
21109
+ const getRequest = index.get(messageUId);
21110
+ getRequest.onsuccess = () => {
21111
+ const message = getRequest.result;
21112
+ if (message) {
21113
+ store.delete(message.messageId);
21418
21114
  }
21419
21115
  };
21420
- transaction.onerror = event => {
21421
- reject(new Error('批量删除消息事务失败'));
21422
- };
21423
21116
  });
21424
21117
  }
21425
21118
  async updateMessageReceiptStatus(event, type) {
21426
21119
  if (!event || !event.messageUIdList || event.messageUIdList.length === 0 || !this.db) {
21427
21120
  return;
21428
21121
  }
21429
- const {
21430
- conversation
21431
- } = event;
21432
- getFullDialogId(conversation);
21433
- return new Promise((resolve, reject) => {
21434
- const transaction = this.db.transaction(this.STORE_NAME, 'readwrite');
21435
- const store = transaction.objectStore(this.STORE_NAME);
21436
- let completed = 0;
21437
- let hasError = false;
21438
- event.messageUIdList.forEach(id => {
21439
- const getRequest = store.get(id);
21440
- getRequest.onsuccess = () => {
21441
- const message = getRequest.result;
21442
- if (message) {
21443
- let needUpdate = false;
21444
- if (type === 0 && message.receivedStatus < ReceivedStatus.RECEIVED) {
21445
- message.receivedStatus = ReceivedStatus.RECEIVED;
21446
- needUpdate = true;
21447
- } else if (type === 1 && message.receivedStatus < ReceivedStatus.READ) {
21448
- message.receivedStatus = ReceivedStatus.READ;
21449
- needUpdate = true;
21450
- }
21451
- if (needUpdate) {
21452
- store.put(message);
21453
- }
21454
- }
21455
- completed++;
21456
- if (completed === event.messageUIdList.length && !hasError) {
21457
- resolve();
21122
+ const transaction = this.db.transaction(this.STORE_NAME, 'readwrite');
21123
+ const store = transaction.objectStore(this.STORE_NAME);
21124
+ const index = store.index('messageUId');
21125
+ event.messageUIdList.forEach(messageUId => {
21126
+ const getRequest = index.get(messageUId);
21127
+ getRequest.onsuccess = () => {
21128
+ const message = getRequest.result;
21129
+ if (message) {
21130
+ let needUpdate = false;
21131
+ if (type === 0 && message.receivedStatus < ReceivedStatus.RECEIVED) {
21132
+ message.receivedStatus = ReceivedStatus.RECEIVED;
21133
+ needUpdate = true;
21134
+ } else if (type === 1 && message.receivedStatus < ReceivedStatus.READ) {
21135
+ message.receivedStatus = ReceivedStatus.READ;
21136
+ needUpdate = true;
21458
21137
  }
21459
- };
21460
- getRequest.onerror = event => {
21461
- if (!hasError) {
21462
- hasError = true;
21463
- reject(new Error('更新消息状态失败'));
21138
+ if (needUpdate) {
21139
+ store.put(message);
21464
21140
  }
21465
- };
21466
- });
21467
- transaction.oncomplete = () => {
21468
- if (!hasError) {
21469
- resolve();
21470
21141
  }
21471
21142
  };
21472
- transaction.onerror = event => {
21473
- reject(new Error('更新消息状态事务失败'));
21474
- };
21475
21143
  });
21476
21144
  }
21477
21145
  async clearBurnAfterReadingExpiredMessages(conversation) {
@@ -21511,8 +21179,8 @@ class MessageCache {
21511
21179
  }
21512
21180
  };
21513
21181
  request.onerror = event => {
21514
- logger.error('清除过期消息失败', event);
21515
- reject(new Error('清除过期消息失败'));
21182
+ logger.error('Failed to clear expired messages', event);
21183
+ reject(new Error('Failed to clear expired messages'));
21516
21184
  };
21517
21185
  });
21518
21186
  }
@@ -21538,108 +21206,452 @@ class MessageCache {
21538
21206
  try {
21539
21207
  message.content = this.decryptContent(message.content);
21540
21208
  } catch (error) {
21541
- logger.error('解密消息内容失败', error);
21209
+ logger.error('Failed to decrypt message content', error);
21542
21210
  message.content = null;
21543
21211
  }
21544
21212
  }
21545
- resolve(message);
21546
- } else {
21547
- resolve(null);
21213
+ resolve(message);
21214
+ } else {
21215
+ resolve(null);
21216
+ }
21217
+ };
21218
+ cursorRequest.onerror = event => {
21219
+ logger.error('Failed to get latest message', event);
21220
+ resolve(null);
21221
+ };
21222
+ });
21223
+ }
21224
+ async upsertMessage(message) {
21225
+ this.addMessages([message], message);
21226
+ }
21227
+ async getMessageById(messageId) {
21228
+ if (!this.db) {
21229
+ return null;
21230
+ }
21231
+ return new Promise((resolve, reject) => {
21232
+ const transaction = this.db.transaction(this.STORE_NAME, 'readonly');
21233
+ const store = transaction.objectStore(this.STORE_NAME);
21234
+ const request = store.get(messageId);
21235
+ request.onsuccess = () => {
21236
+ const message = request.result;
21237
+ if (message) {
21238
+ const decryptedMessage = {
21239
+ ...message
21240
+ };
21241
+ if (typeof decryptedMessage.content === 'string' && decryptedMessage.content) {
21242
+ try {
21243
+ decryptedMessage.content = this.decryptContent(decryptedMessage.content);
21244
+ } catch (error) {
21245
+ logger.error('解密消息内容失败', error);
21246
+ decryptedMessage.content = null;
21247
+ }
21248
+ }
21249
+ resolve(decryptedMessage);
21250
+ } else {
21251
+ resolve(null);
21252
+ }
21253
+ };
21254
+ request.onerror = event => {
21255
+ logger.error('查询消息失败', event);
21256
+ resolve(null);
21257
+ };
21258
+ });
21259
+ }
21260
+ async getMessageIdRange() {
21261
+ if (!this.db) {
21262
+ return null;
21263
+ }
21264
+ return new Promise((resolve, reject) => {
21265
+ const transaction = this.db.transaction(this.STORE_NAME, 'readonly');
21266
+ const store = transaction.objectStore(this.STORE_NAME);
21267
+ let newest = null;
21268
+ let oldest = null;
21269
+ const oldestRequest = store.openCursor();
21270
+ oldestRequest.onsuccess = event => {
21271
+ const cursor = event.target.result;
21272
+ if (cursor) {
21273
+ oldest = cursor.value.messageId;
21274
+ const newestRequest = store.openCursor(null, 'prev');
21275
+ newestRequest.onsuccess = event => {
21276
+ const cursor = event.target.result;
21277
+ if (cursor) {
21278
+ newest = cursor.value.messageId;
21279
+ if (newest && oldest) {
21280
+ resolve({
21281
+ newest,
21282
+ oldest
21283
+ });
21284
+ } else {
21285
+ resolve(null);
21286
+ }
21287
+ } else {
21288
+ resolve(null);
21289
+ }
21290
+ };
21291
+ } else {
21292
+ resolve(null);
21293
+ }
21294
+ };
21295
+ transaction.onerror = event => {
21296
+ resolve(null);
21297
+ };
21298
+ });
21299
+ }
21300
+ async convertToRecallMessages(messageUIds) {
21301
+ if (!messageUIds || messageUIds.length === 0 || !this.db) {
21302
+ return;
21303
+ }
21304
+ const transaction = this.db.transaction(this.STORE_NAME, 'readwrite');
21305
+ const store = transaction.objectStore(this.STORE_NAME);
21306
+ const index = store.index('messageUId');
21307
+ messageUIds.forEach(messageUId => {
21308
+ const request = index.get(messageUId);
21309
+ request.onsuccess = () => {
21310
+ const message = request.result;
21311
+ if (message) {
21312
+ const recallContent = {
21313
+ messageUId: messageUId
21314
+ };
21315
+ const updatedMessage = {
21316
+ ...message,
21317
+ messageType: MessageTypes.RECALL,
21318
+ content: this.encryptContent(recallContent)
21319
+ };
21320
+ store.put(updatedMessage);
21321
+ }
21322
+ };
21323
+ });
21324
+ }
21325
+ }
21326
+ let cache;
21327
+ var MessageCache$1 = {
21328
+ create(appkey, currentUserId) {
21329
+ cache = new MessageCache(appkey, currentUserId);
21330
+ },
21331
+ get() {
21332
+ return cache;
21333
+ }
21334
+ };
21335
+
21336
+ class MessageLoader {
21337
+ watcher;
21338
+ pullingMsg = false;
21339
+ letterbox;
21340
+ serverMsgSeqno = Long.ZERO;
21341
+ pullOfflineFinished = false;
21342
+ intervalTimer;
21343
+ retryTimer;
21344
+ latestSyncTimestamp = 0;
21345
+ started = false;
21346
+ constructor(watcher, options) {
21347
+ this.watcher = watcher;
21348
+ this.letterbox = new Letterbox(options.appkey, accountStore.uid.toString());
21349
+ }
21350
+ start() {
21351
+ this.started = true;
21352
+ this.pullOfflineFinished = false;
21353
+ this.startPullInterval();
21354
+ }
21355
+ stop() {
21356
+ this.started = false;
21357
+ this.stopPullInterval();
21358
+ this.cancelRetryTask();
21359
+ }
21360
+ syncMsg(seqno) {
21361
+ this.serverMsgSeqno = seqno;
21362
+ this.pullMsg();
21363
+ }
21364
+ startPullInterval() {
21365
+ this.stopPullInterval();
21366
+ const d = 3 * 60 * 1000;
21367
+ this.intervalTimer = setInterval(() => {
21368
+ if (Date.now() - this.latestSyncTimestamp >= d) {
21369
+ this.pullMsg();
21370
+ }
21371
+ }, 30000);
21372
+ this.latestSyncTimestamp = Date.now();
21373
+ this.pullMsg();
21374
+ }
21375
+ stopPullInterval() {
21376
+ if (this.intervalTimer) {
21377
+ clearInterval(this.intervalTimer);
21378
+ this.intervalTimer = null;
21379
+ }
21380
+ }
21381
+ try2RePullMsg() {
21382
+ this.retryTimer = setTimeout(() => {
21383
+ this.retryTimer = null;
21384
+ this.pullMsg();
21385
+ }, 1000);
21386
+ }
21387
+ cancelRetryTask() {
21388
+ if (this.retryTimer) {
21389
+ clearTimeout(this.retryTimer);
21390
+ this.retryTimer = null;
21391
+ }
21392
+ }
21393
+ async pullMsg() {
21394
+ if (this.pullingMsg) {
21395
+ return;
21396
+ }
21397
+ if (!this.started) {
21398
+ return;
21399
+ }
21400
+ this.cancelRetryTask();
21401
+ this.pullingMsg = true;
21402
+ const inboxTime = this.letterbox.getInboxOffset();
21403
+ logger.info(`pullMsg -> time: ${inboxTime}`);
21404
+ this.latestSyncTimestamp = Date.now();
21405
+ const {
21406
+ code,
21407
+ data
21408
+ } = await getNewMessages(inboxTime, 60);
21409
+ if (code !== ErrorCode.SUCCESS) {
21410
+ logger.warn('pullMsg failed -> code:', code);
21411
+ this.pullingMsg = false;
21412
+ if (LibLoader.loader?.getConnectionStatus() == ConnectionStatus.CONNECTED) {
21413
+ this.try2RePullMsg();
21414
+ }
21415
+ return;
21416
+ }
21417
+ const {
21418
+ offset,
21419
+ seqno,
21420
+ msg
21421
+ } = data;
21422
+ const cons = Object.keys(msg).map(dialogId => {
21423
+ const conversationType = extractConversationType(Long.fromString(dialogId));
21424
+ return {
21425
+ conversationType,
21426
+ targetId: dialogId
21427
+ };
21428
+ });
21429
+ await ConversationManager$1.get().loadConvsationsIfNotExist(cons);
21430
+ serverMessageParser.parse(msg, (done, outputMsgs) => {
21431
+ const messages = [];
21432
+ let recallMessageUIds = [];
21433
+ const recallMessageIndexes = [];
21434
+ const isOffLineMessage = !this.pullOfflineFinished;
21435
+ outputMsgs.forEach((l, dialogId) => {
21436
+ let messageList = [];
21437
+ l.forEach(m => {
21438
+ if (m.messageType === MessageTypes.RECALL && RecallMessageStore.has(m.content.messageUId)) {
21439
+ RecallMessageStore.remove(m.content.messageUId);
21440
+ recallMessageUIds.push(m.content.messageUId);
21441
+ } else {
21442
+ m.isOffLineMessage = isOffLineMessage;
21443
+ if (!m.messageId || m.messageId > getCurrentMessageId()) {
21444
+ m.messageId = generateNewMessageId();
21445
+ }
21446
+ ConversationManager$1.get().setConversationCacheByMessage(m);
21447
+ messageList.push(m);
21448
+ if (m.messageType === MessageTypes.RECALL) {
21449
+ recallMessageIndexes.push(messageList.length - 1);
21450
+ }
21451
+ }
21452
+ if ([NotiMessageTypes.PRIVATE_OPEN_BURNAFTERREADING, NotiMessageTypes.GROUP_OPEN_BURNAFTERREADING, NotiMessageTypes.PRIVATE_CLOSE_BURNAFTERREADING, NotiMessageTypes.GROUP_CLOSE_BURNAFTERREADING].includes(m.messageType)) {
21453
+ this.handleBurnAfterReadingMessage(m);
21454
+ }
21455
+ });
21456
+ let deletedMessageIndexes = [];
21457
+ for (let i = recallMessageIndexes.length - 1; i >= 0; i--) {
21458
+ const index = recallMessageIndexes[i];
21459
+ const recallMessage = messageList[index];
21460
+ const recallContent = recallMessage.content;
21461
+ const messageIndex = messageList.findIndex(m => m.messageUId === recallContent.messageUId);
21462
+ if (messageIndex !== -1) {
21463
+ deletedMessageIndexes.push(messageIndex);
21464
+ } else {
21465
+ recallMessageUIds.push(recallContent.messageUId);
21466
+ deletedMessageIndexes.push(index);
21467
+ }
21548
21468
  }
21549
- };
21550
- cursorRequest.onerror = event => {
21551
- logger.error('获取最新消息失败', event);
21552
- resolve(null);
21553
- };
21469
+ messageList = messageList.filter((m, index) => !deletedMessageIndexes.includes(index));
21470
+ messages.push(...messageList);
21471
+ if (this.isExistPersistedMessage(messageList)) {
21472
+ splitFullDialog(dialogId);
21473
+ }
21474
+ });
21475
+ let normalMessages = this.handleReceiptMessages(messages);
21476
+ if (normalMessages.length) {
21477
+ this.handleBatchMessages(normalMessages);
21478
+ MessageReceiptManager$1.get()?.sendArrivalReceipts(normalMessages);
21479
+ }
21480
+ if (recallMessageUIds.length) {
21481
+ MessageCache$1.get()?.convertToRecallMessages(recallMessageUIds);
21482
+ this.watcher.onRecall?.(recallMessageUIds);
21483
+ }
21484
+ if (done) {
21485
+ let seqNo_long;
21486
+ if (seqno) {
21487
+ if (Long.isLong(seqno)) {
21488
+ seqNo_long = seqno;
21489
+ } else if (typeof seqno === 'string') {
21490
+ seqNo_long = Long.fromString(seqno);
21491
+ } else if (typeof seqno === 'number') {
21492
+ seqNo_long = Long.fromNumber(seqno);
21493
+ }
21494
+ }
21495
+ if (seqNo_long && Long.isLong(seqNo_long) && seqNo_long.ge(this.serverMsgSeqno)) {
21496
+ this.serverMsgSeqno = seqNo_long;
21497
+ }
21498
+ const isFinished = this.serverMsgSeqno.lessThanOrEqual(offset);
21499
+ logger.info(`pullMsg success -> syncTime: ${offset}, finished: ${isFinished}`);
21500
+ this.letterbox?.setInboxOffset(offset);
21501
+ this.pullingMsg = false;
21502
+ if (isFinished && !this.pullOfflineFinished) {
21503
+ this.pullOfflineFinished = true;
21504
+ this.watcher.pullFinished && this.watcher.pullFinished();
21505
+ }
21506
+ if (!isFinished) {
21507
+ this.pullMsg();
21508
+ }
21509
+ }
21554
21510
  });
21555
21511
  }
21556
- async upsertMessage(message) {
21557
- this.addMessages([message], message);
21512
+ handleBurnAfterReadingMessage(message) {
21513
+ const content = message.content;
21514
+ const conversationType = message.conversationType;
21515
+ const targetId = message.targetId;
21516
+ const {
21517
+ templateId,
21518
+ burnAfterReadingTime
21519
+ } = content;
21520
+ const burnAfterReadingFlag = templateId === 60010010 || templateId === 60010011;
21521
+ ConversationManager$1.get().addStatus({
21522
+ conversationType,
21523
+ targetId,
21524
+ burnAfterReadingFlag: burnAfterReadingFlag,
21525
+ burnAfterReadingTime: burnAfterReadingFlag ? burnAfterReadingTime : null
21526
+ }, true);
21558
21527
  }
21559
- async getMessageById(messageId) {
21560
- if (!this.db) {
21561
- return null;
21562
- }
21563
- return new Promise((resolve, reject) => {
21564
- const transaction = this.db.transaction(this.STORE_NAME, 'readonly');
21565
- const store = transaction.objectStore(this.STORE_NAME);
21566
- const request = store.get(messageId);
21567
- request.onsuccess = () => {
21568
- const message = request.result;
21569
- if (message) {
21570
- const decryptedMessage = {
21571
- ...message
21572
- };
21573
- if (typeof decryptedMessage.content === 'string' && decryptedMessage.content) {
21574
- try {
21575
- decryptedMessage.content = this.decryptContent(decryptedMessage.content);
21576
- } catch (error) {
21577
- logger.error('解密消息内容失败', error);
21578
- decryptedMessage.content = null;
21579
- }
21580
- }
21581
- resolve(decryptedMessage);
21528
+ handleReceiptMessages(messages) {
21529
+ try {
21530
+ const normalMessages = [];
21531
+ const receiptnotificationMessages = [];
21532
+ messages.forEach(msg => {
21533
+ if (msg.messageType === NotiMessageTypes.GROUP_ARRIVAL_RECEIPT || msg.messageType === NotiMessageTypes.GROUP_READ_RECEIPT || msg.messageType === NotiMessageTypes.PRIVATE_ARRIVAL_RECEIPT || msg.messageType === NotiMessageTypes.PRIVATE_READ_RECEIPT) {
21534
+ receiptnotificationMessages.push(msg);
21582
21535
  } else {
21583
- resolve(null);
21536
+ normalMessages.push(msg);
21584
21537
  }
21585
- };
21586
- request.onerror = event => {
21587
- logger.error('查询消息失败', event);
21588
- resolve(null);
21589
- };
21590
- });
21591
- }
21592
- async getMessageIdRange() {
21593
- if (!this.db) {
21594
- return null;
21595
- }
21596
- return new Promise((resolve, reject) => {
21597
- const transaction = this.db.transaction(this.STORE_NAME, 'readonly');
21598
- const store = transaction.objectStore(this.STORE_NAME);
21599
- let newest = null;
21600
- let oldest = null;
21601
- const oldestRequest = store.openCursor();
21602
- oldestRequest.onsuccess = event => {
21603
- const cursor = event.target.result;
21604
- if (cursor) {
21605
- oldest = cursor.value.messageId;
21606
- const newestRequest = store.openCursor(null, 'prev');
21607
- newestRequest.onsuccess = event => {
21608
- const cursor = event.target.result;
21609
- if (cursor) {
21610
- newest = cursor.value.messageId;
21611
- if (newest && oldest) {
21612
- resolve({
21613
- newest,
21614
- oldest
21615
- });
21616
- } else {
21617
- resolve(null);
21618
- }
21538
+ });
21539
+ const sentMessages = normalMessages.filter(m => m.messageDirection === MessageDirection.SEND);
21540
+ receiptnotificationMessages.forEach(notiMsg => {
21541
+ const notiContent = notiMsg.content;
21542
+ const isArrivalReceipt = notiMsg.messageType === NotiMessageTypes.GROUP_ARRIVAL_RECEIPT || notiMsg.messageType === NotiMessageTypes.PRIVATE_ARRIVAL_RECEIPT;
21543
+ sentMessages.forEach(msg => {
21544
+ if (notiContent.msgIdList.includes(msg.messageUId)) {
21545
+ if (isArrivalReceipt) {
21546
+ msg.receivedStatus = ReceivedStatus.RECEIVED;
21619
21547
  } else {
21620
- resolve(null);
21548
+ msg.receivedStatus = ReceivedStatus.READ;
21621
21549
  }
21622
- };
21623
- } else {
21624
- resolve(null);
21550
+ }
21551
+ });
21552
+ this.watcher.onReceiptReceived?.({
21553
+ conversation: {
21554
+ conversationType: notiMsg.conversationType,
21555
+ targetId: notiMsg.targetId
21556
+ },
21557
+ messageUIdList: notiContent.msgIdList.map(id => id.toString())
21558
+ }, notiMsg.messageType === NotiMessageTypes.GROUP_ARRIVAL_RECEIPT || notiMsg.messageType === NotiMessageTypes.PRIVATE_ARRIVAL_RECEIPT ? 0 : 1);
21559
+ });
21560
+ return normalMessages;
21561
+ } catch (error) {
21562
+ logger.error('handleReceiptMessages error', error);
21563
+ return [];
21564
+ }
21565
+ }
21566
+ handleBatchMessages(messages) {
21567
+ if (messages.length) {
21568
+ const targetGroups = new Map();
21569
+ messages.forEach(message => {
21570
+ if (!targetGroups.has(message.targetId)) {
21571
+ targetGroups.set(message.targetId, []);
21625
21572
  }
21626
- };
21627
- transaction.onerror = event => {
21628
- resolve(null);
21629
- };
21573
+ targetGroups.get(message.targetId).push(message);
21574
+ });
21575
+ targetGroups.forEach((targetMessages, targetId) => {
21576
+ const conversationType = targetMessages[0].conversationType;
21577
+ MessageCache$1.get()?.addMessages(targetMessages, {
21578
+ conversationType,
21579
+ targetId
21580
+ });
21581
+ });
21582
+ }
21583
+ const filteredMessages = messages.filter(m => {
21584
+ if (m.messageDirection === MessageDirection.SEND && m.messageId && SentMessageStore.has(m.messageId)) {
21585
+ SentMessageStore.remove(m.messageId);
21586
+ return false;
21587
+ }
21588
+ return true;
21630
21589
  });
21590
+ if (filteredMessages.length) {
21591
+ this.watcher.batchMessage?.(filteredMessages);
21592
+ }
21593
+ }
21594
+ isExistPersistedMessage(messageList) {
21595
+ return messageList.some(m => m.isPersited);
21631
21596
  }
21632
21597
  }
21633
- let cache;
21634
- var MessageCache$1 = {
21635
- create(appkey, currentUserId) {
21636
- cache = new MessageCache(appkey, currentUserId);
21637
- },
21638
- get() {
21639
- return cache;
21598
+
21599
+ class BaseMessage {
21600
+ messageType;
21601
+ content;
21602
+ isPersited;
21603
+ isCounted;
21604
+ isStatusMessage;
21605
+ constructor(messageType, content, isPersited = true, isCounted = true, isStatusMessage = false) {
21606
+ this.messageType = messageType;
21607
+ this.content = content;
21608
+ if (isStatusMessage) {
21609
+ this.isPersited = false;
21610
+ this.isCounted = false;
21611
+ } else {
21612
+ this.isPersited = isPersited;
21613
+ this.isCounted = isCounted;
21614
+ }
21615
+ this.isStatusMessage = isStatusMessage;
21640
21616
  }
21617
+ }
21618
+ const registerMessageType$1 = (messageType, isPersited, isCounted, isStatusMessage) => {
21619
+ const defined = function (content) {
21620
+ return new BaseMessage(messageType, content, isPersited, isCounted, isStatusMessage);
21621
+ };
21622
+ return defined;
21641
21623
  };
21642
21624
 
21625
+ const TextMessage = registerMessageType$1(MessageTypes.TEXT, true, true, false);
21626
+
21627
+ const ImageMessage = registerMessageType$1(MessageTypes.IMAGE, true, true, false);
21628
+
21629
+ const GIFMessage = registerMessageType$1(MessageTypes.GIF, true, true, false);
21630
+
21631
+ const VoiceMessage = registerMessageType$1(MessageTypes.AUDIO, true, true, false);
21632
+
21633
+ const FileMessage = registerMessageType$1(MessageTypes.FILE, true, true, false);
21634
+
21635
+ const VideoMessage = registerMessageType$1(MessageTypes.VIDEO, true, true, false);
21636
+
21637
+ let LocationMessage = registerMessageType$1(MessageTypes.LOCATION, true, true, false);
21638
+ let ChatRecordMessage = registerMessageType$1(MessageTypes.CHAT_RECORD, true, true, false);
21639
+ let ContactMessage = registerMessageType$1(MessageTypes.CONTACT, true, true, false);
21640
+ let InvitationMessage = registerMessageType$1(MessageTypes.GROUP_INVITATION, true, true, false);
21641
+ let RedEnvelopeMessage = registerMessageType$1(MessageTypes.REDPACKET, true, true, false);
21642
+ let TransferMessage = registerMessageType$1(MessageTypes.TRANSFER, true, true, false);
21643
+
21644
+ const GroupArrivalReceiptMessage = registerMessageType$1(NotiMessageTypes.GROUP_ARRIVAL_RECEIPT, false, false, true);
21645
+ const GroupReadReceiptMessage = registerMessageType$1(NotiMessageTypes.GROUP_READ_RECEIPT, false, false, true);
21646
+ const PrivateArrivalReceiptMessage = registerMessageType$1(NotiMessageTypes.PRIVATE_ARRIVAL_RECEIPT, false, false, true);
21647
+ const PrivateReadReceiptMessage = registerMessageType$1(NotiMessageTypes.PRIVATE_READ_RECEIPT, false, false, true);
21648
+ const PrivateOpenBurnAfterReadingMessage = registerMessageType$1(NotiMessageTypes.PRIVATE_OPEN_BURNAFTERREADING, false, false, true);
21649
+ const PrivateCloseBurnAfterReadingMessage = registerMessageType$1(NotiMessageTypes.PRIVATE_CLOSE_BURNAFTERREADING, false, false, true);
21650
+ const GroupOpenBurnAfterReadingMessage = registerMessageType$1(NotiMessageTypes.GROUP_OPEN_BURNAFTERREADING, false, false, true);
21651
+ const GroupCloseBurnAfterReadingMessage = registerMessageType$1(NotiMessageTypes.GROUP_CLOSE_BURNAFTERREADING, false, false, true);
21652
+
21653
+ const RecallCommandMessage = registerMessageType$1(MessageTypes.RECALL, true, false, false);
21654
+
21643
21655
  const DEFAULT_SOCKET_URI = 'wss://imweb.mp.net:6443';
21644
21656
  class LibLoader {
21645
21657
  options;
@@ -29150,34 +29162,9 @@ class IMClient extends EventEmitter {
29150
29162
  this.emit(Events.SUSPEND, this.libLoader.getConnectionStatus());
29151
29163
  },
29152
29164
  batchMessage: messages => {
29153
- if (messages.length) {
29154
- const targetGroups = new Map();
29155
- messages.forEach(message => {
29156
- if (!targetGroups.has(message.targetId)) {
29157
- targetGroups.set(message.targetId, []);
29158
- }
29159
- targetGroups.get(message.targetId).push(message);
29160
- });
29161
- targetGroups.forEach((targetMessages, targetId) => {
29162
- const conversationType = targetMessages[0].conversationType;
29163
- MessageCache$1.get()?.addMessages(targetMessages, {
29164
- conversationType,
29165
- targetId
29166
- });
29167
- });
29168
- }
29169
- const filteredMessages = messages.filter(m => {
29170
- if (m.messageDirection === MessageDirection.SEND && m.messageId && SentMessageStore.has(m.messageId)) {
29171
- SentMessageStore.remove(m.messageId);
29172
- return false;
29173
- }
29174
- return true;
29165
+ this.emit(Events.MESSAGES, {
29166
+ messages
29175
29167
  });
29176
- if (filteredMessages.length) {
29177
- this.emit(Events.MESSAGES, {
29178
- messages: filteredMessages
29179
- });
29180
- }
29181
29168
  },
29182
29169
  pullFinished: () => {
29183
29170
  this.emit(Events.PULL_OFFLINE_MESSAGE_FINISHED);
@@ -29194,7 +29181,6 @@ class IMClient extends EventEmitter {
29194
29181
  });
29195
29182
  },
29196
29183
  onRecall: messageUids => {
29197
- MessageCache$1.get()?.removeMessagesByUId(messageUids);
29198
29184
  messageUids.forEach(messageUId => {
29199
29185
  this.emit(Events.RECALL, messageUId);
29200
29186
  });