@amityco/ts-sdk 7.6.1-bba8c29.0 → 7.6.1-ce05a481.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/@types/core/payload.d.ts +1 -1
- package/dist/@types/core/payload.d.ts.map +1 -1
- package/dist/@types/domains/content.d.ts +8 -2
- package/dist/@types/domains/content.d.ts.map +1 -1
- package/dist/@types/domains/feed.d.ts +6 -1
- package/dist/@types/domains/feed.d.ts.map +1 -1
- package/dist/@types/domains/file.d.ts +3 -1
- package/dist/@types/domains/file.d.ts.map +1 -1
- package/dist/@types/domains/post.d.ts +3 -0
- package/dist/@types/domains/post.d.ts.map +1 -1
- package/dist/communityRepository/api/getCommunity.d.ts +1 -1
- package/dist/communityRepository/api/getCommunity.d.ts.map +1 -1
- package/dist/core/model/index.d.ts.map +1 -1
- package/dist/feedRepository/api/getCustomRankingGlobalFeed.d.ts +1 -1
- package/dist/feedRepository/api/getCustomRankingGlobalFeed.d.ts.map +1 -1
- package/dist/feedRepository/api/queryGlobalFeed.d.ts.map +1 -1
- package/dist/feedRepository/index.d.ts +1 -1
- package/dist/feedRepository/index.d.ts.map +1 -1
- package/dist/feedRepository/observers/getCustomRankingGlobalFeed/LiveCollectionController.d.ts +13 -0
- package/dist/feedRepository/observers/getCustomRankingGlobalFeed/LiveCollectionController.d.ts.map +1 -0
- package/dist/feedRepository/observers/getCustomRankingGlobalFeed/PaginationController.d.ts +5 -0
- package/dist/feedRepository/observers/getCustomRankingGlobalFeed/PaginationController.d.ts.map +1 -0
- package/dist/feedRepository/observers/getCustomRankingGlobalFeed/QueryStreamController.d.ts +15 -0
- package/dist/feedRepository/observers/getCustomRankingGlobalFeed/QueryStreamController.d.ts.map +1 -0
- package/dist/feedRepository/observers/getCustomRankingGlobalFeed.d.ts +23 -0
- package/dist/feedRepository/observers/getCustomRankingGlobalFeed.d.ts.map +1 -0
- package/dist/feedRepository/observers/getGlobalFeed/LiveCollectionController.d.ts +13 -0
- package/dist/feedRepository/observers/getGlobalFeed/LiveCollectionController.d.ts.map +1 -0
- package/dist/feedRepository/observers/getGlobalFeed/PaginationController.d.ts +5 -0
- package/dist/feedRepository/observers/getGlobalFeed/PaginationController.d.ts.map +1 -0
- package/dist/feedRepository/observers/getGlobalFeed/QueryStreamController.d.ts +15 -0
- package/dist/feedRepository/observers/getGlobalFeed/QueryStreamController.d.ts.map +1 -0
- package/dist/feedRepository/observers/getGlobalFeed.d.ts +22 -0
- package/dist/feedRepository/observers/getGlobalFeed.d.ts.map +1 -0
- package/dist/feedRepository/observers/index.d.ts +3 -0
- package/dist/feedRepository/observers/index.d.ts.map +1 -0
- package/dist/feedRepository/observers/utils.d.ts +6 -0
- package/dist/feedRepository/observers/utils.d.ts.map +1 -0
- package/dist/fileRepository/api/index.d.ts +1 -0
- package/dist/fileRepository/api/index.d.ts.map +1 -1
- package/dist/fileRepository/api/uploadClip.d.ts +17 -0
- package/dist/fileRepository/api/uploadClip.d.ts.map +1 -0
- package/dist/index.cjs.js +1565 -1195
- package/dist/index.esm.js +1657 -1287
- package/dist/index.umd.js +2 -2
- package/dist/messagePreview/utils/getSubChannelMessagePreviewWithUser.d.ts +1 -1
- package/dist/postRepository/api/createClipPost.d.ts +32 -0
- package/dist/postRepository/api/createClipPost.d.ts.map +1 -0
- package/dist/postRepository/api/index.d.ts +1 -0
- package/dist/postRepository/api/index.d.ts.map +1 -1
- package/dist/postRepository/events/utils.d.ts.map +1 -1
- package/dist/postRepository/observers/getGlobalPinnedPosts/GlobalPinnedPostLiveCollectionController.d.ts.map +1 -1
- package/dist/postRepository/observers/getPinnedPosts/PinnedPostLiveCollectionController.d.ts.map +1 -1
- package/dist/postRepository/observers/getPinnedPosts/PinnedPostQueryStreamController.d.ts +6 -0
- package/dist/postRepository/observers/getPinnedPosts/PinnedPostQueryStreamController.d.ts.map +1 -1
- package/dist/postRepository/observers/getPosts/PostLiveCollectionController.d.ts.map +1 -1
- package/dist/postRepository/observers/utils.d.ts +13 -0
- package/dist/postRepository/observers/utils.d.ts.map +1 -0
- package/dist/reactionRepository/api/addReaction.d.ts.map +1 -1
- package/dist/reactionRepository/api/removeReaction.d.ts.map +1 -1
- package/dist/utils/linkedObject/postLinkedObject.d.ts.map +1 -1
- package/dist/utils/postTypePredicate.d.ts +1 -0
- package/dist/utils/postTypePredicate.d.ts.map +1 -1
- package/dist/utils/tests/dummy/comment.d.ts +1 -1
- package/package.json +1 -1
- package/src/@types/core/payload.ts +1 -1
- package/src/@types/domains/content.ts +10 -0
- package/src/@types/domains/feed.ts +18 -1
- package/src/@types/domains/file.ts +5 -0
- package/src/@types/domains/post.ts +4 -0
- package/src/commentRepository/api/deleteComment.ts +6 -6
- package/src/communityRepository/api/getCommunity.ts +0 -9
- package/src/core/model/index.ts +2 -1
- package/src/feedRepository/api/getCustomRankingGlobalFeed.ts +1 -1
- package/src/feedRepository/api/queryGlobalFeed.ts +3 -1
- package/src/feedRepository/index.ts +1 -1
- package/src/feedRepository/observers/getCustomRankingGlobalFeed/LiveCollectionController.ts +95 -0
- package/src/feedRepository/observers/getCustomRankingGlobalFeed/PaginationController.ts +25 -0
- package/src/feedRepository/observers/getCustomRankingGlobalFeed/QueryStreamController.ts +101 -0
- package/src/feedRepository/observers/getCustomRankingGlobalFeed.ts +57 -0
- package/src/feedRepository/observers/getGlobalFeed/LiveCollectionController.ts +91 -0
- package/src/feedRepository/observers/getGlobalFeed/PaginationController.ts +23 -0
- package/src/feedRepository/observers/getGlobalFeed/QueryStreamController.ts +99 -0
- package/src/feedRepository/observers/getGlobalFeed.ts +56 -0
- package/src/feedRepository/observers/index.ts +2 -0
- package/src/feedRepository/observers/utils.ts +85 -0
- package/src/fileRepository/api/index.ts +1 -0
- package/src/fileRepository/api/uploadClip.ts +71 -0
- package/src/postRepository/api/createClipPost.ts +62 -0
- package/src/postRepository/api/index.ts +2 -0
- package/src/postRepository/api/queryPosts.ts +1 -1
- package/src/postRepository/events/utils.ts +35 -1
- package/src/postRepository/observers/getGlobalPinnedPosts/GlobalPinnedPostLiveCollectionController.ts +5 -0
- package/src/postRepository/observers/getPinnedPosts/PinnedPostLiveCollectionController.ts +7 -1
- package/src/postRepository/observers/getPinnedPosts/PinnedPostQueryStreamController.ts +27 -0
- package/src/postRepository/observers/getPosts/PostLiveCollectionController.ts +2 -74
- package/src/postRepository/observers/getPosts/PostPaginationController.ts +1 -1
- package/src/postRepository/observers/utils.ts +97 -0
- package/src/reactionRepository/api/addReaction.ts +1 -0
- package/src/reactionRepository/api/removeReaction.ts +1 -0
- package/src/utils/linkedObject/postLinkedObject.ts +15 -5
- package/src/utils/postTypePredicate.ts +9 -0
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import { getActiveClient } from '~/client/api';
|
|
2
|
+
import { dropFromCache } from '~/cache/api';
|
|
3
|
+
|
|
4
|
+
import { ENABLE_CACHE_MESSAGE } from '~/utils/constants';
|
|
5
|
+
import { CustomRankingGlobalFeedLiveCollectionController } from './getCustomRankingGlobalFeed/LiveCollectionController';
|
|
6
|
+
|
|
7
|
+
/* begin_public_function
|
|
8
|
+
id: post.query
|
|
9
|
+
*/
|
|
10
|
+
/**
|
|
11
|
+
* ```js
|
|
12
|
+
* import { PostRepository } from '@amityco/ts-sdk'
|
|
13
|
+
*
|
|
14
|
+
* let posts = []
|
|
15
|
+
* const unsub = PostRepository.getPosts({
|
|
16
|
+
* targetType: Amity.PostTargetType,
|
|
17
|
+
* targetId: Amity.Post['targetId'],
|
|
18
|
+
* }, response => merge(posts, response.data))
|
|
19
|
+
* ```
|
|
20
|
+
*
|
|
21
|
+
* Observe all mutations on a list of {@link Amity.Post} for a given target object
|
|
22
|
+
*
|
|
23
|
+
* @param params.targetType the type of the target
|
|
24
|
+
* @param params.targetId the ID of the target
|
|
25
|
+
* @param callback the function to call when new data are available
|
|
26
|
+
* @param config
|
|
27
|
+
* @returns An {@link Amity.Unsubscriber} function to run when willing to stop observing the messages
|
|
28
|
+
*
|
|
29
|
+
* @category Posts Live Collection
|
|
30
|
+
*/
|
|
31
|
+
export const getCustomRankingGlobalFeed = (
|
|
32
|
+
params: Amity.CustomRankingGlobalFeedLiveCollection,
|
|
33
|
+
callback: Amity.LiveCollectionCallback<Amity.Post>,
|
|
34
|
+
config?: Amity.LiveCollectionConfig,
|
|
35
|
+
): Amity.Unsubscriber => {
|
|
36
|
+
const { log, cache } = getActiveClient();
|
|
37
|
+
|
|
38
|
+
if (!cache) {
|
|
39
|
+
console.log(ENABLE_CACHE_MESSAGE);
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
const timestamp = Date.now();
|
|
43
|
+
log(`getCustomRankingGlobalFeed(tmpid: ${timestamp}) > listen`);
|
|
44
|
+
|
|
45
|
+
const liveCollection = new CustomRankingGlobalFeedLiveCollectionController(params, callback);
|
|
46
|
+
const disposers = liveCollection.startSubscription();
|
|
47
|
+
|
|
48
|
+
const cacheKey = liveCollection.getCacheKey();
|
|
49
|
+
|
|
50
|
+
disposers.push(() => dropFromCache(cacheKey));
|
|
51
|
+
|
|
52
|
+
return () => {
|
|
53
|
+
log(`getCustomRankingGlobalFeed(tmpid: ${timestamp}) > dispose`);
|
|
54
|
+
disposers.forEach(fn => fn());
|
|
55
|
+
};
|
|
56
|
+
};
|
|
57
|
+
/* end_public_function */
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
import hash from 'object-hash';
|
|
2
|
+
import { pullFromCache, pushToCache } from '~/cache/api';
|
|
3
|
+
import { GlobalFeedPaginationController } from './PaginationController';
|
|
4
|
+
import { GlobalFeedQueryStreamController } from './QueryStreamController';
|
|
5
|
+
import { LiveCollectionController } from '~/core/liveCollection/LiveCollectionController';
|
|
6
|
+
import { isNonNullable } from '~/utils';
|
|
7
|
+
import { LinkedObject } from '~/utils/linkedObject';
|
|
8
|
+
import { preparePostPayload } from '~/postRepository/utils/payload';
|
|
9
|
+
import { getGlobalFeedSubscriptions } from '../utils';
|
|
10
|
+
|
|
11
|
+
export class GlobalFeedLiveCollectionController extends LiveCollectionController<
|
|
12
|
+
'post',
|
|
13
|
+
Amity.GlobalFeedLiveCollection,
|
|
14
|
+
Amity.Post,
|
|
15
|
+
GlobalFeedPaginationController
|
|
16
|
+
> {
|
|
17
|
+
private queryStreamController: GlobalFeedQueryStreamController;
|
|
18
|
+
|
|
19
|
+
private query: Amity.GlobalFeedLiveCollection;
|
|
20
|
+
|
|
21
|
+
constructor(
|
|
22
|
+
query: Amity.GlobalFeedLiveCollection,
|
|
23
|
+
callback: Amity.LiveCollectionCallback<Amity.Post>,
|
|
24
|
+
) {
|
|
25
|
+
const queryStreamId = hash(query);
|
|
26
|
+
const cacheKey = ['globalFeed', 'collection', queryStreamId];
|
|
27
|
+
const paginationController = new GlobalFeedPaginationController(query);
|
|
28
|
+
|
|
29
|
+
super(paginationController, queryStreamId, cacheKey, callback);
|
|
30
|
+
|
|
31
|
+
this.query = query;
|
|
32
|
+
this.queryStreamController = new GlobalFeedQueryStreamController(
|
|
33
|
+
this.query,
|
|
34
|
+
this.cacheKey,
|
|
35
|
+
this.notifyChange.bind(this),
|
|
36
|
+
preparePostPayload,
|
|
37
|
+
);
|
|
38
|
+
|
|
39
|
+
this.callback = callback.bind(this);
|
|
40
|
+
this.loadPage({ initial: true });
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
protected setup() {
|
|
44
|
+
const collection = pullFromCache<Amity.GlobalFeedLiveCollectionCache>(this.cacheKey)?.data;
|
|
45
|
+
|
|
46
|
+
if (!collection) {
|
|
47
|
+
pushToCache(this.cacheKey, {
|
|
48
|
+
data: [],
|
|
49
|
+
params: {},
|
|
50
|
+
});
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
protected async persistModel(queryPayload: Amity.PostPayload & Amity.Pagination) {
|
|
55
|
+
await this.queryStreamController.saveToMainDB(queryPayload);
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
protected persistQueryStream({
|
|
59
|
+
response,
|
|
60
|
+
direction,
|
|
61
|
+
refresh,
|
|
62
|
+
}: Amity.LiveCollectionPersistQueryStreamParams<'post'>) {
|
|
63
|
+
this.queryStreamController.appendToQueryStream(response, direction, refresh);
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
startSubscription() {
|
|
67
|
+
return this.queryStreamController.subscribeRTE(getGlobalFeedSubscriptions(this.cacheKey));
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
notifyChange({ origin, loading, error }: Amity.LiveCollectionNotifyParams) {
|
|
71
|
+
const collection = pullFromCache<Amity.GlobalFeedLiveCollectionCache>(this.cacheKey)?.data;
|
|
72
|
+
if (!collection) return;
|
|
73
|
+
|
|
74
|
+
const data = (
|
|
75
|
+
collection.data
|
|
76
|
+
.map(id => pullFromCache<Amity.InternalPost>(['post', 'get', id])!)
|
|
77
|
+
.filter(isNonNullable)
|
|
78
|
+
.map(({ data }) => data) ?? []
|
|
79
|
+
).map(LinkedObject.post);
|
|
80
|
+
|
|
81
|
+
if (!this.shouldNotify(data) && origin === 'event') return;
|
|
82
|
+
|
|
83
|
+
this.callback({
|
|
84
|
+
onNextPage: () => this.loadPage({ direction: Amity.LiveCollectionPageDirection.NEXT }),
|
|
85
|
+
data,
|
|
86
|
+
hasNextPage: !!this.paginationController.getNextToken(),
|
|
87
|
+
loading,
|
|
88
|
+
error,
|
|
89
|
+
});
|
|
90
|
+
}
|
|
91
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { PaginationController } from '~/core/liveCollection/PaginationController';
|
|
2
|
+
|
|
3
|
+
export class GlobalFeedPaginationController extends PaginationController<
|
|
4
|
+
'post',
|
|
5
|
+
Amity.GlobalFeedLiveCollection
|
|
6
|
+
> {
|
|
7
|
+
async getRequest(queryParams: Amity.GlobalFeedLiveCollection, token: string | undefined) {
|
|
8
|
+
const { limit, resolveParent, ...params } = queryParams;
|
|
9
|
+
const options = token ? { token } : { limit };
|
|
10
|
+
|
|
11
|
+
const { data: queryResponse } = await this.http.get<Amity.PostPayload & Amity.Pagination>(
|
|
12
|
+
`/api/v4/me/global-feeds`,
|
|
13
|
+
{
|
|
14
|
+
params: {
|
|
15
|
+
...params,
|
|
16
|
+
resolveParent: resolveParent ?? true,
|
|
17
|
+
options,
|
|
18
|
+
},
|
|
19
|
+
},
|
|
20
|
+
);
|
|
21
|
+
return queryResponse;
|
|
22
|
+
}
|
|
23
|
+
}
|
|
@@ -0,0 +1,99 @@
|
|
|
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 { EnumPostActions } from '~/postRepository/observers/enums';
|
|
7
|
+
|
|
8
|
+
export class GlobalFeedQueryStreamController extends QueryStreamController<
|
|
9
|
+
Amity.PostPayload,
|
|
10
|
+
Amity.GlobalFeedLiveCollection
|
|
11
|
+
> {
|
|
12
|
+
private notifyChange: (params: Amity.LiveCollectionNotifyParams) => void;
|
|
13
|
+
|
|
14
|
+
private preparePayload: (response: Amity.PostPayload) => Amity.ProcessedPostPayload;
|
|
15
|
+
|
|
16
|
+
constructor(
|
|
17
|
+
query: Amity.GlobalFeedLiveCollection,
|
|
18
|
+
cacheKey: string[],
|
|
19
|
+
notifyChange: (params: Amity.LiveCollectionNotifyParams) => void,
|
|
20
|
+
preparePayload: (response: Amity.PostPayload) => Amity.ProcessedPostPayload,
|
|
21
|
+
) {
|
|
22
|
+
super(query, cacheKey);
|
|
23
|
+
this.notifyChange = notifyChange;
|
|
24
|
+
this.preparePayload = preparePayload;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
async saveToMainDB(response: Amity.PostPayload) {
|
|
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.PostPayload & Partial<Amity.Pagination>,
|
|
40
|
+
direction: Amity.LiveCollectionPageDirection,
|
|
41
|
+
refresh = false,
|
|
42
|
+
) {
|
|
43
|
+
if (refresh) {
|
|
44
|
+
pushToCache(this.cacheKey, {
|
|
45
|
+
data: response.posts.map(getResolver('post')),
|
|
46
|
+
});
|
|
47
|
+
} else {
|
|
48
|
+
const collection = pullFromCache<Amity.CommunityLiveCollectionCache>(this.cacheKey)?.data;
|
|
49
|
+
|
|
50
|
+
const posts = collection?.data ?? [];
|
|
51
|
+
|
|
52
|
+
pushToCache(this.cacheKey, {
|
|
53
|
+
...collection,
|
|
54
|
+
data: [...new Set([...posts, ...response.posts.map(getResolver('post'))])],
|
|
55
|
+
});
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
reactor(action: EnumPostActions) {
|
|
60
|
+
return (post: Amity.InternalPost) => {
|
|
61
|
+
const collection = pullFromCache<Amity.GlobalFeedLiveCollectionCache>(this.cacheKey)?.data;
|
|
62
|
+
|
|
63
|
+
if (!collection) return;
|
|
64
|
+
|
|
65
|
+
if (post.parentPostId && !collection.data.includes(post.parentPostId)) return;
|
|
66
|
+
|
|
67
|
+
// Delete Action
|
|
68
|
+
if (action === EnumPostActions.OnPostDeleted) {
|
|
69
|
+
// Parent Post - Remove from collection
|
|
70
|
+
collection.data = collection.data.filter(postId => postId !== post.postId);
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
if (action === EnumPostActions.OnPostCreated || action === EnumPostActions.OnPostApproved) {
|
|
74
|
+
// If the query has dataTypes array with value, check if post.dataType is include in the array
|
|
75
|
+
if (this.query.dataTypes && this.query.dataTypes.length > 0) {
|
|
76
|
+
if (!this.query.dataTypes.includes(post.dataType)) return;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
collection.data = [...new Set([post.postId, ...collection.data])];
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
if (action === EnumPostActions.OnPostDeclined) {
|
|
83
|
+
collection.data = collection.data.filter(postId => postId !== post.postId);
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
pushToCache(this.cacheKey, collection);
|
|
87
|
+
this.notifyChange({ origin: Amity.LiveDataOrigin.EVENT, loading: false });
|
|
88
|
+
};
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
subscribeRTE(
|
|
92
|
+
createSubscriber: {
|
|
93
|
+
fn: (reactor: (post: Amity.InternalPost) => void) => Amity.Unsubscriber;
|
|
94
|
+
action: EnumPostActions;
|
|
95
|
+
}[],
|
|
96
|
+
) {
|
|
97
|
+
return createSubscriber.map(subscriber => subscriber.fn(this.reactor(subscriber.action)));
|
|
98
|
+
}
|
|
99
|
+
}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import { getActiveClient } from '~/client/api';
|
|
2
|
+
import { dropFromCache } from '~/cache/api';
|
|
3
|
+
|
|
4
|
+
import { ENABLE_CACHE_MESSAGE } from '~/utils/constants';
|
|
5
|
+
import { GlobalFeedLiveCollectionController } from './getGlobalFeed/LiveCollectionController';
|
|
6
|
+
|
|
7
|
+
/* begin_public_function
|
|
8
|
+
id: post.query
|
|
9
|
+
*/
|
|
10
|
+
/**
|
|
11
|
+
* ```js
|
|
12
|
+
* import { PostRepository } from '@amityco/ts-sdk'
|
|
13
|
+
*
|
|
14
|
+
* let posts = []
|
|
15
|
+
* const unsub = PostRepository.getPosts({
|
|
16
|
+
* targetType: Amity.PostTargetType,
|
|
17
|
+
* targetId: Amity.Post['targetId'],
|
|
18
|
+
* }, response => merge(posts, response.data))
|
|
19
|
+
* ```
|
|
20
|
+
*
|
|
21
|
+
* Observe all mutations on a list of {@link Amity.Post} for a given target object
|
|
22
|
+
* @param params.targetType the type of the target
|
|
23
|
+
* @param params.targetId the ID of the target
|
|
24
|
+
* @param callback the function to call when new data are available
|
|
25
|
+
* @param config
|
|
26
|
+
* @returns An {@link Amity.Unsubscriber} function to run when willing to stop observing the messages
|
|
27
|
+
*
|
|
28
|
+
* @category Posts Live Collection
|
|
29
|
+
*/
|
|
30
|
+
export const getGlobalFeed = (
|
|
31
|
+
params: Amity.GlobalFeedLiveCollection,
|
|
32
|
+
callback: Amity.LiveCollectionCallback<Amity.Post>,
|
|
33
|
+
config?: Amity.LiveCollectionConfig,
|
|
34
|
+
): Amity.Unsubscriber => {
|
|
35
|
+
const { log, cache } = getActiveClient();
|
|
36
|
+
|
|
37
|
+
if (!cache) {
|
|
38
|
+
console.log(ENABLE_CACHE_MESSAGE);
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
const timestamp = Date.now();
|
|
42
|
+
log(`getGlobalFeed(tmpid: ${timestamp}) > listen`);
|
|
43
|
+
|
|
44
|
+
const liveCollection = new GlobalFeedLiveCollectionController(params, callback);
|
|
45
|
+
const disposers = liveCollection.startSubscription();
|
|
46
|
+
|
|
47
|
+
const cacheKey = liveCollection.getCacheKey();
|
|
48
|
+
|
|
49
|
+
disposers.push(() => dropFromCache(cacheKey));
|
|
50
|
+
|
|
51
|
+
return () => {
|
|
52
|
+
log(`getGlobalFeed(tmpid: ${timestamp}) > dispose`);
|
|
53
|
+
disposers.forEach(fn => fn());
|
|
54
|
+
};
|
|
55
|
+
};
|
|
56
|
+
/* end_public_function */
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
import { pullFromCache } from '~/cache/api';
|
|
2
|
+
import { onCommentCreated, onCommentDeleted } from '~/commentRepository';
|
|
3
|
+
import { getPost } from '~/postRepository/internalApi';
|
|
4
|
+
import {
|
|
5
|
+
onPostCreated,
|
|
6
|
+
onPostUpdated,
|
|
7
|
+
onPostDeleted,
|
|
8
|
+
onPostFlagged,
|
|
9
|
+
onPostUnflagged,
|
|
10
|
+
onPostReactionAdded,
|
|
11
|
+
onPostReactionRemoved,
|
|
12
|
+
onPostApproved,
|
|
13
|
+
onPostDeclined,
|
|
14
|
+
} from '~/postRepository/events';
|
|
15
|
+
import { onLocalPostDeleted } from '~/postRepository/events/onLocalPostDeleted';
|
|
16
|
+
import { onLocalPostReactionAdded } from '~/postRepository/events/onLocalPostReactionAdded';
|
|
17
|
+
import { onLocalPostReactionRemoved } from '~/postRepository/events/onLocalPostReactionRemoved';
|
|
18
|
+
import { onPostUpdatedLocal } from '~/postRepository/events/onPostUpdatedLocal';
|
|
19
|
+
import { EnumPostActions } from '~/postRepository/observers/enums';
|
|
20
|
+
import { convertEventPayload } from '~/utils/event';
|
|
21
|
+
import { onCommentCreatedLocal } from '~/commentRepository/events/onCommentCreatedLocal';
|
|
22
|
+
import { onCommentDeleteLocal } from '~/commentRepository/events/onCommentDeletedLocal';
|
|
23
|
+
import { onCommentReactionAdded, onCommentReactionRemoved } from '~/commentRepository/events';
|
|
24
|
+
import { onLocalCommentReactionAdded } from '~/commentRepository/events/onLocalCommentReactionAdded';
|
|
25
|
+
import { onLocalCommentReactionRemoved } from '~/commentRepository/events/onLocalCommentReactionRemoved';
|
|
26
|
+
|
|
27
|
+
type CommentEventHandler = (callback: Amity.Listener<Amity.InternalComment>) => Amity.Unsubscriber;
|
|
28
|
+
|
|
29
|
+
const commentEventHanlder = (
|
|
30
|
+
callback: Amity.Listener<Amity.InternalComment>,
|
|
31
|
+
eventHandler: CommentEventHandler,
|
|
32
|
+
cacheKey: Amity.CacheKey,
|
|
33
|
+
) => {
|
|
34
|
+
return eventHandler(async (comment: Amity.InternalComment) => {
|
|
35
|
+
const currentCollection =
|
|
36
|
+
pullFromCache<Amity.CustomRankingGlobalFeedLiveCollectionCache>(cacheKey)?.data;
|
|
37
|
+
|
|
38
|
+
if (!currentCollection || !currentCollection.data.includes(comment.referenceId)) return;
|
|
39
|
+
|
|
40
|
+
await getPost(comment.referenceId);
|
|
41
|
+
callback(comment);
|
|
42
|
+
});
|
|
43
|
+
};
|
|
44
|
+
|
|
45
|
+
const generateCommentSubscriptions = (cacheKey: Amity.CacheKey) => {
|
|
46
|
+
const eventHandlers = [
|
|
47
|
+
onCommentCreated,
|
|
48
|
+
onCommentDeleted,
|
|
49
|
+
onCommentReactionAdded,
|
|
50
|
+
onCommentReactionRemoved,
|
|
51
|
+
onCommentCreatedLocal,
|
|
52
|
+
onCommentDeleteLocal,
|
|
53
|
+
onLocalCommentReactionAdded,
|
|
54
|
+
onLocalCommentReactionRemoved,
|
|
55
|
+
];
|
|
56
|
+
|
|
57
|
+
return eventHandlers.map(handler => ({
|
|
58
|
+
fn: convertEventPayload(
|
|
59
|
+
(callback: Amity.Listener<Amity.InternalComment>) =>
|
|
60
|
+
commentEventHanlder(callback, handler, cacheKey),
|
|
61
|
+
'referenceId',
|
|
62
|
+
'post',
|
|
63
|
+
),
|
|
64
|
+
action: EnumPostActions.OnPostUpdated,
|
|
65
|
+
}));
|
|
66
|
+
};
|
|
67
|
+
|
|
68
|
+
export const getGlobalFeedSubscriptions = (cacheKey: Amity.CacheKey) => {
|
|
69
|
+
return [
|
|
70
|
+
{ fn: onPostCreated, action: EnumPostActions.OnPostCreated },
|
|
71
|
+
{ fn: onPostUpdated, action: EnumPostActions.OnPostUpdated },
|
|
72
|
+
{ fn: onPostUpdatedLocal, action: EnumPostActions.OnPostUpdated },
|
|
73
|
+
{ fn: onPostDeleted, action: EnumPostActions.OnPostDeleted },
|
|
74
|
+
{ fn: onPostFlagged, action: EnumPostActions.OnPostFlagged },
|
|
75
|
+
{ fn: onPostUnflagged, action: EnumPostActions.OnPostUnflagged },
|
|
76
|
+
{ fn: onPostApproved, action: EnumPostActions.OnPostApproved },
|
|
77
|
+
{ fn: onPostDeclined, action: EnumPostActions.OnPostDeclined },
|
|
78
|
+
{ fn: onPostReactionAdded, action: EnumPostActions.OnPostReactionAdded },
|
|
79
|
+
{ fn: onPostReactionRemoved, action: EnumPostActions.OnPostReactionRemoved },
|
|
80
|
+
{ fn: onLocalPostReactionAdded, action: EnumPostActions.OnPostReactionAdded },
|
|
81
|
+
{ fn: onLocalPostReactionRemoved, action: EnumPostActions.OnPostReactionRemoved },
|
|
82
|
+
{ fn: onLocalPostDeleted, action: EnumPostActions.OnPostDeleted },
|
|
83
|
+
...generateCommentSubscriptions(cacheKey),
|
|
84
|
+
];
|
|
85
|
+
};
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import { getActiveClient } from '~/client/api/activeClient';
|
|
2
|
+
import { ingestInCache } from '~/cache/api/ingestInCache';
|
|
3
|
+
import GlobalFileAccessType from '~/client/utils/GlobalFileAccessType';
|
|
4
|
+
|
|
5
|
+
/* begin_public_function
|
|
6
|
+
id: file.upload.clip
|
|
7
|
+
*/
|
|
8
|
+
/**
|
|
9
|
+
* ```js
|
|
10
|
+
* import { FileRepository } from '@amityco/ts-sdk'
|
|
11
|
+
* const created = await FileRepository.uploadClip(formData)
|
|
12
|
+
* ```
|
|
13
|
+
*
|
|
14
|
+
* Creates an {@link Amity.File}
|
|
15
|
+
*
|
|
16
|
+
* @param formData The data necessary to create a new {@link Amity.File}
|
|
17
|
+
* @param onProgress The callback to track the upload progress
|
|
18
|
+
* @returns The newly created {@link Amity.File}
|
|
19
|
+
*
|
|
20
|
+
* @category File API
|
|
21
|
+
* @async
|
|
22
|
+
*/
|
|
23
|
+
export const uploadClip = async (
|
|
24
|
+
formData: FormData,
|
|
25
|
+
feedType?: Amity.ContentFeedType,
|
|
26
|
+
onProgress?: (percent: number) => void,
|
|
27
|
+
): Promise<Amity.Cached<Amity.File<'clip'>[]>> => {
|
|
28
|
+
const client = getActiveClient();
|
|
29
|
+
client.log('file/uploadClip', formData);
|
|
30
|
+
|
|
31
|
+
const file = formData.get('files');
|
|
32
|
+
|
|
33
|
+
if (!file) throw new Error('The formData object must have a `files` key.');
|
|
34
|
+
|
|
35
|
+
const accessType = GlobalFileAccessType.getInstance().getFileAccessType();
|
|
36
|
+
formData.append('accessType', accessType);
|
|
37
|
+
|
|
38
|
+
formData.append('preferredFilename', (file as File).name);
|
|
39
|
+
|
|
40
|
+
if (feedType) {
|
|
41
|
+
formData.append('feedType', feedType);
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
const headers =
|
|
45
|
+
'getHeaders' in formData
|
|
46
|
+
? (formData as any).getHeaders()
|
|
47
|
+
: { 'content-type': 'multipart/form-data' };
|
|
48
|
+
|
|
49
|
+
const { data } = await client.upload.post<Amity.CreateFilePayload<'clip'>>(
|
|
50
|
+
'/api/v4/clips',
|
|
51
|
+
formData,
|
|
52
|
+
{
|
|
53
|
+
headers,
|
|
54
|
+
onUploadProgress({ loaded, total = 100 }) {
|
|
55
|
+
onProgress && onProgress(Math.round((loaded * 100) / total));
|
|
56
|
+
},
|
|
57
|
+
},
|
|
58
|
+
);
|
|
59
|
+
|
|
60
|
+
// API-FIX: payload should be serialized properly
|
|
61
|
+
// const { files } = data
|
|
62
|
+
|
|
63
|
+
const cachedAt = client.cache && Date.now();
|
|
64
|
+
if (client.cache) ingestInCache({ files: data }, { cachedAt });
|
|
65
|
+
|
|
66
|
+
return {
|
|
67
|
+
data,
|
|
68
|
+
cachedAt,
|
|
69
|
+
};
|
|
70
|
+
};
|
|
71
|
+
/* end_public_function */
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import { getActiveClient } from '~/client/api/activeClient';
|
|
2
|
+
|
|
3
|
+
import { ingestInCache } from '~/cache/api/ingestInCache';
|
|
4
|
+
import { fireEvent } from '~/core/events';
|
|
5
|
+
import { prepareMembershipPayload } from '~/group/utils';
|
|
6
|
+
import { LinkedObject } from '~/utils/linkedObject';
|
|
7
|
+
|
|
8
|
+
/* begin_public_function
|
|
9
|
+
id: post.create.clip_post
|
|
10
|
+
*/
|
|
11
|
+
/**
|
|
12
|
+
* ```js
|
|
13
|
+
* import { PostRepository } from '@amityco/ts-sdk'
|
|
14
|
+
* const created = await PostRepository.createClipPost({
|
|
15
|
+
* targetType: 'user',
|
|
16
|
+
* targetId: 'foobar',
|
|
17
|
+
* dataType: 'clip',
|
|
18
|
+
* data: { text: 'hello world' },
|
|
19
|
+
* attachments: [{ type: 'clip', fileId: 'fileId123', displayMode: 'fill', isMuted: false }]
|
|
20
|
+
* }))
|
|
21
|
+
* ```
|
|
22
|
+
*
|
|
23
|
+
* Creates an {@link Amity.Post}
|
|
24
|
+
*
|
|
25
|
+
* @param bundle The data necessary to create a new {@link Amity.Post}
|
|
26
|
+
* @returns The newly created {@link Amity.Post}
|
|
27
|
+
*
|
|
28
|
+
* @category Post API
|
|
29
|
+
* @async
|
|
30
|
+
*/
|
|
31
|
+
export const createClipPost = async <T extends Amity.PostContentType | string>(
|
|
32
|
+
bundle: Pick<Amity.Post<T>, 'targetType' | 'targetId'> &
|
|
33
|
+
Partial<Pick<Amity.Post<T>, 'metadata' | 'mentionees' | 'tags'>> & {
|
|
34
|
+
data: { [k: string]: any };
|
|
35
|
+
attachments: {
|
|
36
|
+
type: T;
|
|
37
|
+
fileId: Amity.File['fileId'];
|
|
38
|
+
displayMode?: Amity.ClipDisplayMode;
|
|
39
|
+
isMuted?: boolean;
|
|
40
|
+
}[];
|
|
41
|
+
},
|
|
42
|
+
): Promise<Amity.Cached<Amity.Post>> => {
|
|
43
|
+
const client = getActiveClient();
|
|
44
|
+
client.log('post/createPost', bundle);
|
|
45
|
+
|
|
46
|
+
const { data: payload } = await client.http.post<Amity.PostPayload>('/api/v4/posts', bundle);
|
|
47
|
+
|
|
48
|
+
fireEvent('post.created', payload);
|
|
49
|
+
|
|
50
|
+
const data = prepareMembershipPayload(payload, 'communityUsers');
|
|
51
|
+
const cachedAt = client.cache && Date.now();
|
|
52
|
+
|
|
53
|
+
if (client.cache) ingestInCache(data, { cachedAt });
|
|
54
|
+
|
|
55
|
+
const { posts } = data;
|
|
56
|
+
|
|
57
|
+
return {
|
|
58
|
+
data: LinkedObject.post(posts[0]),
|
|
59
|
+
cachedAt,
|
|
60
|
+
};
|
|
61
|
+
};
|
|
62
|
+
/* end_public_function */
|
|
@@ -43,7 +43,7 @@ export const queryPosts = async (
|
|
|
43
43
|
// API-FIX: parameters should be querystring. (1)
|
|
44
44
|
// API-FIX: backend should answer Amity.Response (2)
|
|
45
45
|
// const { data } = await client.http.get<Amity.Response<Amity.PagedResponse<Amity.PostPayload>>>(
|
|
46
|
-
const { data } = await client.http.get<Amity.PostPayload & Amity.Pagination>(`/api/
|
|
46
|
+
const { data } = await client.http.get<Amity.PostPayload & Amity.Pagination>(`/api/v5/posts`, {
|
|
47
47
|
params: {
|
|
48
48
|
...params,
|
|
49
49
|
isDeleted: inferIsDeleted(includeDeleted),
|
|
@@ -1,10 +1,38 @@
|
|
|
1
1
|
import { getActiveClient } from '~/client/api';
|
|
2
2
|
import { ingestInCache } from '~/cache/api/ingestInCache';
|
|
3
3
|
import { createEventSubscriber, fireEvent } from '~/core/events';
|
|
4
|
-
import { dropFromCache, pullFromCache, queryCache, upsertInCache } from '~/cache/api';
|
|
4
|
+
import { dropFromCache, pullFromCache, pushToCache, queryCache, upsertInCache } from '~/cache/api';
|
|
5
5
|
import { isInTombstone } from '~/cache/api/isInTombstone';
|
|
6
6
|
import { preparePostPayload } from '~/postRepository/utils/payload';
|
|
7
7
|
|
|
8
|
+
const processDeleteChildPost = (payload: Amity.PostPayload) => {
|
|
9
|
+
const post = payload.posts[0];
|
|
10
|
+
if (!post.parentId) return;
|
|
11
|
+
|
|
12
|
+
const parentPost = pullFromCache<Amity.InternalPost>(['post', 'get', post.parentPostId])?.data;
|
|
13
|
+
|
|
14
|
+
if (!parentPost) return;
|
|
15
|
+
|
|
16
|
+
pushToCache(['post', 'get', parentPost.postId], {
|
|
17
|
+
...parentPost,
|
|
18
|
+
children: parentPost.children.filter(childId => childId !== post.postId),
|
|
19
|
+
});
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
const processCreateChildPost = (payload: Amity.PostPayload) => {
|
|
23
|
+
const post = payload.posts[0];
|
|
24
|
+
if (!post.parentId) return;
|
|
25
|
+
|
|
26
|
+
const parentPost = pullFromCache<Amity.InternalPost>(['post', 'get', post.parentPostId])?.data;
|
|
27
|
+
|
|
28
|
+
if (!parentPost) return;
|
|
29
|
+
|
|
30
|
+
pushToCache(['post', 'get', parentPost.postId], {
|
|
31
|
+
...parentPost,
|
|
32
|
+
children: [...new Set([post.postId, ...parentPost.children])],
|
|
33
|
+
});
|
|
34
|
+
};
|
|
35
|
+
|
|
8
36
|
export const createPostEventSubscriber = (
|
|
9
37
|
event: keyof Amity.MqttPostEvents,
|
|
10
38
|
callback: Amity.Listener<Amity.InternalPost>,
|
|
@@ -36,6 +64,8 @@ export const createPostEventSubscriber = (
|
|
|
36
64
|
if (event === 'post.deleted') {
|
|
37
65
|
const { postId, postedUserId } = payload.posts[0];
|
|
38
66
|
|
|
67
|
+
processDeleteChildPost(payload);
|
|
68
|
+
|
|
39
69
|
try {
|
|
40
70
|
isInTombstone('post', postId);
|
|
41
71
|
} catch (e) {
|
|
@@ -70,6 +100,8 @@ export const createPostEventSubscriber = (
|
|
|
70
100
|
queries?.map(({ key, data }) => upsertInCache(key, data as any, { cachedAt: -1 }));
|
|
71
101
|
}
|
|
72
102
|
|
|
103
|
+
if (event === 'post.created') processCreateChildPost(payload);
|
|
104
|
+
|
|
73
105
|
callback(post.data);
|
|
74
106
|
}
|
|
75
107
|
};
|
|
@@ -106,6 +138,8 @@ export const createLocalPostEventSubscriber = (
|
|
|
106
138
|
|
|
107
139
|
const post = pullFromCache<Amity.InternalPost>(['post', 'get', payload.posts[0].postId])!;
|
|
108
140
|
|
|
141
|
+
if (event === 'local.post.deleted') processDeleteChildPost(payload);
|
|
142
|
+
|
|
109
143
|
callback(post.data);
|
|
110
144
|
}
|
|
111
145
|
};
|
|
@@ -8,6 +8,7 @@ import { LinkedObject } from '~/utils/linkedObject';
|
|
|
8
8
|
import { onPostDeleted } from '~/postRepository/events';
|
|
9
9
|
import { EnumPostActions } from '../enums';
|
|
10
10
|
import { onLocalPostDeleted } from '~/postRepository/events/onLocalPostDeleted';
|
|
11
|
+
import { generateCommentSubscriptions } from '../utils';
|
|
11
12
|
|
|
12
13
|
export class GlobalPinnedPostLiveCollectionController extends LiveCollectionController<
|
|
13
14
|
'pinnedPost',
|
|
@@ -71,6 +72,10 @@ export class GlobalPinnedPostLiveCollectionController extends LiveCollectionCont
|
|
|
71
72
|
fn: onPostDeleted,
|
|
72
73
|
action: EnumPostActions.OnPostDeleted,
|
|
73
74
|
},
|
|
75
|
+
...generateCommentSubscriptions({
|
|
76
|
+
cacheKey: this.cacheKey,
|
|
77
|
+
resolveId: id => `global#${id}`,
|
|
78
|
+
}),
|
|
74
79
|
]);
|
|
75
80
|
}
|
|
76
81
|
|
|
@@ -6,6 +6,7 @@ import { LiveCollectionController } from '~/core/liveCollection/LiveCollectionCo
|
|
|
6
6
|
import { isNonNullable } from '~/utils';
|
|
7
7
|
import { LinkedObject } from '~/utils/linkedObject';
|
|
8
8
|
import { sortByLastCreated } from '~/core/query';
|
|
9
|
+
import { generateCommentSubscriptions } from '../utils';
|
|
9
10
|
|
|
10
11
|
export class PinnedPostLiveCollectionController extends LiveCollectionController<
|
|
11
12
|
'pinnedPost',
|
|
@@ -63,7 +64,12 @@ export class PinnedPostLiveCollectionController extends LiveCollectionController
|
|
|
63
64
|
|
|
64
65
|
// eslint-disable-next-line class-methods-use-this
|
|
65
66
|
startSubscription() {
|
|
66
|
-
return
|
|
67
|
+
return this.queryStreamController.subscribeRTE(
|
|
68
|
+
generateCommentSubscriptions({
|
|
69
|
+
cacheKey: this.cacheKey,
|
|
70
|
+
resolveId: id => `${this.query.placement}#${id}`,
|
|
71
|
+
}),
|
|
72
|
+
);
|
|
67
73
|
}
|
|
68
74
|
|
|
69
75
|
notifyChange({ origin, loading, error }: Amity.LiveCollectionNotifyParams) {
|