@amityco/ts-sdk 7.1.1-1d526d8.0 → 7.1.1-c8d4edca.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.
- package/dist/@types/core/events.d.ts +2 -1
- package/dist/@types/core/events.d.ts.map +1 -1
- package/dist/@types/core/model.d.ts +2 -0
- package/dist/@types/core/model.d.ts.map +1 -1
- package/dist/@types/core/readReceipt.d.ts +12 -1
- package/dist/@types/core/readReceipt.d.ts.map +1 -1
- package/dist/@types/domains/channel.d.ts +9 -0
- package/dist/@types/domains/channel.d.ts.map +1 -1
- package/dist/@types/domains/client.d.ts +1 -0
- package/dist/@types/domains/client.d.ts.map +1 -1
- package/dist/channelRepository/api/markChannelsAsReadBySegment.d.ts +16 -0
- package/dist/channelRepository/api/markChannelsAsReadBySegment.d.ts.map +1 -0
- package/dist/channelRepository/events/onChannelUnreadUpdatedLocal.d.ts +12 -0
- package/dist/channelRepository/events/onChannelUnreadUpdatedLocal.d.ts.map +1 -0
- package/dist/channelRepository/observers/getChannel.d.ts.map +1 -1
- package/dist/channelRepository/observers/getChannels/ChannelLiveCollectionController.d.ts.map +1 -1
- package/dist/channelRepository/utils/constructChannelDynamicValue.d.ts.map +1 -1
- package/dist/channelRepository/utils/getLegacyChannelUnread.d.ts +2 -0
- package/dist/channelRepository/utils/getLegacyChannelUnread.d.ts.map +1 -0
- package/dist/channelRepository/utils/prepareChannelPayload.d.ts.map +1 -1
- package/dist/client/api/createClient.d.ts.map +1 -1
- package/dist/client/api/enableUnreadCount.d.ts.map +1 -1
- package/dist/client/api/login.d.ts.map +1 -1
- package/dist/client/utils/ReadReceiptSync/legacyReadReceiptSyncEngine.d.ts +33 -0
- package/dist/client/utils/ReadReceiptSync/legacyReadReceiptSyncEngine.d.ts.map +1 -0
- package/dist/client/utils/ReadReceiptSync/legacyReadReceiptSyncEngineOnLoginHandler.d.ts +3 -0
- package/dist/client/utils/ReadReceiptSync/legacyReadReceiptSyncEngineOnLoginHandler.d.ts.map +1 -0
- package/dist/client/utils/ReadReceiptSync/readReceiptSyncEngine.d.ts +2 -4
- package/dist/client/utils/ReadReceiptSync/readReceiptSyncEngine.d.ts.map +1 -1
- package/dist/core/events.d.ts +3 -3
- package/dist/core/events.d.ts.map +1 -1
- package/dist/core/model/idResolvers.d.ts.map +1 -1
- package/dist/index.cjs.js +360 -40
- package/dist/index.esm.js +360 -40
- package/dist/index.umd.js +4 -4
- package/dist/marker/events/onChannelUnreadInfoUpdatedLocal.d.ts +12 -0
- package/dist/marker/events/onChannelUnreadInfoUpdatedLocal.d.ts.map +1 -0
- package/dist/messageRepository/utils/markReadMessage.d.ts.map +1 -1
- package/package.json +1 -1
- package/src/@types/core/events.ts +2 -1
- package/src/@types/core/model.ts +4 -0
- package/src/@types/core/readReceipt.ts +14 -1
- package/src/@types/domains/channel.ts +11 -0
- package/src/@types/domains/client.ts +2 -0
- package/src/channelRepository/api/markChannelsAsReadBySegment.ts +29 -0
- package/src/channelRepository/events/onChannelUnreadUpdatedLocal.ts +29 -0
- package/src/channelRepository/observers/getChannel.ts +3 -1
- package/src/channelRepository/observers/getChannels/ChannelLiveCollectionController.ts +6 -1
- package/src/channelRepository/utils/constructChannelDynamicValue.ts +12 -2
- package/src/channelRepository/utils/getLegacyChannelUnread.ts +5 -0
- package/src/channelRepository/utils/prepareChannelPayload.ts +57 -17
- package/src/client/api/createClient.ts +3 -0
- package/src/client/api/enableUnreadCount.ts +1 -0
- package/src/client/api/login.ts +5 -1
- package/src/client/utils/ReadReceiptSync/legacyReadReceiptSyncEngine.ts +267 -0
- package/src/client/utils/ReadReceiptSync/legacyReadReceiptSyncEngineOnLoginHandler.ts +21 -0
- package/src/client/utils/ReadReceiptSync/readReceiptSyncEngine.ts +72 -98
- package/src/core/model/idResolvers.ts +2 -0
- package/src/marker/events/onChannelUnreadInfoUpdatedLocal.ts +29 -0
- package/src/marker/events/onChannelUnreadUpdatedLocal.ts +1 -1
- package/src/messageRepository/utils/markReadMessage.ts +10 -3
package/dist/index.cjs.js
CHANGED
|
@@ -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$
|
|
1613
|
+
let instance$6;
|
|
1613
1614
|
var NetworkActivitiesWatcher$1 = {
|
|
1614
1615
|
getInstance: () => {
|
|
1615
|
-
if (!instance$
|
|
1616
|
-
instance$
|
|
1616
|
+
if (!instance$6) {
|
|
1617
|
+
instance$6 = new NetworkActivitiesWatcher();
|
|
1617
1618
|
}
|
|
1618
|
-
return instance$
|
|
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$
|
|
5152
|
+
let instance$5;
|
|
5152
5153
|
var AnalyticsEngine$1 = {
|
|
5153
5154
|
getInstance: () => {
|
|
5154
|
-
if (!instance$
|
|
5155
|
-
instance$
|
|
5155
|
+
if (!instance$5) {
|
|
5156
|
+
instance$5 = new AnalyticsEngine();
|
|
5156
5157
|
}
|
|
5157
|
-
return instance$
|
|
5158
|
+
return instance$5;
|
|
5158
5159
|
},
|
|
5159
5160
|
};
|
|
5160
5161
|
|
|
@@ -5580,6 +5581,223 @@ 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
|
+
console.log('[New 🌟 readReceipts] Sync read receipts', readReceipts);
|
|
5631
|
+
if (readReceipts) {
|
|
5632
|
+
this.markReadApi(readReceipts);
|
|
5633
|
+
}
|
|
5634
|
+
}
|
|
5635
|
+
getUnsyncJobs() {
|
|
5636
|
+
var _a;
|
|
5637
|
+
// Get all read receipts that has latestSyncSegment < latestSegment
|
|
5638
|
+
const readReceipts = (_a = queryCache(['readReceipt'])) === null || _a === void 0 ? void 0 : _a.filter(({ data }) => {
|
|
5639
|
+
return data.latestSyncSegment < data.latestSegment;
|
|
5640
|
+
});
|
|
5641
|
+
// Enqueue unsync read receipts to the job queue
|
|
5642
|
+
readReceipts === null || readReceipts === void 0 ? void 0 : readReceipts.forEach(({ data: readReceipt }) => {
|
|
5643
|
+
this.enqueueReadReceipt(readReceipt.channelId, readReceipt.latestSegment);
|
|
5644
|
+
});
|
|
5645
|
+
}
|
|
5646
|
+
getReadReceipts() {
|
|
5647
|
+
// get all read receipts from queue, now the queue is empty
|
|
5648
|
+
const syncJob = this.jobQueue.splice(0, this.jobQueue.length);
|
|
5649
|
+
if (syncJob.length === 0)
|
|
5650
|
+
return;
|
|
5651
|
+
return syncJob.filter(job => {
|
|
5652
|
+
var _a;
|
|
5653
|
+
const readReceipt = (_a = pullFromCache(['readReceipt', job.channelId])) === null || _a === void 0 ? void 0 : _a.data;
|
|
5654
|
+
if (!readReceipt)
|
|
5655
|
+
return false;
|
|
5656
|
+
if (readReceipt.latestSegment > readReceipt.latestSyncSegment)
|
|
5657
|
+
return true;
|
|
5658
|
+
return false;
|
|
5659
|
+
});
|
|
5660
|
+
}
|
|
5661
|
+
async markReadApi(syncJobs) {
|
|
5662
|
+
var _a;
|
|
5663
|
+
// constuct payload
|
|
5664
|
+
// example: [{ channelId: 'channelId', readToSegment: 2 }]
|
|
5665
|
+
const syncJobsPayload = syncJobs.map(job => {
|
|
5666
|
+
return {
|
|
5667
|
+
channelId: job.channelId,
|
|
5668
|
+
readToSegment: job.segment,
|
|
5669
|
+
};
|
|
5670
|
+
});
|
|
5671
|
+
const response = await markChannelsAsReadBySegment(syncJobsPayload);
|
|
5672
|
+
if (response) {
|
|
5673
|
+
for (let i = 0; i < syncJobs.length; i += 1) {
|
|
5674
|
+
// update lastestSyncSegment in read receipt cache
|
|
5675
|
+
const cacheKey = ['readReceipt', syncJobs[i].channelId];
|
|
5676
|
+
const readReceiptCache = (_a = pullFromCache(cacheKey)) === null || _a === void 0 ? void 0 : _a.data;
|
|
5677
|
+
pushToCache(cacheKey, Object.assign(Object.assign({}, readReceiptCache), { latestSyncSegment: syncJobs[i].segment }));
|
|
5678
|
+
}
|
|
5679
|
+
}
|
|
5680
|
+
else {
|
|
5681
|
+
for (let i = 0; i < syncJobs.length; i += 1) {
|
|
5682
|
+
// push them back to queue if the syncing is failed and retry count is less than max retry
|
|
5683
|
+
if (syncJobs[i].retryCount >= this.MAX_RETRY)
|
|
5684
|
+
return;
|
|
5685
|
+
const updatedJob = Object.assign(Object.assign({}, syncJobs[i]), { syncState: "create" /* Amity.ReadReceiptSyncState.CREATED */, retryCount: syncJobs[i].retryCount + 1 });
|
|
5686
|
+
this.enqueueJob(updatedJob);
|
|
5687
|
+
}
|
|
5688
|
+
}
|
|
5689
|
+
}
|
|
5690
|
+
startObservingReadReceiptQueue() {
|
|
5691
|
+
if (this.client.useLegacyUnreadCount) {
|
|
5692
|
+
this.isActive = true;
|
|
5693
|
+
this.startSyncReadReceipt();
|
|
5694
|
+
}
|
|
5695
|
+
}
|
|
5696
|
+
stopObservingReadReceiptQueue() {
|
|
5697
|
+
this.isActive = false;
|
|
5698
|
+
this.jobQueue.map(job => {
|
|
5699
|
+
if (job.syncState === "syncing" /* Amity.ReadReceiptSyncState.SYNCING */) {
|
|
5700
|
+
return Object.assign(Object.assign({}, job), { syncState: "create" /* Amity.ReadReceiptSyncState.CREATED */ });
|
|
5701
|
+
}
|
|
5702
|
+
return job;
|
|
5703
|
+
});
|
|
5704
|
+
if (this.timer)
|
|
5705
|
+
clearInterval(this.timer);
|
|
5706
|
+
}
|
|
5707
|
+
// Session Management
|
|
5708
|
+
onSessionEstablished() {
|
|
5709
|
+
this.startObservingReadReceiptQueue();
|
|
5710
|
+
}
|
|
5711
|
+
onSessionDestroyed() {
|
|
5712
|
+
this.stopObservingReadReceiptQueue();
|
|
5713
|
+
this.jobQueue = [];
|
|
5714
|
+
}
|
|
5715
|
+
onTokenExpired() {
|
|
5716
|
+
this.stopObservingReadReceiptQueue();
|
|
5717
|
+
}
|
|
5718
|
+
// Network Connection Management
|
|
5719
|
+
onNetworkOffline() {
|
|
5720
|
+
// Stop observing to the read receipt queue.
|
|
5721
|
+
this.stopObservingReadReceiptQueue();
|
|
5722
|
+
}
|
|
5723
|
+
onNetworkOnline() {
|
|
5724
|
+
// Resume observing to the read receipt queue.
|
|
5725
|
+
this.startObservingReadReceiptQueue();
|
|
5726
|
+
}
|
|
5727
|
+
markRead(channelId, segment) {
|
|
5728
|
+
var _a;
|
|
5729
|
+
// Step 1: Optimistic update of channelUnread.readToSegment to message.segment and update unreadCount value
|
|
5730
|
+
const cacheKey = ['channelUnread', 'get', channelId];
|
|
5731
|
+
const channelUnread = (_a = pullFromCache(cacheKey)) === null || _a === void 0 ? void 0 : _a.data;
|
|
5732
|
+
console.log('[New 🌟] Mark read => channel unread', channelUnread);
|
|
5733
|
+
if (channelUnread && segment > channelUnread.readToSegment) {
|
|
5734
|
+
channelUnread.readToSegment = segment;
|
|
5735
|
+
channelUnread.unreadCount = Math.max(channelUnread.lastSegment - segment, 0);
|
|
5736
|
+
pushToCache(cacheKey, channelUnread);
|
|
5737
|
+
fireEvent('local.channelUnread.updated', channelUnread);
|
|
5738
|
+
}
|
|
5739
|
+
// Step 2: Enqueue the read receipt
|
|
5740
|
+
this.enqueueReadReceipt(channelId, segment);
|
|
5741
|
+
}
|
|
5742
|
+
enqueueReadReceipt(channelId, segment) {
|
|
5743
|
+
var _a;
|
|
5744
|
+
const readReceipt = (_a = pullFromCache(['readReceipt', channelId])) === null || _a === void 0 ? void 0 : _a.data;
|
|
5745
|
+
// Create new read receipt if it's not exists and add the job to queue
|
|
5746
|
+
if (!readReceipt) {
|
|
5747
|
+
const readReceiptChannel = {
|
|
5748
|
+
channelId,
|
|
5749
|
+
latestSegment: segment,
|
|
5750
|
+
latestSyncSegment: 0,
|
|
5751
|
+
};
|
|
5752
|
+
pushToCache(['readReceipt', channelId], readReceiptChannel);
|
|
5753
|
+
}
|
|
5754
|
+
else if (readReceipt.latestSegment < segment) {
|
|
5755
|
+
// Update latestSegment in read receipt cache
|
|
5756
|
+
pushToCache(['readReceipt', channelId], Object.assign(Object.assign({}, readReceipt), { latestSegment: segment }));
|
|
5757
|
+
}
|
|
5758
|
+
else if (readReceipt.latestSyncSegment >= segment) {
|
|
5759
|
+
// Skip the job when lastSyncSegment > = segment
|
|
5760
|
+
return;
|
|
5761
|
+
}
|
|
5762
|
+
let syncJob = this.getSyncJob(channelId);
|
|
5763
|
+
if (syncJob === null || syncJob.syncState === "syncing" /* Amity.ReadReceiptSyncState.SYNCING */) {
|
|
5764
|
+
syncJob = {
|
|
5765
|
+
channelId,
|
|
5766
|
+
segment,
|
|
5767
|
+
syncState: "create" /* Amity.ReadReceiptSyncState.CREATED */,
|
|
5768
|
+
retryCount: 0,
|
|
5769
|
+
};
|
|
5770
|
+
this.enqueueJob(syncJob);
|
|
5771
|
+
}
|
|
5772
|
+
else if (syncJob.segment < segment) {
|
|
5773
|
+
syncJob.segment = segment;
|
|
5774
|
+
}
|
|
5775
|
+
}
|
|
5776
|
+
getSyncJob(channelId) {
|
|
5777
|
+
const { jobQueue } = this;
|
|
5778
|
+
const targetJob = jobQueue.find(job => job.channelId === channelId);
|
|
5779
|
+
return targetJob || null;
|
|
5780
|
+
}
|
|
5781
|
+
enqueueJob(syncJob) {
|
|
5782
|
+
if (this.jobQueue.length < this.JOB_QUEUE_SIZE) {
|
|
5783
|
+
this.jobQueue.push(syncJob);
|
|
5784
|
+
}
|
|
5785
|
+
else {
|
|
5786
|
+
// Remove oldest job when queue reach maximum capacity
|
|
5787
|
+
this.jobQueue.shift();
|
|
5788
|
+
this.jobQueue.push(syncJob);
|
|
5789
|
+
}
|
|
5790
|
+
}
|
|
5791
|
+
}
|
|
5792
|
+
let instance$4 = null;
|
|
5793
|
+
var ReadReceiptSyncEngine = {
|
|
5794
|
+
getInstance: () => {
|
|
5795
|
+
if (!instance$4)
|
|
5796
|
+
instance$4 = new MessageReadReceiptSyncEngine();
|
|
5797
|
+
return instance$4;
|
|
5798
|
+
},
|
|
5799
|
+
};
|
|
5800
|
+
|
|
5583
5801
|
/**
|
|
5584
5802
|
*
|
|
5585
5803
|
* Mark subChannel as read by readToSegment
|
|
@@ -5628,7 +5846,7 @@ const reCalculateChannelUnreadInfo = (channelId) => {
|
|
|
5628
5846
|
return channelUnreadInfo;
|
|
5629
5847
|
};
|
|
5630
5848
|
|
|
5631
|
-
class
|
|
5849
|
+
class LegacyMessageReadReceiptSyncEngine {
|
|
5632
5850
|
constructor() {
|
|
5633
5851
|
this.isActive = true;
|
|
5634
5852
|
this.MAX_RETRY = 3;
|
|
@@ -5659,7 +5877,7 @@ class MessageReadReceiptSyncEngine {
|
|
|
5659
5877
|
getUnsyncJobs() {
|
|
5660
5878
|
var _a;
|
|
5661
5879
|
// Get all read receipts that has latestSyncSegment < latestSegment
|
|
5662
|
-
const readReceipts = (_a = queryCache(['
|
|
5880
|
+
const readReceipts = (_a = queryCache(['legacyReadReceipt'])) === null || _a === void 0 ? void 0 : _a.filter(({ data }) => {
|
|
5663
5881
|
return data.latestSyncSegment < data.latestSegment;
|
|
5664
5882
|
});
|
|
5665
5883
|
// Enqueue unsync read receipts to the job queue
|
|
@@ -5678,7 +5896,7 @@ class MessageReadReceiptSyncEngine {
|
|
|
5678
5896
|
return;
|
|
5679
5897
|
// Get readReceipt from cache by subChannelId
|
|
5680
5898
|
const readReceipt = (_a = pullFromCache([
|
|
5681
|
-
'
|
|
5899
|
+
'legacyReadReceipt',
|
|
5682
5900
|
syncJob.subChannelId,
|
|
5683
5901
|
])) === null || _a === void 0 ? void 0 : _a.data;
|
|
5684
5902
|
if (!readReceipt)
|
|
@@ -5701,10 +5919,10 @@ class MessageReadReceiptSyncEngine {
|
|
|
5701
5919
|
if (response) {
|
|
5702
5920
|
this.removeSynedReceipt(syncJob.subChannelId, syncJob.segment);
|
|
5703
5921
|
const readReceiptCache = (_a = pullFromCache([
|
|
5704
|
-
'
|
|
5922
|
+
'legacyReadReceipt',
|
|
5705
5923
|
subChannelId,
|
|
5706
5924
|
])) === null || _a === void 0 ? void 0 : _a.data;
|
|
5707
|
-
pushToCache(['
|
|
5925
|
+
pushToCache(['legacyReadReceipt', subChannelId], Object.assign(Object.assign({}, readReceiptCache), { latestSyncSegment: segment }));
|
|
5708
5926
|
}
|
|
5709
5927
|
else if (!response) {
|
|
5710
5928
|
if (newSyncJob.retryCount > this.MAX_RETRY) {
|
|
@@ -5771,7 +5989,7 @@ class MessageReadReceiptSyncEngine {
|
|
|
5771
5989
|
subChannelUnreadInfo.readToSegment = segment;
|
|
5772
5990
|
subChannelUnreadInfo.unreadCount = Math.max(subChannelUnreadInfo.lastSegment - segment, 0);
|
|
5773
5991
|
const channelUnreadInfo = reCalculateChannelUnreadInfo(subChannelUnreadInfo.channelId);
|
|
5774
|
-
fireEvent('local.
|
|
5992
|
+
fireEvent('local.channelUnreadInfo.updated', channelUnreadInfo);
|
|
5775
5993
|
pushToCache(cacheKey, subChannelUnreadInfo);
|
|
5776
5994
|
fireEvent('local.subChannelUnread.updated', subChannelUnreadInfo);
|
|
5777
5995
|
}
|
|
@@ -5780,7 +5998,10 @@ class MessageReadReceiptSyncEngine {
|
|
|
5780
5998
|
}
|
|
5781
5999
|
enqueueReadReceipt(subChannelId, segment) {
|
|
5782
6000
|
var _a;
|
|
5783
|
-
const readReceipt = (_a = pullFromCache([
|
|
6001
|
+
const readReceipt = (_a = pullFromCache([
|
|
6002
|
+
'legacyReadReceipt',
|
|
6003
|
+
subChannelId,
|
|
6004
|
+
])) === null || _a === void 0 ? void 0 : _a.data;
|
|
5784
6005
|
// Create new read receipt if it's not exists and add job to queue
|
|
5785
6006
|
if (!readReceipt) {
|
|
5786
6007
|
const readReceiptSubChannel = {
|
|
@@ -5788,10 +6009,10 @@ class MessageReadReceiptSyncEngine {
|
|
|
5788
6009
|
latestSegment: segment,
|
|
5789
6010
|
latestSyncSegment: 0,
|
|
5790
6011
|
};
|
|
5791
|
-
pushToCache(['
|
|
6012
|
+
pushToCache(['legacyReadReceipt', subChannelId], readReceiptSubChannel);
|
|
5792
6013
|
}
|
|
5793
6014
|
else if (readReceipt.latestSegment < segment) {
|
|
5794
|
-
pushToCache(['
|
|
6015
|
+
pushToCache(['legacyReadReceipt', subChannelId], Object.assign(Object.assign({}, readReceipt), { latestSegment: segment }));
|
|
5795
6016
|
}
|
|
5796
6017
|
else if (readReceipt.latestSyncSegment >= segment) {
|
|
5797
6018
|
// Skip the job when lastSyncSegment > = segment
|
|
@@ -5834,18 +6055,24 @@ class MessageReadReceiptSyncEngine {
|
|
|
5834
6055
|
}
|
|
5835
6056
|
}
|
|
5836
6057
|
let instance$3 = null;
|
|
5837
|
-
var
|
|
6058
|
+
var LegacyReadReceiptSyncEngine = {
|
|
5838
6059
|
getInstance: () => {
|
|
5839
6060
|
if (!instance$3)
|
|
5840
|
-
instance$3 = new
|
|
6061
|
+
instance$3 = new LegacyMessageReadReceiptSyncEngine();
|
|
5841
6062
|
return instance$3;
|
|
5842
6063
|
},
|
|
5843
6064
|
};
|
|
5844
6065
|
|
|
5845
6066
|
const markReadMessage = (message) => {
|
|
5846
|
-
const
|
|
5847
|
-
|
|
5848
|
-
|
|
6067
|
+
const client = getActiveClient();
|
|
6068
|
+
if (client.useLegacyUnreadCount) {
|
|
6069
|
+
const markReadReceiptEngine = ReadReceiptSyncEngine.getInstance();
|
|
6070
|
+
markReadReceiptEngine.markRead(message.channelId, message.channelSegment);
|
|
6071
|
+
}
|
|
6072
|
+
else {
|
|
6073
|
+
const markReadReceiptEngine = LegacyReadReceiptSyncEngine.getInstance();
|
|
6074
|
+
markReadReceiptEngine.markRead(message.subChannelId, message.channelSegment);
|
|
6075
|
+
}
|
|
5849
6076
|
};
|
|
5850
6077
|
|
|
5851
6078
|
const messageLinkedObject = (message) => {
|
|
@@ -6833,6 +7060,24 @@ const preUpdateChannelCache = (rawPayload, options = { isMessagePreviewUpdated:
|
|
|
6833
7060
|
channels: rawPayload.channels.map(channel => convertFromRaw(channel, { isMessagePreviewUpdated: options.isMessagePreviewUpdated })),
|
|
6834
7061
|
});
|
|
6835
7062
|
};
|
|
7063
|
+
const updateChannelUnread = ({ currentUserId, channels, channelUsers, }) => {
|
|
7064
|
+
for (let i = 0; i < channels.length; i += 1) {
|
|
7065
|
+
const cacheKey = ['channelUnread', 'get', channels[i].channelId];
|
|
7066
|
+
const { readToSegment, lastMentionedSegment } = channelUsers.find(channelUser => channelUser.channelId === channels[i].channelId && channelUser.userId === currentUserId) || {
|
|
7067
|
+
readToSegment: 0,
|
|
7068
|
+
lastMentionedSegment: 0,
|
|
7069
|
+
};
|
|
7070
|
+
pushToCache(cacheKey, {
|
|
7071
|
+
channelId: channels[i].channelId,
|
|
7072
|
+
lastSegment: channels[i].messageCount,
|
|
7073
|
+
readToSegment,
|
|
7074
|
+
lastMentionedSegment,
|
|
7075
|
+
unreadCount: channels[i].messageCount - readToSegment,
|
|
7076
|
+
isMentioned: lastMentionedSegment > readToSegment,
|
|
7077
|
+
isDeleted: channels[i].isDeleted,
|
|
7078
|
+
});
|
|
7079
|
+
}
|
|
7080
|
+
};
|
|
6836
7081
|
const prepareChannelPayload = async (rawPayload, options = { isMessagePreviewUpdated: true }) => {
|
|
6837
7082
|
const client = getActiveClient();
|
|
6838
7083
|
const networkPreviewSetting = await client.getMessagePreviewSetting(false);
|
|
@@ -6842,23 +7087,34 @@ const prepareChannelPayload = async (rawPayload, options = { isMessagePreviewUpd
|
|
|
6842
7087
|
rawPayload.messagePreviews.length > 0) {
|
|
6843
7088
|
updateChannelMessagePreviewCache(rawPayload);
|
|
6844
7089
|
}
|
|
6845
|
-
|
|
6846
|
-
|
|
6847
|
-
|
|
6848
|
-
|
|
6849
|
-
|
|
6850
|
-
|
|
6851
|
-
|
|
6852
|
-
|
|
6853
|
-
|
|
6854
|
-
|
|
6855
|
-
|
|
6856
|
-
|
|
7090
|
+
if (client.useLegacyUnreadCount) {
|
|
7091
|
+
updateChannelUnread({
|
|
7092
|
+
channels: rawPayload.channels,
|
|
7093
|
+
channelUsers: rawPayload.channelUsers,
|
|
7094
|
+
currentUserId: client.userId,
|
|
7095
|
+
});
|
|
7096
|
+
}
|
|
7097
|
+
else {
|
|
7098
|
+
const markerIds = rawPayload.channels
|
|
7099
|
+
// filter channel by type. Only conversation, community and broadcast type are included.
|
|
7100
|
+
.filter(isUnreadCountSupport)
|
|
7101
|
+
.map(({ channelInternalId }) => channelInternalId);
|
|
7102
|
+
if (markerIds.length > 0) {
|
|
7103
|
+
// since the get markers method requires a channel cache to function with the reducer.
|
|
7104
|
+
preUpdateChannelCache(rawPayload, {
|
|
7105
|
+
isMessagePreviewUpdated: options.isMessagePreviewUpdated,
|
|
7106
|
+
});
|
|
7107
|
+
try {
|
|
7108
|
+
await getChannelMarkers(markerIds);
|
|
7109
|
+
}
|
|
7110
|
+
catch (e) {
|
|
7111
|
+
// empty block (from the spec, allow marker fetch to fail without having to do anything)
|
|
7112
|
+
}
|
|
6857
7113
|
}
|
|
6858
7114
|
}
|
|
6859
|
-
//
|
|
7115
|
+
// convert raw channel to internal channel
|
|
6860
7116
|
const channels = rawPayload.channels.map(payload => convertFromRaw(payload, { isMessagePreviewUpdated: options.isMessagePreviewUpdated }));
|
|
6861
|
-
// user
|
|
7117
|
+
// convert raw channel user to membership (add user object)
|
|
6862
7118
|
const channelUsers = rawPayload.channelUsers.map(channelUser => {
|
|
6863
7119
|
return convertRawMembershipToMembership(channelUser);
|
|
6864
7120
|
});
|
|
@@ -6985,15 +7241,28 @@ const getSubChannelsUnreadCount = (channel, marker) => {
|
|
|
6985
7241
|
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
7242
|
};
|
|
6987
7243
|
|
|
7244
|
+
const getLegacyChannelUnread = (channelId) => {
|
|
7245
|
+
var _a;
|
|
7246
|
+
return (_a = pullFromCache(['channelUnread', 'get', channelId])) === null || _a === void 0 ? void 0 : _a.data;
|
|
7247
|
+
};
|
|
7248
|
+
|
|
6988
7249
|
const constructChannelDynamicValue = (channel) => {
|
|
7250
|
+
const client = getActiveClient();
|
|
6989
7251
|
const rest = __rest(channel, ["messageCount"]);
|
|
6990
7252
|
return shallowClone(rest, {
|
|
6991
|
-
get
|
|
6992
|
-
|
|
7253
|
+
get unreadCount() {
|
|
7254
|
+
var _a, _b;
|
|
7255
|
+
return (_b = (_a = getLegacyChannelUnread(rest.channelId)) === null || _a === void 0 ? void 0 : _a.unreadCount) !== null && _b !== void 0 ? _b : 0;
|
|
6993
7256
|
},
|
|
6994
7257
|
get subChannelsUnreadCount() {
|
|
6995
7258
|
return getSubChannelsUnreadCount(rest);
|
|
6996
7259
|
},
|
|
7260
|
+
get isMentioned() {
|
|
7261
|
+
var _a, _b;
|
|
7262
|
+
if (client.useLegacyUnreadCount)
|
|
7263
|
+
return (_b = (_a = getLegacyChannelUnread(rest.channelId)) === null || _a === void 0 ? void 0 : _a.isMentioned) !== null && _b !== void 0 ? _b : false;
|
|
7264
|
+
return getChannelIsMentioned(rest);
|
|
7265
|
+
},
|
|
6997
7266
|
});
|
|
6998
7267
|
};
|
|
6999
7268
|
|
|
@@ -7769,6 +8038,25 @@ var readReceiptSyncEngineOnLoginHandler = () => {
|
|
|
7769
8038
|
};
|
|
7770
8039
|
};
|
|
7771
8040
|
|
|
8041
|
+
var legacyReadReceiptSyncEngineOnLoginHandler = () => {
|
|
8042
|
+
const readReceiptSyncEngine = LegacyReadReceiptSyncEngine.getInstance();
|
|
8043
|
+
readReceiptSyncEngine.startSyncReadReceipt();
|
|
8044
|
+
onSessionStateChange(state => {
|
|
8045
|
+
if (state === "established" /* Amity.SessionStates.ESTABLISHED */) {
|
|
8046
|
+
readReceiptSyncEngine.onSessionEstablished();
|
|
8047
|
+
}
|
|
8048
|
+
else if (state === "tokenExpired" /* Amity.SessionStates.TOKEN_EXPIRED */) {
|
|
8049
|
+
readReceiptSyncEngine.onTokenExpired();
|
|
8050
|
+
}
|
|
8051
|
+
else {
|
|
8052
|
+
readReceiptSyncEngine.onSessionDestroyed();
|
|
8053
|
+
}
|
|
8054
|
+
});
|
|
8055
|
+
return () => {
|
|
8056
|
+
readReceiptSyncEngine.onSessionDestroyed();
|
|
8057
|
+
};
|
|
8058
|
+
};
|
|
8059
|
+
|
|
7772
8060
|
const onOnline = (callback) => {
|
|
7773
8061
|
if (typeof window !== 'undefined' && window.addEventListener) {
|
|
7774
8062
|
window.addEventListener('online', callback);
|
|
@@ -8781,6 +9069,7 @@ const enableUnreadCount = () => {
|
|
|
8781
9069
|
if (client.isUnreadCountEnabled)
|
|
8782
9070
|
return false;
|
|
8783
9071
|
client.isUnreadCountEnabled = true;
|
|
9072
|
+
client.useLegacyUnreadCount = false;
|
|
8784
9073
|
client.emitter.emit('unreadCountEnabled', true);
|
|
8785
9074
|
return true;
|
|
8786
9075
|
};
|
|
@@ -9096,7 +9385,12 @@ const login = async (params, sessionHandler, config) => {
|
|
|
9096
9385
|
// NOTE: This is a temporary solution to handle the channel marker when the user is forced to leave
|
|
9097
9386
|
// the channel because currently backend can't handle this, so every time a user is banned from
|
|
9098
9387
|
// 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(),
|
|
9388
|
+
onChannelDeleted(removeChannelMarkerCache), onChannelMemberBanned(removeChannelMarkerCache), markReadEngineOnLoginHandler(), analyticsEngineOnLoginHandler(), objectResolverEngineOnLoginHandler());
|
|
9389
|
+
if (client.useLegacyUnreadCount) {
|
|
9390
|
+
subscriptions.push(readReceiptSyncEngineOnLoginHandler());
|
|
9391
|
+
}
|
|
9392
|
+
else
|
|
9393
|
+
subscriptions.push(legacyReadReceiptSyncEngineOnLoginHandler());
|
|
9100
9394
|
const markerSyncUnsubscriber = await startMarkerSync();
|
|
9101
9395
|
subscriptions.push(markerSyncUnsubscriber);
|
|
9102
9396
|
}
|
|
@@ -9277,6 +9571,8 @@ const createClient = (apiKey, apiRegion = API_REGIONS.SG, { debugSession = DEFAU
|
|
|
9277
9571
|
const sessionState = "notLoggedIn" /* Amity.SessionStates.NOT_LOGGED_IN */;
|
|
9278
9572
|
const sessionHandler = undefined;
|
|
9279
9573
|
const isUnreadCountEnabled = false;
|
|
9574
|
+
// Legacy unread count is true by default
|
|
9575
|
+
const useLegacyUnreadCount = true;
|
|
9280
9576
|
const client = {
|
|
9281
9577
|
version: `${VERSION}`,
|
|
9282
9578
|
apiKey,
|
|
@@ -9306,6 +9602,7 @@ const createClient = (apiKey, apiRegion = API_REGIONS.SG, { debugSession = DEFAU
|
|
|
9306
9602
|
getMessagePreviewSetting,
|
|
9307
9603
|
use: () => setActiveClient(client),
|
|
9308
9604
|
isUnreadCountEnabled,
|
|
9605
|
+
useLegacyUnreadCount,
|
|
9309
9606
|
getMarkerSyncConsistentMode,
|
|
9310
9607
|
/**
|
|
9311
9608
|
* Prefix for the deviceId key in the local storage or async storage.
|
|
@@ -16436,6 +16733,24 @@ var index$f = /*#__PURE__*/Object.freeze({
|
|
|
16436
16733
|
stopMessageReceiptSync: stopMessageReceiptSync
|
|
16437
16734
|
});
|
|
16438
16735
|
|
|
16736
|
+
/**
|
|
16737
|
+
* Internal used only
|
|
16738
|
+
*
|
|
16739
|
+
* Fired when an {@link Amity.userMessageFeedMarkers} has been resolved by Object Rsesolver
|
|
16740
|
+
*
|
|
16741
|
+
* @param callback The function to call when the event was fired
|
|
16742
|
+
* @returns an {@link Amity.Unsubscriber} function to stop listening
|
|
16743
|
+
*
|
|
16744
|
+
* @category MessageMarker Events
|
|
16745
|
+
*/
|
|
16746
|
+
const onChannelUnreadInfoUpdatedLocal = (callback) => {
|
|
16747
|
+
const client = getActiveClient();
|
|
16748
|
+
const filter = (payload) => {
|
|
16749
|
+
callback(payload);
|
|
16750
|
+
};
|
|
16751
|
+
return createEventSubscriber(client, 'channelMarker/onChannelUnreadInfoUpdatedLocal', 'local.channelUnreadInfo.updated', filter);
|
|
16752
|
+
};
|
|
16753
|
+
|
|
16439
16754
|
/**
|
|
16440
16755
|
* Internal used only
|
|
16441
16756
|
*
|
|
@@ -16451,7 +16766,7 @@ const onChannelUnreadUpdatedLocal = (callback) => {
|
|
|
16451
16766
|
const filter = (payload) => {
|
|
16452
16767
|
callback(payload);
|
|
16453
16768
|
};
|
|
16454
|
-
return createEventSubscriber(client, '
|
|
16769
|
+
return createEventSubscriber(client, 'channel/onChannelUnreadUpdatedLocal', 'local.channelUnread.updated', filter);
|
|
16455
16770
|
};
|
|
16456
16771
|
|
|
16457
16772
|
/* begin_public_function
|
|
@@ -16653,6 +16968,7 @@ const getChannel = (channelId, callback) => {
|
|
|
16653
16968
|
return onSubChannelUpdated(updateMessagePreview);
|
|
16654
16969
|
}, 'channelId', 'channel'),
|
|
16655
16970
|
convertEventPayload(onSubChannelCreated, 'channelId', 'channel'),
|
|
16971
|
+
convertEventPayload(onChannelUnreadInfoUpdatedLocal, 'channelId', 'channel'),
|
|
16656
16972
|
convertEventPayload(onChannelUnreadUpdatedLocal, 'channelId', 'channel'),
|
|
16657
16973
|
], {
|
|
16658
16974
|
forceDispatch: true,
|
|
@@ -17166,6 +17482,10 @@ class ChannelLiveCollectionController extends LiveCollectionController {
|
|
|
17166
17482
|
},
|
|
17167
17483
|
action: "OnResolveUnread" /* Amity.ChannelActionType.OnResolveUnread */,
|
|
17168
17484
|
},
|
|
17485
|
+
{
|
|
17486
|
+
fn: convertEventPayload(onChannelUnreadInfoUpdatedLocal, 'channelId', 'channel'),
|
|
17487
|
+
action: "onUpdate" /* Amity.ChannelActionType.OnUpdate */,
|
|
17488
|
+
},
|
|
17169
17489
|
{
|
|
17170
17490
|
fn: convertEventPayload(onChannelUnreadUpdatedLocal, 'channelId', 'channel'),
|
|
17171
17491
|
action: "onUpdate" /* Amity.ChannelActionType.OnUpdate */,
|