@livelike/react-native
Version:
LiveLike React Native package
118 lines (111 loc) • 3.7 kB
text/typescript
import { useCallback, useRef } from 'react';
import { IWidgetOptionItem, hasDebugLogger } from '@livelike/javascript';
import { useWidgetActions } from './useWidgetActions';
import { useWidgetInteractionActions } from './useWidgetInteractionActions';
import { useWidgetInteractions } from './useWidgetInteractions';
import { useWidgetOptions } from './useWidgetOptions';
import { useWidgetInteractedAnalytics } from './useWidgetInteractedAnalytics';
export type UseCheerMeterOnOptionPressArg = {
widgetId: string;
optionIndex: number;
throttleTime: number;
};
export const useCheerMeterOnOptionPress = ({
widgetId,
optionIndex,
throttleTime,
}: UseCheerMeterOnOptionPressArg) => {
const throttleRef = useRef({
prevDateTime: undefined,
timeout: undefined,
cacheVoteCount: 0,
});
const widgetOptions = useWidgetOptions({ widgetId });
const { createWidgetInteractionAction, updateWidgetInteractionAction } =
useWidgetInteractionActions({ widgetId });
const { updateWidgetOptionsAction } = useWidgetActions({ widgetId });
const widgetOption = widgetOptions?.[optionIndex];
const widgetInteractions = useWidgetInteractions({ widgetId });
const { trackWidgetInteractedAction } = useWidgetInteractedAnalytics({
widgetId,
});
const hasInteractedOption = !!widgetInteractions?.find(
({ option_id }) => option_id === widgetOption?.id
);
return useCallback(() => {
let { timeout, prevDateTime, cacheVoteCount } = throttleRef.current;
const now = Date.now();
clearTimeout(timeout);
throttleRef.current.cacheVoteCount = cacheVoteCount + 1;
if (!prevDateTime || now - prevDateTime >= throttleTime) {
updateCount();
prevDateTime = now;
} else {
timeout = setTimeout(
() => updateCount(),
throttleTime - (now - prevDateTime)
);
}
throttleRef.current = {
prevDateTime,
timeout,
cacheVoteCount: throttleRef.current.cacheVoteCount,
};
function updateCount() {
const interactionItem = {
...widgetOptions[optionIndex],
vote_count: throttleRef.current.cacheVoteCount,
};
trackWidgetInteractedAction<IWidgetOptionItem>({
interactionItem: widgetOptions[optionIndex],
});
throttleRef.current = {
...throttleRef.current,
// reset cache vote count
cacheVoteCount: 0,
};
(hasInteractedOption
? updateWidgetInteractionAction({ interactionItem })
: createWidgetInteractionAction({ interactionItem })
)
.then((res) => {
if (!res) {
return;
}
const updatedOptions = widgetOptions.map((option) => ({ ...option }));
updatedOptions[optionIndex] = {
...updatedOptions[optionIndex],
vote_count:
updatedOptions[optionIndex].vote_count +
interactionItem.vote_count,
};
updateWidgetOptionsAction({
widgetId,
widgetOptions: updatedOptions,
});
})
.catch((e) => {
hasDebugLogger() &&
console.error(
`Error while ${
hasInteractedOption ? 'updating' : 'creating'
} interaction`,
e
);
// add earlier cache vote count back
throttleRef.current = {
...throttleRef.current,
// reset cache vote count
cacheVoteCount: interactionItem.vote_count,
};
});
}
}, [
throttleRef.current,
optionIndex,
hasInteractedOption,
widgetOptions,
updateWidgetInteractionAction,
createWidgetInteractionAction,
]);
};