@amityco/ts-sdk-react-native
Version:
Amity Social Cloud Typescript SDK
153 lines (125 loc) • 4.27 kB
text/typescript
/* eslint-disable no-use-before-define */
import { getResolver } from '~/core/model';
import { pullFromCache, pushToCache } from '~/cache/api';
import { getActiveClient } from '~/client/api';
import {
createQuery,
filterByPropEquality,
queryOptions,
runQuery,
sortByFirstCreated,
sortByLastCreated,
} from '~/core/query';
import {
COLLECTION_DEFAULT_CACHING_POLICY,
COLLECTION_DEFAULT_PAGINATION_LIMIT,
ENABLE_CACHE_MESSAGE,
} from '~/utils/constants';
import { queryStreams as _queryStreams } from '../internalApi/queryStreams';
import { onStreamRecorded, onStreamStarted, onStreamStopped } from '../events';
/* begin_public_function
id: stream.query
*/
/**
* ```js
* import { StreamRepository } from '@amityco/ts-sdk-react-native'
* const streams = await StreamRepository.getStreams()
* ```
*
* Observe all mutations on a list of {@link Amity.Stream}s
*
* @param params for querying streams
* @param callback the function to call when new data are available
* @param config
* @returns An {@link Amity.Unsubscriber} function to run when willing to stop observing the streams
*
* @category Stream Live Collection
*/
export const getStreams = (
params: Amity.StreamLiveCollection,
callback: Amity.LiveCollectionCallback<Amity.Stream>,
config?: Amity.LiveCollectionConfig,
) => {
const { log, cache } = getActiveClient();
if (!cache) {
console.log(ENABLE_CACHE_MESSAGE);
}
const timestamp = Date.now();
log(`getStreams(tmpid: ${timestamp}) > listen`);
const { limit: queryLimit, ...queryParams } = params;
const limit = queryLimit ?? COLLECTION_DEFAULT_PAGINATION_LIMIT;
const { policy = COLLECTION_DEFAULT_CACHING_POLICY } = config ?? {};
const disposers: Amity.Unsubscriber[] = [];
const cacheKey = ['streams', 'collection', params];
const applyFilter = (data: Amity.Stream[]): Amity.Stream[] => {
let streams = filterByPropEquality(data, 'isDeleted', params.isDeleted);
streams = streams.sort(
params.sortBy === 'lastCreated' ? sortByLastCreated : sortByFirstCreated,
);
return streams;
};
const responder = (data: Amity.StreamLiveCollectionCache, isEventModel = false) => {
const streams: Amity.Stream[] =
data.data
.map(streamId => {
return pullFromCache<Amity.Stream>(['stream', 'get', streamId])!;
})
.filter(Boolean)
.map(({ data }) => data) ?? [];
callback({
onNextPage: onFetch,
/*
* Only apply filter to RTE Model
*/
data: isEventModel ? applyFilter(streams) : streams,
hasNextPage: !!data.params?.page,
loading: data.loading,
error: data.error,
});
};
const realtimeRouter = (_: Amity.StreamActionType) => (stream: Amity.Stream) => {
const collection = pullFromCache<Amity.StreamLiveCollectionCache>(cacheKey)?.data;
if (!collection) return;
collection.data = [...new Set([stream.streamId, ...collection.data])];
pushToCache(cacheKey, collection);
responder(collection, true);
};
const onFetch = (initial = false) => {
const collection = pullFromCache<Amity.StreamLiveCollectionCache>(cacheKey)?.data;
const streams = collection?.data ?? [];
if (!initial && streams.length > 0 && !collection?.params.page) return;
const query = createQuery(_queryStreams, {
...queryParams,
limit: initial ? limit : undefined,
page: !initial ? collection?.params.page : undefined,
});
runQuery(
query,
({ data: result, error, loading, paging }) => {
const data = {
loading,
error,
params: { page: paging?.next },
data: streams,
};
if (result) {
data.data = [...new Set([...streams, ...result.map(getResolver('stream'))])];
}
pushToCache(cacheKey, data);
responder(data);
},
queryOptions(policy),
);
};
disposers.push(
onStreamRecorded(realtimeRouter('onStreamRecorded')),
onStreamStarted(realtimeRouter('onStreamStarted')),
onStreamStopped(realtimeRouter('onStreamStopped')),
);
onFetch(true);
return () => {
log(`getStreams(tmpid: ${timestamp}) > dispose`);
disposers.forEach(fn => fn());
};
};
/* end_public_function */