@amityco/ts-sdk-react-native
Version:
Amity Social Cloud Typescript SDK
164 lines (130 loc) • 5.09 kB
text/typescript
import { getActiveClient } from '~/client/api';
import { ingestInCache } from '~/cache/api/ingestInCache';
import { createEventSubscriber, fireEvent } from '~/core/events';
import {
dropFromCache,
mergeInCache,
pullFromCache,
pushToCache,
queryCache,
upsertInCache,
} from '~/cache/api';
import { isInTombstone } from '~/cache/api/isInTombstone';
import { preparePostPayload } from '~/postRepository/utils/payload';
const processDeleteChildPost = (payload: Amity.PostPayload) => {
const post = payload.posts[0];
if (!post.parentId) {
// post is parent post => should mark child post as delete as well
post.children.forEach(childrenId =>
mergeInCache(['post', 'get', childrenId], {
isDeleted: true,
}),
);
} else {
// child post in a parent post
const parentPost = pullFromCache<Amity.InternalPost>(['post', 'get', post.parentPostId])?.data;
if (!parentPost) return;
pushToCache(['post', 'get', parentPost.postId], {
...parentPost,
children: parentPost.children.filter(childId => childId !== post.postId),
});
}
};
const processCreateChildPost = (payload: Amity.PostPayload) => {
const post = payload.posts[0];
if (!post.parentId) return;
const parentPost = pullFromCache<Amity.InternalPost>(['post', 'get', post.parentPostId])?.data;
if (!parentPost) return;
pushToCache(['post', 'get', parentPost.postId], {
...parentPost,
children: [...new Set([post.postId, ...parentPost.children])],
});
};
export const createPostEventSubscriber = (
event: keyof Amity.MqttPostEvents,
callback: Amity.Listener<Amity.InternalPost>,
) => {
const client = getActiveClient();
const filter = (payload: Amity.PostPayload) => {
if (!client.cache) {
callback(payload.posts[0]);
} else {
const data = preparePostPayload(payload);
const { communities } = data;
// NOTE: The event data should be merge with existing cache rather than replace it
ingestInCache(data, undefined, false);
if (communities?.[0] && !['post.updated'].includes(event)) {
fireEvent('community.updated', {
communities,
categories: [],
communityUsers: data.communityUsers,
feeds: [],
files: [],
users: [],
});
}
if (event === 'post.deleted') {
const { postId, postedUserId } = payload.posts[0];
processDeleteChildPost(payload);
try {
isInTombstone('post', postId);
} catch (e) {
// Already in tombstone, skip to update client
return;
}
// If this post NOT BELONG to current user, let **put it to tombstone in all cases**
// For the case incoming post belong to current user, If from **different device will treat it as SOFT DELETE**
// But for same device if it is soft delete it just need to handle as update cache
// But if it is hard delete, it will pushed into tombstone before fire an event to BE. it means it will stay in tombstone already
// and will got skip to notify in a previous code block
if (postedUserId !== client.userId) {
dropFromCache(['post', 'get', postId]);
}
return callback(payload.posts[0]);
}
const post = pullFromCache<Amity.InternalPost>(['post', 'get', payload.posts[0].postId])!;
if (['post.created', 'post.approved', 'post.declined'].includes(event)) {
let queries = queryCache(['post', 'query'])
// @ts-ignore
?.filter(({ key }) => key[2]?.targetId === post.data.targetId);
if (event === 'post.declined') {
// @ts-ignore
queries = queries?.filter(({ key }) => key[2]?.feedType === 'reviewing');
}
queries?.map(({ key, data }) => upsertInCache(key, data as any, { cachedAt: -1 }));
}
if (event === 'post.created') processCreateChildPost(payload);
callback(post.data);
}
};
return createEventSubscriber(client, event, event, filter);
};
export const createLocalPostEventSubscriber = (
event: keyof Omit<Amity.LocalPostEvents, 'local.post.addReaction' | 'local.post.removeReaction'>,
callback: Amity.Listener<Amity.InternalPost>,
) => {
const client = getActiveClient();
const filter = (payload: Amity.PostPayload) => {
if (!client.cache) {
callback(payload.posts[0]);
} else {
const data = preparePostPayload(payload);
const { communities } = data;
ingestInCache(data);
if (communities?.[0] && !['local.post.updated'].includes(event)) {
fireEvent('community.updated', {
communities,
categories: [],
communityUsers: data.communityUsers,
feeds: [],
files: [],
users: [],
});
}
const post = pullFromCache<Amity.InternalPost>(['post', 'get', payload.posts[0].postId])!;
if (event === 'local.post.deleted') processDeleteChildPost(payload);
callback(post.data);
}
};
return createEventSubscriber(client, event, event, filter);
};