@amityco/ts-sdk 7.1.1-67cf0d9.0 → 7.1.1-6dd179b0.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 (149) hide show
  1. package/dist/@types/core/events.d.ts +5 -2
  2. package/dist/@types/core/events.d.ts.map +1 -1
  3. package/dist/@types/core/model.d.ts +4 -2
  4. package/dist/@types/core/model.d.ts.map +1 -1
  5. package/dist/@types/core/payload.d.ts +18 -0
  6. package/dist/@types/core/payload.d.ts.map +1 -1
  7. package/dist/@types/core/readReceipt.d.ts +1 -12
  8. package/dist/@types/core/readReceipt.d.ts.map +1 -1
  9. package/dist/@types/domains/channel.d.ts +0 -10
  10. package/dist/@types/domains/channel.d.ts.map +1 -1
  11. package/dist/@types/domains/client.d.ts +0 -2
  12. package/dist/@types/domains/client.d.ts.map +1 -1
  13. package/dist/@types/domains/notification.d.ts +81 -0
  14. package/dist/@types/domains/notification.d.ts.map +1 -0
  15. package/dist/@types/index.d.ts +1 -0
  16. package/dist/@types/index.d.ts.map +1 -1
  17. package/dist/channelRepository/events/onChannelDeleted.d.ts.map +1 -1
  18. package/dist/channelRepository/events/onChannelLeft.d.ts.map +1 -1
  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/index.d.ts +0 -1
  22. package/dist/channelRepository/observers/index.d.ts.map +1 -1
  23. package/dist/channelRepository/utils/constructChannelDynamicValue.d.ts.map +1 -1
  24. package/dist/channelRepository/utils/prepareChannelPayload.d.ts.map +1 -1
  25. package/dist/client/api/createClient.d.ts +0 -1
  26. package/dist/client/api/createClient.d.ts.map +1 -1
  27. package/dist/client/api/enableUnreadCount.d.ts.map +1 -1
  28. package/dist/client/api/login.d.ts.map +1 -1
  29. package/dist/client/utils/ReadReceiptSync/readReceiptSyncEngine.d.ts +4 -2
  30. package/dist/client/utils/ReadReceiptSync/readReceiptSyncEngine.d.ts.map +1 -1
  31. package/dist/client/utils/endpoints.d.ts +0 -1
  32. package/dist/client/utils/endpoints.d.ts.map +1 -1
  33. package/dist/client/utils/setClientToken.d.ts.map +1 -1
  34. package/dist/core/events.d.ts +3 -3
  35. package/dist/core/events.d.ts.map +1 -1
  36. package/dist/core/model/idResolvers.d.ts.map +1 -1
  37. package/dist/core/model/index.d.ts.map +1 -1
  38. package/dist/index.cjs.js +468 -596
  39. package/dist/index.d.ts +1 -0
  40. package/dist/index.d.ts.map +1 -1
  41. package/dist/index.esm.js +451 -580
  42. package/dist/index.umd.js +4 -4
  43. package/dist/{channelRepository → marker}/events/onChannelUnreadUpdatedLocal.d.ts +2 -2
  44. package/dist/marker/events/onChannelUnreadUpdatedLocal.d.ts.map +1 -0
  45. package/dist/messageRepository/events/onMessageCreated.d.ts.map +1 -1
  46. package/dist/messageRepository/observers/getMessage.d.ts.map +1 -1
  47. package/dist/messageRepository/utils/markReadMessage.d.ts.map +1 -1
  48. package/dist/notificationTray/api/index.d.ts +3 -0
  49. package/dist/notificationTray/api/index.d.ts.map +1 -0
  50. package/dist/notificationTray/api/markItemsSeen.d.ts +16 -0
  51. package/dist/notificationTray/api/markItemsSeen.d.ts.map +1 -0
  52. package/dist/notificationTray/api/markTraySeen.d.ts +19 -0
  53. package/dist/notificationTray/api/markTraySeen.d.ts.map +1 -0
  54. package/dist/notificationTray/events/index.d.ts +2 -0
  55. package/dist/notificationTray/events/index.d.ts.map +1 -0
  56. package/dist/notificationTray/events/onNotificationTraySeenUpdated.d.ts +17 -0
  57. package/dist/notificationTray/events/onNotificationTraySeenUpdated.d.ts.map +1 -0
  58. package/dist/notificationTray/index.d.ts +4 -0
  59. package/dist/notificationTray/index.d.ts.map +1 -0
  60. package/dist/notificationTray/internalApi/getNotificationTraySeen.d.ts +30 -0
  61. package/dist/notificationTray/internalApi/getNotificationTraySeen.d.ts.map +1 -0
  62. package/dist/notificationTray/observers/getNotificationTrayItems/NotificationTrayItemsLiveCollectionController.d.ts +13 -0
  63. package/dist/notificationTray/observers/getNotificationTrayItems/NotificationTrayItemsLiveCollectionController.d.ts.map +1 -0
  64. package/dist/notificationTray/observers/getNotificationTrayItems/NotificationTrayItemsPaginationController.d.ts +9 -0
  65. package/dist/notificationTray/observers/getNotificationTrayItems/NotificationTrayItemsPaginationController.d.ts.map +1 -0
  66. package/dist/notificationTray/observers/getNotificationTrayItems/NotificationTrayItemsQuerystreamController.d.ts +9 -0
  67. package/dist/notificationTray/observers/getNotificationTrayItems/NotificationTrayItemsQuerystreamController.d.ts.map +1 -0
  68. package/dist/notificationTray/observers/getNotificationTrayItems.d.ts +12 -0
  69. package/dist/notificationTray/observers/getNotificationTrayItems.d.ts.map +1 -0
  70. package/dist/notificationTray/observers/getNotificationTraySeen.d.ts +21 -0
  71. package/dist/notificationTray/observers/getNotificationTraySeen.d.ts.map +1 -0
  72. package/dist/notificationTray/observers/index.d.ts +3 -0
  73. package/dist/notificationTray/observers/index.d.ts.map +1 -0
  74. package/dist/notificationTray/utils/prepareNotificationTrayItemsPayload.d.ts +2 -0
  75. package/dist/notificationTray/utils/prepareNotificationTrayItemsPayload.d.ts.map +1 -0
  76. package/dist/utils/linkedObject/index.d.ts +1 -0
  77. package/dist/utils/linkedObject/index.d.ts.map +1 -1
  78. package/dist/utils/linkedObject/notificationTrayLinkedObject.d.ts +2 -0
  79. package/dist/utils/linkedObject/notificationTrayLinkedObject.d.ts.map +1 -0
  80. package/package.json +1 -1
  81. package/src/@types/core/events.ts +6 -2
  82. package/src/@types/core/model.ts +6 -4
  83. package/src/@types/core/payload.ts +25 -0
  84. package/src/@types/core/readReceipt.ts +1 -14
  85. package/src/@types/domains/channel.ts +0 -13
  86. package/src/@types/domains/client.ts +0 -3
  87. package/src/@types/domains/notification.ts +90 -0
  88. package/src/@types/index.ts +1 -0
  89. package/src/channelRepository/events/onChannelDeleted.ts +4 -17
  90. package/src/channelRepository/events/onChannelLeft.ts +3 -11
  91. package/src/channelRepository/observers/getChannel.ts +1 -3
  92. package/src/channelRepository/observers/getChannels/ChannelLiveCollectionController.ts +1 -6
  93. package/src/channelRepository/observers/index.ts +0 -1
  94. package/src/channelRepository/utils/constructChannelDynamicValue.ts +2 -12
  95. package/src/channelRepository/utils/prepareChannelPayload.ts +17 -68
  96. package/src/client/api/createClient.ts +1 -7
  97. package/src/client/api/enableUnreadCount.ts +0 -1
  98. package/src/client/api/login.ts +1 -5
  99. package/src/client/utils/ReadReceiptSync/readReceiptSyncEngine.ts +99 -74
  100. package/src/client/utils/endpoints.ts +0 -1
  101. package/src/client/utils/setClientToken.ts +0 -8
  102. package/src/core/model/idResolvers.ts +3 -2
  103. package/src/core/model/index.ts +2 -0
  104. package/src/fileRepository/api/uploadFile.ts +1 -1
  105. package/src/fileRepository/api/uploadImage.ts +1 -1
  106. package/src/fileRepository/api/uploadVideo.ts +1 -1
  107. package/src/index.ts +2 -0
  108. package/src/{channelRepository → marker}/events/onChannelUnreadUpdatedLocal.ts +3 -3
  109. package/src/messageRepository/events/onMessageCreated.ts +1 -45
  110. package/src/messageRepository/observers/getMessage.ts +1 -0
  111. package/src/messageRepository/utils/markReadMessage.ts +3 -10
  112. package/src/notificationTray/api/index.ts +2 -0
  113. package/src/notificationTray/api/markItemsSeen.ts +59 -0
  114. package/src/notificationTray/api/markTraySeen.ts +65 -0
  115. package/src/notificationTray/events/index.ts +1 -0
  116. package/src/notificationTray/events/onNotificationTraySeenUpdated.ts +36 -0
  117. package/src/notificationTray/index.ts +3 -0
  118. package/src/notificationTray/internalApi/getNotificationTraySeen.ts +81 -0
  119. package/src/notificationTray/observers/getNotificationTrayItems/NotificationTrayItemsLiveCollectionController.ts +96 -0
  120. package/src/notificationTray/observers/getNotificationTrayItems/NotificationTrayItemsPaginationController.ts +31 -0
  121. package/src/notificationTray/observers/getNotificationTrayItems/NotificationTrayItemsQuerystreamController.ts +68 -0
  122. package/src/notificationTray/observers/getNotificationTrayItems.ts +44 -0
  123. package/src/notificationTray/observers/getNotificationTraySeen.ts +43 -0
  124. package/src/notificationTray/observers/index.ts +2 -0
  125. package/src/notificationTray/utils/prepareNotificationTrayItemsPayload.ts +12 -0
  126. package/src/utils/linkedObject/index.ts +2 -0
  127. package/src/utils/linkedObject/notificationTrayLinkedObject.ts +19 -0
  128. package/dist/channelRepository/api/markChannelsAsReadBySegment.d.ts +0 -16
  129. package/dist/channelRepository/api/markChannelsAsReadBySegment.d.ts.map +0 -1
  130. package/dist/channelRepository/events/onChannelUnreadUpdatedLocal.d.ts.map +0 -1
  131. package/dist/channelRepository/internalApi/getTotalChannelsUnread.d.ts +0 -11
  132. package/dist/channelRepository/internalApi/getTotalChannelsUnread.d.ts.map +0 -1
  133. package/dist/channelRepository/observers/getTotalChannelsUnread.d.ts +0 -20
  134. package/dist/channelRepository/observers/getTotalChannelsUnread.d.ts.map +0 -1
  135. package/dist/channelRepository/utils/getLegacyChannelUnread.d.ts +0 -2
  136. package/dist/channelRepository/utils/getLegacyChannelUnread.d.ts.map +0 -1
  137. package/dist/client/utils/ReadReceiptSync/legacyReadReceiptSyncEngine.d.ts +0 -33
  138. package/dist/client/utils/ReadReceiptSync/legacyReadReceiptSyncEngine.d.ts.map +0 -1
  139. package/dist/client/utils/ReadReceiptSync/legacyReadReceiptSyncEngineOnLoginHandler.d.ts +0 -3
  140. package/dist/client/utils/ReadReceiptSync/legacyReadReceiptSyncEngineOnLoginHandler.d.ts.map +0 -1
  141. package/dist/marker/events/onChannelUnreadInfoUpdatedLocal.d.ts +0 -12
  142. package/dist/marker/events/onChannelUnreadInfoUpdatedLocal.d.ts.map +0 -1
  143. package/src/channelRepository/api/markChannelsAsReadBySegment.ts +0 -29
  144. package/src/channelRepository/internalApi/getTotalChannelsUnread.ts +0 -38
  145. package/src/channelRepository/observers/getTotalChannelsUnread.ts +0 -129
  146. package/src/channelRepository/utils/getLegacyChannelUnread.ts +0 -5
  147. package/src/client/utils/ReadReceiptSync/legacyReadReceiptSyncEngine.ts +0 -267
  148. package/src/client/utils/ReadReceiptSync/legacyReadReceiptSyncEngineOnLoginHandler.ts +0 -21
  149. package/src/marker/events/onChannelUnreadInfoUpdatedLocal.ts +0 -29
@@ -6,7 +6,6 @@ import { ingestInCache } from '~/cache/api/ingestInCache';
6
6
  import { prepareChannelPayload } from '../utils';
7
7
  import { deleteChannelUnreadByChannelId } from '../../marker/utils/deleteChannelUnreadByChannelId';
8
8
  import { addFlagIsDeletedSubChannelUnreadByChannelId } from '~/marker/utils/addFlagIsDeletedSubChannelUnreadByChannelId';
9
- import { dropFromCache } from '~/cache/api';
10
9
 
11
10
  type CallbackFn = (
12
11
  channel: Amity.StaticInternalChannel,
@@ -41,17 +40,10 @@ export const onChannelLeft = (
41
40
  isMessagePreviewUpdated: isLeftByMe,
42
41
  });
43
42
 
44
- const isConsistentMode = client.getMarkerSyncConsistentMode() && client.isUnreadCountEnabled;
45
- const isLegacyUnreadCount = client.useLegacyUnreadCount;
46
-
47
- if (isLeftByMe) {
43
+ if (client.isUnreadCountEnabled && client.getMarkerSyncConsistentMode() && isLeftByMe) {
48
44
  preparedPayload.channels.forEach(channel => {
49
- if (isConsistentMode) {
50
- addFlagIsDeletedSubChannelUnreadByChannelId(channel.channelId);
51
- deleteChannelUnreadByChannelId(channel.channelId);
52
- } else if (isLegacyUnreadCount) {
53
- dropFromCache(['channelUnread', 'get', channel.channelId]);
54
- }
45
+ addFlagIsDeletedSubChannelUnreadByChannelId(channel.channelId);
46
+ deleteChannelUnreadByChannelId(channel.channelId);
55
47
  });
56
48
  }
57
49
 
@@ -32,9 +32,8 @@ import { isEqual } from '~/utils/isEqual';
32
32
  import { updateChannelCache } from '../utils/updateChannelCache';
33
33
  import { onChannelMarkerUpdated } from '~/marker/events/onChannelMarkerUpdated';
34
34
  import { onSubChannelCreated } from '~/subChannelRepository';
35
- import { onChannelUnreadInfoUpdatedLocal } from '~/marker/events/onChannelUnreadInfoUpdatedLocal';
35
+ import { onChannelUnreadUpdatedLocal } from '~/marker/events/onChannelUnreadUpdatedLocal';
36
36
  import { constructChannelObject } from '../utils/constructChannelObject';
37
- import { onChannelUnreadUpdatedLocal } from '../events/onChannelUnreadUpdatedLocal';
38
37
 
39
38
  /* begin_public_function
40
39
  id: channel.get
@@ -296,7 +295,6 @@ export const getChannel = (
296
295
  'channel',
297
296
  ),
298
297
  convertEventPayload(onSubChannelCreated, 'channelId', 'channel'),
299
- convertEventPayload(onChannelUnreadInfoUpdatedLocal, 'channelId', 'channel'),
300
298
  convertEventPayload(onChannelUnreadUpdatedLocal, 'channelId', 'channel'),
301
299
  ],
302
300
  {
@@ -55,9 +55,8 @@ import { prepareUnreadCountInfo } from '~/channelRepository/utils/prepareUnreadC
55
55
  import { resolveUnreadInfoOnChannelEvent } from '~/channelRepository/utils/resolveUnreadInfoOnChannelEvent';
56
56
  import { onChannelResolved } from '~/channelRepository/events/onChannelResolved';
57
57
  import { onUserMessageFeedMarkerResolved } from '~/marker/events/onUserMessageFeedMarkerResolved';
58
- import { onChannelUnreadInfoUpdatedLocal } from '~/marker/events/onChannelUnreadInfoUpdatedLocal';
58
+ import { onChannelUnreadUpdatedLocal } from '~/marker/events/onChannelUnreadUpdatedLocal';
59
59
  import { constructChannelObject } from '~/channelRepository/utils/constructChannelObject';
60
- import { onChannelUnreadUpdatedLocal } from '~/channelRepository/events/onChannelUnreadUpdatedLocal';
61
60
 
62
61
  export class ChannelLiveCollectionController extends LiveCollectionController<
63
62
  'channel',
@@ -567,10 +566,6 @@ export class ChannelLiveCollectionController extends LiveCollectionController<
567
566
  },
568
567
  action: Amity.ChannelActionType.OnResolveUnread,
569
568
  },
570
- {
571
- fn: convertEventPayload(onChannelUnreadInfoUpdatedLocal, 'channelId', 'channel'),
572
- action: Amity.ChannelActionType.OnUpdate,
573
- },
574
569
  {
575
570
  fn: convertEventPayload(onChannelUnreadUpdatedLocal, 'channelId', 'channel'),
576
571
  action: Amity.ChannelActionType.OnUpdate,
@@ -1,3 +1,2 @@
1
1
  export * from './getChannel';
2
2
  export * from './getChannels';
3
- export * from './getTotalChannelsUnread';
@@ -1,27 +1,17 @@
1
- import { get } from 'http';
2
1
  import { shallowClone } from '~/utils/shallowClone';
3
2
  import { getChannelIsMentioned } from './getChannelIsMentioned';
4
3
  import { getSubChannelsUnreadCount } from './getSubChannelsUnreadCount';
5
- import { getActiveClient } from '~/client/api/activeClient';
6
- import { getLegacyChannelUnread } from './getLegacyChannelUnread';
7
4
 
8
5
  export const constructChannelDynamicValue = (
9
6
  channel: Amity.StaticInternalChannel,
10
7
  ): Amity.InternalChannel => {
11
- const client = getActiveClient();
12
8
  const { messageCount, ...rest } = channel;
13
-
14
9
  return shallowClone(rest, {
15
- get unreadCount() {
16
- return getLegacyChannelUnread(rest.channelId)?.unreadCount ?? 0;
10
+ get isMentioned() {
11
+ return getChannelIsMentioned(rest);
17
12
  },
18
13
  get subChannelsUnreadCount() {
19
14
  return getSubChannelsUnreadCount(rest);
20
15
  },
21
- get isMentioned() {
22
- if (client.useLegacyUnreadCount)
23
- return getLegacyChannelUnread(rest.channelId)?.isMentioned ?? false;
24
- return getChannelIsMentioned(rest);
25
- },
26
16
  });
27
17
  };
@@ -5,8 +5,9 @@ import { getChannelMarkers } from '~/marker/api/getChannelMarkers';
5
5
  import { updateChannelMessagePreviewCache } from '~/messagePreview/utils';
6
6
  import { getActiveClient } from '~/client/api/activeClient';
7
7
  import { pullFromCache } from '~/cache/api/pullFromCache';
8
+ import { getSubChannelsUnreadCount } from './getSubChannelsUnreadCount';
9
+ import { getChannelIsMentioned } from './getChannelIsMentioned';
8
10
  import { convertRawUserToInternalUser } from '~/userRepository/utils/convertRawUserToInternalUser';
9
- import { pushToCache } from '~/cache/api';
10
11
 
11
12
  export const MARKER_INCLUDED_CHANNEL_TYPE = ['broadcast', 'conversation', 'community'];
12
13
  export const isUnreadCountSupport = ({ type }: Pick<Amity.RawChannel, 'type'>) =>
@@ -47,48 +48,6 @@ export const preUpdateChannelCache = (
47
48
  });
48
49
  };
49
50
 
50
- const updateChannelUnread = ({
51
- currentUserId,
52
- channels,
53
- channelUsers,
54
- }: {
55
- currentUserId: Amity.User['userId'];
56
- channels: Amity.RawChannel[];
57
- channelUsers: Amity.RawMembership<'channel'>[];
58
- }) => {
59
- for (let i = 0; i < channels.length; i += 1) {
60
- const cacheKey = ['channelUnread', 'get', channels[i].channelId];
61
- const channelUser = channelUsers.find(
62
- channelUser =>
63
- channelUser.channelId === channels[i].channelId && channelUser.userId === currentUserId,
64
- );
65
-
66
- let unreadCount = 0;
67
- let readToSegment = null;
68
- let lastMentionedSegment = null;
69
- let isMentioned = false;
70
-
71
- if (channelUser) {
72
- readToSegment = channelUser.readToSegment;
73
- lastMentionedSegment = channelUser.lastMentionedSegment;
74
- unreadCount = Math.max(channels[i].messageCount - readToSegment, 0);
75
- isMentioned = lastMentionedSegment > readToSegment;
76
- }
77
-
78
- const cacheChannelUnread: Amity.ChannelUnread = {
79
- channelId: channels[i].channelId,
80
- lastSegment: channels[i].messageCount,
81
- readToSegment,
82
- lastMentionedSegment,
83
- unreadCount,
84
- isMentioned,
85
- isDeleted: channels[i].isDeleted || false,
86
- };
87
-
88
- pushToCache(cacheKey, cacheChannelUnread);
89
- }
90
- };
91
-
92
51
  export const prepareChannelPayload = async (
93
52
  rawPayload: Amity.ChannelPayload,
94
53
  options: { isMessagePreviewUpdated?: boolean } = { isMessagePreviewUpdated: true },
@@ -105,38 +64,28 @@ export const prepareChannelPayload = async (
105
64
  updateChannelMessagePreviewCache(rawPayload);
106
65
  }
107
66
 
108
- if (client.useLegacyUnreadCount) {
109
- updateChannelUnread({
110
- channels: rawPayload.channels,
111
- channelUsers: rawPayload.channelUsers,
112
- currentUserId: client.userId!,
113
- });
114
- } else {
115
- const markerIds = rawPayload.channels
116
- // filter channel by type. Only conversation, community and broadcast type are included.
117
- .filter(isUnreadCountSupport)
118
- .map(({ channelInternalId }) => channelInternalId);
119
-
120
- if (markerIds.length > 0) {
121
- // since the get markers method requires a channel cache to function with the reducer.
122
- preUpdateChannelCache(rawPayload, {
123
- isMessagePreviewUpdated: options.isMessagePreviewUpdated,
124
- });
125
-
126
- try {
127
- await getChannelMarkers(markerIds);
128
- } catch (e) {
129
- // empty block (from the spec, allow marker fetch to fail without having to do anything)
130
- }
67
+ const markerIds = rawPayload.channels
68
+ // filter channel by type. Only conversation, community and broadcast type are included.
69
+ .filter(isUnreadCountSupport)
70
+ .map(({ channelInternalId }) => channelInternalId);
71
+
72
+ if (markerIds.length > 0) {
73
+ // since the get markers method requires a channel cache to function with the reducer.
74
+ preUpdateChannelCache(rawPayload, { isMessagePreviewUpdated: options.isMessagePreviewUpdated });
75
+
76
+ try {
77
+ await getChannelMarkers(markerIds);
78
+ } catch (e) {
79
+ // empty block (from the spec, allow marker fetch to fail without having to do anything)
131
80
  }
132
81
  }
133
82
 
134
- // convert raw channel to internal channel
83
+ // attach marker to channel
135
84
  const channels = rawPayload.channels.map(payload =>
136
85
  convertFromRaw(payload, { isMessagePreviewUpdated: options.isMessagePreviewUpdated }),
137
86
  );
138
87
 
139
- // convert raw channel user to membership (add user object)
88
+ // user marker to channel users
140
89
  const channelUsers: Amity.Membership<'channel'>[] = rawPayload.channelUsers.map(channelUser => {
141
90
  return convertRawMembershipToMembership<'channel'>(channelUser);
142
91
  });
@@ -50,7 +50,7 @@ export const createClient = (
50
50
  rteEnabled = true,
51
51
  }: {
52
52
  debugSession?: string;
53
- apiEndpoint?: { http?: string; mqtt?: string; upload?: string };
53
+ apiEndpoint?: { http?: string; mqtt?: string };
54
54
  prefixDeviceIdKey?: string;
55
55
  rteEnabled?: boolean;
56
56
  } = {},
@@ -63,11 +63,9 @@ export const createClient = (
63
63
  });
64
64
 
65
65
  const httpEndpoint = apiEndpoint?.http ?? computeUrl('http', apiRegion);
66
- const uploadEndpoint = apiEndpoint?.upload ?? computeUrl('upload', apiRegion);
67
66
  const mqttEndpoint = apiEndpoint?.mqtt ?? computeUrl('mqtt', apiRegion);
68
67
 
69
68
  const http = createHttpTransport(httpEndpoint);
70
- const upload = createHttpTransport(uploadEndpoint);
71
69
 
72
70
  let ws;
73
71
  let mqtt;
@@ -88,8 +86,6 @@ export const createClient = (
88
86
  const sessionHandler = undefined;
89
87
 
90
88
  const isUnreadCountEnabled = false;
91
- // Legacy unread count is true by default
92
- const useLegacyUnreadCount = true;
93
89
 
94
90
  const client = {
95
91
  version: `${VERSION}`,
@@ -107,7 +103,6 @@ export const createClient = (
107
103
  http,
108
104
  ws,
109
105
  mqtt,
110
- upload,
111
106
  emitter,
112
107
 
113
108
  /*
@@ -127,7 +122,6 @@ export const createClient = (
127
122
  use: () => setActiveClient(client),
128
123
 
129
124
  isUnreadCountEnabled,
130
- useLegacyUnreadCount,
131
125
 
132
126
  getMarkerSyncConsistentMode,
133
127
 
@@ -17,7 +17,6 @@ export const enableUnreadCount = () => {
17
17
  if (client.isUnreadCountEnabled) return false;
18
18
 
19
19
  client.isUnreadCountEnabled = true;
20
- client.useLegacyUnreadCount = false;
21
20
 
22
21
  client.emitter.emit('unreadCountEnabled', true);
23
22
 
@@ -11,7 +11,6 @@ import { onUserDeleted } from '~/userRepository/events/onUserDeleted';
11
11
 
12
12
  import analyticsEngineOnLoginHandler from '~/analytic/utils/analyticsEngineOnLoginHandler';
13
13
  import readReceiptSyncEngineOnLoginHandler from '~/client/utils/ReadReceiptSync/readReceiptSyncEngineOnLoginHandler';
14
- import legacyReadReceiptSyncEngineOnLoginHandler from '~/client/utils/ReadReceiptSync/legacyReadReceiptSyncEngineOnLoginHandler';
15
14
  import objectResolverEngineOnLoginHandler from '~/client/utils/ObjectResolver/objectResolverEngineOnLoginHandler';
16
15
  import { logout } from './logout';
17
16
 
@@ -201,13 +200,10 @@ export const login = async (
201
200
 
202
201
  markReadEngineOnLoginHandler(),
203
202
  analyticsEngineOnLoginHandler(),
203
+ readReceiptSyncEngineOnLoginHandler(),
204
204
  objectResolverEngineOnLoginHandler(),
205
205
  );
206
206
 
207
- if (client.useLegacyUnreadCount) {
208
- subscriptions.push(readReceiptSyncEngineOnLoginHandler());
209
- } else subscriptions.push(legacyReadReceiptSyncEngineOnLoginHandler());
210
-
211
207
  const markerSyncUnsubscriber = await startMarkerSync();
212
208
  subscriptions.push(markerSyncUnsubscriber);
213
209
  }
@@ -1,7 +1,8 @@
1
1
  import { pullFromCache, pushToCache, queryCache } from '~/cache/api';
2
2
  import { getActiveClient } from '../../api/activeClient';
3
+ import { markAsReadBySegment } from '~/subChannelRepository/api/markAsReadBySegment';
4
+ import { reCalculateChannelUnreadInfo } from '~/marker/utils/reCalculateChannelUnreadInfo';
3
5
  import { fireEvent } from '~/core/events';
4
- import { markChannelsAsReadBySegment } from '~/channelRepository/api/markChannelsAsReadBySegment';
5
6
 
6
7
  export class MessageReadReceiptSyncEngine {
7
8
  private client: Amity.Client;
@@ -37,9 +38,9 @@ export class MessageReadReceiptSyncEngine {
37
38
  syncReadReceipts(): void {
38
39
  if (this.jobQueue.length === 0 || this.isActive === false) return;
39
40
 
40
- const readReceipts = this.getReadReceipts();
41
- if (readReceipts) {
42
- this.markReadApi(readReceipts);
41
+ const readReceipt = this.getReadReceipt();
42
+ if (readReceipt) {
43
+ this.markReadApi(readReceipt);
43
44
  }
44
45
  }
45
46
 
@@ -51,64 +52,79 @@ export class MessageReadReceiptSyncEngine {
51
52
 
52
53
  // Enqueue unsync read receipts to the job queue
53
54
  readReceipts?.forEach(({ data: readReceipt }) => {
54
- this.enqueueReadReceipt(readReceipt.channelId, readReceipt.latestSegment);
55
+ this.enqueueReadReceipt(readReceipt.subChannelId, readReceipt.latestSegment);
55
56
  });
56
57
  }
57
58
 
58
- private getReadReceipts(): Amity.ReadReceiptSyncJob[] | undefined {
59
- // get all read receipts from queue, now the queue is empty
60
- const syncJob = this.jobQueue.splice(0, this.jobQueue.length);
61
- if (syncJob.length === 0) return;
59
+ private getReadReceipt(): Amity.ReadReceiptSyncJob | undefined {
60
+ // Get first read receipt in queue
61
+ const syncJob = this.jobQueue[0];
62
62
 
63
- return syncJob.filter(job => {
64
- const readReceipt = pullFromCache<Amity.ReadReceipt>(['readReceipt', job.channelId])?.data;
65
- if (!readReceipt) return false;
66
- if (readReceipt.latestSegment > readReceipt.latestSyncSegment) return true;
67
- return false;
68
- });
63
+ if (!syncJob) return;
64
+ // Skip when it's syncing
65
+ if (syncJob.syncState === Amity.ReadReceiptSyncState.SYNCING) return;
66
+
67
+ // Get readReceipt from cache by subChannelId
68
+ const readReceipt = pullFromCache<Amity.ReadReceipt>([
69
+ 'readReceipt',
70
+ syncJob.subChannelId,
71
+ ])?.data;
72
+
73
+ if (!readReceipt) return;
74
+
75
+ if (readReceipt?.latestSegment > readReceipt?.latestSyncSegment) {
76
+ syncJob.segment = readReceipt.latestSegment;
77
+ return syncJob;
78
+ }
79
+ // Clear all synced job in job queue
80
+ this.removeSynedReceipt(readReceipt.subChannelId, readReceipt.latestSegment);
81
+
82
+ // Recursion getReadReceipt() until get unsync read receipt or job queue is empty
83
+ return this.getReadReceipt();
69
84
  }
70
85
 
71
- private async markReadApi(syncJobs: Amity.ReadReceiptSyncJob[]): Promise<void> {
72
- // constuct payload
73
- // example: [{ channelId: 'channelId', readToSegment: 2 }]
74
- const syncJobsPayload = syncJobs.map(job => {
75
- return {
76
- channelId: job.channelId,
77
- readToSegment: job.segment,
78
- };
79
- });
86
+ private async markReadApi(syncJob: Amity.ReadReceiptSyncJob): Promise<void> {
87
+ const newSyncJob = syncJob;
88
+ newSyncJob.syncState = Amity.ReadReceiptSyncState.SYNCING;
89
+
90
+ const { subChannelId, segment } = newSyncJob;
80
91
 
81
- const response = await markChannelsAsReadBySegment(syncJobsPayload);
92
+ const response = await markAsReadBySegment({ subChannelId, readToSegment: segment });
82
93
 
83
94
  if (response) {
84
- for (let i = 0; i < syncJobs.length; i += 1) {
85
- // update lastestSyncSegment in read receipt cache
86
- const cacheKey = ['readReceipt', syncJobs[i].channelId];
87
- const readReceiptCache = pullFromCache<Amity.ReadReceipt>(cacheKey)?.data;
88
-
89
- pushToCache(cacheKey, {
90
- ...readReceiptCache,
91
- latestSyncSegment: syncJobs[i].segment,
92
- });
95
+ this.removeSynedReceipt(syncJob.subChannelId, syncJob.segment);
96
+
97
+ const readReceiptCache = pullFromCache<Amity.ReadReceipt>([
98
+ 'readReceipt',
99
+ subChannelId,
100
+ ])?.data;
101
+
102
+ pushToCache(['readReceipt', subChannelId], {
103
+ ...readReceiptCache,
104
+ latestSyncSegment: segment,
105
+ });
106
+ } else if (!response) {
107
+ if (newSyncJob.retryCount > this.MAX_RETRY) {
108
+ this.removeJobFromQueue(newSyncJob);
109
+ } else {
110
+ newSyncJob.retryCount += 1;
111
+ newSyncJob.syncState = Amity.ReadReceiptSyncState.CREATED;
93
112
  }
94
- } else {
95
- for (let i = 0; i < syncJobs.length; i += 1) {
96
- // push them back to queue if the syncing is failed and retry count is less than max retry
97
- if (syncJobs[i].retryCount >= this.MAX_RETRY) return;
113
+ }
114
+ }
98
115
 
99
- const updatedJob = {
100
- ...syncJobs[i],
101
- syncState: Amity.ReadReceiptSyncState.CREATED,
102
- retryCount: syncJobs[i].retryCount + 1,
103
- };
116
+ private removeSynedReceipt(subChannelId: string, segment: number) {
117
+ const syncJobs = this.jobQueue;
104
118
 
105
- this.enqueueJob(updatedJob);
119
+ syncJobs.forEach(job => {
120
+ if (job.subChannelId === subChannelId && job.segment <= segment) {
121
+ this.removeJobFromQueue(job);
106
122
  }
107
- }
123
+ });
108
124
  }
109
125
 
110
126
  private startObservingReadReceiptQueue(): void {
111
- if (this.client.useLegacyUnreadCount) {
127
+ if (this.client.isUnreadCountEnabled) {
112
128
  this.isActive = true;
113
129
  this.startSyncReadReceipt();
114
130
  }
@@ -117,7 +133,8 @@ export class MessageReadReceiptSyncEngine {
117
133
  private stopObservingReadReceiptQueue(): void {
118
134
  this.isActive = false;
119
135
 
120
- this.jobQueue.map(job => {
136
+ const syncJobs = this.jobQueue;
137
+ syncJobs.map(job => {
121
138
  if (job.syncState === Amity.ReadReceiptSyncState.SYNCING) {
122
139
  return { ...job, syncState: Amity.ReadReceiptSyncState.CREATED };
123
140
  }
@@ -153,51 +170,50 @@ export class MessageReadReceiptSyncEngine {
153
170
  this.startObservingReadReceiptQueue();
154
171
  }
155
172
 
156
- markRead(channelId: string, segment: number): void {
157
- // Step 1: Optimistic update of channelUnread.readToSegment to message.segment and update unreadCount value
158
- const cacheKey = ['channelUnread', 'get', channelId];
159
- const channelUnread = pullFromCache<Amity.ChannelUnread>(cacheKey)?.data;
173
+ markRead(subChannelId: string, segment: number): void {
174
+ // Step 1: Optimistic update of subChannelUnreadInfo.readToSegment to message.segment
175
+ const cacheKey = ['subChannelUnreadInfo', 'get', subChannelId];
176
+ const subChannelUnreadInfo = pullFromCache<Amity.SubChannelUnreadInfo>(cacheKey)?.data;
160
177
 
161
- if (
162
- typeof channelUnread?.readToSegment === 'number' &&
163
- channelUnread &&
164
- segment > channelUnread.readToSegment
165
- ) {
166
- channelUnread.readToSegment = segment;
167
- channelUnread.unreadCount = Math.max(channelUnread.lastSegment - segment, 0);
178
+ if (subChannelUnreadInfo && segment > subChannelUnreadInfo.readToSegment) {
179
+ subChannelUnreadInfo.readToSegment = segment;
180
+ subChannelUnreadInfo.unreadCount = Math.max(subChannelUnreadInfo.lastSegment - segment, 0);
168
181
 
169
- pushToCache(cacheKey, channelUnread);
170
- fireEvent('local.channelUnread.updated', channelUnread);
182
+ const channelUnreadInfo = reCalculateChannelUnreadInfo(subChannelUnreadInfo.channelId);
183
+ fireEvent('local.channelUnread.updated', channelUnreadInfo);
184
+
185
+ pushToCache(cacheKey, subChannelUnreadInfo);
186
+ fireEvent('local.subChannelUnread.updated', subChannelUnreadInfo);
171
187
  }
172
188
 
173
189
  // Step 2: Enqueue the read receipt
174
- this.enqueueReadReceipt(channelId, segment);
190
+ this.enqueueReadReceipt(subChannelId, segment);
175
191
  }
176
192
 
177
- private enqueueReadReceipt(channelId: string, segment: number): void {
178
- const readReceipt = pullFromCache<Amity.ReadReceipt>(['readReceipt', channelId])?.data;
193
+ private enqueueReadReceipt(subChannelId: string, segment: number): void {
194
+ const readReceipt = pullFromCache<Amity.ReadReceipt>(['readReceipt', subChannelId])?.data;
179
195
 
180
- // Create new read receipt if it's not exists and add the job to queue
196
+ // Create new read receipt if it's not exists and add job to queue
181
197
  if (!readReceipt) {
182
- const readReceiptChannel: Amity.ReadReceipt = {
183
- channelId,
198
+ const readReceiptSubChannel: Amity.ReadReceipt = {
199
+ subChannelId,
184
200
  latestSegment: segment,
185
201
  latestSyncSegment: 0,
186
202
  };
187
- pushToCache(['readReceipt', channelId], readReceiptChannel);
203
+
204
+ pushToCache(['readReceipt', subChannelId], readReceiptSubChannel);
188
205
  } else if (readReceipt.latestSegment < segment) {
189
- // Update latestSegment in read receipt cache
190
- pushToCache(['readReceipt', channelId], { ...readReceipt, latestSegment: segment });
206
+ pushToCache(['readReceipt', subChannelId], { ...readReceipt, latestSegment: segment });
191
207
  } else if (readReceipt.latestSyncSegment >= segment) {
192
208
  // Skip the job when lastSyncSegment > = segment
193
209
  return;
194
210
  }
195
211
 
196
- let syncJob: Amity.ReadReceiptSyncJob | null = this.getSyncJob(channelId);
212
+ let syncJob: Amity.ReadReceiptSyncJob | null = this.getSyncJob(subChannelId);
197
213
 
198
214
  if (syncJob === null || syncJob.syncState === Amity.ReadReceiptSyncState.SYNCING) {
199
215
  syncJob = {
200
- channelId,
216
+ subChannelId,
201
217
  segment,
202
218
  syncState: Amity.ReadReceiptSyncState.CREATED,
203
219
  retryCount: 0,
@@ -209,9 +225,11 @@ export class MessageReadReceiptSyncEngine {
209
225
  }
210
226
  }
211
227
 
212
- private getSyncJob(channelId: string): Amity.ReadReceiptSyncJob | null {
213
- const { jobQueue } = this;
214
- const targetJob = jobQueue.find(job => job.channelId === channelId);
228
+ private getSyncJob(subChannelId: string): Amity.ReadReceiptSyncJob | null {
229
+ const syncJobs = this.jobQueue;
230
+
231
+ const targetJob = syncJobs.find(job => job.subChannelId === subChannelId);
232
+
215
233
  return targetJob || null;
216
234
  }
217
235
 
@@ -224,6 +242,13 @@ export class MessageReadReceiptSyncEngine {
224
242
  this.jobQueue.push(syncJob);
225
243
  }
226
244
  }
245
+
246
+ private removeJobFromQueue(item: Amity.ReadReceiptSyncJob) {
247
+ const index = this.jobQueue.indexOf(item);
248
+ if (index > -1) {
249
+ this.jobQueue.splice(index, 1);
250
+ }
251
+ }
227
252
  }
228
253
 
229
254
  let instance: MessageReadReceiptSyncEngine | null = null;
@@ -6,7 +6,6 @@ export const API_REGIONS = {
6
6
 
7
7
  const URLS = {
8
8
  http: 'https://apix.{region}.amity.co',
9
- upload: 'https://upload.{region}.amity.co',
10
9
  mqtt: 'wss://sse.{region}.amity.co:443/mqtt',
11
10
  } as const;
12
11
 
@@ -30,14 +30,6 @@ export const setClientToken = async (params: Parameters<typeof getToken>[0]) =>
30
30
  isUserDeleted: false,
31
31
  };
32
32
 
33
- client.upload.defaults.headers.common.Authorization = `Bearer ${accessToken}`;
34
-
35
- client.upload.defaults.metadata = {
36
- tokenExpiry: expiresAt,
37
- isGlobalBanned: false,
38
- isUserDeleted: false,
39
- };
40
-
41
33
  // manually setup the token for ws transport
42
34
  if (client.ws) client.ws.io.opts.query = { token: accessToken };
43
35
 
@@ -26,8 +26,6 @@ const idResolvers: Resolvers = {
26
26
  channelUnreadInfo: ({ channelId }) => channelId,
27
27
  subChannelUnreadInfo: ({ subChannelId }) => subChannelId,
28
28
 
29
- channelUnread: ({ channelId }) => channelId,
30
-
31
29
  channelMarker: ({ entityId, userId }) => `${entityId}#${userId}`,
32
30
  subChannelMarker: ({ entityId, feedId, userId }) => `${entityId}#${feedId}#${userId}`,
33
31
  messageMarker: ({ feedId, contentId, creatorId }) => `${feedId}#${contentId}#${creatorId}`,
@@ -61,6 +59,9 @@ const idResolvers: Resolvers = {
61
59
 
62
60
  pin: ({ placement, referenceId }) => `${placement}#${referenceId}`,
63
61
  pinTarget: ({ targetId }) => targetId,
62
+
63
+ notificationTrayItem: ({ _id }) => _id,
64
+ notificationTraySeen: ({ userId }) => userId,
64
65
  };
65
66
 
66
67
  /**
@@ -52,6 +52,8 @@ export const PAYLOAD2MODEL: Record<string, Amity.Domain> = {
52
52
 
53
53
  pinTargets: 'pinTarget',
54
54
  pins: 'pin',
55
+
56
+ notificationTrayItems: 'notificationTrayItem',
55
57
  };
56
58
 
57
59
  /** hidden */
@@ -42,7 +42,7 @@ export const uploadFile = async <T extends Amity.FileType = any>(
42
42
  ? (formData as any).getHeaders()
43
43
  : { 'content-type': 'multipart/form-data' };
44
44
 
45
- const { data } = await client.upload.post<Amity.CreateFilePayload<T>>('/api/v4/files', formData, {
45
+ const { data } = await client.http.post<Amity.CreateFilePayload<T>>('/api/v4/files', formData, {
46
46
  headers,
47
47
  onUploadProgress({ loaded, total = 100 }) {
48
48
  onProgress && onProgress(Math.round((loaded * 100) / total));
@@ -42,7 +42,7 @@ export const uploadImage = async (
42
42
  ? (formData as any).getHeaders()
43
43
  : { 'content-type': 'multipart/form-data' };
44
44
 
45
- const { data } = await client.upload.post<Amity.CreateFilePayload<'image'>>(
45
+ const { data } = await client.http.post<Amity.CreateFilePayload<'image'>>(
46
46
  '/api/v4/images',
47
47
  formData,
48
48
  {
@@ -48,7 +48,7 @@ export const uploadVideo = async (
48
48
  ? (formData as any).getHeaders()
49
49
  : { 'content-type': 'multipart/form-data' };
50
50
 
51
- const { data } = await client.upload.post<Amity.CreateFilePayload<'video'>>(
51
+ const { data } = await client.http.post<Amity.CreateFilePayload<'video'>>(
52
52
  '/api/v4/videos',
53
53
  formData,
54
54
  {
package/src/index.ts CHANGED
@@ -49,3 +49,5 @@ export * as AdRepository from './adRepository';
49
49
 
50
50
  // // external apis
51
51
  export * from './external/api';
52
+
53
+ export * as notificationTray from './notificationTray';