@amityco/ts-sdk 6.26.3 → 6.27.1-061592b.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 (131) hide show
  1. package/.env +26 -26
  2. package/dist/@types/core/model.d.ts +5 -5
  3. package/dist/@types/core/model.d.ts.map +1 -1
  4. package/dist/@types/core/payload.d.ts +1 -1
  5. package/dist/@types/core/payload.d.ts.map +1 -1
  6. package/dist/@types/domains/ad.d.ts +14 -2
  7. package/dist/@types/domains/ad.d.ts.map +1 -1
  8. package/dist/@types/domains/file.d.ts +6 -0
  9. package/dist/@types/domains/file.d.ts.map +1 -1
  10. package/dist/@types/domains/message.d.ts +4 -1
  11. package/dist/@types/domains/message.d.ts.map +1 -1
  12. package/dist/@types/domains/post.d.ts +3 -3
  13. package/dist/@types/domains/post.d.ts.map +1 -1
  14. package/dist/adRepository/api/getNetworkAds.d.ts.map +1 -1
  15. package/dist/analytic/service/analytic/AnalyticsEngine.d.ts +2 -2
  16. package/dist/analytic/service/analytic/AnalyticsEngine.d.ts.map +1 -1
  17. package/dist/analytic/service/analytic/AnalyticsEventCapturer.d.ts +11 -5
  18. package/dist/analytic/service/analytic/AnalyticsEventCapturer.d.ts.map +1 -1
  19. package/dist/client/api/getToken.d.ts +10 -5
  20. package/dist/client/api/getToken.d.ts.map +1 -1
  21. package/dist/client/api/index.d.ts +1 -0
  22. package/dist/client/api/index.d.ts.map +1 -1
  23. package/dist/client/api/login.d.ts.map +1 -1
  24. package/dist/client/api/logout.d.ts.map +1 -1
  25. package/dist/client/api/renewal.d.ts.map +1 -1
  26. package/dist/client/api/setUploadedFileAccessType.d.ts +2 -0
  27. package/dist/client/api/setUploadedFileAccessType.d.ts.map +1 -0
  28. package/dist/client/events/index.d.ts +1 -0
  29. package/dist/client/events/index.d.ts.map +1 -1
  30. package/dist/client/events/onNetworkActivities.d.ts +11 -0
  31. package/dist/client/events/onNetworkActivities.d.ts.map +1 -0
  32. package/dist/client/utils/GlobalFileAccessType.d.ts +10 -0
  33. package/dist/client/utils/GlobalFileAccessType.d.ts.map +1 -0
  34. package/dist/client/utils/NetworkActivitiesWatcher.d.ts +12 -0
  35. package/dist/client/utils/NetworkActivitiesWatcher.d.ts.map +1 -0
  36. package/dist/commentRepository/observers/getComments.d.ts +1 -1
  37. package/dist/commentRepository/observers/getComments.d.ts.map +1 -1
  38. package/dist/communityRepository/utils/payload.d.ts +7 -0
  39. package/dist/communityRepository/utils/payload.d.ts.map +1 -1
  40. package/dist/core/transports/http.d.ts.map +1 -1
  41. package/dist/fileRepository/api/createFile.d.ts.map +1 -1
  42. package/dist/fileRepository/api/createImage.d.ts.map +1 -1
  43. package/dist/fileRepository/api/createVideo.d.ts.map +1 -1
  44. package/dist/fileRepository/api/uploadFile.d.ts.map +1 -1
  45. package/dist/fileRepository/api/uploadImage.d.ts.map +1 -1
  46. package/dist/fileRepository/api/uploadVideo.d.ts.map +1 -1
  47. package/dist/index.cjs.js +898 -688
  48. package/dist/index.esm.js +729 -517
  49. package/dist/index.umd.js +4 -4
  50. package/dist/messageRepository/api/createMessage.d.ts +7 -25
  51. package/dist/messageRepository/api/createMessage.d.ts.map +1 -1
  52. package/dist/messageRepository/events/onMessageCreated.d.ts.map +1 -1
  53. package/dist/messageRepository/observers/getMessages/MessageLiveCollectionController.d.ts +4 -4
  54. package/dist/messageRepository/observers/getMessages/MessageLiveCollectionController.d.ts.map +1 -1
  55. package/dist/messageRepository/observers/getMessages/MessageQueryStreamController.d.ts.map +1 -1
  56. package/dist/messageRepository/utils/prepareMessagePayload.d.ts.map +1 -1
  57. package/dist/postRepository/api/editPost.d.ts +1 -1
  58. package/dist/postRepository/api/editPost.d.ts.map +1 -1
  59. package/dist/postRepository/api/updatePost.d.ts +1 -1
  60. package/dist/postRepository/api/updatePost.d.ts.map +1 -1
  61. package/dist/postRepository/internalApi/getPost.d.ts +5 -0
  62. package/dist/postRepository/internalApi/getPost.d.ts.map +1 -0
  63. package/dist/postRepository/internalApi/index.d.ts +13 -0
  64. package/dist/postRepository/internalApi/index.d.ts.map +1 -0
  65. package/dist/postRepository/observers/getPost.d.ts.map +1 -1
  66. package/dist/postRepository/observers/getPosts/PostLiveCollectionController.d.ts +14 -0
  67. package/dist/postRepository/observers/getPosts/PostLiveCollectionController.d.ts.map +1 -0
  68. package/dist/postRepository/observers/getPosts/PostPaginationController.d.ts +5 -0
  69. package/dist/postRepository/observers/getPosts/PostPaginationController.d.ts.map +1 -0
  70. package/dist/postRepository/observers/getPosts/PostQueryStreamController.d.ts +15 -0
  71. package/dist/postRepository/observers/getPosts/PostQueryStreamController.d.ts.map +1 -0
  72. package/dist/postRepository/observers/getPosts/enums.d.ts +12 -0
  73. package/dist/postRepository/observers/getPosts/enums.d.ts.map +1 -0
  74. package/dist/postRepository/observers/getPosts.d.ts.map +1 -1
  75. package/dist/postRepository/utils/payload.d.ts +2 -0
  76. package/dist/postRepository/utils/payload.d.ts.map +1 -0
  77. package/dist/utils/linkedObject/adLinkedObject.d.ts +1 -1
  78. package/dist/utils/linkedObject/adLinkedObject.d.ts.map +1 -1
  79. package/dist/utils/linkedObject/categoryLinkedObject.d.ts.map +1 -1
  80. package/dist/utils/linkedObject/index.d.ts +1 -1
  81. package/dist/utils/linkedObject/userLinkedObject.d.ts.map +1 -1
  82. package/dist/utils/tests/dummy/post.d.ts +3 -3
  83. package/package.json +1 -1
  84. package/src/@types/core/model.ts +5 -5
  85. package/src/@types/core/payload.ts +1 -1
  86. package/src/@types/domains/ad.ts +17 -6
  87. package/src/@types/domains/file.ts +8 -0
  88. package/src/@types/domains/message.ts +6 -1
  89. package/src/@types/domains/post.ts +3 -4
  90. package/src/adRepository/api/getNetworkAds.ts +22 -8
  91. package/src/analytic/service/analytic/AnalyticsEngine.ts +2 -2
  92. package/src/analytic/service/analytic/AnalyticsEventCapturer.ts +45 -27
  93. package/src/client/api/getToken.ts +15 -7
  94. package/src/client/api/index.ts +2 -0
  95. package/src/client/api/login.ts +11 -7
  96. package/src/client/api/logout.ts +4 -0
  97. package/src/client/api/renewal.ts +6 -1
  98. package/src/client/api/setUploadedFileAccessType.ts +5 -0
  99. package/src/client/api/tests/getToken.test.ts +3 -3
  100. package/src/client/events/index.ts +2 -0
  101. package/src/client/events/onNetworkActivities.ts +14 -0
  102. package/src/client/utils/GlobalFileAccessType.ts +23 -0
  103. package/src/client/utils/NetworkActivitiesWatcher.ts +31 -0
  104. package/src/commentRepository/observers/getComments.ts +1 -1
  105. package/src/communityRepository/utils/payload.ts +19 -3
  106. package/src/core/model/idResolvers.ts +1 -1
  107. package/src/core/transports/http.ts +25 -1
  108. package/src/fileRepository/api/createFile.ts +4 -0
  109. package/src/fileRepository/api/createImage.ts +4 -0
  110. package/src/fileRepository/api/createVideo.ts +4 -0
  111. package/src/fileRepository/api/uploadFile.ts +4 -0
  112. package/src/fileRepository/api/uploadImage.ts +4 -0
  113. package/src/fileRepository/api/uploadVideo.ts +4 -0
  114. package/src/messageRepository/api/createMessage.ts +83 -98
  115. package/src/messageRepository/events/onMessageCreated.ts +12 -6
  116. package/src/messageRepository/observers/getMessages/MessageLiveCollectionController.ts +26 -24
  117. package/src/messageRepository/observers/getMessages/MessageQueryStreamController.ts +3 -2
  118. package/src/messageRepository/observers/observeMessages.ts +3 -3
  119. package/src/messageRepository/utils/prepareMessagePayload.ts +1 -1
  120. package/src/postRepository/internalApi/getPost.ts +65 -0
  121. package/src/postRepository/internalApi/index.ts +16 -0
  122. package/src/postRepository/observers/getPost.ts +8 -1
  123. package/src/postRepository/observers/getPosts/PostLiveCollectionController.ts +190 -0
  124. package/src/postRepository/observers/getPosts/PostPaginationController.ts +45 -0
  125. package/src/postRepository/observers/getPosts/PostQueryStreamController.ts +102 -0
  126. package/src/postRepository/observers/getPosts/enums.ts +11 -0
  127. package/src/postRepository/observers/getPosts.ts +6 -197
  128. package/src/postRepository/utils/payload.ts +17 -0
  129. package/src/utils/linkedObject/adLinkedObject.ts +11 -11
  130. package/src/utils/linkedObject/categoryLinkedObject.ts +6 -28
  131. package/src/utils/linkedObject/userLinkedObject.ts +8 -27
@@ -3,10 +3,10 @@ import { fireEvent } from '~/core/events';
3
3
  import { getActiveClient, getActiveUser } from '~/client/api';
4
4
  import { ingestInCache } from '~/cache/api/ingestInCache';
5
5
  import { UNSYNCED_OBJECT_CACHED_AT_VALUE } from '~/utils/constants';
6
- import { upsertInCache, pullFromCache, pushToCache, dropFromCache } from '~/cache/api';
6
+ import { dropFromCache, pullFromCache, pushToCache, upsertInCache } from '~/cache/api';
7
7
 
8
- import { convertParams, prepareMessagePayload } from '../utils';
9
8
  import { LinkedObject } from '~/utils/linkedObject';
9
+ import { convertParams, prepareMessagePayload } from '../utils';
10
10
 
11
11
  const getLocalId = () => `LOCAL_${uuid()}`;
12
12
 
@@ -16,109 +16,32 @@ let uniqueId: string | undefined;
16
16
  /* begin_public_function
17
17
  id: message.create.text_message, message.create.image_message, message.create.file_message, message.create.video_message, message.create.audio_message, message.create.custom_message
18
18
  */
19
- /**
20
- * ```js
21
- * import { createMessage, createQuery, runQuery } from '@amityco/ts-sdk'
22
- *
23
- * const query = createQuery(createMessage, {
24
- * subChannelId: 'foobar',
25
- * data: { text: 'hello world' },
26
- * });
27
- *
28
- * runQuery(query, ({ data: message, loading }) => {
29
- * console.log(message);
30
- * });
31
- * ```
32
- *
33
- * Creates an {@link Amity.Message}
34
- *
35
- * @param bundle The data necessary to create a new {@link Amity.Message}
36
- * @returns The newly created {@link Amity.Message}
37
- *
38
- * @category Message API
39
- * @async
40
- */
41
- export const createMessage = async <T extends Amity.MessageContentType>(
42
- bundle: Pick<
43
- Amity.Message<T>,
44
- 'subChannelId' | 'parentId' | 'dataType' | 'tags' | 'metadata' | 'mentionees'
45
- > & {
46
- data?: Amity.Message<T>['data'];
47
- fileId?: Amity.File['fileId'];
48
- // Custom referenceId is a workaround for the case:
49
- // User wants to create an image message. He should
50
- // - create and show dummy message in ui
51
- // - upload image to get fileId, while uploading show a spinner in dummy message in ui
52
- // - call createMessage and pass fileId
53
- // - replace dummy message with the actual message received from backend
54
- // Custom referenceId is needed to make relation between dummy message and actual message.
55
- // TODO: passing file src into createMessage so that sdk uploads files itself,
56
- // returns the dummy message bound with the file to eliminate the need to create
57
- // the dummy message on the user side,
58
- referenceId?: string;
59
- },
60
- ): Promise<Amity.Cached<Amity.Message>> => {
61
- const client = getActiveClient();
62
- client.log('message/createMessage', bundle);
63
-
64
- const referenceId = bundle.referenceId || uniqueId || getLocalId();
65
- uniqueId = undefined;
66
-
67
- const { data: payload } = await client.http.post<Amity.MessagePayload>('/api/v5/messages', {
68
- ...convertParams(bundle),
69
- referenceId,
70
- });
71
-
72
- const data = await prepareMessagePayload(payload);
73
- const { messages } = data;
74
-
75
- const cachedAt = client.cache && Date.now();
76
- if (client.cache) {
77
- dropFromCache(['message', 'get', referenceId]);
78
- ingestInCache(data, { cachedAt });
79
- }
80
-
81
- fireEvent('local.message.created', { messages });
82
19
 
83
- return {
84
- data: LinkedObject.message(messages[0]),
85
- cachedAt,
86
- };
20
+ type createMessageParam<T extends Amity.MessageContentType> = Pick<
21
+ Amity.Message<T>,
22
+ 'subChannelId' | 'parentId' | 'dataType' | 'tags' | 'metadata' | 'mentionees'
23
+ > & {
24
+ data?: Amity.Message<T>['data'];
25
+ fileId?: Amity.File['fileId'];
26
+ referenceId?: string;
87
27
  };
88
28
 
89
- /**
90
- * ```js
91
- * import { createMessage } from '@amityco/ts-sdk'
92
- *
93
- * const created = createMessage.optimistically({
94
- * channelId: 'foobar',
95
- * data: { text: 'hello world' }
96
- * })
97
- * ```
98
- *
99
- * Creates an {@link Amity.Message} in cache
100
- *
101
- * @param bundle The data necessary to create a new {@link Amity.Message}
102
- * @returns The newly created {@link Amity.Message}
103
- *
104
- * @category Message API
105
- */
106
- createMessage.optimistically = ({
107
- referenceId,
108
- ...bundle
109
- }: Parameters<typeof createMessage>[0]): Amity.Cached<Amity.Message> | undefined => {
29
+ const createMessageOptimistic = <T extends Amity.MessageContentType>(
30
+ bundle: createMessageParam<T>,
31
+ ): Amity.InternalMessage | undefined => {
110
32
  const client = getActiveClient();
111
33
 
112
34
  if (!client.cache) return;
113
35
 
114
36
  /*
115
- * when creating messages optimistically a messageId needs to be added by the
116
- * client, created a new variable so as to allow backward compatibility of API
37
+ * When creating messages optimistically a messageId needs to be added by the
38
+ * client, created a new variable to allow backward compatibility of API
117
39
  *
118
40
  * Updated to handle client requirement to add messageId while uploading
119
- * message with image. Temporary!
41
+ * a message with image.
42
+ * Temporary!
120
43
  */
121
- uniqueId = referenceId || getLocalId();
44
+ uniqueId = bundle.referenceId || getLocalId();
122
45
  const bundleWithMessageId = { messageId: uniqueId, uniqueId, ...bundle };
123
46
 
124
47
  client.log('message/createMessage.optimistically', bundleWithMessageId);
@@ -153,6 +76,8 @@ createMessage.optimistically = ({
153
76
  childrenNumber: 0,
154
77
  createdAt: createdTime,
155
78
  updatedAt: createdTime,
79
+ syncState: Amity.SyncState.Syncing,
80
+ isDeleted: false,
156
81
  ...bundleWithMessageId,
157
82
  } as Amity.InternalMessage;
158
83
 
@@ -161,9 +86,69 @@ createMessage.optimistically = ({
161
86
  pushToCache(['message', 'get', message.messageId], message, { cachedAt });
162
87
  fireEvent('local.message.created', { messages: [message] });
163
88
 
164
- return {
165
- cachedAt,
166
- data: LinkedObject.message(message),
167
- };
89
+ return message;
90
+ };
91
+ /**
92
+ * ```js
93
+ * import { createMessage, createQuery, runQuery } from '@amityco/ts-sdk'
94
+ *
95
+ * const query = createQuery(createMessage, {
96
+ * subChannelId: 'foobar',
97
+ * data: { text: 'hello world' },
98
+ * });
99
+ *
100
+ * runQuery(query, ({ data: message, loading }) => {
101
+ * console.log(message);
102
+ * });
103
+ * ```
104
+ *
105
+ * Creates an {@link Amity.Message}
106
+ *
107
+ * @param bundle The data necessary to create a new {@link Amity.Message}
108
+ * @returns The newly created {@link Amity.Message}
109
+ *
110
+ * @category Message API
111
+ * @async
112
+ */
113
+ export const createMessage = async <T extends Amity.MessageContentType>(
114
+ bundle: createMessageParam<T>,
115
+ ): Promise<Amity.Cached<Amity.Message>> => {
116
+ const client = getActiveClient();
117
+ client.log('message/createMessage', bundle);
118
+
119
+ const optimisticData = createMessageOptimistic<T>(bundle);
120
+
121
+ const referenceId = bundle.referenceId || uniqueId || getLocalId();
122
+ uniqueId = undefined;
123
+
124
+ try {
125
+ const { data: payload } = await client.http.post<Amity.MessagePayload>('/api/v5/messages', {
126
+ ...convertParams(bundle),
127
+ referenceId,
128
+ });
129
+
130
+ const data = await prepareMessagePayload(payload);
131
+ const { messages } = data;
132
+
133
+ const cachedAt = client.cache && Date.now();
134
+ if (client.cache) {
135
+ ingestInCache(data, { cachedAt });
136
+ }
137
+
138
+ fireEvent('local.message.created', {
139
+ messages: [{ ...messages[0], syncState: Amity.SyncState.Synced }],
140
+ });
141
+
142
+ return {
143
+ data: LinkedObject.message(messages[0]),
144
+ cachedAt,
145
+ };
146
+ } catch (e) {
147
+ fireEvent('local.message.created', {
148
+ messages: [{ ...optimisticData, syncState: Amity.SyncState.Error } as Amity.InternalMessage],
149
+ });
150
+
151
+ throw e;
152
+ }
168
153
  };
169
154
  /* end_public_function */
@@ -1,11 +1,11 @@
1
1
  import { getActiveClient } from '~/client/api/activeClient';
2
2
  import { createEventSubscriber } from '~/core/events';
3
3
  import { ingestInCache } from '~/cache/api/ingestInCache';
4
- import { prepareMessagePayload } from '../utils';
5
4
  import { updateSubChannelUnreadFromMessage } from '~/marker/utils/updateSubChannelUnreadFromMessage';
6
5
  import { reCalculateChannelUnreadInfo } from '~/marker/utils/reCalculateChannelUnreadInfo';
7
- import { markReadMessage } from '../utils/markReadMessage';
8
6
  import { getActiveUser } from '~/client/api/activeUser';
7
+ import { markReadMessage } from '../utils/markReadMessage';
8
+ import { prepareMessagePayload } from '../utils';
9
9
 
10
10
  /**
11
11
  * ```js
@@ -64,10 +64,16 @@ export const onMessageCreatedLocal = (
64
64
  const client = getActiveClient();
65
65
 
66
66
  const disposers = [
67
- createEventSubscriber(client, 'message/onMessageCreated', 'local.message.created', payload =>
68
- payload.messages.forEach(message => {
69
- callback(message);
70
- }),
67
+ createEventSubscriber(
68
+ client,
69
+ 'message/onMessageCreated',
70
+ 'local.message.created',
71
+ async payload => {
72
+ ingestInCache(payload);
73
+ return payload.messages.forEach(message => {
74
+ callback(message);
75
+ });
76
+ },
71
77
  ),
72
78
  ];
73
79
 
@@ -1,8 +1,7 @@
1
1
  import hash from 'object-hash';
2
2
  import { pullFromCache, pushToCache } from '~/cache/api';
3
- import { MessagePaginationController } from './MessagePaginationController';
4
- import { MessageQueryStreamController } from './MessageQueryStreamController';
5
3
  import {
4
+ onMessageCreatedLocal,
6
5
  onMessageCreatedMqtt,
7
6
  onMessageDeleted,
8
7
  onMessageFlagCleared,
@@ -18,6 +17,8 @@ import { onMessageMarked, onMessageMarkerFetched } from '~/marker/events';
18
17
  import { filterByPropEquality } from '~/core/query';
19
18
  import { prepareMessagePayload } from '~/messageRepository/utils';
20
19
  import { LinkedObject } from '~/utils/linkedObject';
20
+ import { MessageQueryStreamController } from './MessageQueryStreamController';
21
+ import { MessagePaginationController } from './MessagePaginationController';
21
22
 
22
23
  export class MessageLiveCollectionController extends LiveCollectionController<
23
24
  'message',
@@ -52,31 +53,10 @@ export class MessageLiveCollectionController extends LiveCollectionController<
52
53
  this.loadPage({ initial: true });
53
54
  }
54
55
 
55
- protected setup() {
56
- const collection = pullFromCache<Amity.MessageLiveCollectionCache>(this.cacheKey)?.data;
57
- if (!collection) {
58
- pushToCache(this.cacheKey, {
59
- data: [],
60
- query: this.query,
61
- });
62
- }
63
- }
64
-
65
- protected async persistModel(response: Amity.MessagePayload & Amity.Pagination) {
66
- await this.queryStreamController.saveToMainDB(response);
67
- }
68
-
69
- protected persistQueryStream({
70
- response,
71
- direction,
72
- refresh,
73
- }: Amity.LiveCollectionPersistQueryStreamParams<'message'>) {
74
- this.queryStreamController.appendToQueryStream(response, direction, refresh);
75
- }
76
-
77
56
  startSubscription() {
78
57
  return this.queryStreamController.subscribeRTE([
79
58
  { fn: onMessageCreatedMqtt, action: 'onCreate' },
59
+ { fn: onMessageCreatedLocal, action: 'onCreate' },
80
60
  { fn: onMessageDeleted, action: 'onDelete' },
81
61
  { fn: onMessageUpdated, action: 'onUpdate' },
82
62
  { fn: onMessageFlagged, action: 'onFlagged' },
@@ -160,4 +140,26 @@ export class MessageLiveCollectionController extends LiveCollectionController<
160
140
 
161
141
  return messages;
162
142
  }
143
+
144
+ protected setup() {
145
+ const collection = pullFromCache<Amity.MessageLiveCollectionCache>(this.cacheKey)?.data;
146
+ if (!collection) {
147
+ pushToCache(this.cacheKey, {
148
+ data: [],
149
+ query: this.query,
150
+ });
151
+ }
152
+ }
153
+
154
+ protected async persistModel(response: Amity.MessagePayload & Amity.Pagination) {
155
+ await this.queryStreamController.saveToMainDB(response);
156
+ }
157
+
158
+ protected persistQueryStream({
159
+ response,
160
+ direction,
161
+ refresh,
162
+ }: Amity.LiveCollectionPersistQueryStreamParams<'message'>) {
163
+ this.queryStreamController.appendToQueryStream(response, direction, refresh);
164
+ }
163
165
  }
@@ -72,6 +72,7 @@ export class MessageQueryStreamController extends QueryStreamController<
72
72
  return (payload: Amity.InternalMessage) => {
73
73
  if (action === 'onCreate') {
74
74
  const collection = pullFromCache<Amity.MessageLiveCollectionCache>(this.cacheKey)?.data;
75
+ const { referenceId } = payload;
75
76
 
76
77
  if (!collection) return;
77
78
  if (this.query.subChannelId !== payload?.subChannelId || !collection) return;
@@ -115,11 +116,11 @@ export class MessageQueryStreamController extends QueryStreamController<
115
116
  (!this.query.sortBy || this.query.sortBy === 'segmentDesc') &&
116
117
  !this.paginationController.getPrevToken()
117
118
  ) {
118
- collection.data = [...new Set([payload.messageId, ...collection.data])];
119
+ collection.data = [...new Set([referenceId ?? payload.messageId, ...collection.data])];
119
120
  }
120
121
 
121
122
  if (this.query.sortBy === 'segmentAsc' && !this.paginationController.getNextToken()) {
122
- collection.data = [...new Set([...collection.data, payload.messageId])];
123
+ collection.data = [...new Set([...collection.data, referenceId ?? payload.messageId])];
123
124
  }
124
125
 
125
126
  pushToCache(this.cacheKey, collection);
@@ -2,13 +2,13 @@ import { getActiveClient } from '~/client/api';
2
2
  import { onMessageMarked, onMessageMarkerFetched } from '~/marker/events';
3
3
  import { convertEventPayload } from '~/utils/event';
4
4
 
5
+ import { LinkedObject } from '~/utils/linkedObject';
5
6
  import {
7
+ onMessageCreatedLocal,
6
8
  onMessageCreatedMqtt,
7
- onMessageUpdated,
8
9
  onMessageDeleted,
9
- onMessageCreatedLocal,
10
+ onMessageUpdated,
10
11
  } from '../events';
11
- import { LinkedObject } from '~/utils/linkedObject';
12
12
 
13
13
  /**
14
14
  * ```js
@@ -8,7 +8,6 @@ import { MessageContentType } from '~/@types';
8
8
  import { convertFromRaw as convertSubChannelFromRaw } from '~/subChannelRepository/utils/convertSubChannelFromRaw';
9
9
  import { updateSubChannelCache } from '~/subChannelRepository/utils/updateSubChannelCache';
10
10
  import { COLLECTION_DEFAULT_PAGINATION_LIMIT } from '~/utils/constants';
11
- import { getMessageReadCount } from './getMessageReadCount';
12
11
 
13
12
  export function convertFromRaw(
14
13
  message: Amity.RawMessage,
@@ -62,6 +61,7 @@ export function convertFromRaw(
62
61
  subChannelId: messageFeedId,
63
62
  uniqueId: cache ? cache.data.uniqueId : messageId,
64
63
  referenceId,
64
+ syncState: Amity.SyncState.Synced,
65
65
  };
66
66
 
67
67
  if (mentionedUsers) {
@@ -0,0 +1,65 @@
1
+ import { getActiveClient } from '~/client/api';
2
+
3
+ import { pullFromCache } from '~/cache/api';
4
+ import { ingestInCache } from '~/cache/api/ingestInCache';
5
+ import { isInTombstone } from '~/cache/api/isInTombstone';
6
+ import { checkIfShouldGoesToTombstone } from '~/cache/utils';
7
+ import { pushToTombstone } from '~/cache/api/pushToTombstone';
8
+ import { prepareMembershipPayload } from '~/group/utils';
9
+
10
+ export const getPost = async (
11
+ postId: Amity.InternalPost['postId'],
12
+ ): Promise<Amity.Cached<Amity.InternalPost>> => {
13
+ const client = getActiveClient();
14
+ client.log('post/getPost', postId);
15
+
16
+ isInTombstone('post', postId);
17
+
18
+ let payload: Amity.PostPayload;
19
+
20
+ try {
21
+ // API-FIX: endpoint should not be /list, parameters should be querystring.
22
+ const response = await client.http.get<Amity.PostPayload>(
23
+ `/api/v3/posts/${encodeURIComponent(postId)}`,
24
+ );
25
+ payload = response.data;
26
+ } catch (error) {
27
+ if (checkIfShouldGoesToTombstone((error as Amity.ErrorResponse)?.code)) {
28
+ pushToTombstone('post', postId);
29
+ }
30
+
31
+ throw error;
32
+ }
33
+
34
+ const data = prepareMembershipPayload(payload, 'communityUsers');
35
+
36
+ const cachedAt = client.cache && Date.now();
37
+ if (client.cache) ingestInCache(data, { cachedAt });
38
+
39
+ const { posts } = data;
40
+
41
+ const result = posts.find(post => post.postId === postId)!;
42
+
43
+ return {
44
+ data: result,
45
+ cachedAt,
46
+ };
47
+ };
48
+
49
+ getPost.locally = (
50
+ postId: Amity.InternalPost['postId'],
51
+ ): Amity.Cached<Amity.InternalPost> | undefined => {
52
+ const client = getActiveClient();
53
+ client.log('post/getPost.locally', postId);
54
+
55
+ if (!client.cache) return;
56
+
57
+ const cached = pullFromCache<Amity.InternalPost>(['post', 'get', postId]);
58
+
59
+ if (!cached) return;
60
+
61
+ return {
62
+ data: cached.data,
63
+ cachedAt: cached.cachedAt,
64
+ };
65
+ };
@@ -0,0 +1,16 @@
1
+ export * from './getPostByIds';
2
+
3
+ export * from './createPost';
4
+ export * from './updatePost';
5
+ export * from './editPost';
6
+
7
+ export * from './deletePost';
8
+ export * from './softDeletePost';
9
+ export * from './hardDeletePost';
10
+
11
+ export * from './approvePost';
12
+ export * from './declinePost';
13
+
14
+ export * from './flagPost';
15
+ export * from './unflagPost';
16
+ export * from './isPostFlaggedByMe';
@@ -42,7 +42,14 @@ export const getPost = (
42
42
  postId: Amity.Post['postId'],
43
43
  callback: Amity.LiveObjectCallback<Amity.Post>,
44
44
  ): Amity.Unsubscriber => {
45
- return liveObject(postId, callback, 'postId', _getPost, [
45
+ const responder: Amity.LiveObjectCallback<Amity.InternalPost> = (
46
+ snapshot: Amity.LiveObject<Amity.InternalPost>,
47
+ ) => {
48
+ const { data } = snapshot;
49
+ callback({ ...snapshot, data: data ? LinkedObject.post(snapshot.data) : data });
50
+ };
51
+
52
+ return liveObject(postId, responder, 'postId', _getPost, [
46
53
  onPostApproved,
47
54
  onPostDeclined,
48
55
  (callback: Amity.Listener<Amity.InternalPost>) => {
@@ -0,0 +1,190 @@
1
+ import hash from 'object-hash';
2
+ import { pullFromCache, pushToCache } from '~/cache/api';
3
+ import { PostPaginationController } from './PostPaginationController';
4
+ import { PostQueryStreamController } from './PostQueryStreamController';
5
+ import { LiveCollectionController } from '~/core/liveCollection/LiveCollectionController';
6
+ import {
7
+ onPostCreated,
8
+ onPostUpdated,
9
+ onPostDeleted,
10
+ onPostFlagged,
11
+ onPostUnflagged,
12
+ onPostReactionAdded,
13
+ onPostReactionRemoved,
14
+ onPostApproved,
15
+ onPostDeclined,
16
+ } from '~/postRepository/events';
17
+ import {
18
+ filterByFeedType,
19
+ filterByPostDataTypes,
20
+ filterByPropEquality,
21
+ sortByFirstCreated,
22
+ sortByLastCreated,
23
+ } from '~/core/query';
24
+ import { isNonNullable } from '~/utils';
25
+ import { EnumPostActions } from './enums';
26
+ import { LinkedObject } from '~/utils/linkedObject';
27
+ import { preparePostPayload } from '~/postRepository/utils/payload';
28
+ import { convertEventPayload } from '~/utils/event';
29
+ import { onCommentCreated, onCommentDeleted } from '~/commentRepository';
30
+ import { getPost } from '~/postRepository/internalApi/getPost';
31
+
32
+ export class PostLiveCollectionController extends LiveCollectionController<
33
+ 'post',
34
+ Amity.PostLiveCollection,
35
+ Amity.Post,
36
+ PostPaginationController
37
+ > {
38
+ private queryStreamController: PostQueryStreamController;
39
+
40
+ private query: Amity.PostLiveCollection;
41
+
42
+ constructor(query: Amity.PostLiveCollection, callback: Amity.LiveCollectionCallback<Amity.Post>) {
43
+ const queryStreamId = hash(query);
44
+ const cacheKey = ['posts', 'collection', queryStreamId];
45
+ const paginationController = new PostPaginationController(query);
46
+
47
+ super(paginationController, queryStreamId, cacheKey, callback);
48
+
49
+ this.query = query;
50
+ this.queryStreamController = new PostQueryStreamController(
51
+ this.query,
52
+ this.cacheKey,
53
+ this.notifyChange.bind(this),
54
+ preparePostPayload,
55
+ );
56
+
57
+ this.callback = callback.bind(this);
58
+ this.loadPage({ initial: true });
59
+ }
60
+
61
+ protected setup() {
62
+ const collection = pullFromCache<Amity.PostLiveCollectionCache>(this.cacheKey)?.data;
63
+ if (!collection) {
64
+ pushToCache(this.cacheKey, {
65
+ data: [],
66
+ params: {},
67
+ });
68
+ }
69
+ }
70
+
71
+ protected async persistModel(queryPayload: Amity.PostPayload & Amity.Pagination) {
72
+ await this.queryStreamController.saveToMainDB(queryPayload);
73
+ }
74
+
75
+ protected persistQueryStream({
76
+ response,
77
+ direction,
78
+ refresh,
79
+ }: Amity.LiveCollectionPersistQueryStreamParams<'post'>) {
80
+ this.queryStreamController.appendToQueryStream(response, direction, refresh);
81
+ }
82
+
83
+ startSubscription() {
84
+ return this.queryStreamController.subscribeRTE([
85
+ { fn: onPostCreated, action: EnumPostActions.OnPostCreated },
86
+ { fn: onPostUpdated, action: EnumPostActions.OnPostUpdated },
87
+ { fn: onPostDeleted, action: EnumPostActions.OnPostDeleted },
88
+ { fn: onPostFlagged, action: EnumPostActions.OnPostFlagged },
89
+ { fn: onPostUnflagged, action: EnumPostActions.OnPostUnflagged },
90
+ { fn: onPostApproved, action: EnumPostActions.OnPostApproved },
91
+ { fn: onPostDeclined, action: EnumPostActions.OnPostDeclined },
92
+ { fn: onPostReactionAdded, action: EnumPostActions.OnPostReactionAdded },
93
+ { fn: onPostReactionRemoved, action: EnumPostActions.OnPostReactionRemoved },
94
+ {
95
+ fn: convertEventPayload(
96
+ (callback: Amity.Listener<Amity.InternalComment>) => {
97
+ return onCommentCreated(async (comment: Amity.InternalComment) => {
98
+ const currentCollection = pullFromCache<Amity.PostLiveCollectionCache>(
99
+ this.cacheKey,
100
+ )?.data;
101
+
102
+ if (!currentCollection || currentCollection.data.includes(comment.referenceId))
103
+ return;
104
+
105
+ await getPost(comment.referenceId);
106
+ callback(comment);
107
+ });
108
+ },
109
+ 'referenceId',
110
+ 'post',
111
+ ),
112
+ action: EnumPostActions.OnPostUpdated,
113
+ },
114
+ {
115
+ fn: convertEventPayload(
116
+ (callback: Amity.Listener<Amity.InternalComment>) => {
117
+ return onCommentDeleted(async (comment: Amity.InternalComment) => {
118
+ const currentCollection = pullFromCache<Amity.PostLiveCollectionCache>(
119
+ this.cacheKey,
120
+ )?.data;
121
+
122
+ if (!currentCollection || currentCollection.data.includes(comment.referenceId))
123
+ return;
124
+
125
+ await getPost(comment.referenceId);
126
+ callback(comment);
127
+ });
128
+ },
129
+ 'referenceId',
130
+ 'post',
131
+ ),
132
+ action: EnumPostActions.OnPostUpdated,
133
+ },
134
+ ]);
135
+ }
136
+
137
+ notifyChange({ origin, loading, error }: Amity.LiveCollectionNotifyParams) {
138
+ const collection = pullFromCache<Amity.PostLiveCollectionCache>(this.cacheKey)?.data;
139
+ if (!collection) return;
140
+
141
+ const data = this.applyFilter(
142
+ collection.data
143
+ .map(id => pullFromCache<Amity.InternalPost>(['post', 'get', id])!)
144
+ .filter(isNonNullable)
145
+ .map(({ data }) => data) ?? [],
146
+ ).map(LinkedObject.post);
147
+
148
+ if (!this.shouldNotify(data) && origin === 'event') return;
149
+
150
+ this.callback({
151
+ onNextPage: () => this.loadPage({ direction: Amity.LiveCollectionPageDirection.NEXT }),
152
+ data,
153
+ hasNextPage: !!this.paginationController.getNextToken(),
154
+ loading,
155
+ error,
156
+ });
157
+ }
158
+
159
+ applyFilter(data: Amity.InternalPost[]) {
160
+ let posts = data;
161
+
162
+ if (!this.query.includeDeleted) {
163
+ posts = filterByPropEquality(posts, 'isDeleted', false);
164
+ }
165
+
166
+ if (this.query.tags) {
167
+ posts = posts.filter(p => p.tags?.some(t => this.query.tags?.includes(t)));
168
+ }
169
+
170
+ if (this.query.targetType === 'community' && this.query.feedType) {
171
+ posts = filterByFeedType(posts, this.query.feedType);
172
+ }
173
+
174
+ if (this.query.dataTypes?.length) {
175
+ posts = filterByPostDataTypes(posts, this.query.dataTypes);
176
+ }
177
+
178
+ switch (this.query.sortBy) {
179
+ case 'firstCreated':
180
+ posts = posts.sort(sortByFirstCreated);
181
+ break;
182
+ case 'lastCreated':
183
+ default:
184
+ posts = posts.sort(sortByLastCreated);
185
+ break;
186
+ }
187
+
188
+ return posts;
189
+ }
190
+ }