UNPKG

@livelike/react-native

Version:

LiveLike React Native package

251 lines (245 loc) 8.33 kB
import { getRewardTransactions, getTargetedWidgetIdAndKind, addProgramListener, removeProgramListener, WidgetCreatedEvent, getPostedWidgets, getWidgetsInteractions, PREDICTION_FOLLOW_UP_WIDGET_KIND, PREDICTION_WIDGET_ID_PROP, getWidgetInteractions } from '@livelike/javascript'; import { useCallback, useEffect, useRef, useState } from 'react'; import { getSelectedOptionIndex, getWidgeUIPhase, getWidgetResultState, getWidgetRewardsFromRewardTransactions, widgetStoreActions, timelineWidgetStoreActions } from '../store'; import { useApi } from './useApi'; import { WidgetMode } from '../types'; export function useLoadTimelineWidgetEffect(_ref) { let { programId, mode } = _ref; const [moreWidgets, setMoreWidgets] = useState(false); const nextIteratorRef = useRef(); const { onApi, isLoading, error, data } = useApi(() => getPostedWidgets({ programId }).then(widgetsPayload => { if (!widgetsPayload.done) { setMoreWidgets(true); nextIteratorRef.current = widgetsPayload.next; } return widgetsPayload; }).then(getWidgetsDetails)); useEffect(() => { if (mode === WidgetMode.POPUP) { timelineWidgetStoreActions.updateTimelineWidgetStateAction({ programId, widgetTimelineState: { widgets: [] } }); return; } onApi().then(apiData => updateWidgetsState(apiData, programId)); }, [programId, mode]); useEffect(() => { if (!data && mode === WidgetMode.INTERACTIVE_TIMELINE) { return; } function onProgramListener(_ref2) { let { event, message } = _ref2; if (Object.values(WidgetCreatedEvent).includes(event)) { const { id: widgetId, kind: widgetKind } = message; const widgetPayload = message; (PREDICTION_FOLLOW_UP_WIDGET_KIND.includes(widgetKind) ? getWidgetInteractions({ widgetId, widgetKind, interactionUrl: widgetPayload.widget_interactions_url_template }) : Promise.resolve([])).then(widgetInteractions => { widgetStoreActions.updateWidgetStateAction({ widgetId, widgetState: { widgetPayload, widgetInteractions, widgetResultState: getWidgetResultState({ widgetPayload, widgetInteractions }), widgetUIPhase: getWidgeUIPhase({ widgetPayload, widgetInteractions }), selectedOptionIndex: getSelectedOptionIndex({ widgetPayload, widgetInteractions }), isTimelineWidget: true } }); timelineWidgetStoreActions.updateTimelineWidgetsAction({ programId, widgets: [{ widgetId, widgetKind }], prepend: true }); }); } } addProgramListener({ programId }, onProgramListener); return () => { removeProgramListener({ programId }, onProgramListener); }; }, [data, programId, mode]); const onLoadMore = useCallback(() => { if (nextIteratorRef.current) { return nextIteratorRef.current().then(res => { if (res.done) { setMoreWidgets(false); nextIteratorRef.current = null; } return res.value; }).then(getWidgetsDetails).then(widgetsData => updateWidgetsState(widgetsData, programId)); } }, [nextIteratorRef.current, programId]); return { onApi, isLoading, error, data, onLoadMore: moreWidgets ? onLoadMore : null }; } const getWidgetsDetails = widgetsPayload => { return Promise.all([getWidgetsInteractions({ interactionUrl: widgetsPayload.widget_interactions_url_template }), Promise.all(widgetsPayload.widgets.map(widget => getTargetedWidgetIdAndKind({ widget }))).then(widgetIdsAndKinds => getAllRewardTransasctions(widgetIdsAndKinds.map(_ref3 => { let { widgetId } = _ref3; return widgetId; })))]).then(_ref4 => { let [widgetInteractions, widgetRewards] = _ref4; return [widgetsPayload.widgets, widgetInteractions, widgetRewards]; }); }; const updateWidgetsState = (_ref5, programId) => { let [widgets, widgetInteractions, widgetRewards] = _ref5; const { widgetRecords: widgetsPayloadRecord, followUpWidgetRecords } = getWidgetPayloadRecord(widgets); const widgetsInteractionsRecord = getWidgetsInteractionsRecord(widgetInteractions, followUpWidgetRecords); const widgetsRewardsRecord = getWidgetsRewardsRecord(widgetRewards, followUpWidgetRecords); // set individual widget state so that widget details are not reloaded // This is done to avoid sending multiple widget details request for every widget rendered // that would give same response. Object.keys(widgetsPayloadRecord).forEach(widgetId => { const widgetPayload = widgetsPayloadRecord[widgetId]; const widgetInteractions = widgetsInteractionsRecord[widgetId] ?? []; widgetStoreActions.updateWidgetStateAction({ widgetId, widgetState: { widgetPayload, widgetInteractions, widgetRewards: widgetsRewardsRecord[widgetId], widgetResultState: getWidgetResultState({ widgetPayload, widgetInteractions }), widgetUIPhase: getWidgeUIPhase({ widgetPayload, widgetInteractions }), selectedOptionIndex: getSelectedOptionIndex({ widgetPayload, widgetInteractions }), isTimelineWidget: true } }); }); timelineWidgetStoreActions.updateTimelineWidgetsAction({ programId, widgets: widgets.map(_ref6 => { let { id: widgetId, kind: widgetKind } = _ref6; return { widgetId, widgetKind }; }) }); }; // get all reward transactions incase there are multiple pages of // reward transactions const getAllRewardTransasctions = async widgetIds => { const response = await getRewardTransactions({ widgetIds }); let results = response.results; let done = response.done; while (!done) { const res = await response.next(); results = results.concat(res.value.results); done = res.done; } return results; }; // create a record of widgetId vs widgetpayload function getWidgetPayloadRecord(widgets) { const followUpWidgetRecords = {}; const widgetRecords = widgets.reduce((record, widgetPayload) => { record[widgetPayload.id] = widgetPayload; if (PREDICTION_FOLLOW_UP_WIDGET_KIND.includes(widgetPayload.kind)) { followUpWidgetRecords[widgetPayload.id] = widgetPayload; } return record; }, {}); return { widgetRecords, followUpWidgetRecords }; } // create a record of widgetId vs widgetInteractions function getWidgetsInteractionsRecord(widgetsInteractions, followUpWidgetRecords) { const record = {}; for (const interactions of Object.values(widgetsInteractions)) { for (const interaction of interactions) { record[interaction.widget_id] = [...(record[interaction.widget_id] ?? []), interaction]; } } // set followup widget interaction using its corresponding prediction widget id for (const predictionWidget of Object.values(followUpWidgetRecords)) { const widgetId = predictionWidget[PREDICTION_WIDGET_ID_PROP[predictionWidget.kind]]; if (widgetId && record[widgetId]) { record[predictionWidget.id] = record[widgetId]; } } return record; } // create a record of widgetId vs widgetRewards function getWidgetsRewardsRecord(widgetsRewards, followUpWidgetRecords) { const record = {}; for (const reward of widgetsRewards) { record[reward.widget_id] = [...(record[reward.widget_id] ?? []), ...getWidgetRewardsFromRewardTransactions([reward])]; } // set followup widget rewards using its corresponding prediction widget id for (const predictionWidget of Object.values(followUpWidgetRecords)) { const widgetId = predictionWidget[PREDICTION_WIDGET_ID_PROP[predictionWidget.kind]]; if (widgetId && record[widgetId]) { record[predictionWidget.id] = record[widgetId]; } } return record; } //# sourceMappingURL=useLoadTimelineWidgetEffect.js.map