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