UNPKG

@100mslive/hms-video-store

Version:

@100mslive Core SDK which abstracts the complexities of webRTC while providing a reactive store for data management with a unidirectional data flow

160 lines (135 loc) • 5.67 kB
import { HMSPoll, HMSPollQuestionResponse, HMSPollsUpdate, HMSUpdateListener } from '../../interfaces'; import { Store } from '../../sdk/store'; import { createHMSPollFromPollParams } from '../../session-store/interactivity-center/HMSInteractivityCenter'; import { PollResult } from '../../signal/interfaces'; import HMSTransport from '../../transport'; import { convertDateNumToDate } from '../../utils/date'; import { HMSNotificationMethod } from '../HMSNotificationMethod'; import { PollStartNotification, PollStatsNotification, PollStopNotification } from '../HMSNotifications'; export class PollsManager { constructor(private store: Store, private transport: HMSTransport, public listener?: HMSUpdateListener) {} handleNotification(method: string, notification: any) { switch (method) { case HMSNotificationMethod.POLL_START: { this.handlePollStart(notification as PollStartNotification); break; } case HMSNotificationMethod.POLL_STOP: { this.handlePollStop(notification as PollStopNotification); break; } case HMSNotificationMethod.POLL_STATS: this.handlePollStats(notification as PollStatsNotification); break; default: break; } } private async handlePollStart(notification: PollStartNotification) { const polls: HMSPoll[] = []; for (const pollParams of notification.polls) { const pollInStore = this.store.getPoll(pollParams.poll_id); if (pollInStore && pollInStore.state === 'started') { this.listener?.onPollsUpdate(HMSPollsUpdate.POLL_STARTED, [pollInStore]); return; } const questions = await this.transport.signal.getPollQuestions({ poll_id: pollParams.poll_id, index: 0, count: 50, }); const poll = createHMSPollFromPollParams(pollParams); poll.questions = questions.questions.map(({ question, options, answer }) => ({ ...question, options, answer })); await this.updatePollResponses(poll, true); polls.push(poll); this.store.setPoll(poll); } this.listener?.onPollsUpdate(HMSPollsUpdate.POLL_STARTED, polls); } private async handlePollStop(notification: PollStopNotification) { const stoppedPolls: HMSPoll[] = []; for (const poll of notification.polls) { const savedPoll = this.store.getPoll(poll.poll_id); if (savedPoll) { savedPoll.state = 'stopped'; savedPoll.stoppedAt = convertDateNumToDate(poll.stopped_at); savedPoll.stoppedBy = poll.stopped_by; const pollResult = await this.transport.signal.getPollResult({ poll_id: poll.poll_id }); this.updatePollResult(savedPoll, pollResult); stoppedPolls.push(savedPoll); } } if (stoppedPolls.length > 0) { this.listener?.onPollsUpdate(HMSPollsUpdate.POLL_STOPPED, stoppedPolls); } } private async handlePollStats(notification: PollStatsNotification) { const updatedPolls: HMSPoll[] = []; for (const updatedPoll of notification.polls) { const savedPoll = this.store.getPoll(updatedPoll.poll_id); if (!savedPoll) { return; } this.updatePollResult(savedPoll, updatedPoll); updatedPolls.push(savedPoll); } if (updatedPolls.length > 0) { this.listener?.onPollsUpdate(HMSPollsUpdate.POLL_STATS_UPDATED, updatedPolls); } } private updatePollResult(savedPoll: HMSPoll, pollResult: PollResult) { savedPoll.result = { ...savedPoll.result }; savedPoll.result.totalUsers = pollResult.user_count; savedPoll.result.maxUsers = pollResult.max_user; savedPoll.result.totalResponses = pollResult.total_response; pollResult.questions?.forEach(updatedQuestion => { const savedQuestion = savedPoll.questions?.find(question => question.index === updatedQuestion.question); if (!savedQuestion) { return; } savedQuestion.result = { ...savedQuestion.result }; savedQuestion.result.correctResponses = updatedQuestion.correct; savedQuestion.result.skippedCount = updatedQuestion.skipped; savedQuestion.result.totalResponses = updatedQuestion.total; updatedQuestion.options?.forEach((updatedVoteCount, index) => { const savedOption = savedQuestion.options?.[index]; if (savedOption && savedOption.voteCount !== updatedVoteCount) { savedOption.voteCount = updatedVoteCount; } }); }); } private async updatePollResponses(poll: HMSPoll, self: boolean) { const serverResponseParams = await this.transport.signal.getPollResponses({ poll_id: poll.id, index: 0, count: 50, self, }); serverResponseParams.responses?.forEach(({ response, peer, final }) => { const question = poll?.questions?.find(question => question.index === response.question); if (!question) { return; } const pollResponse: HMSPollQuestionResponse = { id: response.response_id, questionIndex: response.question, option: response.option, options: response.options, text: response.text, responseFinal: final, peer: { peerid: peer.peerid, userHash: peer.hash, userid: peer.userid, username: peer.username }, skipped: response.skipped, type: response.type, update: response.update, }; if (Array.isArray(question.responses) && question.responses.length > 0) { if (!question.responses.find(({ id }) => id === pollResponse.id)) { question.responses.push(pollResponse); } } else { question.responses = [pollResponse]; } }); } }