@amityco/ts-sdk-react-native 6.25.2-843ba7e.0 → 6.26.1-4e1acd6.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 (68) hide show
  1. package/dist/@types/core/model.d.ts +4 -0
  2. package/dist/@types/core/model.d.ts.map +1 -1
  3. package/dist/@types/core/payload.d.ts +7 -0
  4. package/dist/@types/core/payload.d.ts.map +1 -1
  5. package/dist/@types/domains/ad.d.ts +74 -0
  6. package/dist/@types/domains/ad.d.ts.map +1 -0
  7. package/dist/@types/domains/analytics.d.ts +3 -1
  8. package/dist/@types/domains/analytics.d.ts.map +1 -1
  9. package/dist/@types/index.d.ts +2 -0
  10. package/dist/@types/index.d.ts.map +1 -1
  11. package/dist/adRepository/api/getNetworkAds.d.ts +2 -0
  12. package/dist/adRepository/api/getNetworkAds.d.ts.map +1 -0
  13. package/dist/adRepository/api/index.d.ts +2 -0
  14. package/dist/adRepository/api/index.d.ts.map +1 -0
  15. package/dist/adRepository/index.d.ts +2 -0
  16. package/dist/adRepository/index.d.ts.map +1 -0
  17. package/dist/analytic/service/analytic/AnalyticsEngine.d.ts +2 -0
  18. package/dist/analytic/service/analytic/AnalyticsEngine.d.ts.map +1 -1
  19. package/dist/analytic/service/analytic/AnalyticsEventCapturer.d.ts +3 -0
  20. package/dist/analytic/service/analytic/AnalyticsEventCapturer.d.ts.map +1 -1
  21. package/dist/client/api/getToken.d.ts +1 -1
  22. package/dist/client/api/getToken.d.ts.map +1 -1
  23. package/dist/commentRepository/observers/getComments/CommentLiveCollectionController.d.ts +14 -0
  24. package/dist/commentRepository/observers/getComments/CommentLiveCollectionController.d.ts.map +1 -0
  25. package/dist/commentRepository/observers/getComments/CommentPaginationController.d.ts +5 -0
  26. package/dist/commentRepository/observers/getComments/CommentPaginationController.d.ts.map +1 -0
  27. package/dist/commentRepository/observers/getComments/CommentQueryStreamController.d.ts +15 -0
  28. package/dist/commentRepository/observers/getComments/CommentQueryStreamController.d.ts.map +1 -0
  29. package/dist/commentRepository/observers/getComments/enums.d.ts +10 -0
  30. package/dist/commentRepository/observers/getComments/enums.d.ts.map +1 -0
  31. package/dist/commentRepository/observers/getComments.d.ts.map +1 -1
  32. package/dist/commentRepository/utils/payload.d.ts +2 -0
  33. package/dist/commentRepository/utils/payload.d.ts.map +1 -0
  34. package/dist/core/model/idResolvers.d.ts.map +1 -1
  35. package/dist/core/model/index.d.ts.map +1 -1
  36. package/dist/index.cjs.js +309 -169
  37. package/dist/index.d.ts +1 -0
  38. package/dist/index.d.ts.map +1 -1
  39. package/dist/index.esm.js +293 -154
  40. package/dist/index.umd.js +3 -3
  41. package/dist/utils/linkedObject/adLinkedObject.d.ts +2 -0
  42. package/dist/utils/linkedObject/adLinkedObject.d.ts.map +1 -0
  43. package/dist/utils/linkedObject/index.d.ts +1 -0
  44. package/dist/utils/linkedObject/index.d.ts.map +1 -1
  45. package/package.json +1 -1
  46. package/src/@types/core/model.ts +6 -0
  47. package/src/@types/core/payload.ts +12 -0
  48. package/src/@types/domains/ad.ts +88 -0
  49. package/src/@types/domains/analytics.ts +2 -0
  50. package/src/@types/index.ts +2 -0
  51. package/src/adRepository/api/getNetworkAds.ts +24 -0
  52. package/src/adRepository/api/index.ts +1 -0
  53. package/src/adRepository/index.ts +1 -0
  54. package/src/analytic/service/analytic/AnalyticsEngine.ts +18 -0
  55. package/src/analytic/service/analytic/AnalyticsEventCapturer.ts +49 -8
  56. package/src/client/api/getToken.ts +1 -1
  57. package/src/client/api/login.ts +1 -1
  58. package/src/commentRepository/observers/getComments/CommentLiveCollectionController.ts +132 -0
  59. package/src/commentRepository/observers/getComments/CommentPaginationController.ts +25 -0
  60. package/src/commentRepository/observers/getComments/CommentQueryStreamController.ts +90 -0
  61. package/src/commentRepository/observers/getComments/enums.ts +9 -0
  62. package/src/commentRepository/observers/getComments.ts +5 -141
  63. package/src/commentRepository/utils/payload.ts +5 -0
  64. package/src/core/model/idResolvers.ts +3 -0
  65. package/src/core/model/index.ts +2 -0
  66. package/src/index.ts +3 -0
  67. package/src/utils/linkedObject/adLinkedObject.ts +50 -0
  68. package/src/utils/linkedObject/index.ts +2 -0
@@ -0,0 +1,2 @@
1
+ export declare const adLinkedObject: (ad: Amity.RawAd) => Amity.Ad;
2
+ //# sourceMappingURL=adLinkedObject.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"adLinkedObject.d.ts","sourceRoot":"","sources":["../../../src/utils/linkedObject/adLinkedObject.ts"],"names":[],"mappings":"AAGA,eAAO,MAAM,cAAc,OAAQ,MAAM,KAAK,KAAG,MAAM,EA8CtD,CAAC"}
@@ -1,4 +1,5 @@
1
1
  export declare const LinkedObject: {
2
+ ad: (ad: Amity.RawAd) => Amity.Ad;
2
3
  comment: (comment: Amity.InternalComment<any>) => Amity.Comment<any>;
3
4
  post: (post: Amity.InternalPost<any>) => Amity.Post<any>;
4
5
  user: (user: Amity.InternalUser) => Amity.User;
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/utils/linkedObject/index.ts"],"names":[],"mappings":"AAWA,eAAO,MAAM,YAAY;;;;;;;;;;;CAWxB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/utils/linkedObject/index.ts"],"names":[],"mappings":"AAYA,eAAO,MAAM,YAAY;;;;;;;;;;;;CAYxB,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@amityco/ts-sdk-react-native",
3
- "version": "6.25.2-843ba7e.0",
3
+ "version": "6.26.1-4e1acd6.0",
4
4
  "license": "CC-BY-ND-4.0",
5
5
  "author": "amity.co <developers@amity.co> (https://amity.co)",
6
6
  "description": "Amity Social Cloud Typescript SDK",
@@ -49,6 +49,9 @@ declare global {
49
49
  followCount: Amity.FollowCount;
50
50
 
51
51
  feed: Amity.Feed;
52
+
53
+ ad: Pick<Amity.Ad, 'adId'>;
54
+ advertiser: Pick<Amity.AdvertiserItem, 'advertiserId'>;
52
55
  };
53
56
 
54
57
  type Model = ValueOf<Models>;
@@ -102,6 +105,9 @@ declare global {
102
105
  followCount: Pick<Amity.FollowInfo, 'userId' | 'followerCount'>;
103
106
 
104
107
  feed: Pick<Amity.Feed, 'targetId' | 'feedId'>;
108
+
109
+ ad: Pick<Amity.Ad, 'adId'>;
110
+ advertiser: Pick<Amity.AdvertiserItem, 'advertiserId'>;
105
111
  };
106
112
  }
107
113
  }
@@ -34,6 +34,13 @@ declare global {
34
34
  }[];
35
35
  };
36
36
 
37
+ type AdPayload = {
38
+ ads: Amity.RawAd[];
39
+ advertisers: Amity.RawAdvertiser[];
40
+ files: Amity.File[];
41
+ settings: Amity.AdsSettings;
42
+ };
43
+
37
44
  // API-FIX: backend should return a payload like { files: Amity.File<T>[] }
38
45
  type CreateFilePayload<T extends Amity.FileType = any> = Amity.File<T>[];
39
46
  type FilePayload<T extends Amity.FileType = any> = Amity.File<T>;
@@ -354,6 +361,11 @@ declare global {
354
361
  communityUsers: Amity.Membership<'community'>[];
355
362
  };
356
363
 
364
+ type ProcessedCommentPayload<T extends Amity.CommentContentType = any> = Omit<
365
+ CommentPayload<T>,
366
+ 'users' | 'files' | 'communityUsers'
367
+ >;
368
+
357
369
  type PollPayload = {
358
370
  users: Amity.InternalUser[];
359
371
  polls: Amity.Poll[];
@@ -0,0 +1,88 @@
1
+ export {};
2
+
3
+ declare global {
4
+ namespace Amity {
5
+ const enum AdPlacement {
6
+ FEED = 'feed',
7
+ STORY = 'story',
8
+ COMMENT = 'comment',
9
+ CHATLIST = 'chatlist',
10
+ CHAT = 'chat',
11
+ }
12
+
13
+ const enum SettingDisplayType {
14
+ Fixed = 'fixed',
15
+ TimeWindow = 'time-window',
16
+ }
17
+
18
+ type AdTarget = {
19
+ communityIds: Amity.Community['communityId'][];
20
+ };
21
+
22
+ type RawAd = {
23
+ adId: string;
24
+ advertiserId: string;
25
+ name: string;
26
+ placements: AdPlacement[];
27
+ headline: string;
28
+ description: string;
29
+ body: string;
30
+ image1_1: string;
31
+ image9_16: string;
32
+ callToAction: string;
33
+ callToActionUrl: string;
34
+ targets: Amity.AdTarget;
35
+ startAt: Amity.timestamp;
36
+ endAt: Amity.timestamp;
37
+ createdAt: Amity.timestamp;
38
+ updatedAt: Amity.timestamp;
39
+ };
40
+
41
+ type RawAdvertiser = {
42
+ advertiserId: string;
43
+ name: string;
44
+ companyName: string;
45
+ avatarFileId: string;
46
+ adsCount: number;
47
+ createdAt: Amity.timestamp;
48
+ updatedAt: Amity.timestamp;
49
+ };
50
+
51
+ type AdFrequency = {
52
+ type: Amity.SettingDisplayType;
53
+ value: number;
54
+ };
55
+
56
+ type FrequencySettings = {
57
+ feed?: Amity.AdFrequency;
58
+ story?: Amity.AdFrequency;
59
+ comment?: Amity.AdFrequency;
60
+ };
61
+
62
+ type AdsSettings = {
63
+ enabled: boolean;
64
+ maxActiveAds: number;
65
+ frequency: Amity.FrequencySettings;
66
+ updatedAt: Amity.timestamp;
67
+ };
68
+
69
+ type Advertiser = RawAdvertiser & {
70
+ avatar?: Amity.File<'image'>;
71
+ };
72
+
73
+ type Ad = Omit<RawAd, 'image1_1' | 'image9_16'> & {
74
+ advertiser?: Amity.Advertiser;
75
+ image1_1?: Amity.File<'image'>;
76
+ image9_16?: Amity.File<'image'>;
77
+ // analytics: {
78
+ // markAsSeen: (placement: Amity.AdPlacement) => void;
79
+ // markLinkAsClicked: (placement: Amity.AdPlacement) => void;
80
+ // };
81
+ };
82
+
83
+ type NetworkAds = {
84
+ ads: Amity.Ad[];
85
+ settings: Amity.AdsSettings;
86
+ };
87
+ }
88
+ }
@@ -10,6 +10,7 @@ declare global {
10
10
  const enum AnalyticEventContentType {
11
11
  Post = 'post',
12
12
  Story = 'story',
13
+ Ad = 'ad',
13
14
  }
14
15
 
15
16
  type AnalyticEventModel = {
@@ -17,6 +18,7 @@ declare global {
17
18
  contentType: AnalyticEventContentType;
18
19
  activityType: AnalyticEventActivityType;
19
20
  timestamp: Amity.timestamp;
21
+ metadata?: Record<string, string>;
20
22
  };
21
23
 
22
24
  type AnalyticPostData = {
@@ -35,3 +35,5 @@ export * from './domains/content';
35
35
  export * from './domains/file';
36
36
  export * from './domains/message';
37
37
  export * from './domains/post';
38
+ export * from './domains/story';
39
+ export * from './domains/ad';
@@ -0,0 +1,24 @@
1
+ import { getActiveClient } from '~/client';
2
+ import { ingestInCache } from '~/cache/api/ingestInCache';
3
+ import { pushToCache } from '~/cache/api';
4
+ import { LinkedObject } from '~/utils/linkedObject';
5
+
6
+ const convertToNetworkAds = (data: Amity.AdPayload): Amity.NetworkAds => {
7
+ const { ads, settings } = data;
8
+
9
+ return {
10
+ ads: ads.map(LinkedObject.ad),
11
+ settings,
12
+ };
13
+ };
14
+
15
+ export const getNetworkAds = async (): Promise<Amity.NetworkAds> => {
16
+ const client = getActiveClient();
17
+
18
+ const { data } = await client.http.get<Amity.AdPayload>('/api/v1/ads/me');
19
+ const { settings, ...rest } = data;
20
+ ingestInCache(rest as Omit<Amity.AdPayload, 'settings'>);
21
+ pushToCache(['ad', 'setting'], settings);
22
+
23
+ return convertToNetworkAds(data);
24
+ };
@@ -0,0 +1 @@
1
+ export { getNetworkAds } from './getNetworkAds';
@@ -0,0 +1 @@
1
+ export * from './api';
@@ -33,6 +33,24 @@ class AnalyticsEngine {
33
33
  }
34
34
  }
35
35
 
36
+ markAdAsViewed(ad: Amity.RawAd, placement: Amity.AdPlacement) {
37
+ if (
38
+ this._client.sessionState === Amity.SessionStates.ESTABLISHED ||
39
+ this._client.sessionState === Amity.SessionStates.TOKEN_EXPIRED
40
+ ) {
41
+ this._eventCapturer.markAdAsViewed(ad, placement);
42
+ }
43
+ }
44
+
45
+ markAdAsClicked(ad: Amity.RawAd, placement: Amity.AdPlacement) {
46
+ if (
47
+ this._client.sessionState === Amity.SessionStates.ESTABLISHED ||
48
+ this._client.sessionState === Amity.SessionStates.TOKEN_EXPIRED
49
+ ) {
50
+ this._eventCapturer.markAdAsClicked(ad, placement);
51
+ }
52
+ }
53
+
36
54
  markStoryAsClicked(story: Amity.InternalStory) {
37
55
  if (
38
56
  this._client.sessionState === Amity.SessionStates.ESTABLISHED ||
@@ -48,8 +48,13 @@ export class AnalyticsEventCapturer {
48
48
  return true;
49
49
  }
50
50
 
51
- markPostAsViewed(postId: Amity.InternalPost['postId']) {
52
- if (!this.isAbleToEnqueue({ itemId: postId, expireTime: this._expireTime })) return;
51
+ markAs(
52
+ itemId: string,
53
+ contentType: Amity.AnalyticEventContentType,
54
+ activityType: Amity.AnalyticEventActivityType,
55
+ metadata: Record<string, string> | undefined = undefined,
56
+ ) {
57
+ if (!this.isAbleToEnqueue({ itemId, expireTime: this._expireTime })) return;
53
58
 
54
59
  const now = new Date();
55
60
 
@@ -66,15 +71,25 @@ export class AnalyticsEventCapturer {
66
71
  currentData.event.shift();
67
72
  }
68
73
 
69
- currentData.event.push({
70
- contentId: postId,
71
- contentType: Amity.AnalyticEventContentType.Post,
72
- activityType: Amity.AnalyticEventActivityType.View,
74
+ const analyticItem: Amity.AnalyticEventModel = {
75
+ contentId: itemId,
76
+ contentType,
77
+ activityType,
73
78
  timestamp: now.toISOString(),
74
- });
79
+ };
80
+
81
+ if (metadata) {
82
+ analyticItem.metadata = metadata;
83
+ }
84
+
85
+ currentData.event.push(analyticItem);
75
86
 
76
87
  upsertInCache(ANALYTIC_CACHE_KEY, currentData);
77
- this._recentViewed[postId] = now;
88
+ this._recentViewed[itemId] = now;
89
+ }
90
+
91
+ markPostAsViewed(postId: Amity.InternalPost['postId']) {
92
+ this.markAs(postId, Amity.AnalyticEventContentType.Post, Amity.AnalyticEventActivityType.View);
78
93
  }
79
94
 
80
95
  markStory(story: Amity.InternalStory, activityType: Amity.AnalyticEventActivityType) {
@@ -163,4 +178,30 @@ export class AnalyticsEventCapturer {
163
178
  markStoryAsClicked(story: Amity.InternalStory) {
164
179
  this.markStory(story, Amity.AnalyticEventActivityType.Click);
165
180
  }
181
+
182
+ markAdAsViewed(ad: Amity.RawAd, placement: Amity.AdPlacement) {
183
+ const metadata = {
184
+ placement,
185
+ };
186
+
187
+ this.markAs(
188
+ `${ad.adId}.${Amity.AnalyticEventActivityType.View}.${placement}`,
189
+ Amity.AnalyticEventContentType.Ad,
190
+ Amity.AnalyticEventActivityType.View,
191
+ metadata,
192
+ );
193
+ }
194
+
195
+ markAdAsClicked(ad: Amity.RawAd, placement: Amity.AdPlacement) {
196
+ const metadata = {
197
+ placement,
198
+ };
199
+
200
+ this.markAs(
201
+ `${ad.adId}.${Amity.AnalyticEventActivityType.View}.${placement}`,
202
+ Amity.AnalyticEventContentType.Ad,
203
+ Amity.AnalyticEventActivityType.Click,
204
+ metadata,
205
+ );
206
+ }
166
207
  }
@@ -16,7 +16,7 @@ import { getDeviceInfo } from '~/core/device';
16
16
  */
17
17
  export const getToken = async (params: {
18
18
  userId: Amity.InternalUser['userId'];
19
- displayName: Amity.InternalUser['displayName'];
19
+ displayName?: Amity.InternalUser['displayName'];
20
20
  authToken?: string;
21
21
  deviceId: Amity.Device['deviceId'];
22
22
  }) => {
@@ -93,7 +93,7 @@ export const login = async (
93
93
  try {
94
94
  const { users } = await setClientToken({
95
95
  ...params,
96
- displayName: params?.displayName || params.userId,
96
+ displayName: params?.displayName,
97
97
  deviceId: params?.deviceId || defaultDeviceId,
98
98
  });
99
99
 
@@ -0,0 +1,132 @@
1
+ import hash from 'object-hash';
2
+ import { pullFromCache, pushToCache } from '~/cache/api';
3
+ import { CommentPaginationController } from './CommentPaginationController';
4
+ import { CommentQueryStreamController } from './CommentQueryStreamController';
5
+ import { LiveCollectionController } from '~/core/liveCollection/LiveCollectionController';
6
+ import {
7
+ onCommentCreated,
8
+ onCommentUpdated,
9
+ onCommentDeleted,
10
+ onCommentFlagged,
11
+ onCommentUnflagged,
12
+ onCommentReactionAdded,
13
+ onCommentReactionRemoved,
14
+ } from '~/commentRepository/events';
15
+ import { filterByPropEquality, sortByFirstCreated, sortByLastCreated } from '~/core/query';
16
+ import { isNonNullable } from '~/utils';
17
+ import { EnumCommentActions } from './enums';
18
+ import { LinkedObject } from '~/utils/linkedObject';
19
+ import { prepareCommentPayload } from '~/commentRepository/utils/payload';
20
+
21
+ export class CommentLiveCollectionController extends LiveCollectionController<
22
+ 'comment',
23
+ Amity.CommentLiveCollection,
24
+ Amity.Comment,
25
+ CommentPaginationController
26
+ > {
27
+ private queryStreamController: CommentQueryStreamController;
28
+
29
+ private query: Amity.CommentLiveCollection;
30
+
31
+ constructor(
32
+ query: Amity.CommentLiveCollection,
33
+ callback: Amity.LiveCollectionCallback<Amity.Comment>,
34
+ ) {
35
+ const queryStreamId = hash(query);
36
+ const cacheKey = ['comments', 'collection', queryStreamId];
37
+ const paginationController = new CommentPaginationController(query);
38
+
39
+ super(paginationController, queryStreamId, cacheKey, callback);
40
+
41
+ this.query = query;
42
+ this.queryStreamController = new CommentQueryStreamController(
43
+ this.query,
44
+ this.cacheKey,
45
+ this.notifyChange.bind(this),
46
+ prepareCommentPayload,
47
+ );
48
+
49
+ this.callback = callback.bind(this);
50
+ this.loadPage({ initial: true });
51
+ }
52
+
53
+ protected setup() {
54
+ const collection = pullFromCache<Amity.CommentLiveCollectionCache>(this.cacheKey)?.data;
55
+ if (!collection) {
56
+ pushToCache(this.cacheKey, {
57
+ data: [],
58
+ params: {},
59
+ });
60
+ }
61
+ }
62
+
63
+ protected async persistModel(queryPayload: Amity.CommentPayload & Amity.Pagination) {
64
+ await this.queryStreamController.saveToMainDB(queryPayload);
65
+ }
66
+
67
+ protected persistQueryStream({
68
+ response,
69
+ direction,
70
+ refresh,
71
+ }: Amity.LiveCollectionPersistQueryStreamParams<'comment'>) {
72
+ this.queryStreamController.appendToQueryStream(response, direction, refresh);
73
+ }
74
+
75
+ startSubscription() {
76
+ return this.queryStreamController.subscribeRTE([
77
+ { fn: onCommentCreated, action: EnumCommentActions.OnCommentCreated },
78
+ { fn: onCommentUpdated, action: EnumCommentActions.OnCommentUpdated },
79
+ { fn: onCommentDeleted, action: EnumCommentActions.OnCommentDeleted },
80
+ { fn: onCommentFlagged, action: EnumCommentActions.OnCommentFlagged },
81
+ { fn: onCommentUnflagged, action: EnumCommentActions.OnCommentUnflagged },
82
+ { fn: onCommentReactionAdded, action: EnumCommentActions.OnCommentReactionAdded },
83
+ { fn: onCommentReactionRemoved, action: EnumCommentActions.OnCommentReactionRemoved },
84
+ ]);
85
+ }
86
+
87
+ notifyChange({ origin, loading, error }: Amity.LiveCollectionNotifyParams) {
88
+ const collection = pullFromCache<Amity.CommentLiveCollectionCache>(this.cacheKey)?.data;
89
+ if (!collection) return;
90
+
91
+ const data = this.applyFilter(
92
+ collection.data
93
+ .map(id => pullFromCache<Amity.InternalComment>(['comments', 'get', id])!)
94
+ .filter(isNonNullable)
95
+ .map(({ data }) => data) ?? [],
96
+ ).map(LinkedObject.comment);
97
+
98
+ if (!this.shouldNotify(data) && origin === 'event') return;
99
+
100
+ this.callback({
101
+ onNextPage: () => this.loadPage({ direction: Amity.LiveCollectionPageDirection.NEXT }),
102
+ data,
103
+ hasNextPage: !!this.paginationController.getNextToken(),
104
+ loading,
105
+ error,
106
+ });
107
+ }
108
+
109
+ applyFilter(data: Amity.InternalComment[]) {
110
+ let comments = data;
111
+
112
+ if (this.query.includeDeleted) {
113
+ comments = filterByPropEquality(comments, 'isDeleted', false);
114
+ }
115
+
116
+ if (this.query.parentId) {
117
+ comments = comments.filter(comment => comment.parentId === this.query.parentId);
118
+ }
119
+
120
+ switch (this.query.sortBy) {
121
+ case 'firstCreated':
122
+ comments = comments.sort(sortByFirstCreated);
123
+ break;
124
+ case 'lastCreated':
125
+ default:
126
+ comments = comments.sort(sortByLastCreated);
127
+ break;
128
+ }
129
+
130
+ return comments;
131
+ }
132
+ }
@@ -0,0 +1,25 @@
1
+ import { PaginationController } from '~/core/liveCollection/PaginationController';
2
+ import { COLLECTION_DEFAULT_PAGINATION_LIMIT } from '~/utils/constants';
3
+ import { inferIsDeleted } from '~/utils/inferIsDeleted';
4
+
5
+ export class CommentPaginationController extends PaginationController<
6
+ 'comment',
7
+ Amity.CommentLiveCollection
8
+ > {
9
+ async getRequest(queryParams: Amity.CommentLiveCollection, token: string | undefined) {
10
+ const { limit = COLLECTION_DEFAULT_PAGINATION_LIMIT, includeDeleted, ...params } = queryParams;
11
+ const options = token ? { token } : { limit };
12
+
13
+ const { data: queryResponse } = await this.http.get<Amity.CommentPayload & Amity.Pagination>(
14
+ `/api/v3/comments`,
15
+ {
16
+ params: {
17
+ ...params,
18
+ isDeleted: inferIsDeleted(includeDeleted),
19
+ options,
20
+ },
21
+ },
22
+ );
23
+ return queryResponse;
24
+ }
25
+ }
@@ -0,0 +1,90 @@
1
+ import { QueryStreamController } from '~/core/liveCollection/QueryStreamController';
2
+ import { pullFromCache, pushToCache } from '~/cache/api';
3
+ import { ingestInCache } from '~/cache/api/ingestInCache';
4
+ import { getResolver } from '~/core/model';
5
+ import { getActiveClient } from '~/client';
6
+ import { EnumCommentActions } from './enums';
7
+
8
+ export class CommentQueryStreamController extends QueryStreamController<
9
+ Amity.CommentPayload,
10
+ Amity.CommentLiveCollection
11
+ > {
12
+ private notifyChange: (params: Amity.LiveCollectionNotifyParams) => void;
13
+
14
+ private preparePayload: (response: Amity.CommentPayload) => Amity.ProcessedCommentPayload;
15
+
16
+ constructor(
17
+ query: Amity.CommentLiveCollection,
18
+ cacheKey: string[],
19
+ notifyChange: (params: Amity.LiveCollectionNotifyParams) => void,
20
+ preparePayload: (response: Amity.CommentPayload) => Amity.ProcessedCommentPayload,
21
+ ) {
22
+ super(query, cacheKey);
23
+ this.notifyChange = notifyChange;
24
+ this.preparePayload = preparePayload;
25
+ }
26
+
27
+ async saveToMainDB(response: Amity.CommentPayload) {
28
+ const processedPayload = await this.preparePayload(response);
29
+
30
+ const client = getActiveClient();
31
+ const cachedAt = client.cache && Date.now();
32
+
33
+ if (client.cache) {
34
+ ingestInCache(processedPayload, { cachedAt });
35
+ }
36
+ }
37
+
38
+ appendToQueryStream(
39
+ response: Amity.CommentPayload & Partial<Amity.Pagination>,
40
+ direction: Amity.LiveCollectionPageDirection,
41
+ refresh = false,
42
+ ) {
43
+ if (refresh) {
44
+ pushToCache(this.cacheKey, {
45
+ data: response.comments.map(getResolver('comment')),
46
+ });
47
+ } else {
48
+ const collection = pullFromCache<Amity.CommunityLiveCollectionCache>(this.cacheKey)?.data;
49
+
50
+ const comments = collection?.data ?? [];
51
+
52
+ pushToCache(this.cacheKey, {
53
+ ...collection,
54
+ data: [...new Set([...comments, ...response.comments.map(getResolver('comment'))])],
55
+ });
56
+ }
57
+ }
58
+
59
+ reactor(action: EnumCommentActions) {
60
+ return (comment: Amity.InternalComment) => {
61
+ const collection = pullFromCache<Amity.CommentLiveCollectionCache>(this.cacheKey)?.data;
62
+
63
+ if (
64
+ this.query.referenceId !== comment.referenceId ||
65
+ this.query.referenceType !== comment.referenceType ||
66
+ !collection
67
+ ) {
68
+ return;
69
+ }
70
+
71
+ if (action === EnumCommentActions.OnCommentCreated) {
72
+ collection.data = [...new Set([comment.commentId, ...collection.data])];
73
+ } else if (action === EnumCommentActions.OnCommentDeleted) {
74
+ collection.data = collection.data.filter(p => p !== comment.commentId);
75
+ }
76
+
77
+ pushToCache(this.cacheKey, collection);
78
+ this.notifyChange({ origin: Amity.LiveDataOrigin.EVENT, loading: false });
79
+ };
80
+ }
81
+
82
+ subscribeRTE(
83
+ createSubscriber: {
84
+ fn: (reactor: (comment: Amity.InternalComment) => void) => Amity.Unsubscriber;
85
+ action: EnumCommentActions;
86
+ }[],
87
+ ) {
88
+ return createSubscriber.map(subscriber => subscriber.fn(this.reactor(subscriber.action)));
89
+ }
90
+ }
@@ -0,0 +1,9 @@
1
+ export enum EnumCommentActions {
2
+ OnCommentCreated = 'onCommentCreated',
3
+ OnCommentUpdated = 'onCommentUpdated',
4
+ OnCommentDeleted = 'onCommentDeleted',
5
+ OnCommentFlagged = 'onCommentFlagged',
6
+ OnCommentUnflagged = 'onCommentUnflagged',
7
+ OnCommentReactionAdded = 'onCommentReactionAdded',
8
+ OnCommentReactionRemoved = 'onCommentReactionRemoved',
9
+ }