@amityco/ts-sdk-react-native 6.23.0 → 6.23.1-d5c2fe6.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/events.d.ts +5 -0
  3. package/dist/@types/core/events.d.ts.map +1 -1
  4. package/dist/@types/domains/community.d.ts +16 -1
  5. package/dist/@types/domains/community.d.ts.map +1 -1
  6. package/dist/client/api/secureLogout.d.ts +1 -1
  7. package/dist/client/utils/ReadReceiptSync/readReceiptSyncEngine.d.ts.map +1 -1
  8. package/dist/commentRepository/api/deleteComment.d.ts.map +1 -1
  9. package/dist/commentRepository/events/utils.d.ts.map +1 -1
  10. package/dist/commentRepository/internalApi/createComment.d.ts.map +1 -1
  11. package/dist/communityRepository/api/createCommunity.d.ts.map +1 -1
  12. package/dist/communityRepository/api/getCommunities.d.ts.map +1 -1
  13. package/dist/communityRepository/api/getCommunity.d.ts.map +1 -1
  14. package/dist/communityRepository/api/queryCommunities.d.ts.map +1 -1
  15. package/dist/communityRepository/api/updateCommunity.d.ts.map +1 -1
  16. package/dist/communityRepository/communityMembership/observers/getMembers/CommunityMembersLiveCollectionController.d.ts +14 -0
  17. package/dist/communityRepository/communityMembership/observers/getMembers/CommunityMembersLiveCollectionController.d.ts.map +1 -0
  18. package/dist/communityRepository/communityMembership/observers/getMembers/CommunityMembersPaginationController.d.ts +9 -0
  19. package/dist/communityRepository/communityMembership/observers/getMembers/CommunityMembersPaginationController.d.ts.map +1 -0
  20. package/dist/communityRepository/communityMembership/observers/getMembers/CommunityMembersQueryStreamController.d.ts +15 -0
  21. package/dist/communityRepository/communityMembership/observers/getMembers/CommunityMembersQueryStreamController.d.ts.map +1 -0
  22. package/dist/communityRepository/communityMembership/observers/getMembers/enums.d.ts +10 -0
  23. package/dist/communityRepository/communityMembership/observers/getMembers/enums.d.ts.map +1 -0
  24. package/dist/communityRepository/communityMembership/observers/getMembers.d.ts.map +1 -1
  25. package/dist/communityRepository/communityMembership/observers/searchMembers.d.ts +20 -0
  26. package/dist/communityRepository/communityMembership/observers/searchMembers.d.ts.map +1 -0
  27. package/dist/communityRepository/observers/getCommunities/CommunitiesLiveCollectionController.d.ts +14 -0
  28. package/dist/communityRepository/observers/getCommunities/CommunitiesLiveCollectionController.d.ts.map +1 -0
  29. package/dist/communityRepository/observers/getCommunities/CommunitiesPaginationController.d.ts +9 -0
  30. package/dist/communityRepository/observers/getCommunities/CommunitiesPaginationController.d.ts.map +1 -0
  31. package/dist/communityRepository/observers/getCommunities/CommunitiesQueryStreamController.d.ts +15 -0
  32. package/dist/communityRepository/observers/getCommunities/CommunitiesQueryStreamController.d.ts.map +1 -0
  33. package/dist/communityRepository/observers/getCommunities/enums.d.ts +6 -0
  34. package/dist/communityRepository/observers/getCommunities/enums.d.ts.map +1 -0
  35. package/dist/communityRepository/observers/getCommunities.d.ts.map +1 -1
  36. package/dist/communityRepository/observers/index.d.ts +1 -0
  37. package/dist/communityRepository/observers/index.d.ts.map +1 -1
  38. package/dist/communityRepository/observers/searchCommunities/SearchCommunitiesLiveCollectionController.d.ts +14 -0
  39. package/dist/communityRepository/observers/searchCommunities/SearchCommunitiesLiveCollectionController.d.ts.map +1 -0
  40. package/dist/communityRepository/observers/searchCommunities/SearchCommunitiesPaginationController.d.ts +9 -0
  41. package/dist/communityRepository/observers/searchCommunities/SearchCommunitiesPaginationController.d.ts.map +1 -0
  42. package/dist/communityRepository/observers/searchCommunities/SearchCommunitiesQueryStreamController.d.ts +15 -0
  43. package/dist/communityRepository/observers/searchCommunities/SearchCommunitiesQueryStreamController.d.ts.map +1 -0
  44. package/dist/communityRepository/observers/searchCommunities/enums.d.ts +6 -0
  45. package/dist/communityRepository/observers/searchCommunities/enums.d.ts.map +1 -0
  46. package/dist/communityRepository/observers/searchCommunities.d.ts +20 -0
  47. package/dist/communityRepository/observers/searchCommunities.d.ts.map +1 -0
  48. package/dist/communityRepository/utils/payload.d.ts.map +1 -1
  49. package/dist/communityRepository/utils/saveCommunityUsers.d.ts +2 -0
  50. package/dist/communityRepository/utils/saveCommunityUsers.d.ts.map +1 -0
  51. package/dist/core/events.d.ts +3 -3
  52. package/dist/core/events.d.ts.map +1 -1
  53. package/dist/core/liveCollection/LiveCollectionController.d.ts +4 -1
  54. package/dist/core/liveCollection/LiveCollectionController.d.ts.map +1 -1
  55. package/dist/index.cjs.js +1149 -797
  56. package/dist/index.esm.js +1148 -796
  57. package/dist/index.umd.js +4 -4
  58. package/dist/marker/events/onChannelUnreadUpdatedLocal.d.ts +12 -0
  59. package/dist/marker/events/onChannelUnreadUpdatedLocal.d.ts.map +1 -0
  60. package/dist/marker/events/onSubChannelUnreadUpdatedLocal.d.ts +12 -0
  61. package/dist/marker/events/onSubChannelUnreadUpdatedLocal.d.ts.map +1 -0
  62. package/dist/marker/events/onUserFeedMarkerUpdated.d.ts.map +1 -1
  63. package/dist/marker/utils/reCalculateChannelUnreadInfo.d.ts +1 -1
  64. package/dist/marker/utils/reCalculateChannelUnreadInfo.d.ts.map +1 -1
  65. package/dist/postRepository/observers/getPost.d.ts.map +1 -1
  66. package/dist/postRepository/observers/getPosts.d.ts.map +1 -1
  67. package/dist/streamRepository/api/getStreams.d.ts +2 -2
  68. package/dist/streamRepository/events/onStreamFlagged.d.ts +17 -0
  69. package/dist/streamRepository/events/onStreamFlagged.d.ts.map +1 -0
  70. package/dist/streamRepository/events/onStreamTerminated.d.ts +17 -0
  71. package/dist/streamRepository/events/onStreamTerminated.d.ts.map +1 -0
  72. package/dist/streamRepository/observers/getStreams.d.ts +1 -1
  73. package/dist/utils/liveObject.d.ts +3 -0
  74. package/dist/utils/liveObject.d.ts.map +1 -1
  75. package/package.json +1 -1
  76. package/src/@types/core/events.ts +8 -0
  77. package/src/@types/domains/community.ts +26 -1
  78. package/src/channelRepository/channelMembership/observers/getMembers/ChannelMemberLiveCollectionController.ts +2 -2
  79. package/src/channelRepository/observers/getChannel.ts +2 -2
  80. package/src/channelRepository/observers/getChannels/ChannelLiveCollectionController.ts +7 -7
  81. package/src/client/api/secureLogout.ts +1 -1
  82. package/src/client/utils/ReadReceiptSync/readReceiptSyncEngine.ts +6 -3
  83. package/src/commentRepository/api/createComment.ts +2 -2
  84. package/src/commentRepository/api/deleteComment.ts +2 -4
  85. package/src/commentRepository/events/utils.ts +8 -5
  86. package/src/commentRepository/internalApi/createComment.ts +3 -2
  87. package/src/commentRepository/internalApi/deleteComment.ts +2 -2
  88. package/src/communityRepository/api/createCommunity.ts +5 -2
  89. package/src/communityRepository/api/getCommunities.ts +5 -1
  90. package/src/communityRepository/api/getCommunity.ts +5 -1
  91. package/src/communityRepository/api/queryCommunities.ts +2 -2
  92. package/src/communityRepository/api/updateCommunity.ts +5 -1
  93. package/src/communityRepository/communityMembership/observers/getMembers/CommunityMembersLiveCollectionController.ts +152 -0
  94. package/src/communityRepository/communityMembership/observers/getMembers/CommunityMembersPaginationController.ts +26 -0
  95. package/src/communityRepository/communityMembership/observers/getMembers/CommunityMembersQueryStreamController.ts +107 -0
  96. package/src/communityRepository/communityMembership/observers/getMembers/enums.ts +9 -0
  97. package/src/communityRepository/communityMembership/observers/getMembers.ts +15 -128
  98. package/src/communityRepository/communityMembership/observers/searchMembers.ts +60 -0
  99. package/src/communityRepository/observers/getCommunities/CommunitiesLiveCollectionController.ts +147 -0
  100. package/src/communityRepository/observers/getCommunities/CommunitiesPaginationController.ts +31 -0
  101. package/src/communityRepository/observers/getCommunities/CommunitiesQueryStreamController.ts +88 -0
  102. package/src/communityRepository/observers/getCommunities/enums.ts +5 -0
  103. package/src/communityRepository/observers/getCommunities.ts +7 -150
  104. package/src/communityRepository/observers/index.ts +1 -0
  105. package/src/communityRepository/observers/searchCommunities/SearchCommunitiesLiveCollectionController.ts +129 -0
  106. package/src/communityRepository/observers/searchCommunities/SearchCommunitiesPaginationController.ts +31 -0
  107. package/src/communityRepository/observers/searchCommunities/SearchCommunitiesQueryStreamController.ts +81 -0
  108. package/src/communityRepository/observers/searchCommunities/enums.ts +5 -0
  109. package/src/communityRepository/observers/searchCommunities.ts +56 -0
  110. package/src/communityRepository/utils/payload.ts +35 -1
  111. package/src/communityRepository/utils/saveCommunityUsers.ts +16 -0
  112. package/src/core/liveCollection/LiveCollectionController.ts +6 -3
  113. package/src/marker/events/onChannelUnreadUpdatedLocal.ts +29 -0
  114. package/src/marker/events/onSubChannelMarkerFetched.ts +1 -1
  115. package/src/marker/events/onSubChannelUnreadUpdatedLocal.ts +29 -0
  116. package/src/marker/events/onUserFeedMarkerUpdated.ts +3 -4
  117. package/src/marker/utils/reCalculateChannelUnreadInfo.ts +7 -3
  118. package/src/messageRepository/observers/getMessages/MessageLiveCollectionController.ts +3 -3
  119. package/src/postRepository/api/editPost.ts +1 -1
  120. package/src/postRepository/api/updatePost.ts +1 -1
  121. package/src/postRepository/observers/getPost.ts +26 -0
  122. package/src/postRepository/observers/getPosts.ts +31 -0
  123. package/src/storyRepository/observers/getGlobalStoryTargets/GlobalStoryLiveCollectionController.ts +2 -2
  124. package/src/storyRepository/observers/getStoriesByTargetIds/StoryLiveCollectionController.ts +1 -1
  125. package/src/streamRepository/api/getStreams.ts +2 -2
  126. package/src/streamRepository/events/onStreamFlagged.ts +37 -0
  127. package/src/streamRepository/events/onStreamTerminated.ts +37 -0
  128. package/src/streamRepository/observers/getStreams.ts +1 -1
  129. package/src/subChannelRepository/observers/getSubChannel.ts +2 -2
  130. package/src/subChannelRepository/observers/getSubChannels/SubChannelLiveCollectionController.ts +4 -4
  131. package/src/utils/liveObject.ts +3 -0
@@ -0,0 +1,31 @@
1
+ import { PaginationController } from '~/core/liveCollection/PaginationController';
2
+ import { COLLECTION_DEFAULT_PAGINATION_LIMIT } from '~/utils/constants';
3
+ import { inferIsDeleted } from '~/utils/inferIsDeleted';
4
+
5
+ /**
6
+ * TODO: handle cache receive cache option, and cache policy
7
+ * TODO: check if querybyIds is supported
8
+ */
9
+ export class CommunitiesPaginationController extends PaginationController<
10
+ 'community',
11
+ Amity.CommunityLiveCollection
12
+ > {
13
+ async getRequest(queryParams: Amity.CommunityLiveCollection, token: string | undefined) {
14
+ const { limit = COLLECTION_DEFAULT_PAGINATION_LIMIT, ...params } = queryParams;
15
+ const options = token ? { token } : { limit };
16
+
17
+ const { data: queryResponse } = await this.http.get<Amity.CommunityPayload & Amity.Pagination>(
18
+ `/api/v3/communities`,
19
+ {
20
+ params: {
21
+ ...params,
22
+ isDeleted: inferIsDeleted(params.includeDeleted),
23
+ keyword: params.displayName,
24
+ filter: params.membership,
25
+ options,
26
+ },
27
+ },
28
+ );
29
+ return queryResponse;
30
+ }
31
+ }
@@ -0,0 +1,88 @@
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 { saveCommunityUsers } from '~/communityRepository/utils/saveCommunityUsers';
7
+ import { EnumCommunityActions } from './enums';
8
+
9
+ export class CommunitiesQueryStreamController extends QueryStreamController<
10
+ Amity.CommunityPayload,
11
+ Amity.CommunityLiveCollection
12
+ > {
13
+ private notifyChange: (params: Amity.LiveCollectionNotifyParams) => void;
14
+
15
+ private preparePayload: (response: Amity.CommunityPayload) => Amity.ProcessedCommunityPayload;
16
+
17
+ constructor(
18
+ query: Amity.CommunityLiveCollection,
19
+ cacheKey: string[],
20
+ notifyChange: (params: Amity.LiveCollectionNotifyParams) => void,
21
+ preparePayload: (response: Amity.CommunityPayload) => Amity.ProcessedCommunityPayload,
22
+ ) {
23
+ super(query, cacheKey);
24
+ this.notifyChange = notifyChange;
25
+ this.preparePayload = preparePayload;
26
+ }
27
+
28
+ async saveToMainDB(response: Amity.CommunityPayload) {
29
+ const processedPayload = await this.preparePayload(response);
30
+
31
+ const client = getActiveClient();
32
+ const cachedAt = client.cache && Date.now();
33
+
34
+ if (client.cache) {
35
+ ingestInCache(processedPayload, { cachedAt });
36
+ saveCommunityUsers(response.communities, response.communityUsers);
37
+ }
38
+ }
39
+
40
+ appendToQueryStream(
41
+ response: Amity.CommunityPayload & Partial<Amity.Pagination>,
42
+ direction: Amity.LiveCollectionPageDirection,
43
+ refresh = false,
44
+ ) {
45
+ if (refresh) {
46
+ pushToCache(this.cacheKey, {
47
+ data: response.communities.map(getResolver('community')),
48
+ });
49
+ } else {
50
+ const collection = pullFromCache<Amity.CommunityLiveCollectionCache>(this.cacheKey)?.data;
51
+
52
+ const communities = collection?.data ?? [];
53
+
54
+ pushToCache(this.cacheKey, {
55
+ ...collection,
56
+ data: [...new Set([...communities, ...response.communities.map(getResolver('community'))])],
57
+ });
58
+ }
59
+ }
60
+
61
+ reactor(action: EnumCommunityActions) {
62
+ return (community: Amity.Community) => {
63
+ const collection = pullFromCache<Amity.CommunityLiveCollectionCache>(this.cacheKey)?.data;
64
+ if (!collection) return;
65
+
66
+ if (this.query.displayName && action === EnumCommunityActions.OnCommunityCreated) {
67
+ return;
68
+ }
69
+
70
+ /*
71
+ * Simply update a collection and let responder decide what to do with data
72
+ */
73
+ collection.data = [...new Set([community.communityId, ...collection.data])];
74
+
75
+ pushToCache(this.cacheKey, collection);
76
+ this.notifyChange({ origin: Amity.LiveDataOrigin.EVENT, loading: false });
77
+ };
78
+ }
79
+
80
+ subscribeRTE(
81
+ createSubscriber: {
82
+ fn: (reactor: (channel: Amity.Community) => void) => Amity.Unsubscriber;
83
+ action: EnumCommunityActions;
84
+ }[],
85
+ ) {
86
+ return createSubscriber.map(subscriber => subscriber.fn(this.reactor(subscriber.action)));
87
+ }
88
+ }
@@ -0,0 +1,5 @@
1
+ export enum EnumCommunityActions {
2
+ OnCommunityCreated = 'onCommunityCreated',
3
+ OnCommunityDeleted = 'onCommunityDeleted',
4
+ OnCommunityUpdated = 'onCommunityUpdated',
5
+ }
@@ -1,31 +1,7 @@
1
- /* eslint-disable no-use-before-define */
2
- import { getResolver } from '~/core/model';
3
- import { dropFromCache, pullFromCache, pushToCache } from '~/cache/api';
1
+ import { dropFromCache } from '~/cache/api';
4
2
  import { getActiveClient } from '~/client/api';
5
- import {
6
- createQuery,
7
- filterByCommunityMembership,
8
- filterByPropEquality,
9
- filterByStringComparePartially,
10
- queryOptions,
11
- runQuery,
12
- sortByDisplayName,
13
- sortByFirstCreated,
14
- sortByLastCreated,
15
- } from '~/core/query';
16
- import {
17
- COLLECTION_DEFAULT_CACHING_POLICY,
18
- COLLECTION_DEFAULT_PAGINATION_LIMIT,
19
- ENABLE_CACHE_MESSAGE,
20
- } from '~/utils/constants';
21
- import { CACHE_SHORTEN_LIFESPAN } from '~/cache/utils';
22
- import { onCommunityCreated, onCommunityDeleted, onCommunityUpdated } from '../events';
23
- import {
24
- onCommunityJoined,
25
- onCommunityLeft,
26
- onCommunityUserChanged,
27
- } from '../communityMembership/events';
28
- import { queryCommunities } from '../api/queryCommunities';
3
+ import { ENABLE_CACHE_MESSAGE } from '~/utils/constants';
4
+ import { CommunityLiveCollectionController } from './getCommunities/CommunitiesLiveCollectionController';
29
5
 
30
6
  /* begin_public_function
31
7
  id: community.query
@@ -53,7 +29,7 @@ export const getCommunities = (
53
29
  callback: Amity.LiveCollectionCallback<Amity.Community>,
54
30
  config?: Amity.LiveCollectionConfig,
55
31
  ) => {
56
- const { log, cache, userId } = getActiveClient();
32
+ const { log, cache } = getActiveClient();
57
33
 
58
34
  if (!cache) {
59
35
  console.log(ENABLE_CACHE_MESSAGE);
@@ -62,130 +38,11 @@ export const getCommunities = (
62
38
  const timestamp = Date.now();
63
39
  log(`getCommunities(tmpid: ${timestamp}) > listen`);
64
40
 
65
- const { limit: queryLimit, ...queryParams } = params;
41
+ const communitiesLiveCollection = new CommunityLiveCollectionController(params, callback);
42
+ const disposers = communitiesLiveCollection.startSubscription();
66
43
 
67
- const limit = queryLimit ?? COLLECTION_DEFAULT_PAGINATION_LIMIT;
68
- const { policy = COLLECTION_DEFAULT_CACHING_POLICY } = config ?? {};
44
+ const cacheKey = communitiesLiveCollection.getCacheKey();
69
45
 
70
- const disposers: Amity.Unsubscriber[] = [];
71
- const cacheKey = ['community', 'collection', queryParams as Amity.Serializable];
72
-
73
- const responder = (data: Amity.CommunityLiveCollectionCache) => {
74
- let communities: Amity.Community[] =
75
- data.data
76
- .map(communityId => pullFromCache<Amity.Community>(['community', 'get', communityId])!)
77
- .filter(Boolean)
78
- .map(({ data }) => data) ?? [];
79
-
80
- communities = filterByStringComparePartially(communities, 'displayName', params.displayName);
81
-
82
- if (!params.includeDeleted) {
83
- communities = filterByPropEquality(communities, 'isDeleted', false);
84
- }
85
-
86
- if (params.categoryId) {
87
- communities = communities.filter(c => c.categoryIds?.includes(params.categoryId!));
88
- }
89
-
90
- if (params.tags) {
91
- communities = communities.filter(c => c.tags?.some(t => params.tags?.includes(t)));
92
- }
93
-
94
- if (params.membership && userId) {
95
- communities = filterByCommunityMembership(communities, params.membership, userId);
96
- }
97
-
98
- const sortBy = params.sortBy || 'lastCreated';
99
-
100
- if (sortBy === 'lastCreated' || sortBy === 'firstCreated') {
101
- communities = communities.sort(
102
- sortBy === 'lastCreated' ? sortByLastCreated : sortByFirstCreated,
103
- );
104
- }
105
-
106
- /*
107
- * The server returns communities with empty | null displayName's first before
108
- * returning sorted list of communities with displayNames
109
- *
110
- * This section needs to be updated as displayNames can be null as well
111
- */
112
- if (sortBy === 'displayName') {
113
- communities = communities
114
- // this needs to be aligned with the backend data type
115
- .map(c => (c.displayName ? c : { ...c, displayName: '' }))
116
- // @ts-ignore
117
- .sort(sortByDisplayName);
118
- }
119
-
120
- callback({
121
- onNextPage: onFetch,
122
- data: communities,
123
- hasNextPage: !!data.params?.page,
124
- loading: data.loading,
125
- error: data.error,
126
- });
127
- };
128
-
129
- const realtimeRouter = (_: Amity.CommunityActionType) => (community: Amity.Community) => {
130
- const collection = pullFromCache<Amity.CommunityLiveCollectionCache>(cacheKey)?.data;
131
- if (!collection) return;
132
-
133
- /*
134
- * Simply update collection and let responder decide what to do with data
135
- */
136
- collection.data = [...new Set([community.communityId, ...collection.data])];
137
-
138
- pushToCache(cacheKey, collection);
139
- responder(collection);
140
- };
141
-
142
- const onFetch = (initial = false) => {
143
- const collection = pullFromCache<Amity.CommunityLiveCollectionCache>(cacheKey)?.data;
144
-
145
- const communities = collection?.data ?? [];
146
-
147
- if (!initial && communities.length > 0 && !collection?.params.page) return;
148
-
149
- const query = createQuery(queryCommunities, {
150
- ...queryParams,
151
- limit: initial ? limit : undefined,
152
- page: !initial ? collection?.params.page : undefined,
153
- });
154
-
155
- runQuery(
156
- query,
157
- ({ data: result, error, loading, paging }) => {
158
- const data = {
159
- loading,
160
- error,
161
- params: { page: paging?.next },
162
- data: communities,
163
- };
164
-
165
- if (result) {
166
- data.data = initial
167
- ? result.map(getResolver('community'))
168
- : [...new Set([...communities, ...result.map(getResolver('community'))])];
169
- }
170
-
171
- pushToCache(cacheKey, data);
172
-
173
- responder(data);
174
- },
175
- queryOptions(policy, CACHE_SHORTEN_LIFESPAN),
176
- );
177
- };
178
-
179
- disposers.push(
180
- onCommunityCreated(realtimeRouter('onCreate')),
181
- onCommunityDeleted(realtimeRouter('onDelete')),
182
- onCommunityUpdated(realtimeRouter('onUpdate')),
183
- onCommunityJoined(realtimeRouter('onJoin')),
184
- onCommunityLeft(realtimeRouter('onLeft')),
185
- onCommunityUserChanged(realtimeRouter('onMemberCountChanged')),
186
- );
187
-
188
- onFetch(true);
189
46
  disposers.push(() => dropFromCache(cacheKey));
190
47
 
191
48
  return () => {
@@ -1,5 +1,6 @@
1
1
  export * from './observeCommunity';
2
2
 
3
+ export * from './searchCommunities';
3
4
  export * from './getCommunities';
4
5
  export * from './getCommunity';
5
6
  export * from './getTrendingCommunities';
@@ -0,0 +1,129 @@
1
+ /* eslint-disable no-use-before-define */
2
+ import hash from 'object-hash';
3
+ import { pullFromCache, pushToCache } from '~/cache/api';
4
+ import { CommunitiesPaginationController } from './SearchCommunitiesPaginationController';
5
+ import { CommunitiesQueryStreamController } from './SearchCommunitiesQueryStreamController';
6
+ import { LiveCollectionController } from '~/core/liveCollection/LiveCollectionController';
7
+ import {
8
+ onCommunityCreated,
9
+ onCommunityDeleted,
10
+ onCommunityUpdated,
11
+ } from '~/communityRepository/events';
12
+ import {
13
+ filterByCommunityMembership,
14
+ filterByPropEquality,
15
+ sortByDisplayName,
16
+ sortByFirstCreated,
17
+ sortByLastCreated,
18
+ } from '~/core/query';
19
+ import { prepareCommunityPayload } from '~/communityRepository/utils';
20
+ import { getActiveClient } from '~/client';
21
+ import { EnumCommunityActions } from './enums';
22
+
23
+ export class SearchCommunityLiveCollectionController extends LiveCollectionController<
24
+ 'community',
25
+ Amity.SearchCommunityLiveCollection,
26
+ Amity.Community,
27
+ CommunitiesPaginationController
28
+ > {
29
+ private queryStreamController: CommunitiesQueryStreamController;
30
+
31
+ private query: Amity.SearchCommunityLiveCollection;
32
+
33
+ constructor(
34
+ query: Amity.SearchCommunityLiveCollection,
35
+ callback: Amity.LiveCollectionCallback<Amity.Community>,
36
+ ) {
37
+ const queryStreamId = hash(query);
38
+ const cacheKey = ['community', 'collection', queryStreamId];
39
+ const paginationController = new CommunitiesPaginationController(query);
40
+
41
+ super(paginationController, queryStreamId, cacheKey, callback);
42
+
43
+ this.query = query;
44
+ this.queryStreamController = new CommunitiesQueryStreamController(
45
+ this.query,
46
+ this.cacheKey,
47
+ this.notifyChange.bind(this),
48
+ prepareCommunityPayload,
49
+ );
50
+
51
+ this.callback = callback.bind(this);
52
+ this.loadPage({ initial: true });
53
+ }
54
+
55
+ protected setup() {
56
+ const collection = pullFromCache<Amity.SearchCommunityLiveCollectionCache>(this.cacheKey)?.data;
57
+ if (!collection) {
58
+ pushToCache(this.cacheKey, {
59
+ data: [],
60
+ params: {},
61
+ });
62
+ }
63
+ }
64
+
65
+ protected async persistModel(queryPayload: Amity.CommunityPayload & Amity.Pagination) {
66
+ await this.queryStreamController.saveToMainDB(queryPayload);
67
+ }
68
+
69
+ protected persistQueryStream({
70
+ response,
71
+ direction,
72
+ refresh,
73
+ }: Amity.LiveCollectionPersistQueryStreamParams<'community'>) {
74
+ this.queryStreamController.appendToQueryStream(response, direction, refresh);
75
+ }
76
+
77
+ startSubscription() {
78
+ return this.queryStreamController.subscribeRTE([
79
+ { fn: onCommunityDeleted, action: EnumCommunityActions.OnCommunityDeleted },
80
+ { fn: onCommunityUpdated, action: EnumCommunityActions.OnCommunityUpdated },
81
+ ]);
82
+ }
83
+
84
+ notifyChange({ origin, loading, error }: Amity.LiveCollectionNotifyParams) {
85
+ const collection = pullFromCache<Amity.SearchCommunityLiveCollectionCache>(this.cacheKey)?.data;
86
+ if (!collection) return;
87
+
88
+ const data = this.applyFilter(
89
+ collection.data
90
+ .map(id => pullFromCache<Amity.Community>(['community', 'get', id])!)
91
+ .filter(Boolean)
92
+ .map(({ data }) => data) ?? [],
93
+ );
94
+
95
+ if (!this.shouldNotify(data) && origin === 'event') return;
96
+
97
+ this.callback({
98
+ onNextPage: () => this.loadPage({ direction: Amity.LiveCollectionPageDirection.NEXT }),
99
+ data,
100
+ hasNextPage: !!this.paginationController.getNextToken(),
101
+ loading,
102
+ error,
103
+ });
104
+ }
105
+
106
+ applyFilter(data: Amity.Community[]) {
107
+ const { userId } = getActiveClient();
108
+
109
+ let communities = data;
110
+
111
+ if (this.query.includeDeleted) {
112
+ communities = filterByPropEquality(communities, 'isDeleted', false);
113
+ }
114
+
115
+ if (this.query.categoryId) {
116
+ communities = communities.filter(c => c.categoryIds?.includes(this.query.categoryId!));
117
+ }
118
+
119
+ if (this.query.tags) {
120
+ communities = communities.filter(c => c.tags?.some(t => this.query.tags?.includes(t)));
121
+ }
122
+
123
+ if (this.query.membership && userId) {
124
+ communities = filterByCommunityMembership(communities, this.query.membership, userId);
125
+ }
126
+
127
+ return communities;
128
+ }
129
+ }
@@ -0,0 +1,31 @@
1
+ import { PaginationController } from '~/core/liveCollection/PaginationController';
2
+ import { COLLECTION_DEFAULT_PAGINATION_LIMIT } from '~/utils/constants';
3
+ import { inferIsDeleted } from '~/utils/inferIsDeleted';
4
+
5
+ /**
6
+ * TODO: handle cache receive cache option, and cache policy
7
+ * TODO: check if querybyIds is supported
8
+ */
9
+ export class CommunitiesPaginationController extends PaginationController<
10
+ 'community',
11
+ Amity.SearchCommunityLiveCollection
12
+ > {
13
+ async getRequest(queryParams: Amity.SearchCommunityLiveCollection, token: string | undefined) {
14
+ const { limit = COLLECTION_DEFAULT_PAGINATION_LIMIT, ...params } = queryParams;
15
+ const options = token ? { token } : { limit };
16
+
17
+ const { data: queryResponse } = await this.http.get<Amity.CommunityPayload & Amity.Pagination>(
18
+ `/api/v3/communities`,
19
+ {
20
+ params: {
21
+ ...params,
22
+ isDeleted: inferIsDeleted(params.includeDeleted),
23
+ keyword: params.displayName,
24
+ filter: params.membership,
25
+ options,
26
+ },
27
+ },
28
+ );
29
+ return queryResponse;
30
+ }
31
+ }
@@ -0,0 +1,81 @@
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 { EnumCommunityActions } from './enums';
7
+
8
+ export class CommunitiesQueryStreamController extends QueryStreamController<
9
+ Amity.CommunityPayload,
10
+ Amity.SearchCommunityLiveCollection
11
+ > {
12
+ private notifyChange: (params: Amity.LiveCollectionNotifyParams) => void;
13
+
14
+ private preparePayload: (response: Amity.CommunityPayload) => Amity.ProcessedCommunityPayload;
15
+
16
+ constructor(
17
+ query: Amity.SearchCommunityLiveCollection,
18
+ cacheKey: string[],
19
+ notifyChange: (params: Amity.LiveCollectionNotifyParams) => void,
20
+ preparePayload: (response: Amity.CommunityPayload) => Amity.ProcessedCommunityPayload,
21
+ ) {
22
+ super(query, cacheKey);
23
+ this.notifyChange = notifyChange;
24
+ this.preparePayload = preparePayload;
25
+ }
26
+
27
+ async saveToMainDB(response: Amity.CommunityPayload) {
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.CommunityPayload & Partial<Amity.Pagination>,
40
+ direction: Amity.LiveCollectionPageDirection,
41
+ refresh = false,
42
+ ) {
43
+ if (refresh) {
44
+ pushToCache(this.cacheKey, {
45
+ data: response.communities.map(getResolver('community')),
46
+ });
47
+ } else {
48
+ const collection = pullFromCache<Amity.SearchCommunityLiveCollectionCache>(
49
+ this.cacheKey,
50
+ )?.data;
51
+
52
+ const communities = collection?.data ?? [];
53
+
54
+ pushToCache(this.cacheKey, {
55
+ ...collection,
56
+ data: [...new Set([...communities, ...response.communities.map(getResolver('community'))])],
57
+ });
58
+ }
59
+ }
60
+
61
+ reactor(action: EnumCommunityActions) {
62
+ return (community: Amity.Community) => {
63
+ const collection = pullFromCache<Amity.SearchCommunityLiveCollectionCache>(
64
+ this.cacheKey,
65
+ )?.data;
66
+ if (!collection) return;
67
+
68
+ pushToCache(this.cacheKey, collection);
69
+ this.notifyChange({ origin: Amity.LiveDataOrigin.EVENT, loading: false });
70
+ };
71
+ }
72
+
73
+ subscribeRTE(
74
+ createSubscriber: {
75
+ fn: (reactor: (channel: Amity.Community) => void) => Amity.Unsubscriber;
76
+ action: EnumCommunityActions;
77
+ }[],
78
+ ) {
79
+ return createSubscriber.map(subscriber => subscriber.fn(this.reactor(subscriber.action)));
80
+ }
81
+ }
@@ -0,0 +1,5 @@
1
+ export enum EnumCommunityActions {
2
+ OnCommunityCreated = 'onCommunityCreated',
3
+ OnCommunityDeleted = 'onCommunityDeleted',
4
+ OnCommunityUpdated = 'onCommunityUpdated',
5
+ }
@@ -0,0 +1,56 @@
1
+ import { dropFromCache } from '~/cache/api';
2
+ import { getActiveClient } from '~/client/api';
3
+ import { ENABLE_CACHE_MESSAGE } from '~/utils/constants';
4
+ import { SearchCommunityLiveCollectionController } from './searchCommunities/SearchCommunitiesLiveCollectionController';
5
+
6
+ /* begin_public_function
7
+ id: community.query
8
+ */
9
+ /**
10
+ * ```js
11
+ * import { CommunityRepository } from '@amityco/ts-sdk-react-native'
12
+ *
13
+ * let communities = []
14
+ * const unsub = CommunityRepository.searchCommunities({
15
+ * displayName: Amity.Community['displayName'],
16
+ * }, response => merge(communities, response.data))
17
+ * ```
18
+ *
19
+ * Observe all mutations on a list of {@link Amity.Community}s
20
+ *
21
+ * @param params for querying communities
22
+ * @param callback the function to call when new data are available
23
+ * @returns An {@link Amity.Unsubscriber} function to run when willing to stop observing the communities
24
+ *
25
+ * @category Community Live Collection
26
+ */
27
+ export const searchCommunities = (
28
+ params: Amity.CommunityLiveCollection,
29
+ callback: Amity.LiveCollectionCallback<Amity.Community>,
30
+ config?: Amity.LiveCollectionConfig,
31
+ ) => {
32
+ const { log, cache } = getActiveClient();
33
+
34
+ if (!cache) {
35
+ console.log(ENABLE_CACHE_MESSAGE);
36
+ }
37
+
38
+ const timestamp = Date.now();
39
+ log(`searchCommunities(tmpid: ${timestamp}) > listen`);
40
+
41
+ const searchCommunitiesLiveCollection = new SearchCommunityLiveCollectionController(
42
+ params,
43
+ callback,
44
+ );
45
+ const disposers = searchCommunitiesLiveCollection.startSubscription();
46
+
47
+ const cacheKey = searchCommunitiesLiveCollection.getCacheKey();
48
+
49
+ disposers.push(() => dropFromCache(cacheKey));
50
+
51
+ return () => {
52
+ log(`searchCommunities(tmpid: ${timestamp}) > dispose`);
53
+ disposers.forEach(fn => fn());
54
+ };
55
+ };
56
+ /* end_public_function */
@@ -1,4 +1,5 @@
1
1
  import { CommunityPostSettingMaps, DefaultCommunityPostSetting } from '~/@types';
2
+ import { pullFromCache } from '~/cache/api';
2
3
  import { withUsers } from '~/group/utils';
3
4
  import { updateMembershipStatus } from './communityWithMembership';
4
5
 
@@ -13,6 +14,22 @@ const getMatchPostSetting = (value: {
13
14
  value.onlyAdminCanPost === CommunityPostSettingMaps[key].onlyAdminCanPost,
14
15
  ) ?? DefaultCommunityPostSetting;
15
16
 
17
+ const convertCommunityUsersToUniqueObject = (
18
+ communityUsers: Amity.RawMembership<'community'>[],
19
+ ) => {
20
+ if (!communityUsers) return communityUsers;
21
+
22
+ const result: {
23
+ [key: string]: Amity.RawMembership<'community'>;
24
+ } = {};
25
+
26
+ communityUsers.forEach(user => {
27
+ result[`${user.userId}#${user.communityId}`] = user;
28
+ });
29
+
30
+ return result;
31
+ };
32
+
16
33
  export const prepareCommunityPayload = (
17
34
  rawPayload: Amity.CommunityPayload,
18
35
  ): Amity.ProcessedCommunityPayload => {
@@ -27,7 +44,24 @@ export const prepareCommunityPayload = (
27
44
  }),
28
45
  );
29
46
 
30
- const communityUsers = withUsers(rawPayload.communityUsers);
47
+ const mergeCommunityUsers = communities.reduce<{
48
+ [key: string]: Amity.RawMembership<'community'>;
49
+ }>((acc, { communityId }) => {
50
+ const users = pullFromCache<Amity.RawMembership<'community'>[]>([
51
+ 'communityUsers',
52
+ 'collection',
53
+ communityId,
54
+ ])?.data;
55
+
56
+ if (!users) return acc;
57
+
58
+ return {
59
+ ...convertCommunityUsersToUniqueObject(users),
60
+ ...acc,
61
+ };
62
+ }, convertCommunityUsersToUniqueObject(rawPayload.communityUsers));
63
+
64
+ const communityUsers = withUsers(Object.values(mergeCommunityUsers));
31
65
 
32
66
  const communityWithMembershipStatus = updateMembershipStatus(communities, communityUsers);
33
67
 
@@ -0,0 +1,16 @@
1
+ import { pushToCache } from '~/cache/api';
2
+
3
+ export const saveCommunityUsers = (
4
+ communities: Amity.CommunityPayload['communities'],
5
+ communityUsers: Amity.CommunityPayload['communityUsers'],
6
+ ) => {
7
+ if (communities.length === 0 || communityUsers.length === 0) return;
8
+
9
+ communities.forEach(({ communityId }) => {
10
+ const collection = communityUsers.filter(
11
+ ({ communityId: userCommunityId }) => communityId === userCommunityId,
12
+ );
13
+
14
+ pushToCache(['communityUsers', 'collection', communityId], collection);
15
+ });
16
+ };