@amityco/ts-sdk 7.0.3-7f3fd9b.0 → 7.1.1-17d9051c.0

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 (84) hide show
  1. package/dist/@types/core/events.d.ts +2 -1
  2. package/dist/@types/core/events.d.ts.map +1 -1
  3. package/dist/@types/core/model.d.ts +2 -0
  4. package/dist/@types/core/model.d.ts.map +1 -1
  5. package/dist/@types/core/readReceipt.d.ts +12 -1
  6. package/dist/@types/core/readReceipt.d.ts.map +1 -1
  7. package/dist/@types/domains/channel.d.ts +10 -0
  8. package/dist/@types/domains/channel.d.ts.map +1 -1
  9. package/dist/@types/domains/client.d.ts +1 -0
  10. package/dist/@types/domains/client.d.ts.map +1 -1
  11. package/dist/channelRepository/api/markChannelsAsReadBySegment.d.ts +16 -0
  12. package/dist/channelRepository/api/markChannelsAsReadBySegment.d.ts.map +1 -0
  13. package/dist/channelRepository/events/onChannelDeleted.d.ts.map +1 -1
  14. package/dist/channelRepository/events/onChannelLeft.d.ts.map +1 -1
  15. package/dist/{marker → channelRepository}/events/onChannelUnreadUpdatedLocal.d.ts +2 -2
  16. package/dist/channelRepository/events/onChannelUnreadUpdatedLocal.d.ts.map +1 -0
  17. package/dist/channelRepository/internalApi/getTotalChannelsUnread.d.ts +16 -0
  18. package/dist/channelRepository/internalApi/getTotalChannelsUnread.d.ts.map +1 -0
  19. package/dist/channelRepository/observers/getChannel.d.ts.map +1 -1
  20. package/dist/channelRepository/observers/getChannels/ChannelLiveCollectionController.d.ts.map +1 -1
  21. package/dist/channelRepository/observers/getTotalChannelsUnread.d.ts +20 -0
  22. package/dist/channelRepository/observers/getTotalChannelsUnread.d.ts.map +1 -0
  23. package/dist/channelRepository/observers/index.d.ts +1 -0
  24. package/dist/channelRepository/observers/index.d.ts.map +1 -1
  25. package/dist/channelRepository/utils/constructChannelDynamicValue.d.ts.map +1 -1
  26. package/dist/channelRepository/utils/getLegacyChannelUnread.d.ts +2 -0
  27. package/dist/channelRepository/utils/getLegacyChannelUnread.d.ts.map +1 -0
  28. package/dist/channelRepository/utils/prepareChannelPayload.d.ts.map +1 -1
  29. package/dist/client/api/createClient.d.ts.map +1 -1
  30. package/dist/client/api/enableUnreadCount.d.ts.map +1 -1
  31. package/dist/client/api/login.d.ts.map +1 -1
  32. package/dist/client/utils/ReadReceiptSync/legacyReadReceiptSyncEngine.d.ts +33 -0
  33. package/dist/client/utils/ReadReceiptSync/legacyReadReceiptSyncEngine.d.ts.map +1 -0
  34. package/dist/client/utils/ReadReceiptSync/legacyReadReceiptSyncEngineOnLoginHandler.d.ts +3 -0
  35. package/dist/client/utils/ReadReceiptSync/legacyReadReceiptSyncEngineOnLoginHandler.d.ts.map +1 -0
  36. package/dist/client/utils/ReadReceiptSync/readReceiptSyncEngine.d.ts +2 -4
  37. package/dist/client/utils/ReadReceiptSync/readReceiptSyncEngine.d.ts.map +1 -1
  38. package/dist/core/events.d.ts +3 -3
  39. package/dist/core/events.d.ts.map +1 -1
  40. package/dist/core/model/idResolvers.d.ts.map +1 -1
  41. package/dist/index.cjs.js +534 -51
  42. package/dist/index.esm.js +534 -51
  43. package/dist/index.umd.js +4 -4
  44. package/dist/marker/events/onChannelUnreadInfoUpdatedLocal.d.ts +12 -0
  45. package/dist/marker/events/onChannelUnreadInfoUpdatedLocal.d.ts.map +1 -0
  46. package/dist/messageRepository/events/onMessageCreated.d.ts.map +1 -1
  47. package/dist/messageRepository/observers/getMessage.d.ts.map +1 -1
  48. package/dist/messageRepository/utils/markReadMessage.d.ts.map +1 -1
  49. package/dist/reactionRepository/api/addReaction.d.ts.map +1 -1
  50. package/dist/reactionRepository/api/removeReaction.d.ts.map +1 -1
  51. package/dist/reactionRepository/observers/getReactions/ReactionPaginationController.d.ts.map +1 -1
  52. package/package.json +1 -1
  53. package/src/@types/core/events.ts +2 -1
  54. package/src/@types/core/model.ts +4 -0
  55. package/src/@types/core/readReceipt.ts +14 -1
  56. package/src/@types/domains/channel.ts +13 -0
  57. package/src/@types/domains/client.ts +2 -0
  58. package/src/channelRepository/api/markChannelsAsReadBySegment.ts +29 -0
  59. package/src/channelRepository/events/onChannelDeleted.ts +17 -4
  60. package/src/channelRepository/events/onChannelLeft.ts +11 -3
  61. package/src/{marker → channelRepository}/events/onChannelUnreadUpdatedLocal.ts +3 -3
  62. package/src/channelRepository/internalApi/getTotalChannelsUnread.ts +43 -0
  63. package/src/channelRepository/observers/getChannel.ts +3 -1
  64. package/src/channelRepository/observers/getChannels/ChannelLiveCollectionController.ts +6 -1
  65. package/src/channelRepository/observers/getTotalChannelsUnread.ts +130 -0
  66. package/src/channelRepository/observers/index.ts +1 -0
  67. package/src/channelRepository/utils/constructChannelDynamicValue.ts +12 -2
  68. package/src/channelRepository/utils/getLegacyChannelUnread.ts +5 -0
  69. package/src/channelRepository/utils/prepareChannelPayload.ts +57 -17
  70. package/src/client/api/createClient.ts +3 -0
  71. package/src/client/api/enableUnreadCount.ts +1 -0
  72. package/src/client/api/login.ts +5 -1
  73. package/src/client/utils/ReadReceiptSync/legacyReadReceiptSyncEngine.ts +267 -0
  74. package/src/client/utils/ReadReceiptSync/legacyReadReceiptSyncEngineOnLoginHandler.ts +21 -0
  75. package/src/client/utils/ReadReceiptSync/readReceiptSyncEngine.ts +70 -99
  76. package/src/core/model/idResolvers.ts +2 -0
  77. package/src/marker/events/onChannelUnreadInfoUpdatedLocal.ts +29 -0
  78. package/src/messageRepository/events/onMessageCreated.ts +34 -0
  79. package/src/messageRepository/observers/getMessage.ts +0 -1
  80. package/src/messageRepository/utils/markReadMessage.ts +10 -3
  81. package/src/reactionRepository/api/addReaction.ts +8 -0
  82. package/src/reactionRepository/api/removeReaction.ts +8 -0
  83. package/src/reactionRepository/observers/getReactions/ReactionPaginationController.ts +8 -0
  84. package/dist/marker/events/onChannelUnreadUpdatedLocal.d.ts.map +0 -1
package/dist/index.cjs.js CHANGED
@@ -102,8 +102,8 @@ const PostContentType = Object.freeze({
102
102
 
103
103
  function getVersion() {
104
104
  try {
105
- // the string ''v7.0.2-cjs'' should be replaced by actual value by @rollup/plugin-replace
106
- return 'v7.0.2-cjs';
105
+ // the string ''v7.1.0-cjs'' should be replaced by actual value by @rollup/plugin-replace
106
+ return 'v7.1.0-cjs';
107
107
  }
108
108
  catch (error) {
109
109
  return '__dev__';
@@ -516,6 +516,7 @@ const idResolvers = {
516
516
  messagePreviewSubChannel: ({ subChannelId }) => `${subChannelId}`,
517
517
  channelUnreadInfo: ({ channelId }) => channelId,
518
518
  subChannelUnreadInfo: ({ subChannelId }) => subChannelId,
519
+ channelUnread: ({ channelId }) => channelId,
519
520
  channelMarker: ({ entityId, userId }) => `${entityId}#${userId}`,
520
521
  subChannelMarker: ({ entityId, feedId, userId }) => `${entityId}#${feedId}#${userId}`,
521
522
  messageMarker: ({ feedId, contentId, creatorId }) => `${feedId}#${contentId}#${creatorId}`,
@@ -1609,13 +1610,13 @@ class NetworkActivitiesWatcher {
1609
1610
  this._listener.clear();
1610
1611
  }
1611
1612
  }
1612
- let instance$5;
1613
+ let instance$6;
1613
1614
  var NetworkActivitiesWatcher$1 = {
1614
1615
  getInstance: () => {
1615
- if (!instance$5) {
1616
- instance$5 = new NetworkActivitiesWatcher();
1616
+ if (!instance$6) {
1617
+ instance$6 = new NetworkActivitiesWatcher();
1617
1618
  }
1618
- return instance$5;
1619
+ return instance$6;
1619
1620
  },
1620
1621
  };
1621
1622
 
@@ -5148,13 +5149,13 @@ class AnalyticsEngine {
5148
5149
  this._eventCapturer.resetAllBuckets();
5149
5150
  }
5150
5151
  }
5151
- let instance$4;
5152
+ let instance$5;
5152
5153
  var AnalyticsEngine$1 = {
5153
5154
  getInstance: () => {
5154
- if (!instance$4) {
5155
- instance$4 = new AnalyticsEngine();
5155
+ if (!instance$5) {
5156
+ instance$5 = new AnalyticsEngine();
5156
5157
  }
5157
- return instance$4;
5158
+ return instance$5;
5158
5159
  },
5159
5160
  };
5160
5161
 
@@ -5580,6 +5581,221 @@ const getMessageReadCount = (message, marker) => {
5580
5581
  getCachedMarker$2(message)) !== null && _a !== void 0 ? _a : { readCount: 0, deliveredCount: 0 };
5581
5582
  }; // and if not found in cache use default value `0`
5582
5583
 
5584
+ /**
5585
+ *
5586
+ * Mark subChannel as read by readToSegment
5587
+ *
5588
+ * @param subChannelIds the IDs of the {@link Amity.SubChannel} to update
5589
+ * @param readToSegment the segment to mark as read
5590
+ * @returns a success boolean if the {@link Amity.SubChannel} was updated
5591
+ *
5592
+ * @category Channel API
5593
+ * @async
5594
+ */
5595
+ const markChannelsAsReadBySegment = async (readings) => {
5596
+ const client = getActiveClient();
5597
+ try {
5598
+ await client.http.post('api/v3/channels/seen', { channels: readings });
5599
+ return true;
5600
+ }
5601
+ catch (e) {
5602
+ return false;
5603
+ }
5604
+ };
5605
+
5606
+ class MessageReadReceiptSyncEngine {
5607
+ constructor() {
5608
+ this.isActive = true;
5609
+ this.MAX_RETRY = 3;
5610
+ this.JOB_QUEUE_SIZE = 120;
5611
+ this.jobQueue = [];
5612
+ // Interval for message read receipt sync in seconds
5613
+ this.RECEIPT_SYNC_INTERVAL = 1;
5614
+ this.client = getActiveClient();
5615
+ // Get remaining unsync read receipts from cache
5616
+ this.getUnsyncJobs();
5617
+ }
5618
+ // Call this when client call client.login
5619
+ startSyncReadReceipt() {
5620
+ // Start timer when start receipt sync
5621
+ this.timer = setInterval(() => {
5622
+ this.syncReadReceipts();
5623
+ }, this.RECEIPT_SYNC_INTERVAL * 1000);
5624
+ }
5625
+ // Read receipt observer handling
5626
+ syncReadReceipts() {
5627
+ if (this.jobQueue.length === 0 || this.isActive === false)
5628
+ return;
5629
+ const readReceipts = this.getReadReceipts();
5630
+ if (readReceipts) {
5631
+ this.markReadApi(readReceipts);
5632
+ }
5633
+ }
5634
+ getUnsyncJobs() {
5635
+ var _a;
5636
+ // Get all read receipts that has latestSyncSegment < latestSegment
5637
+ const readReceipts = (_a = queryCache(['readReceipt'])) === null || _a === void 0 ? void 0 : _a.filter(({ data }) => {
5638
+ return data.latestSyncSegment < data.latestSegment;
5639
+ });
5640
+ // Enqueue unsync read receipts to the job queue
5641
+ readReceipts === null || readReceipts === void 0 ? void 0 : readReceipts.forEach(({ data: readReceipt }) => {
5642
+ this.enqueueReadReceipt(readReceipt.channelId, readReceipt.latestSegment);
5643
+ });
5644
+ }
5645
+ getReadReceipts() {
5646
+ // get all read receipts from queue, now the queue is empty
5647
+ const syncJob = this.jobQueue.splice(0, this.jobQueue.length);
5648
+ if (syncJob.length === 0)
5649
+ return;
5650
+ return syncJob.filter(job => {
5651
+ var _a;
5652
+ const readReceipt = (_a = pullFromCache(['readReceipt', job.channelId])) === null || _a === void 0 ? void 0 : _a.data;
5653
+ if (!readReceipt)
5654
+ return false;
5655
+ if (readReceipt.latestSegment > readReceipt.latestSyncSegment)
5656
+ return true;
5657
+ return false;
5658
+ });
5659
+ }
5660
+ async markReadApi(syncJobs) {
5661
+ var _a;
5662
+ // constuct payload
5663
+ // example: [{ channelId: 'channelId', readToSegment: 2 }]
5664
+ const syncJobsPayload = syncJobs.map(job => {
5665
+ return {
5666
+ channelId: job.channelId,
5667
+ readToSegment: job.segment,
5668
+ };
5669
+ });
5670
+ const response = await markChannelsAsReadBySegment(syncJobsPayload);
5671
+ if (response) {
5672
+ for (let i = 0; i < syncJobs.length; i += 1) {
5673
+ // update lastestSyncSegment in read receipt cache
5674
+ const cacheKey = ['readReceipt', syncJobs[i].channelId];
5675
+ const readReceiptCache = (_a = pullFromCache(cacheKey)) === null || _a === void 0 ? void 0 : _a.data;
5676
+ pushToCache(cacheKey, Object.assign(Object.assign({}, readReceiptCache), { latestSyncSegment: syncJobs[i].segment }));
5677
+ }
5678
+ }
5679
+ else {
5680
+ for (let i = 0; i < syncJobs.length; i += 1) {
5681
+ // push them back to queue if the syncing is failed and retry count is less than max retry
5682
+ if (syncJobs[i].retryCount >= this.MAX_RETRY)
5683
+ return;
5684
+ const updatedJob = Object.assign(Object.assign({}, syncJobs[i]), { syncState: "create" /* Amity.ReadReceiptSyncState.CREATED */, retryCount: syncJobs[i].retryCount + 1 });
5685
+ this.enqueueJob(updatedJob);
5686
+ }
5687
+ }
5688
+ }
5689
+ startObservingReadReceiptQueue() {
5690
+ if (this.client.useLegacyUnreadCount) {
5691
+ this.isActive = true;
5692
+ this.startSyncReadReceipt();
5693
+ }
5694
+ }
5695
+ stopObservingReadReceiptQueue() {
5696
+ this.isActive = false;
5697
+ this.jobQueue.map(job => {
5698
+ if (job.syncState === "syncing" /* Amity.ReadReceiptSyncState.SYNCING */) {
5699
+ return Object.assign(Object.assign({}, job), { syncState: "create" /* Amity.ReadReceiptSyncState.CREATED */ });
5700
+ }
5701
+ return job;
5702
+ });
5703
+ if (this.timer)
5704
+ clearInterval(this.timer);
5705
+ }
5706
+ // Session Management
5707
+ onSessionEstablished() {
5708
+ this.startObservingReadReceiptQueue();
5709
+ }
5710
+ onSessionDestroyed() {
5711
+ this.stopObservingReadReceiptQueue();
5712
+ this.jobQueue = [];
5713
+ }
5714
+ onTokenExpired() {
5715
+ this.stopObservingReadReceiptQueue();
5716
+ }
5717
+ // Network Connection Management
5718
+ onNetworkOffline() {
5719
+ // Stop observing to the read receipt queue.
5720
+ this.stopObservingReadReceiptQueue();
5721
+ }
5722
+ onNetworkOnline() {
5723
+ // Resume observing to the read receipt queue.
5724
+ this.startObservingReadReceiptQueue();
5725
+ }
5726
+ markRead(channelId, segment) {
5727
+ var _a;
5728
+ // Step 1: Optimistic update of channelUnread.readToSegment to message.segment and update unreadCount value
5729
+ const cacheKey = ['channelUnread', 'get', channelId];
5730
+ const channelUnread = (_a = pullFromCache(cacheKey)) === null || _a === void 0 ? void 0 : _a.data;
5731
+ if (channelUnread && segment > channelUnread.readToSegment) {
5732
+ channelUnread.readToSegment = segment;
5733
+ channelUnread.unreadCount = Math.max(channelUnread.lastSegment - segment, 0);
5734
+ pushToCache(cacheKey, channelUnread);
5735
+ fireEvent('local.channelUnread.updated', channelUnread);
5736
+ }
5737
+ // Step 2: Enqueue the read receipt
5738
+ this.enqueueReadReceipt(channelId, segment);
5739
+ }
5740
+ enqueueReadReceipt(channelId, segment) {
5741
+ var _a;
5742
+ const readReceipt = (_a = pullFromCache(['readReceipt', channelId])) === null || _a === void 0 ? void 0 : _a.data;
5743
+ // Create new read receipt if it's not exists and add the job to queue
5744
+ if (!readReceipt) {
5745
+ const readReceiptChannel = {
5746
+ channelId,
5747
+ latestSegment: segment,
5748
+ latestSyncSegment: 0,
5749
+ };
5750
+ pushToCache(['readReceipt', channelId], readReceiptChannel);
5751
+ }
5752
+ else if (readReceipt.latestSegment < segment) {
5753
+ // Update latestSegment in read receipt cache
5754
+ pushToCache(['readReceipt', channelId], Object.assign(Object.assign({}, readReceipt), { latestSegment: segment }));
5755
+ }
5756
+ else if (readReceipt.latestSyncSegment >= segment) {
5757
+ // Skip the job when lastSyncSegment > = segment
5758
+ return;
5759
+ }
5760
+ let syncJob = this.getSyncJob(channelId);
5761
+ if (syncJob === null || syncJob.syncState === "syncing" /* Amity.ReadReceiptSyncState.SYNCING */) {
5762
+ syncJob = {
5763
+ channelId,
5764
+ segment,
5765
+ syncState: "create" /* Amity.ReadReceiptSyncState.CREATED */,
5766
+ retryCount: 0,
5767
+ };
5768
+ this.enqueueJob(syncJob);
5769
+ }
5770
+ else if (syncJob.segment < segment) {
5771
+ syncJob.segment = segment;
5772
+ }
5773
+ }
5774
+ getSyncJob(channelId) {
5775
+ const { jobQueue } = this;
5776
+ const targetJob = jobQueue.find(job => job.channelId === channelId);
5777
+ return targetJob || null;
5778
+ }
5779
+ enqueueJob(syncJob) {
5780
+ if (this.jobQueue.length < this.JOB_QUEUE_SIZE) {
5781
+ this.jobQueue.push(syncJob);
5782
+ }
5783
+ else {
5784
+ // Remove oldest job when queue reach maximum capacity
5785
+ this.jobQueue.shift();
5786
+ this.jobQueue.push(syncJob);
5787
+ }
5788
+ }
5789
+ }
5790
+ let instance$4 = null;
5791
+ var ReadReceiptSyncEngine = {
5792
+ getInstance: () => {
5793
+ if (!instance$4)
5794
+ instance$4 = new MessageReadReceiptSyncEngine();
5795
+ return instance$4;
5796
+ },
5797
+ };
5798
+
5583
5799
  /**
5584
5800
  *
5585
5801
  * Mark subChannel as read by readToSegment
@@ -5628,7 +5844,7 @@ const reCalculateChannelUnreadInfo = (channelId) => {
5628
5844
  return channelUnreadInfo;
5629
5845
  };
5630
5846
 
5631
- class MessageReadReceiptSyncEngine {
5847
+ class LegacyMessageReadReceiptSyncEngine {
5632
5848
  constructor() {
5633
5849
  this.isActive = true;
5634
5850
  this.MAX_RETRY = 3;
@@ -5659,7 +5875,7 @@ class MessageReadReceiptSyncEngine {
5659
5875
  getUnsyncJobs() {
5660
5876
  var _a;
5661
5877
  // Get all read receipts that has latestSyncSegment < latestSegment
5662
- const readReceipts = (_a = queryCache(['readReceipt'])) === null || _a === void 0 ? void 0 : _a.filter(({ data }) => {
5878
+ const readReceipts = (_a = queryCache(['legacyReadReceipt'])) === null || _a === void 0 ? void 0 : _a.filter(({ data }) => {
5663
5879
  return data.latestSyncSegment < data.latestSegment;
5664
5880
  });
5665
5881
  // Enqueue unsync read receipts to the job queue
@@ -5678,7 +5894,7 @@ class MessageReadReceiptSyncEngine {
5678
5894
  return;
5679
5895
  // Get readReceipt from cache by subChannelId
5680
5896
  const readReceipt = (_a = pullFromCache([
5681
- 'readReceipt',
5897
+ 'legacyReadReceipt',
5682
5898
  syncJob.subChannelId,
5683
5899
  ])) === null || _a === void 0 ? void 0 : _a.data;
5684
5900
  if (!readReceipt)
@@ -5701,10 +5917,10 @@ class MessageReadReceiptSyncEngine {
5701
5917
  if (response) {
5702
5918
  this.removeSynedReceipt(syncJob.subChannelId, syncJob.segment);
5703
5919
  const readReceiptCache = (_a = pullFromCache([
5704
- 'readReceipt',
5920
+ 'legacyReadReceipt',
5705
5921
  subChannelId,
5706
5922
  ])) === null || _a === void 0 ? void 0 : _a.data;
5707
- pushToCache(['readReceipt', subChannelId], Object.assign(Object.assign({}, readReceiptCache), { latestSyncSegment: segment }));
5923
+ pushToCache(['legacyReadReceipt', subChannelId], Object.assign(Object.assign({}, readReceiptCache), { latestSyncSegment: segment }));
5708
5924
  }
5709
5925
  else if (!response) {
5710
5926
  if (newSyncJob.retryCount > this.MAX_RETRY) {
@@ -5771,7 +5987,7 @@ class MessageReadReceiptSyncEngine {
5771
5987
  subChannelUnreadInfo.readToSegment = segment;
5772
5988
  subChannelUnreadInfo.unreadCount = Math.max(subChannelUnreadInfo.lastSegment - segment, 0);
5773
5989
  const channelUnreadInfo = reCalculateChannelUnreadInfo(subChannelUnreadInfo.channelId);
5774
- fireEvent('local.channelUnread.updated', channelUnreadInfo);
5990
+ fireEvent('local.channelUnreadInfo.updated', channelUnreadInfo);
5775
5991
  pushToCache(cacheKey, subChannelUnreadInfo);
5776
5992
  fireEvent('local.subChannelUnread.updated', subChannelUnreadInfo);
5777
5993
  }
@@ -5780,7 +5996,10 @@ class MessageReadReceiptSyncEngine {
5780
5996
  }
5781
5997
  enqueueReadReceipt(subChannelId, segment) {
5782
5998
  var _a;
5783
- const readReceipt = (_a = pullFromCache(['readReceipt', subChannelId])) === null || _a === void 0 ? void 0 : _a.data;
5999
+ const readReceipt = (_a = pullFromCache([
6000
+ 'legacyReadReceipt',
6001
+ subChannelId,
6002
+ ])) === null || _a === void 0 ? void 0 : _a.data;
5784
6003
  // Create new read receipt if it's not exists and add job to queue
5785
6004
  if (!readReceipt) {
5786
6005
  const readReceiptSubChannel = {
@@ -5788,10 +6007,10 @@ class MessageReadReceiptSyncEngine {
5788
6007
  latestSegment: segment,
5789
6008
  latestSyncSegment: 0,
5790
6009
  };
5791
- pushToCache(['readReceipt', subChannelId], readReceiptSubChannel);
6010
+ pushToCache(['legacyReadReceipt', subChannelId], readReceiptSubChannel);
5792
6011
  }
5793
6012
  else if (readReceipt.latestSegment < segment) {
5794
- pushToCache(['readReceipt', subChannelId], Object.assign(Object.assign({}, readReceipt), { latestSegment: segment }));
6013
+ pushToCache(['legacyReadReceipt', subChannelId], Object.assign(Object.assign({}, readReceipt), { latestSegment: segment }));
5795
6014
  }
5796
6015
  else if (readReceipt.latestSyncSegment >= segment) {
5797
6016
  // Skip the job when lastSyncSegment > = segment
@@ -5834,18 +6053,24 @@ class MessageReadReceiptSyncEngine {
5834
6053
  }
5835
6054
  }
5836
6055
  let instance$3 = null;
5837
- var ReadReceiptSyncEngine = {
6056
+ var LegacyReadReceiptSyncEngine = {
5838
6057
  getInstance: () => {
5839
6058
  if (!instance$3)
5840
- instance$3 = new MessageReadReceiptSyncEngine();
6059
+ instance$3 = new LegacyMessageReadReceiptSyncEngine();
5841
6060
  return instance$3;
5842
6061
  },
5843
6062
  };
5844
6063
 
5845
6064
  const markReadMessage = (message) => {
5846
- const { subChannelId, channelSegment } = message;
5847
- const markReadReceiptEngine = ReadReceiptSyncEngine.getInstance();
5848
- markReadReceiptEngine.markRead(subChannelId, channelSegment);
6065
+ const client = getActiveClient();
6066
+ if (client.useLegacyUnreadCount) {
6067
+ const markReadReceiptEngine = ReadReceiptSyncEngine.getInstance();
6068
+ markReadReceiptEngine.markRead(message.channelId, message.channelSegment);
6069
+ }
6070
+ else {
6071
+ const markReadReceiptEngine = LegacyReadReceiptSyncEngine.getInstance();
6072
+ markReadReceiptEngine.markRead(message.subChannelId, message.channelSegment);
6073
+ }
5849
6074
  };
5850
6075
 
5851
6076
  const messageLinkedObject = (message) => {
@@ -6833,6 +7058,24 @@ const preUpdateChannelCache = (rawPayload, options = { isMessagePreviewUpdated:
6833
7058
  channels: rawPayload.channels.map(channel => convertFromRaw(channel, { isMessagePreviewUpdated: options.isMessagePreviewUpdated })),
6834
7059
  });
6835
7060
  };
7061
+ const updateChannelUnread = ({ currentUserId, channels, channelUsers, }) => {
7062
+ for (let i = 0; i < channels.length; i += 1) {
7063
+ const cacheKey = ['channelUnread', 'get', channels[i].channelId];
7064
+ const { readToSegment, lastMentionedSegment } = channelUsers.find(channelUser => channelUser.channelId === channels[i].channelId && channelUser.userId === currentUserId) || {
7065
+ readToSegment: 0,
7066
+ lastMentionedSegment: 0,
7067
+ };
7068
+ pushToCache(cacheKey, {
7069
+ channelId: channels[i].channelId,
7070
+ lastSegment: channels[i].messageCount,
7071
+ readToSegment,
7072
+ lastMentionedSegment,
7073
+ unreadCount: Math.max(channels[i].messageCount - readToSegment, 0),
7074
+ isMentioned: lastMentionedSegment > readToSegment,
7075
+ isDeleted: channels[i].isDeleted,
7076
+ });
7077
+ }
7078
+ };
6836
7079
  const prepareChannelPayload = async (rawPayload, options = { isMessagePreviewUpdated: true }) => {
6837
7080
  const client = getActiveClient();
6838
7081
  const networkPreviewSetting = await client.getMessagePreviewSetting(false);
@@ -6842,23 +7085,34 @@ const prepareChannelPayload = async (rawPayload, options = { isMessagePreviewUpd
6842
7085
  rawPayload.messagePreviews.length > 0) {
6843
7086
  updateChannelMessagePreviewCache(rawPayload);
6844
7087
  }
6845
- const markerIds = rawPayload.channels
6846
- // filter channel by type. Only conversation, community and broadcast type are included.
6847
- .filter(isUnreadCountSupport)
6848
- .map(({ channelInternalId }) => channelInternalId);
6849
- if (markerIds.length > 0) {
6850
- // since the get markers method requires a channel cache to function with the reducer.
6851
- preUpdateChannelCache(rawPayload, { isMessagePreviewUpdated: options.isMessagePreviewUpdated });
6852
- try {
6853
- await getChannelMarkers(markerIds);
6854
- }
6855
- catch (e) {
6856
- // empty block (from the spec, allow marker fetch to fail without having to do anything)
7088
+ if (client.useLegacyUnreadCount) {
7089
+ updateChannelUnread({
7090
+ channels: rawPayload.channels,
7091
+ channelUsers: rawPayload.channelUsers,
7092
+ currentUserId: client.userId,
7093
+ });
7094
+ }
7095
+ else {
7096
+ const markerIds = rawPayload.channels
7097
+ // filter channel by type. Only conversation, community and broadcast type are included.
7098
+ .filter(isUnreadCountSupport)
7099
+ .map(({ channelInternalId }) => channelInternalId);
7100
+ if (markerIds.length > 0) {
7101
+ // since the get markers method requires a channel cache to function with the reducer.
7102
+ preUpdateChannelCache(rawPayload, {
7103
+ isMessagePreviewUpdated: options.isMessagePreviewUpdated,
7104
+ });
7105
+ try {
7106
+ await getChannelMarkers(markerIds);
7107
+ }
7108
+ catch (e) {
7109
+ // empty block (from the spec, allow marker fetch to fail without having to do anything)
7110
+ }
6857
7111
  }
6858
7112
  }
6859
- // attach marker to channel
7113
+ // convert raw channel to internal channel
6860
7114
  const channels = rawPayload.channels.map(payload => convertFromRaw(payload, { isMessagePreviewUpdated: options.isMessagePreviewUpdated }));
6861
- // user marker to channel users
7115
+ // convert raw channel user to membership (add user object)
6862
7116
  const channelUsers = rawPayload.channelUsers.map(channelUser => {
6863
7117
  return convertRawMembershipToMembership(channelUser);
6864
7118
  });
@@ -6985,15 +7239,28 @@ const getSubChannelsUnreadCount = (channel, marker) => {
6985
7239
  return (_e = (_c = marker === null || marker === void 0 ? void 0 : marker.unreadCount) !== null && _c !== void 0 ? _c : (_d = getCachedMarker(channel.channelInternalId)) === null || _d === void 0 ? void 0 : _d.unreadCount) !== null && _e !== void 0 ? _e : 0;
6986
7240
  };
6987
7241
 
7242
+ const getLegacyChannelUnread = (channelId) => {
7243
+ var _a;
7244
+ return (_a = pullFromCache(['channelUnread', 'get', channelId])) === null || _a === void 0 ? void 0 : _a.data;
7245
+ };
7246
+
6988
7247
  const constructChannelDynamicValue = (channel) => {
7248
+ const client = getActiveClient();
6989
7249
  const rest = __rest(channel, ["messageCount"]);
6990
7250
  return shallowClone(rest, {
6991
- get isMentioned() {
6992
- return getChannelIsMentioned(rest);
7251
+ get unreadCount() {
7252
+ var _a, _b;
7253
+ return (_b = (_a = getLegacyChannelUnread(rest.channelId)) === null || _a === void 0 ? void 0 : _a.unreadCount) !== null && _b !== void 0 ? _b : 0;
6993
7254
  },
6994
7255
  get subChannelsUnreadCount() {
6995
7256
  return getSubChannelsUnreadCount(rest);
6996
7257
  },
7258
+ get isMentioned() {
7259
+ var _a, _b;
7260
+ if (client.useLegacyUnreadCount)
7261
+ return (_b = (_a = getLegacyChannelUnread(rest.channelId)) === null || _a === void 0 ? void 0 : _a.isMentioned) !== null && _b !== void 0 ? _b : false;
7262
+ return getChannelIsMentioned(rest);
7263
+ },
6997
7264
  });
6998
7265
  };
6999
7266
 
@@ -7650,12 +7917,21 @@ const onChannelDeleted = (callback) => {
7650
7917
  const client = getActiveClient();
7651
7918
  const filter = async (payload) => {
7652
7919
  const data = await prepareChannelPayload(payload);
7653
- if (client.isUnreadCountEnabled && client.getMarkerSyncConsistentMode()) {
7654
- data.channels.forEach(channel => {
7920
+ const isConsistentMode = client.getMarkerSyncConsistentMode() && client.isUnreadCountEnabled;
7921
+ const isLegacyUnreadCount = client.useLegacyUnreadCount;
7922
+ data.channels.forEach(channel => {
7923
+ if (isConsistentMode) {
7655
7924
  addFlagIsDeletedSubChannelUnreadByChannelId(channel.channelId);
7656
7925
  deleteChannelUnreadByChannelId(channel.channelId);
7657
- });
7658
- }
7926
+ }
7927
+ else if (isLegacyUnreadCount) {
7928
+ const cacheKey = ['channelUnread', 'get', channel.channelId];
7929
+ const cache = pullFromCache(cacheKey);
7930
+ if (cache) {
7931
+ pushToCache(cacheKey, Object.assign(Object.assign({}, cache), { isDeleted: true }));
7932
+ }
7933
+ }
7934
+ });
7659
7935
  ingestInCache(data);
7660
7936
  callbacks$b.forEach(cb => cb(data.channels[0]));
7661
7937
  };
@@ -7769,6 +8045,25 @@ var readReceiptSyncEngineOnLoginHandler = () => {
7769
8045
  };
7770
8046
  };
7771
8047
 
8048
+ var legacyReadReceiptSyncEngineOnLoginHandler = () => {
8049
+ const readReceiptSyncEngine = LegacyReadReceiptSyncEngine.getInstance();
8050
+ readReceiptSyncEngine.startSyncReadReceipt();
8051
+ onSessionStateChange(state => {
8052
+ if (state === "established" /* Amity.SessionStates.ESTABLISHED */) {
8053
+ readReceiptSyncEngine.onSessionEstablished();
8054
+ }
8055
+ else if (state === "tokenExpired" /* Amity.SessionStates.TOKEN_EXPIRED */) {
8056
+ readReceiptSyncEngine.onTokenExpired();
8057
+ }
8058
+ else {
8059
+ readReceiptSyncEngine.onSessionDestroyed();
8060
+ }
8061
+ });
8062
+ return () => {
8063
+ readReceiptSyncEngine.onSessionDestroyed();
8064
+ };
8065
+ };
8066
+
7772
8067
  const onOnline = (callback) => {
7773
8068
  if (typeof window !== 'undefined' && window.addEventListener) {
7774
8069
  window.addEventListener('online', callback);
@@ -8335,10 +8630,17 @@ const onChannelLeft = (callback) => {
8335
8630
  const preparedPayload = await prepareChannelPayload(payload, {
8336
8631
  isMessagePreviewUpdated: isLeftByMe,
8337
8632
  });
8338
- if (client.isUnreadCountEnabled && client.getMarkerSyncConsistentMode() && isLeftByMe) {
8633
+ const isConsistentMode = client.getMarkerSyncConsistentMode() && client.isUnreadCountEnabled;
8634
+ const isLegacyUnreadCount = client.useLegacyUnreadCount;
8635
+ if (isLeftByMe) {
8339
8636
  preparedPayload.channels.forEach(channel => {
8340
- addFlagIsDeletedSubChannelUnreadByChannelId(channel.channelId);
8341
- deleteChannelUnreadByChannelId(channel.channelId);
8637
+ if (isConsistentMode) {
8638
+ addFlagIsDeletedSubChannelUnreadByChannelId(channel.channelId);
8639
+ deleteChannelUnreadByChannelId(channel.channelId);
8640
+ }
8641
+ else if (isLegacyUnreadCount) {
8642
+ dropFromCache(['channelUnread', 'get', channel.channelId]);
8643
+ }
8342
8644
  });
8343
8645
  }
8344
8646
  const { channels, channelUsers } = preparedPayload;
@@ -8606,6 +8908,29 @@ const onMessageCreatedMqtt = (callback) => {
8606
8908
  reCalculateChannelUnreadInfo(message.channelId);
8607
8909
  });
8608
8910
  }
8911
+ if (client.useLegacyUnreadCount) {
8912
+ rawPayload.messages.forEach(message => {
8913
+ var _a, _b;
8914
+ const channelUnread = (_a = pullFromCache([
8915
+ 'channelUnread',
8916
+ 'get',
8917
+ message.channelId,
8918
+ ])) === null || _a === void 0 ? void 0 : _a.data;
8919
+ if (!channelUnread || channelUnread.lastSegment >= message.segment)
8920
+ return;
8921
+ const lastSegment = message.segment;
8922
+ const isMentionedInMessage = (_b = message.mentionedUsers) === null || _b === void 0 ? void 0 : _b.some(mention => {
8923
+ return (mention.type === 'channel' ||
8924
+ (mention.type === 'user' &&
8925
+ client.userId &&
8926
+ mention.userPublicIds.includes(client.userId)));
8927
+ });
8928
+ const lastMentionSegment = isMentionedInMessage
8929
+ ? message.segment
8930
+ : channelUnread.lastMentionSegment;
8931
+ pushToCache(['channelUnread', 'get', message.channelId], Object.assign(Object.assign({}, channelUnread), { lastSegment, unreadCount: Math.max(lastSegment - channelUnread.readToSegment, 0), lastMentionSegment, isMentioned: !(channelUnread.readToSegment >= lastMentionSegment) }));
8932
+ });
8933
+ }
8609
8934
  // Update in cache
8610
8935
  ingestInCache(payload);
8611
8936
  payload.messages.forEach(message => {
@@ -8781,6 +9106,7 @@ const enableUnreadCount = () => {
8781
9106
  if (client.isUnreadCountEnabled)
8782
9107
  return false;
8783
9108
  client.isUnreadCountEnabled = true;
9109
+ client.useLegacyUnreadCount = false;
8784
9110
  client.emitter.emit('unreadCountEnabled', true);
8785
9111
  return true;
8786
9112
  };
@@ -9096,7 +9422,12 @@ const login = async (params, sessionHandler, config) => {
9096
9422
  // NOTE: This is a temporary solution to handle the channel marker when the user is forced to leave
9097
9423
  // the channel because currently backend can't handle this, so every time a user is banned from
9098
9424
  // a channel or the channel is deleted the channel's unread count will not be reset to zero
9099
- onChannelDeleted(removeChannelMarkerCache), onChannelMemberBanned(removeChannelMarkerCache), markReadEngineOnLoginHandler(), analyticsEngineOnLoginHandler(), readReceiptSyncEngineOnLoginHandler(), objectResolverEngineOnLoginHandler());
9425
+ onChannelDeleted(removeChannelMarkerCache), onChannelMemberBanned(removeChannelMarkerCache), markReadEngineOnLoginHandler(), analyticsEngineOnLoginHandler(), objectResolverEngineOnLoginHandler());
9426
+ if (client.useLegacyUnreadCount) {
9427
+ subscriptions.push(readReceiptSyncEngineOnLoginHandler());
9428
+ }
9429
+ else
9430
+ subscriptions.push(legacyReadReceiptSyncEngineOnLoginHandler());
9100
9431
  const markerSyncUnsubscriber = await startMarkerSync();
9101
9432
  subscriptions.push(markerSyncUnsubscriber);
9102
9433
  }
@@ -9277,6 +9608,8 @@ const createClient = (apiKey, apiRegion = API_REGIONS.SG, { debugSession = DEFAU
9277
9608
  const sessionState = "notLoggedIn" /* Amity.SessionStates.NOT_LOGGED_IN */;
9278
9609
  const sessionHandler = undefined;
9279
9610
  const isUnreadCountEnabled = false;
9611
+ // Legacy unread count is true by default
9612
+ const useLegacyUnreadCount = true;
9280
9613
  const client = {
9281
9614
  version: `${VERSION}`,
9282
9615
  apiKey,
@@ -9306,6 +9639,7 @@ const createClient = (apiKey, apiRegion = API_REGIONS.SG, { debugSession = DEFAU
9306
9639
  getMessagePreviewSetting,
9307
9640
  use: () => setActiveClient(client),
9308
9641
  isUnreadCountEnabled,
9642
+ useLegacyUnreadCount,
9309
9643
  getMarkerSyncConsistentMode,
9310
9644
  /**
9311
9645
  * Prefix for the deviceId key in the local storage or async storage.
@@ -12740,6 +13074,8 @@ const addReaction = async (referenceType, referenceId, reactionName) => {
12740
13074
  referenceType,
12741
13075
  reactionName,
12742
13076
  });
13077
+ if (!['post', 'comment', 'story', 'message'].includes(referenceType))
13078
+ throw new ASCApiError('The reference type is not valid. It should be one of post, comment, story, or message', 400000 /* Amity.ServerError.BAD_REQUEST */, "error" /* Amity.ErrorLevel.ERROR */);
12743
13079
  const { data } = await client.http.post('/api/v2/reactions', {
12744
13080
  referenceId,
12745
13081
  referenceType,
@@ -12859,6 +13195,8 @@ const removeReaction = async (referenceType, referenceId, reactionName) => {
12859
13195
  referenceType,
12860
13196
  reactionName,
12861
13197
  });
13198
+ if (!['post', 'comment', 'story', 'message'].includes(referenceType))
13199
+ throw new ASCApiError('The reference type is not valid. It should be one of post, comment, story, or message', 400000 /* Amity.ServerError.BAD_REQUEST */, "error" /* Amity.ErrorLevel.ERROR */);
12862
13200
  const { data } = await client.http.delete(`/api/v2/reactions`, {
12863
13201
  data: {
12864
13202
  referenceId,
@@ -13784,6 +14122,8 @@ class ReactionPaginationController extends PaginationController {
13784
14122
  const client = getActiveClient();
13785
14123
  client.log('reaction/queryReactions', queryParams);
13786
14124
  const path = '/api/v3/reactions';
14125
+ if (!['post', 'comment', 'story', 'message'].includes(params.referenceType))
14126
+ throw new ASCApiError('The reference type is not valid. It should be one of post, comment, story, or message', 400000 /* Amity.ServerError.BAD_REQUEST */, "error" /* Amity.ErrorLevel.ERROR */);
13787
14127
  const { data: queryResponse } = await this.http.get(path, {
13788
14128
  params: Object.assign(Object.assign({}, params), { referenceVersion: REFERENCE_API_V5, // Need to put this param to make it can query reaction for message in sub-channel
13789
14129
  options }),
@@ -16433,19 +16773,37 @@ var index$f = /*#__PURE__*/Object.freeze({
16433
16773
  /**
16434
16774
  * Internal used only
16435
16775
  *
16436
- * Fired when an {@link Amity.userMessageFeedMarkers} has been resolved by Object Rsesolver
16776
+ * Fired when an {@link Amity.channelUnreadInfo} has been updated.
16437
16777
  *
16438
16778
  * @param callback The function to call when the event was fired
16439
16779
  * @returns an {@link Amity.Unsubscriber} function to stop listening
16440
16780
  *
16441
- * @category MessageMarker Events
16781
+ * @category ChannelMarker Events
16782
+ */
16783
+ const onChannelUnreadInfoUpdatedLocal = (callback) => {
16784
+ const client = getActiveClient();
16785
+ const filter = (payload) => {
16786
+ callback(payload);
16787
+ };
16788
+ return createEventSubscriber(client, 'channelMarker/onChannelUnreadInfoUpdatedLocal', 'local.channelUnreadInfo.updated', filter);
16789
+ };
16790
+
16791
+ /**
16792
+ * Internal used only
16793
+ *
16794
+ * Fired when an {@link Amity.ChannelUnread} has been updated.
16795
+ *
16796
+ * @param callback The function to call when the event was fired
16797
+ * @returns an {@link Amity.Unsubscriber} function to stop listening
16798
+ *
16799
+ * @category Channel Events
16442
16800
  */
16443
16801
  const onChannelUnreadUpdatedLocal = (callback) => {
16444
16802
  const client = getActiveClient();
16445
16803
  const filter = (payload) => {
16446
16804
  callback(payload);
16447
16805
  };
16448
- return createEventSubscriber(client, 'channelMarker/onChannelUnreadUpdatedLocal', 'local.channelUnread.updated', filter);
16806
+ return createEventSubscriber(client, 'channel/onChannelUnreadUpdatedLocal', 'local.channelUnread.updated', filter);
16449
16807
  };
16450
16808
 
16451
16809
  /* begin_public_function
@@ -16647,6 +17005,7 @@ const getChannel = (channelId, callback) => {
16647
17005
  return onSubChannelUpdated(updateMessagePreview);
16648
17006
  }, 'channelId', 'channel'),
16649
17007
  convertEventPayload(onSubChannelCreated, 'channelId', 'channel'),
17008
+ convertEventPayload(onChannelUnreadInfoUpdatedLocal, 'channelId', 'channel'),
16650
17009
  convertEventPayload(onChannelUnreadUpdatedLocal, 'channelId', 'channel'),
16651
17010
  ], {
16652
17011
  forceDispatch: true,
@@ -17160,6 +17519,10 @@ class ChannelLiveCollectionController extends LiveCollectionController {
17160
17519
  },
17161
17520
  action: "OnResolveUnread" /* Amity.ChannelActionType.OnResolveUnread */,
17162
17521
  },
17522
+ {
17523
+ fn: convertEventPayload(onChannelUnreadInfoUpdatedLocal, 'channelId', 'channel'),
17524
+ action: "onUpdate" /* Amity.ChannelActionType.OnUpdate */,
17525
+ },
17163
17526
  {
17164
17527
  fn: convertEventPayload(onChannelUnreadUpdatedLocal, 'channelId', 'channel'),
17165
17528
  action: "onUpdate" /* Amity.ChannelActionType.OnUpdate */,
@@ -17225,6 +17588,125 @@ const getChannels = (params, callback, config) => {
17225
17588
  };
17226
17589
  /* end_public_function */
17227
17590
 
17591
+ /**
17592
+ * ```js
17593
+ * import { getChannelByIds } from '@amityco/ts-sdk'
17594
+ * const channels = await getChannelByIds(['foo', 'bar'])
17595
+ * ```
17596
+ *
17597
+ * Fetches a collection of {@link Amity.Channel} objects
17598
+ *
17599
+ * @param channelIds the IDs of the {@link Amity.Channel} to fetch
17600
+ * @returns the associated collection of {@link Amity.Channel} objects
17601
+ *
17602
+ * @category Channel API
17603
+ * @async
17604
+ */
17605
+ const getTotalChannelsUnread$1 = () => {
17606
+ var _a;
17607
+ const client = getActiveClient();
17608
+ client.log('channel/getTotalChannelsUnread.locally');
17609
+ const cachedChannelsUnread = ((_a = queryCache(['channelUnread', 'get'])) === null || _a === void 0 ? void 0 : _a.filter(({ data }) => {
17610
+ return !data.isDeleted;
17611
+ })) || [];
17612
+ const totalChannelsUnread = (cachedChannelsUnread === null || cachedChannelsUnread === void 0 ? void 0 : cachedChannelsUnread.reduce((acc, { data }) => {
17613
+ acc.unreadCount += data.unreadCount;
17614
+ acc.isMentioned = acc.isMentioned || data.isMentioned;
17615
+ return acc;
17616
+ }, { unreadCount: 0, isMentioned: false })) || { unreadCount: 0, isMentioned: false };
17617
+ const cachedAt = client.cache && Date.now();
17618
+ return {
17619
+ data: totalChannelsUnread,
17620
+ cachedAt,
17621
+ };
17622
+ };
17623
+
17624
+ /* begin_public_function
17625
+ id: totalChannelsUnread.get
17626
+ */
17627
+ /**
17628
+ * ```js
17629
+ * import { ChannelRepository } from '@amityco/ts-sdk';
17630
+ *
17631
+ * let totalChannelsUnread;
17632
+ *
17633
+ * const unsubscribe = ChannelRepository.getTotalChannelsUnread(response => {
17634
+ * userUnread = response.data;
17635
+ * });
17636
+ * ```
17637
+ *
17638
+ * Observe all mutation on a given {@link Amity.UserUnread}
17639
+ *
17640
+ * @returns An {@link Amity.UserUnread} function to run when willing to stop observing the message
17641
+ *
17642
+ * @category User Unread Live Object
17643
+ *
17644
+ */
17645
+ const getTotalChannelsUnread = (callback) => {
17646
+ const { _id: userId } = getActiveUser();
17647
+ if (!userId)
17648
+ throw new ASCError('The _id has not been defined in ActiveUser', 800000 /* Amity.ClientError.UNKNOWN_ERROR */, "error" /* Amity.ErrorLevel.ERROR */);
17649
+ const { log, cache } = getActiveClient();
17650
+ if (!cache) {
17651
+ console.log('For using Live Object feature you need to enable Cache!');
17652
+ }
17653
+ const timestamp = Date.now();
17654
+ log(`liveTotalChannelsUnread(tmpid: ${timestamp}) > listen`);
17655
+ const disposers = [];
17656
+ let isUnsyncedModel = false; // for messages
17657
+ let model;
17658
+ const dispatcher = (data) => {
17659
+ const { data: userUnread } = data;
17660
+ const callbackModel = userUnread
17661
+ ? {
17662
+ unreadCount: userUnread.unreadCount,
17663
+ isMentioned: userUnread.isMentioned,
17664
+ }
17665
+ : undefined;
17666
+ model = callbackModel ? convertGetterPropsToStatic(callbackModel) : callbackModel;
17667
+ callback({
17668
+ data: callbackModel
17669
+ ? Object.assign(Object.assign({}, callbackModel), { isMentioned: callbackModel.isMentioned }) : callbackModel,
17670
+ loading: data.loading,
17671
+ error: data.error,
17672
+ });
17673
+ };
17674
+ const realtimeRouter = (userUnread) => {
17675
+ if (isEqual(model, userUnread))
17676
+ return;
17677
+ dispatcher({
17678
+ loading: false,
17679
+ data: userUnread,
17680
+ });
17681
+ };
17682
+ const onFetch = () => {
17683
+ const query = createQuery(async () => getTotalChannelsUnread$1());
17684
+ runQuery(query, ({ error, data, loading, origin, cachedAt }) => {
17685
+ if (cachedAt === UNSYNCED_OBJECT_CACHED_AT_VALUE) {
17686
+ dispatcher({
17687
+ data,
17688
+ origin,
17689
+ loading: false,
17690
+ error: new ASCApiError(UNSYNCED_OBJECT_CACHED_AT_MESSAGE, 800800 /* Amity.ClientError.DISALOOW_UNSYNCED_OBJECT */, "error" /* Amity.ErrorLevel.ERROR */),
17691
+ });
17692
+ isUnsyncedModel = true;
17693
+ disposers.forEach(fn => fn());
17694
+ }
17695
+ else if (!isUnsyncedModel) {
17696
+ dispatcher({ loading, data, origin, error });
17697
+ }
17698
+ if (error) {
17699
+ disposers.forEach(fn => fn());
17700
+ }
17701
+ });
17702
+ };
17703
+ disposers.push(onChannelUnreadUpdatedLocal(realtimeRouter));
17704
+ onFetch();
17705
+ return () => {
17706
+ disposers.forEach(fn => fn());
17707
+ };
17708
+ };
17709
+
17228
17710
  /* begin_public_function
17229
17711
  id: channel.member.add
17230
17712
  */
@@ -17828,6 +18310,7 @@ var index$c = /*#__PURE__*/Object.freeze({
17828
18310
  onChannelMemberRoleRemoved: onChannelMemberRoleRemoved,
17829
18311
  getChannel: getChannel,
17830
18312
  getChannels: getChannels,
18313
+ getTotalChannelsUnread: getTotalChannelsUnread,
17831
18314
  MARKER_INCLUDED_CHANNEL_TYPE: MARKER_INCLUDED_CHANNEL_TYPE,
17832
18315
  isUnreadCountSupport: isUnreadCountSupport,
17833
18316
  convertFromRaw: convertFromRaw,