@amityco/ts-sdk-react-native
Version:
Amity Social Cloud Typescript SDK
139 lines (109 loc) • 3.21 kB
text/typescript
import { onOffline } from '~/client/utils/onOffline';
import { onOnline } from '~/client/utils/onOnline';
import { SECOND } from '~/utils/constants';
import { createLiveReaction as _createLiveReaction } from '../internalApi/createLiveReaction';
class LiveReactionSyncEngine {
private readonly TIMER_INTERVAL_MS = 1 * SECOND;
private buffer: (Amity.CreateLiveReactionRequest & { streamId: string })[] = [];
private timer: NodeJS.Timer | undefined;
private isSyncing = false;
private connectionListener: (() => void)[] = [];
private isConnected = true;
constructor() {
this.addConnectionListener();
}
startReactionsSync() {
if (!this.timer) {
this.timer = setInterval(() => {
if (this.isConnected) this.syncLiveReactions();
}, this.TIMER_INTERVAL_MS);
}
}
stopReactionsSync() {
if (this.timer) {
clearInterval(this.timer);
this.timer = undefined;
}
}
createLiveReaction(liveReaction: Amity.CreateLiveReactionRequest & { streamId: string }) {
this.buffer.push(liveReaction);
}
private addConnectionListener() {
if (this.connectionListener.length > 0) return;
this.connectionListener.push(
onOnline(() => {
this.isConnected = true;
}),
);
this.connectionListener.push(
onOffline(() => {
this.isConnected = false;
}),
);
}
private removeConnectionListener() {
if (this.connectionListener.length > 0) {
this.connectionListener.forEach(listener => listener());
this.connectionListener = [];
}
}
private syncLiveReactions() {
if (this.isSyncing) {
return;
}
this.isSyncing = true;
const reactions = this.buffer;
// Clear buffer
this.clearBuffer();
const payloads: Record<string, Amity.CreateLiveReactionRequest[]> = reactions.reduce(
(prev: Record<string, Amity.CreateLiveReactionRequest[]>, curr) => {
const { streamId, ...rest } = curr;
if (!prev[streamId]) {
// eslint-disable-next-line no-param-reassign
prev[streamId] = [rest];
} else prev[streamId].push(rest);
return prev;
},
{} as Record<string, Amity.CreateLiveReactionRequest[]>,
);
// Call server api `POST /api/v1/reactions/live` to sync live reactions
Object.entries(payloads).forEach(([streamId, reactions]) => {
_createLiveReaction({
liveStreamId: streamId,
reactions,
});
});
// After sending request
this.isSyncing = false;
}
private clearBuffer() {
this.buffer = [];
}
// Session Management : SessionComponent
onSessionEstablished() {
this.startReactionsSync();
this.addConnectionListener();
}
onSessionDestroyed() {
// Stop timer
this.stopReactionsSync();
// Clear buffer
this.clearBuffer();
// Reset state
this.isSyncing = false;
// remove connection listener
this.removeConnectionListener();
}
onTokenExpired() {
this.stopReactionsSync();
}
}
let instance: LiveReactionSyncEngine;
export default {
getInstance: () => {
if (!instance) {
instance = new LiveReactionSyncEngine();
}
return instance;
},
};