@amityco/ts-sdk 7.1.1-1d526d8.0 → 7.1.1-279cf96.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 (87) 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 +2 -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 +11 -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 +1 -0
  30. package/dist/client/api/createClient.d.ts.map +1 -1
  31. package/dist/client/api/enableUnreadCount.d.ts.map +1 -1
  32. package/dist/client/api/login.d.ts.map +1 -1
  33. package/dist/client/utils/ReadReceiptSync/legacyReadReceiptSyncEngine.d.ts +33 -0
  34. package/dist/client/utils/ReadReceiptSync/legacyReadReceiptSyncEngine.d.ts.map +1 -0
  35. package/dist/client/utils/ReadReceiptSync/legacyReadReceiptSyncEngineOnLoginHandler.d.ts +3 -0
  36. package/dist/client/utils/ReadReceiptSync/legacyReadReceiptSyncEngineOnLoginHandler.d.ts.map +1 -0
  37. package/dist/client/utils/ReadReceiptSync/readReceiptSyncEngine.d.ts +2 -4
  38. package/dist/client/utils/ReadReceiptSync/readReceiptSyncEngine.d.ts.map +1 -1
  39. package/dist/client/utils/endpoints.d.ts +1 -0
  40. package/dist/client/utils/endpoints.d.ts.map +1 -1
  41. package/dist/client/utils/setClientToken.d.ts.map +1 -1
  42. package/dist/core/events.d.ts +3 -3
  43. package/dist/core/events.d.ts.map +1 -1
  44. package/dist/core/model/idResolvers.d.ts.map +1 -1
  45. package/dist/index.cjs.js +551 -55
  46. package/dist/index.esm.js +551 -55
  47. package/dist/index.umd.js +4 -4
  48. package/dist/marker/events/onChannelUnreadInfoUpdatedLocal.d.ts +12 -0
  49. package/dist/marker/events/onChannelUnreadInfoUpdatedLocal.d.ts.map +1 -0
  50. package/dist/messageRepository/events/onMessageCreated.d.ts.map +1 -1
  51. package/dist/messageRepository/observers/getMessage.d.ts.map +1 -1
  52. package/dist/messageRepository/utils/markReadMessage.d.ts.map +1 -1
  53. package/package.json +1 -1
  54. package/src/@types/core/events.ts +2 -1
  55. package/src/@types/core/model.ts +4 -0
  56. package/src/@types/core/readReceipt.ts +14 -1
  57. package/src/@types/domains/channel.ts +13 -0
  58. package/src/@types/domains/client.ts +3 -0
  59. package/src/channelRepository/api/markChannelsAsReadBySegment.ts +29 -0
  60. package/src/channelRepository/events/onChannelDeleted.ts +17 -4
  61. package/src/channelRepository/events/onChannelLeft.ts +11 -3
  62. package/src/{marker → channelRepository}/events/onChannelUnreadUpdatedLocal.ts +3 -3
  63. package/src/channelRepository/internalApi/getTotalChannelsUnread.ts +38 -0
  64. package/src/channelRepository/observers/getChannel.ts +3 -1
  65. package/src/channelRepository/observers/getChannels/ChannelLiveCollectionController.ts +6 -1
  66. package/src/channelRepository/observers/getTotalChannelsUnread.ts +129 -0
  67. package/src/channelRepository/observers/index.ts +1 -0
  68. package/src/channelRepository/utils/constructChannelDynamicValue.ts +12 -2
  69. package/src/channelRepository/utils/getLegacyChannelUnread.ts +5 -0
  70. package/src/channelRepository/utils/prepareChannelPayload.ts +66 -17
  71. package/src/client/api/createClient.ts +7 -1
  72. package/src/client/api/enableUnreadCount.ts +1 -0
  73. package/src/client/api/login.ts +5 -1
  74. package/src/client/utils/ReadReceiptSync/legacyReadReceiptSyncEngine.ts +267 -0
  75. package/src/client/utils/ReadReceiptSync/legacyReadReceiptSyncEngineOnLoginHandler.ts +21 -0
  76. package/src/client/utils/ReadReceiptSync/readReceiptSyncEngine.ts +74 -99
  77. package/src/client/utils/endpoints.ts +1 -0
  78. package/src/client/utils/setClientToken.ts +8 -0
  79. package/src/core/model/idResolvers.ts +2 -0
  80. package/src/fileRepository/api/uploadFile.ts +1 -1
  81. package/src/fileRepository/api/uploadImage.ts +1 -1
  82. package/src/fileRepository/api/uploadVideo.ts +1 -1
  83. package/src/marker/events/onChannelUnreadInfoUpdatedLocal.ts +29 -0
  84. package/src/messageRepository/events/onMessageCreated.ts +45 -1
  85. package/src/messageRepository/observers/getMessage.ts +0 -1
  86. package/src/messageRepository/utils/markReadMessage.ts +10 -3
  87. package/dist/marker/events/onChannelUnreadUpdatedLocal.d.ts.map +0 -1
package/dist/index.esm.js CHANGED
@@ -501,6 +501,7 @@ const idResolvers = {
501
501
  messagePreviewSubChannel: ({ subChannelId }) => `${subChannelId}`,
502
502
  channelUnreadInfo: ({ channelId }) => channelId,
503
503
  subChannelUnreadInfo: ({ subChannelId }) => subChannelId,
504
+ channelUnread: ({ channelId }) => channelId,
504
505
  channelMarker: ({ entityId, userId }) => `${entityId}#${userId}`,
505
506
  subChannelMarker: ({ entityId, feedId, userId }) => `${entityId}#${feedId}#${userId}`,
506
507
  messageMarker: ({ feedId, contentId, creatorId }) => `${feedId}#${contentId}#${creatorId}`,
@@ -1546,6 +1547,7 @@ const API_REGIONS = {
1546
1547
  };
1547
1548
  const URLS = {
1548
1549
  http: 'https://apix.{region}.amity.co',
1550
+ upload: 'https://upload.{region}.amity.co',
1549
1551
  mqtt: 'wss://sse.{region}.amity.co:443/mqtt',
1550
1552
  };
1551
1553
  function computeUrl(type, region) {
@@ -1594,13 +1596,13 @@ class NetworkActivitiesWatcher {
1594
1596
  this._listener.clear();
1595
1597
  }
1596
1598
  }
1597
- let instance$5;
1599
+ let instance$6;
1598
1600
  var NetworkActivitiesWatcher$1 = {
1599
1601
  getInstance: () => {
1600
- if (!instance$5) {
1601
- instance$5 = new NetworkActivitiesWatcher();
1602
+ if (!instance$6) {
1603
+ instance$6 = new NetworkActivitiesWatcher();
1602
1604
  }
1603
- return instance$5;
1605
+ return instance$6;
1604
1606
  },
1605
1607
  };
1606
1608
 
@@ -21240,13 +21242,13 @@ class AnalyticsEngine {
21240
21242
  this._eventCapturer.resetAllBuckets();
21241
21243
  }
21242
21244
  }
21243
- let instance$4;
21245
+ let instance$5;
21244
21246
  var AnalyticsEngine$1 = {
21245
21247
  getInstance: () => {
21246
- if (!instance$4) {
21247
- instance$4 = new AnalyticsEngine();
21248
+ if (!instance$5) {
21249
+ instance$5 = new AnalyticsEngine();
21248
21250
  }
21249
- return instance$4;
21251
+ return instance$5;
21250
21252
  },
21251
21253
  };
21252
21254
 
@@ -21672,6 +21674,223 @@ const getMessageReadCount = (message, marker) => {
21672
21674
  getCachedMarker$2(message)) !== null && _a !== void 0 ? _a : { readCount: 0, deliveredCount: 0 };
21673
21675
  }; // and if not found in cache use default value `0`
21674
21676
 
21677
+ /**
21678
+ *
21679
+ * Mark subChannel as read by readToSegment
21680
+ *
21681
+ * @param subChannelIds the IDs of the {@link Amity.SubChannel} to update
21682
+ * @param readToSegment the segment to mark as read
21683
+ * @returns a success boolean if the {@link Amity.SubChannel} was updated
21684
+ *
21685
+ * @category Channel API
21686
+ * @async
21687
+ */
21688
+ const markChannelsAsReadBySegment = async (readings) => {
21689
+ const client = getActiveClient();
21690
+ try {
21691
+ await client.http.post('api/v3/channels/seen', { channels: readings });
21692
+ return true;
21693
+ }
21694
+ catch (e) {
21695
+ return false;
21696
+ }
21697
+ };
21698
+
21699
+ class MessageReadReceiptSyncEngine {
21700
+ constructor() {
21701
+ this.isActive = true;
21702
+ this.MAX_RETRY = 3;
21703
+ this.JOB_QUEUE_SIZE = 120;
21704
+ this.jobQueue = [];
21705
+ // Interval for message read receipt sync in seconds
21706
+ this.RECEIPT_SYNC_INTERVAL = 1;
21707
+ this.client = getActiveClient();
21708
+ // Get remaining unsync read receipts from cache
21709
+ this.getUnsyncJobs();
21710
+ }
21711
+ // Call this when client call client.login
21712
+ startSyncReadReceipt() {
21713
+ // Start timer when start receipt sync
21714
+ this.timer = setInterval(() => {
21715
+ this.syncReadReceipts();
21716
+ }, this.RECEIPT_SYNC_INTERVAL * 1000);
21717
+ }
21718
+ // Read receipt observer handling
21719
+ syncReadReceipts() {
21720
+ if (this.jobQueue.length === 0 || this.isActive === false)
21721
+ return;
21722
+ const readReceipts = this.getReadReceipts();
21723
+ if (readReceipts) {
21724
+ this.markReadApi(readReceipts);
21725
+ }
21726
+ }
21727
+ getUnsyncJobs() {
21728
+ var _a;
21729
+ // Get all read receipts that has latestSyncSegment < latestSegment
21730
+ const readReceipts = (_a = queryCache(['readReceipt'])) === null || _a === void 0 ? void 0 : _a.filter(({ data }) => {
21731
+ return data.latestSyncSegment < data.latestSegment;
21732
+ });
21733
+ // Enqueue unsync read receipts to the job queue
21734
+ readReceipts === null || readReceipts === void 0 ? void 0 : readReceipts.forEach(({ data: readReceipt }) => {
21735
+ this.enqueueReadReceipt(readReceipt.channelId, readReceipt.latestSegment);
21736
+ });
21737
+ }
21738
+ getReadReceipts() {
21739
+ // get all read receipts from queue, now the queue is empty
21740
+ const syncJob = this.jobQueue.splice(0, this.jobQueue.length);
21741
+ if (syncJob.length === 0)
21742
+ return;
21743
+ return syncJob.filter(job => {
21744
+ var _a;
21745
+ const readReceipt = (_a = pullFromCache(['readReceipt', job.channelId])) === null || _a === void 0 ? void 0 : _a.data;
21746
+ if (!readReceipt)
21747
+ return false;
21748
+ if (readReceipt.latestSegment > readReceipt.latestSyncSegment)
21749
+ return true;
21750
+ return false;
21751
+ });
21752
+ }
21753
+ async markReadApi(syncJobs) {
21754
+ var _a;
21755
+ // constuct payload
21756
+ // example: [{ channelId: 'channelId', readToSegment: 2 }]
21757
+ const syncJobsPayload = syncJobs.map(job => {
21758
+ return {
21759
+ channelId: job.channelId,
21760
+ readToSegment: job.segment,
21761
+ };
21762
+ });
21763
+ const response = await markChannelsAsReadBySegment(syncJobsPayload);
21764
+ if (response) {
21765
+ for (let i = 0; i < syncJobs.length; i += 1) {
21766
+ // update lastestSyncSegment in read receipt cache
21767
+ const cacheKey = ['readReceipt', syncJobs[i].channelId];
21768
+ const readReceiptCache = (_a = pullFromCache(cacheKey)) === null || _a === void 0 ? void 0 : _a.data;
21769
+ pushToCache(cacheKey, Object.assign(Object.assign({}, readReceiptCache), { latestSyncSegment: syncJobs[i].segment }));
21770
+ }
21771
+ }
21772
+ else {
21773
+ for (let i = 0; i < syncJobs.length; i += 1) {
21774
+ // push them back to queue if the syncing is failed and retry count is less than max retry
21775
+ if (syncJobs[i].retryCount >= this.MAX_RETRY)
21776
+ return;
21777
+ const updatedJob = Object.assign(Object.assign({}, syncJobs[i]), { syncState: "create" /* Amity.ReadReceiptSyncState.CREATED */, retryCount: syncJobs[i].retryCount + 1 });
21778
+ this.enqueueJob(updatedJob);
21779
+ }
21780
+ }
21781
+ }
21782
+ startObservingReadReceiptQueue() {
21783
+ if (this.client.useLegacyUnreadCount) {
21784
+ this.isActive = true;
21785
+ this.startSyncReadReceipt();
21786
+ }
21787
+ }
21788
+ stopObservingReadReceiptQueue() {
21789
+ this.isActive = false;
21790
+ this.jobQueue.map(job => {
21791
+ if (job.syncState === "syncing" /* Amity.ReadReceiptSyncState.SYNCING */) {
21792
+ return Object.assign(Object.assign({}, job), { syncState: "create" /* Amity.ReadReceiptSyncState.CREATED */ });
21793
+ }
21794
+ return job;
21795
+ });
21796
+ if (this.timer)
21797
+ clearInterval(this.timer);
21798
+ }
21799
+ // Session Management
21800
+ onSessionEstablished() {
21801
+ this.startObservingReadReceiptQueue();
21802
+ }
21803
+ onSessionDestroyed() {
21804
+ this.stopObservingReadReceiptQueue();
21805
+ this.jobQueue = [];
21806
+ }
21807
+ onTokenExpired() {
21808
+ this.stopObservingReadReceiptQueue();
21809
+ }
21810
+ // Network Connection Management
21811
+ onNetworkOffline() {
21812
+ // Stop observing to the read receipt queue.
21813
+ this.stopObservingReadReceiptQueue();
21814
+ }
21815
+ onNetworkOnline() {
21816
+ // Resume observing to the read receipt queue.
21817
+ this.startObservingReadReceiptQueue();
21818
+ }
21819
+ markRead(channelId, segment) {
21820
+ var _a;
21821
+ // Step 1: Optimistic update of channelUnread.readToSegment to message.segment and update unreadCount value
21822
+ const cacheKey = ['channelUnread', 'get', channelId];
21823
+ const channelUnread = (_a = pullFromCache(cacheKey)) === null || _a === void 0 ? void 0 : _a.data;
21824
+ if (typeof (channelUnread === null || channelUnread === void 0 ? void 0 : channelUnread.readToSegment) === 'number' &&
21825
+ channelUnread &&
21826
+ segment > channelUnread.readToSegment) {
21827
+ channelUnread.readToSegment = segment;
21828
+ channelUnread.unreadCount = Math.max(channelUnread.lastSegment - segment, 0);
21829
+ pushToCache(cacheKey, channelUnread);
21830
+ fireEvent('local.channelUnread.updated', channelUnread);
21831
+ }
21832
+ // Step 2: Enqueue the read receipt
21833
+ this.enqueueReadReceipt(channelId, segment);
21834
+ }
21835
+ enqueueReadReceipt(channelId, segment) {
21836
+ var _a;
21837
+ const readReceipt = (_a = pullFromCache(['readReceipt', channelId])) === null || _a === void 0 ? void 0 : _a.data;
21838
+ // Create new read receipt if it's not exists and add the job to queue
21839
+ if (!readReceipt) {
21840
+ const readReceiptChannel = {
21841
+ channelId,
21842
+ latestSegment: segment,
21843
+ latestSyncSegment: 0,
21844
+ };
21845
+ pushToCache(['readReceipt', channelId], readReceiptChannel);
21846
+ }
21847
+ else if (readReceipt.latestSegment < segment) {
21848
+ // Update latestSegment in read receipt cache
21849
+ pushToCache(['readReceipt', channelId], Object.assign(Object.assign({}, readReceipt), { latestSegment: segment }));
21850
+ }
21851
+ else if (readReceipt.latestSyncSegment >= segment) {
21852
+ // Skip the job when lastSyncSegment > = segment
21853
+ return;
21854
+ }
21855
+ let syncJob = this.getSyncJob(channelId);
21856
+ if (syncJob === null || syncJob.syncState === "syncing" /* Amity.ReadReceiptSyncState.SYNCING */) {
21857
+ syncJob = {
21858
+ channelId,
21859
+ segment,
21860
+ syncState: "create" /* Amity.ReadReceiptSyncState.CREATED */,
21861
+ retryCount: 0,
21862
+ };
21863
+ this.enqueueJob(syncJob);
21864
+ }
21865
+ else if (syncJob.segment < segment) {
21866
+ syncJob.segment = segment;
21867
+ }
21868
+ }
21869
+ getSyncJob(channelId) {
21870
+ const { jobQueue } = this;
21871
+ const targetJob = jobQueue.find(job => job.channelId === channelId);
21872
+ return targetJob || null;
21873
+ }
21874
+ enqueueJob(syncJob) {
21875
+ if (this.jobQueue.length < this.JOB_QUEUE_SIZE) {
21876
+ this.jobQueue.push(syncJob);
21877
+ }
21878
+ else {
21879
+ // Remove oldest job when queue reach maximum capacity
21880
+ this.jobQueue.shift();
21881
+ this.jobQueue.push(syncJob);
21882
+ }
21883
+ }
21884
+ }
21885
+ let instance$4 = null;
21886
+ var ReadReceiptSyncEngine = {
21887
+ getInstance: () => {
21888
+ if (!instance$4)
21889
+ instance$4 = new MessageReadReceiptSyncEngine();
21890
+ return instance$4;
21891
+ },
21892
+ };
21893
+
21675
21894
  /**
21676
21895
  *
21677
21896
  * Mark subChannel as read by readToSegment
@@ -21720,7 +21939,7 @@ const reCalculateChannelUnreadInfo = (channelId) => {
21720
21939
  return channelUnreadInfo;
21721
21940
  };
21722
21941
 
21723
- class MessageReadReceiptSyncEngine {
21942
+ class LegacyMessageReadReceiptSyncEngine {
21724
21943
  constructor() {
21725
21944
  this.isActive = true;
21726
21945
  this.MAX_RETRY = 3;
@@ -21751,7 +21970,7 @@ class MessageReadReceiptSyncEngine {
21751
21970
  getUnsyncJobs() {
21752
21971
  var _a;
21753
21972
  // Get all read receipts that has latestSyncSegment < latestSegment
21754
- const readReceipts = (_a = queryCache(['readReceipt'])) === null || _a === void 0 ? void 0 : _a.filter(({ data }) => {
21973
+ const readReceipts = (_a = queryCache(['legacyReadReceipt'])) === null || _a === void 0 ? void 0 : _a.filter(({ data }) => {
21755
21974
  return data.latestSyncSegment < data.latestSegment;
21756
21975
  });
21757
21976
  // Enqueue unsync read receipts to the job queue
@@ -21770,7 +21989,7 @@ class MessageReadReceiptSyncEngine {
21770
21989
  return;
21771
21990
  // Get readReceipt from cache by subChannelId
21772
21991
  const readReceipt = (_a = pullFromCache([
21773
- 'readReceipt',
21992
+ 'legacyReadReceipt',
21774
21993
  syncJob.subChannelId,
21775
21994
  ])) === null || _a === void 0 ? void 0 : _a.data;
21776
21995
  if (!readReceipt)
@@ -21793,10 +22012,10 @@ class MessageReadReceiptSyncEngine {
21793
22012
  if (response) {
21794
22013
  this.removeSynedReceipt(syncJob.subChannelId, syncJob.segment);
21795
22014
  const readReceiptCache = (_a = pullFromCache([
21796
- 'readReceipt',
22015
+ 'legacyReadReceipt',
21797
22016
  subChannelId,
21798
22017
  ])) === null || _a === void 0 ? void 0 : _a.data;
21799
- pushToCache(['readReceipt', subChannelId], Object.assign(Object.assign({}, readReceiptCache), { latestSyncSegment: segment }));
22018
+ pushToCache(['legacyReadReceipt', subChannelId], Object.assign(Object.assign({}, readReceiptCache), { latestSyncSegment: segment }));
21800
22019
  }
21801
22020
  else if (!response) {
21802
22021
  if (newSyncJob.retryCount > this.MAX_RETRY) {
@@ -21863,7 +22082,7 @@ class MessageReadReceiptSyncEngine {
21863
22082
  subChannelUnreadInfo.readToSegment = segment;
21864
22083
  subChannelUnreadInfo.unreadCount = Math.max(subChannelUnreadInfo.lastSegment - segment, 0);
21865
22084
  const channelUnreadInfo = reCalculateChannelUnreadInfo(subChannelUnreadInfo.channelId);
21866
- fireEvent('local.channelUnread.updated', channelUnreadInfo);
22085
+ fireEvent('local.channelUnreadInfo.updated', channelUnreadInfo);
21867
22086
  pushToCache(cacheKey, subChannelUnreadInfo);
21868
22087
  fireEvent('local.subChannelUnread.updated', subChannelUnreadInfo);
21869
22088
  }
@@ -21872,7 +22091,10 @@ class MessageReadReceiptSyncEngine {
21872
22091
  }
21873
22092
  enqueueReadReceipt(subChannelId, segment) {
21874
22093
  var _a;
21875
- const readReceipt = (_a = pullFromCache(['readReceipt', subChannelId])) === null || _a === void 0 ? void 0 : _a.data;
22094
+ const readReceipt = (_a = pullFromCache([
22095
+ 'legacyReadReceipt',
22096
+ subChannelId,
22097
+ ])) === null || _a === void 0 ? void 0 : _a.data;
21876
22098
  // Create new read receipt if it's not exists and add job to queue
21877
22099
  if (!readReceipt) {
21878
22100
  const readReceiptSubChannel = {
@@ -21880,10 +22102,10 @@ class MessageReadReceiptSyncEngine {
21880
22102
  latestSegment: segment,
21881
22103
  latestSyncSegment: 0,
21882
22104
  };
21883
- pushToCache(['readReceipt', subChannelId], readReceiptSubChannel);
22105
+ pushToCache(['legacyReadReceipt', subChannelId], readReceiptSubChannel);
21884
22106
  }
21885
22107
  else if (readReceipt.latestSegment < segment) {
21886
- pushToCache(['readReceipt', subChannelId], Object.assign(Object.assign({}, readReceipt), { latestSegment: segment }));
22108
+ pushToCache(['legacyReadReceipt', subChannelId], Object.assign(Object.assign({}, readReceipt), { latestSegment: segment }));
21887
22109
  }
21888
22110
  else if (readReceipt.latestSyncSegment >= segment) {
21889
22111
  // Skip the job when lastSyncSegment > = segment
@@ -21926,18 +22148,24 @@ class MessageReadReceiptSyncEngine {
21926
22148
  }
21927
22149
  }
21928
22150
  let instance$3 = null;
21929
- var ReadReceiptSyncEngine = {
22151
+ var LegacyReadReceiptSyncEngine = {
21930
22152
  getInstance: () => {
21931
22153
  if (!instance$3)
21932
- instance$3 = new MessageReadReceiptSyncEngine();
22154
+ instance$3 = new LegacyMessageReadReceiptSyncEngine();
21933
22155
  return instance$3;
21934
22156
  },
21935
22157
  };
21936
22158
 
21937
22159
  const markReadMessage = (message) => {
21938
- const { subChannelId, channelSegment } = message;
21939
- const markReadReceiptEngine = ReadReceiptSyncEngine.getInstance();
21940
- markReadReceiptEngine.markRead(subChannelId, channelSegment);
22160
+ const client = getActiveClient();
22161
+ if (client.useLegacyUnreadCount) {
22162
+ const markReadReceiptEngine = ReadReceiptSyncEngine.getInstance();
22163
+ markReadReceiptEngine.markRead(message.channelId, message.channelSegment);
22164
+ }
22165
+ else {
22166
+ const markReadReceiptEngine = LegacyReadReceiptSyncEngine.getInstance();
22167
+ markReadReceiptEngine.markRead(message.subChannelId, message.channelSegment);
22168
+ }
21941
22169
  };
21942
22170
 
21943
22171
  const messageLinkedObject = (message) => {
@@ -22925,6 +23153,31 @@ const preUpdateChannelCache = (rawPayload, options = { isMessagePreviewUpdated:
22925
23153
  channels: rawPayload.channels.map(channel => convertFromRaw(channel, { isMessagePreviewUpdated: options.isMessagePreviewUpdated })),
22926
23154
  });
22927
23155
  };
23156
+ const updateChannelUnread = ({ currentUserId, channels, channelUsers, }) => {
23157
+ for (let i = 0; i < channels.length; i += 1) {
23158
+ const cacheKey = ['channelUnread', 'get', channels[i].channelId];
23159
+ const channelUser = channelUsers.find(channelUser => channelUser.channelId === channels[i].channelId && channelUser.userId === currentUserId);
23160
+ let unreadCount = 0;
23161
+ let readToSegment = null;
23162
+ let lastMentionedSegment = null;
23163
+ let isMentioned = false;
23164
+ if (channelUser) {
23165
+ readToSegment = channelUser.readToSegment;
23166
+ lastMentionedSegment = channelUser.lastMentionedSegment;
23167
+ unreadCount = Math.max(channels[i].messageCount - readToSegment, 0);
23168
+ isMentioned = lastMentionedSegment > readToSegment;
23169
+ }
23170
+ pushToCache(cacheKey, {
23171
+ channelId: channels[i].channelId,
23172
+ lastSegment: channels[i].messageCount,
23173
+ readToSegment,
23174
+ lastMentionedSegment,
23175
+ unreadCount,
23176
+ isMentioned,
23177
+ isDeleted: channels[i].isDeleted,
23178
+ });
23179
+ }
23180
+ };
22928
23181
  const prepareChannelPayload = async (rawPayload, options = { isMessagePreviewUpdated: true }) => {
22929
23182
  const client = getActiveClient();
22930
23183
  const networkPreviewSetting = await client.getMessagePreviewSetting(false);
@@ -22934,23 +23187,34 @@ const prepareChannelPayload = async (rawPayload, options = { isMessagePreviewUpd
22934
23187
  rawPayload.messagePreviews.length > 0) {
22935
23188
  updateChannelMessagePreviewCache(rawPayload);
22936
23189
  }
22937
- const markerIds = rawPayload.channels
22938
- // filter channel by type. Only conversation, community and broadcast type are included.
22939
- .filter(isUnreadCountSupport)
22940
- .map(({ channelInternalId }) => channelInternalId);
22941
- if (markerIds.length > 0) {
22942
- // since the get markers method requires a channel cache to function with the reducer.
22943
- preUpdateChannelCache(rawPayload, { isMessagePreviewUpdated: options.isMessagePreviewUpdated });
22944
- try {
22945
- await getChannelMarkers(markerIds);
22946
- }
22947
- catch (e) {
22948
- // empty block (from the spec, allow marker fetch to fail without having to do anything)
23190
+ if (client.useLegacyUnreadCount) {
23191
+ updateChannelUnread({
23192
+ channels: rawPayload.channels,
23193
+ channelUsers: rawPayload.channelUsers,
23194
+ currentUserId: client.userId,
23195
+ });
23196
+ }
23197
+ else {
23198
+ const markerIds = rawPayload.channels
23199
+ // filter channel by type. Only conversation, community and broadcast type are included.
23200
+ .filter(isUnreadCountSupport)
23201
+ .map(({ channelInternalId }) => channelInternalId);
23202
+ if (markerIds.length > 0) {
23203
+ // since the get markers method requires a channel cache to function with the reducer.
23204
+ preUpdateChannelCache(rawPayload, {
23205
+ isMessagePreviewUpdated: options.isMessagePreviewUpdated,
23206
+ });
23207
+ try {
23208
+ await getChannelMarkers(markerIds);
23209
+ }
23210
+ catch (e) {
23211
+ // empty block (from the spec, allow marker fetch to fail without having to do anything)
23212
+ }
22949
23213
  }
22950
23214
  }
22951
- // attach marker to channel
23215
+ // convert raw channel to internal channel
22952
23216
  const channels = rawPayload.channels.map(payload => convertFromRaw(payload, { isMessagePreviewUpdated: options.isMessagePreviewUpdated }));
22953
- // user marker to channel users
23217
+ // convert raw channel user to membership (add user object)
22954
23218
  const channelUsers = rawPayload.channelUsers.map(channelUser => {
22955
23219
  return convertRawMembershipToMembership(channelUser);
22956
23220
  });
@@ -23077,15 +23341,28 @@ const getSubChannelsUnreadCount = (channel, marker) => {
23077
23341
  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;
23078
23342
  };
23079
23343
 
23344
+ const getLegacyChannelUnread = (channelId) => {
23345
+ var _a;
23346
+ return (_a = pullFromCache(['channelUnread', 'get', channelId])) === null || _a === void 0 ? void 0 : _a.data;
23347
+ };
23348
+
23080
23349
  const constructChannelDynamicValue = (channel) => {
23350
+ const client = getActiveClient();
23081
23351
  const rest = __rest(channel, ["messageCount"]);
23082
23352
  return shallowClone(rest, {
23083
- get isMentioned() {
23084
- return getChannelIsMentioned(rest);
23353
+ get unreadCount() {
23354
+ var _a, _b;
23355
+ return (_b = (_a = getLegacyChannelUnread(rest.channelId)) === null || _a === void 0 ? void 0 : _a.unreadCount) !== null && _b !== void 0 ? _b : 0;
23085
23356
  },
23086
23357
  get subChannelsUnreadCount() {
23087
23358
  return getSubChannelsUnreadCount(rest);
23088
23359
  },
23360
+ get isMentioned() {
23361
+ var _a, _b;
23362
+ if (client.useLegacyUnreadCount)
23363
+ return (_b = (_a = getLegacyChannelUnread(rest.channelId)) === null || _a === void 0 ? void 0 : _a.isMentioned) !== null && _b !== void 0 ? _b : false;
23364
+ return getChannelIsMentioned(rest);
23365
+ },
23089
23366
  });
23090
23367
  };
23091
23368
 
@@ -23698,6 +23975,12 @@ const setClientToken = async (params) => {
23698
23975
  isGlobalBanned: false,
23699
23976
  isUserDeleted: false,
23700
23977
  };
23978
+ client.upload.defaults.headers.common.Authorization = `Bearer ${accessToken}`;
23979
+ client.upload.defaults.metadata = {
23980
+ tokenExpiry: expiresAt,
23981
+ isGlobalBanned: false,
23982
+ isUserDeleted: false,
23983
+ };
23701
23984
  // manually setup the token for ws transport
23702
23985
  if (client.ws)
23703
23986
  client.ws.io.opts.query = { token: accessToken };
@@ -23742,12 +24025,21 @@ const onChannelDeleted = (callback) => {
23742
24025
  const client = getActiveClient();
23743
24026
  const filter = async (payload) => {
23744
24027
  const data = await prepareChannelPayload(payload);
23745
- if (client.isUnreadCountEnabled && client.getMarkerSyncConsistentMode()) {
23746
- data.channels.forEach(channel => {
24028
+ const isConsistentMode = client.getMarkerSyncConsistentMode() && client.isUnreadCountEnabled;
24029
+ const isLegacyUnreadCount = client.useLegacyUnreadCount;
24030
+ data.channels.forEach(channel => {
24031
+ if (isConsistentMode) {
23747
24032
  addFlagIsDeletedSubChannelUnreadByChannelId(channel.channelId);
23748
24033
  deleteChannelUnreadByChannelId(channel.channelId);
23749
- });
23750
- }
24034
+ }
24035
+ else if (isLegacyUnreadCount) {
24036
+ const cacheKey = ['channelUnread', 'get', channel.channelId];
24037
+ const cache = pullFromCache(cacheKey);
24038
+ if (cache) {
24039
+ pushToCache(cacheKey, Object.assign(Object.assign({}, cache), { isDeleted: true }));
24040
+ }
24041
+ }
24042
+ });
23751
24043
  ingestInCache(data);
23752
24044
  callbacks$b.forEach(cb => cb(data.channels[0]));
23753
24045
  };
@@ -23861,6 +24153,25 @@ var readReceiptSyncEngineOnLoginHandler = () => {
23861
24153
  };
23862
24154
  };
23863
24155
 
24156
+ var legacyReadReceiptSyncEngineOnLoginHandler = () => {
24157
+ const readReceiptSyncEngine = LegacyReadReceiptSyncEngine.getInstance();
24158
+ readReceiptSyncEngine.startSyncReadReceipt();
24159
+ onSessionStateChange(state => {
24160
+ if (state === "established" /* Amity.SessionStates.ESTABLISHED */) {
24161
+ readReceiptSyncEngine.onSessionEstablished();
24162
+ }
24163
+ else if (state === "tokenExpired" /* Amity.SessionStates.TOKEN_EXPIRED */) {
24164
+ readReceiptSyncEngine.onTokenExpired();
24165
+ }
24166
+ else {
24167
+ readReceiptSyncEngine.onSessionDestroyed();
24168
+ }
24169
+ });
24170
+ return () => {
24171
+ readReceiptSyncEngine.onSessionDestroyed();
24172
+ };
24173
+ };
24174
+
23864
24175
  const onOnline = (callback) => {
23865
24176
  if (typeof window !== 'undefined' && window.addEventListener) {
23866
24177
  window.addEventListener('online', callback);
@@ -24427,10 +24738,17 @@ const onChannelLeft = (callback) => {
24427
24738
  const preparedPayload = await prepareChannelPayload(payload, {
24428
24739
  isMessagePreviewUpdated: isLeftByMe,
24429
24740
  });
24430
- if (client.isUnreadCountEnabled && client.getMarkerSyncConsistentMode() && isLeftByMe) {
24741
+ const isConsistentMode = client.getMarkerSyncConsistentMode() && client.isUnreadCountEnabled;
24742
+ const isLegacyUnreadCount = client.useLegacyUnreadCount;
24743
+ if (isLeftByMe) {
24431
24744
  preparedPayload.channels.forEach(channel => {
24432
- addFlagIsDeletedSubChannelUnreadByChannelId(channel.channelId);
24433
- deleteChannelUnreadByChannelId(channel.channelId);
24745
+ if (isConsistentMode) {
24746
+ addFlagIsDeletedSubChannelUnreadByChannelId(channel.channelId);
24747
+ deleteChannelUnreadByChannelId(channel.channelId);
24748
+ }
24749
+ else if (isLegacyUnreadCount) {
24750
+ dropFromCache(['channelUnread', 'get', channel.channelId]);
24751
+ }
24434
24752
  });
24435
24753
  }
24436
24754
  const { channels, channelUsers } = preparedPayload;
@@ -24698,6 +25016,34 @@ const onMessageCreatedMqtt = (callback) => {
24698
25016
  reCalculateChannelUnreadInfo(message.channelId);
24699
25017
  });
24700
25018
  }
25019
+ if (client.useLegacyUnreadCount) {
25020
+ rawPayload.messages.forEach(message => {
25021
+ var _a, _b;
25022
+ const channelUnread = (_a = pullFromCache([
25023
+ 'channelUnread',
25024
+ 'get',
25025
+ message.channelId,
25026
+ ])) === null || _a === void 0 ? void 0 : _a.data;
25027
+ if (!channelUnread ||
25028
+ channelUnread.lastSegment >= message.segment ||
25029
+ typeof channelUnread.readToSegment !== 'number' ||
25030
+ typeof channelUnread.lastMentionSegment !== 'number')
25031
+ return;
25032
+ const lastSegment = message.segment;
25033
+ const isMentionedInMessage = (_b = message.mentionedUsers) === null || _b === void 0 ? void 0 : _b.some(mention => {
25034
+ return (mention.type === 'channel' ||
25035
+ (mention.type === 'user' &&
25036
+ client.userId &&
25037
+ mention.userPublicIds.includes(client.userId)));
25038
+ });
25039
+ const lastMentionSegment = isMentionedInMessage
25040
+ ? message.segment
25041
+ : channelUnread.lastMentionSegment;
25042
+ const updatedChannelUnread = Object.assign(Object.assign({}, channelUnread), { lastSegment, unreadCount: Math.max(lastSegment - channelUnread.readToSegment, 0), lastMentionSegment, isMentioned: !(channelUnread.readToSegment >= lastMentionSegment) });
25043
+ pushToCache(['channelUnread', 'get', message.channelId], updatedChannelUnread);
25044
+ fireEvent('local.channelUnread.updated', updatedChannelUnread);
25045
+ });
25046
+ }
24701
25047
  // Update in cache
24702
25048
  ingestInCache(payload);
24703
25049
  payload.messages.forEach(message => {
@@ -24873,6 +25219,7 @@ const enableUnreadCount = () => {
24873
25219
  if (client.isUnreadCountEnabled)
24874
25220
  return false;
24875
25221
  client.isUnreadCountEnabled = true;
25222
+ client.useLegacyUnreadCount = false;
24876
25223
  client.emitter.emit('unreadCountEnabled', true);
24877
25224
  return true;
24878
25225
  };
@@ -25188,7 +25535,12 @@ const login = async (params, sessionHandler, config) => {
25188
25535
  // NOTE: This is a temporary solution to handle the channel marker when the user is forced to leave
25189
25536
  // the channel because currently backend can't handle this, so every time a user is banned from
25190
25537
  // a channel or the channel is deleted the channel's unread count will not be reset to zero
25191
- onChannelDeleted(removeChannelMarkerCache), onChannelMemberBanned(removeChannelMarkerCache), markReadEngineOnLoginHandler(), analyticsEngineOnLoginHandler(), readReceiptSyncEngineOnLoginHandler(), objectResolverEngineOnLoginHandler());
25538
+ onChannelDeleted(removeChannelMarkerCache), onChannelMemberBanned(removeChannelMarkerCache), markReadEngineOnLoginHandler(), analyticsEngineOnLoginHandler(), objectResolverEngineOnLoginHandler());
25539
+ if (client.useLegacyUnreadCount) {
25540
+ subscriptions.push(readReceiptSyncEngineOnLoginHandler());
25541
+ }
25542
+ else
25543
+ subscriptions.push(legacyReadReceiptSyncEngineOnLoginHandler());
25192
25544
  const markerSyncUnsubscriber = await startMarkerSync();
25193
25545
  subscriptions.push(markerSyncUnsubscriber);
25194
25546
  }
@@ -25346,15 +25698,17 @@ const DEFAULT_DEBUG_SESSION = 'amity';
25346
25698
  * @category Client API
25347
25699
  * */
25348
25700
  const createClient = (apiKey, apiRegion = API_REGIONS.SG, { debugSession = DEFAULT_DEBUG_SESSION, apiEndpoint, prefixDeviceIdKey, rteEnabled = true, } = {}) => {
25349
- var _a, _b;
25701
+ var _a, _b, _c;
25350
25702
  const log = createLogger(debugSession);
25351
25703
  log('client/api/createClient', {
25352
25704
  apiKey: apiKey.replace(/.{5}$/g, 'xxxxx'),
25353
25705
  apiRegion,
25354
25706
  });
25355
25707
  const httpEndpoint = (_a = apiEndpoint === null || apiEndpoint === void 0 ? void 0 : apiEndpoint.http) !== null && _a !== void 0 ? _a : computeUrl('http', apiRegion);
25356
- const mqttEndpoint = (_b = apiEndpoint === null || apiEndpoint === void 0 ? void 0 : apiEndpoint.mqtt) !== null && _b !== void 0 ? _b : computeUrl('mqtt', apiRegion);
25708
+ const uploadEndpoint = (_b = apiEndpoint === null || apiEndpoint === void 0 ? void 0 : apiEndpoint.upload) !== null && _b !== void 0 ? _b : computeUrl('upload', apiRegion);
25709
+ const mqttEndpoint = (_c = apiEndpoint === null || apiEndpoint === void 0 ? void 0 : apiEndpoint.mqtt) !== null && _c !== void 0 ? _c : computeUrl('mqtt', apiRegion);
25357
25710
  const http = createHttpTransport(httpEndpoint);
25711
+ const upload = createHttpTransport(uploadEndpoint);
25358
25712
  let ws;
25359
25713
  let mqtt;
25360
25714
  if (rteEnabled) {
@@ -25369,6 +25723,8 @@ const createClient = (apiKey, apiRegion = API_REGIONS.SG, { debugSession = DEFAU
25369
25723
  const sessionState = "notLoggedIn" /* Amity.SessionStates.NOT_LOGGED_IN */;
25370
25724
  const sessionHandler = undefined;
25371
25725
  const isUnreadCountEnabled = false;
25726
+ // Legacy unread count is true by default
25727
+ const useLegacyUnreadCount = true;
25372
25728
  const client = {
25373
25729
  version: `${VERSION}`,
25374
25730
  apiKey,
@@ -25383,6 +25739,7 @@ const createClient = (apiKey, apiRegion = API_REGIONS.SG, { debugSession = DEFAU
25383
25739
  http,
25384
25740
  ws,
25385
25741
  mqtt,
25742
+ upload,
25386
25743
  emitter,
25387
25744
  /*
25388
25745
  * Session Components
@@ -25398,6 +25755,7 @@ const createClient = (apiKey, apiRegion = API_REGIONS.SG, { debugSession = DEFAU
25398
25755
  getMessagePreviewSetting,
25399
25756
  use: () => setActiveClient(client),
25400
25757
  isUnreadCountEnabled,
25758
+ useLegacyUnreadCount,
25401
25759
  getMarkerSyncConsistentMode,
25402
25760
  /**
25403
25761
  * Prefix for the deviceId key in the local storage or async storage.
@@ -25411,7 +25769,7 @@ const createClient = (apiKey, apiRegion = API_REGIONS.SG, { debugSession = DEFAU
25411
25769
  return activeClient;
25412
25770
  setActiveClient(client);
25413
25771
  }
25414
- catch (_c) {
25772
+ catch (_d) {
25415
25773
  setActiveClient(client);
25416
25774
  }
25417
25775
  return client;
@@ -28200,7 +28558,7 @@ const uploadFile = async (formData, onProgress) => {
28200
28558
  const headers = 'getHeaders' in formData
28201
28559
  ? formData.getHeaders()
28202
28560
  : { 'content-type': 'multipart/form-data' };
28203
- const { data } = await client.http.post('/api/v4/files', formData, {
28561
+ const { data } = await client.upload.post('/api/v4/files', formData, {
28204
28562
  headers,
28205
28563
  onUploadProgress({ loaded, total = 100 }) {
28206
28564
  onProgress && onProgress(Math.round((loaded * 100) / total));
@@ -28290,7 +28648,7 @@ const uploadVideo = async (formData, feedType, onProgress) => {
28290
28648
  const headers = 'getHeaders' in formData
28291
28649
  ? formData.getHeaders()
28292
28650
  : { 'content-type': 'multipart/form-data' };
28293
- const { data } = await client.http.post('/api/v4/videos', formData, {
28651
+ const { data } = await client.upload.post('/api/v4/videos', formData, {
28294
28652
  headers,
28295
28653
  onUploadProgress({ loaded, total = 100 }) {
28296
28654
  onProgress && onProgress(Math.round((loaded * 100) / total));
@@ -28338,7 +28696,7 @@ const uploadImage = async (formData, onProgress) => {
28338
28696
  const headers = 'getHeaders' in formData
28339
28697
  ? formData.getHeaders()
28340
28698
  : { 'content-type': 'multipart/form-data' };
28341
- const { data } = await client.http.post('/api/v4/images', formData, {
28699
+ const { data } = await client.upload.post('/api/v4/images', formData, {
28342
28700
  headers,
28343
28701
  onUploadProgress({ loaded, total = 100 }) {
28344
28702
  onProgress && onProgress(Math.round((loaded * 100) / total));
@@ -32531,19 +32889,37 @@ var index$f = /*#__PURE__*/Object.freeze({
32531
32889
  /**
32532
32890
  * Internal used only
32533
32891
  *
32534
- * Fired when an {@link Amity.userMessageFeedMarkers} has been resolved by Object Rsesolver
32892
+ * Fired when an {@link Amity.channelUnreadInfo} has been updated.
32535
32893
  *
32536
32894
  * @param callback The function to call when the event was fired
32537
32895
  * @returns an {@link Amity.Unsubscriber} function to stop listening
32538
32896
  *
32539
- * @category MessageMarker Events
32897
+ * @category ChannelMarker Events
32898
+ */
32899
+ const onChannelUnreadInfoUpdatedLocal = (callback) => {
32900
+ const client = getActiveClient();
32901
+ const filter = (payload) => {
32902
+ callback(payload);
32903
+ };
32904
+ return createEventSubscriber(client, 'channelMarker/onChannelUnreadInfoUpdatedLocal', 'local.channelUnreadInfo.updated', filter);
32905
+ };
32906
+
32907
+ /**
32908
+ * Internal used only
32909
+ *
32910
+ * Fired when an {@link Amity.ChannelUnread} has been updated.
32911
+ *
32912
+ * @param callback The function to call when the event was fired
32913
+ * @returns an {@link Amity.Unsubscriber} function to stop listening
32914
+ *
32915
+ * @category Channel Events
32540
32916
  */
32541
32917
  const onChannelUnreadUpdatedLocal = (callback) => {
32542
32918
  const client = getActiveClient();
32543
32919
  const filter = (payload) => {
32544
32920
  callback(payload);
32545
32921
  };
32546
- return createEventSubscriber(client, 'channelMarker/onChannelUnreadUpdatedLocal', 'local.channelUnread.updated', filter);
32922
+ return createEventSubscriber(client, 'channel/onChannelUnreadUpdatedLocal', 'local.channelUnread.updated', filter);
32547
32923
  };
32548
32924
 
32549
32925
  /* begin_public_function
@@ -32745,6 +33121,7 @@ const getChannel = (channelId, callback) => {
32745
33121
  return onSubChannelUpdated(updateMessagePreview);
32746
33122
  }, 'channelId', 'channel'),
32747
33123
  convertEventPayload(onSubChannelCreated, 'channelId', 'channel'),
33124
+ convertEventPayload(onChannelUnreadInfoUpdatedLocal, 'channelId', 'channel'),
32748
33125
  convertEventPayload(onChannelUnreadUpdatedLocal, 'channelId', 'channel'),
32749
33126
  ], {
32750
33127
  forceDispatch: true,
@@ -33258,6 +33635,10 @@ class ChannelLiveCollectionController extends LiveCollectionController {
33258
33635
  },
33259
33636
  action: "OnResolveUnread" /* Amity.ChannelActionType.OnResolveUnread */,
33260
33637
  },
33638
+ {
33639
+ fn: convertEventPayload(onChannelUnreadInfoUpdatedLocal, 'channelId', 'channel'),
33640
+ action: "onUpdate" /* Amity.ChannelActionType.OnUpdate */,
33641
+ },
33261
33642
  {
33262
33643
  fn: convertEventPayload(onChannelUnreadUpdatedLocal, 'channelId', 'channel'),
33263
33644
  action: "onUpdate" /* Amity.ChannelActionType.OnUpdate */,
@@ -33323,6 +33704,120 @@ const getChannels = (params, callback, config) => {
33323
33704
  };
33324
33705
  /* end_public_function */
33325
33706
 
33707
+ /**
33708
+ *
33709
+ * Calculate user unread from {@link Amity.ChannelUnread} objects
33710
+ *
33711
+ * @returns the {@link Amity.UserUnread} objects
33712
+ *
33713
+ * @category Channel API
33714
+ * @async
33715
+ */
33716
+ const getTotalChannelsUnread$1 = () => {
33717
+ var _a;
33718
+ const client = getActiveClient();
33719
+ client.log('channel/getTotalChannelsUnread.locally');
33720
+ const cachedChannelsUnread = ((_a = queryCache(['channelUnread', 'get'])) === null || _a === void 0 ? void 0 : _a.filter(({ data }) => {
33721
+ return !data.isDeleted;
33722
+ })) || [];
33723
+ const totalChannelsUnread = (cachedChannelsUnread === null || cachedChannelsUnread === void 0 ? void 0 : cachedChannelsUnread.reduce((acc, { data }) => {
33724
+ acc.unreadCount += data.unreadCount;
33725
+ acc.isMentioned = acc.isMentioned || data.isMentioned;
33726
+ return acc;
33727
+ }, { unreadCount: 0, isMentioned: false })) || { unreadCount: 0, isMentioned: false };
33728
+ const cachedAt = client.cache && Date.now();
33729
+ return {
33730
+ data: totalChannelsUnread,
33731
+ cachedAt,
33732
+ };
33733
+ };
33734
+
33735
+ /* begin_public_function
33736
+ id: totalChannelsUnread.get
33737
+ */
33738
+ /**
33739
+ * ```js
33740
+ * import { ChannelRepository } from '@amityco/ts-sdk';
33741
+ *
33742
+ * let totalChannelsUnread;
33743
+ *
33744
+ * const unsubscribe = ChannelRepository.getTotalChannelsUnread(response => {
33745
+ * unread = response.data;
33746
+ * });
33747
+ * ```
33748
+ *
33749
+ * Observe all mutation on a given {@link Amity.UserUnread}
33750
+ *
33751
+ * @returns An {@link Amity.UserUnread} function to run when willing to stop observing the message
33752
+ *
33753
+ * @category User Unread Live Object
33754
+ *
33755
+ */
33756
+ const getTotalChannelsUnread = (callback) => {
33757
+ const { _id: userId } = getActiveUser();
33758
+ if (!userId)
33759
+ throw new ASCError('The _id has not been defined in ActiveUser', 800000 /* Amity.ClientError.UNKNOWN_ERROR */, "error" /* Amity.ErrorLevel.ERROR */);
33760
+ const { log, cache } = getActiveClient();
33761
+ if (!cache) {
33762
+ console.log('For using Live Object feature you need to enable Cache!');
33763
+ }
33764
+ const timestamp = Date.now();
33765
+ log(`liveTotalChannelsUnread(tmpid: ${timestamp}) > listen`);
33766
+ const disposers = [];
33767
+ let isUnsyncedModel = false; // for messages
33768
+ let model;
33769
+ const dispatcher = (data) => {
33770
+ const { data: userUnread } = data;
33771
+ const callbackModel = userUnread
33772
+ ? {
33773
+ unreadCount: userUnread.unreadCount,
33774
+ isMentioned: userUnread.isMentioned,
33775
+ }
33776
+ : undefined;
33777
+ model = callbackModel ? convertGetterPropsToStatic(callbackModel) : callbackModel;
33778
+ callback({
33779
+ data: callbackModel
33780
+ ? Object.assign(Object.assign({}, callbackModel), { isMentioned: callbackModel.isMentioned }) : callbackModel,
33781
+ loading: data.loading,
33782
+ error: data.error,
33783
+ });
33784
+ };
33785
+ const realtimeRouter = (userUnread) => {
33786
+ if (isEqual(model, userUnread))
33787
+ return;
33788
+ dispatcher({
33789
+ loading: false,
33790
+ data: userUnread,
33791
+ });
33792
+ };
33793
+ const onFetch = () => {
33794
+ const query = createQuery(async () => getTotalChannelsUnread$1());
33795
+ runQuery(query, ({ error, data, loading, origin, cachedAt }) => {
33796
+ if (cachedAt === UNSYNCED_OBJECT_CACHED_AT_VALUE) {
33797
+ dispatcher({
33798
+ data,
33799
+ origin,
33800
+ loading: false,
33801
+ error: new ASCApiError(UNSYNCED_OBJECT_CACHED_AT_MESSAGE, 800800 /* Amity.ClientError.DISALOOW_UNSYNCED_OBJECT */, "error" /* Amity.ErrorLevel.ERROR */),
33802
+ });
33803
+ isUnsyncedModel = true;
33804
+ disposers.forEach(fn => fn());
33805
+ }
33806
+ else if (!isUnsyncedModel) {
33807
+ dispatcher({ loading, data, origin, error });
33808
+ }
33809
+ if (error) {
33810
+ disposers.forEach(fn => fn());
33811
+ }
33812
+ });
33813
+ };
33814
+ disposers.push(onChannelUnreadUpdatedLocal(realtimeRouter));
33815
+ onFetch();
33816
+ return () => {
33817
+ disposers.forEach(fn => fn());
33818
+ };
33819
+ };
33820
+
33326
33821
  /* begin_public_function
33327
33822
  id: channel.member.add
33328
33823
  */
@@ -33926,6 +34421,7 @@ var index$c = /*#__PURE__*/Object.freeze({
33926
34421
  onChannelMemberRoleRemoved: onChannelMemberRoleRemoved,
33927
34422
  getChannel: getChannel,
33928
34423
  getChannels: getChannels,
34424
+ getTotalChannelsUnread: getTotalChannelsUnread,
33929
34425
  MARKER_INCLUDED_CHANNEL_TYPE: MARKER_INCLUDED_CHANNEL_TYPE,
33930
34426
  isUnreadCountSupport: isUnreadCountSupport,
33931
34427
  convertFromRaw: convertFromRaw,