import escapeTextContentForBrowser from 'escape-html'; import type { ApiPollJSON, ApiPollOptionJSON } from 'mastodon/api_types/polls'; import emojify from 'mastodon/features/emoji/emoji'; import { CustomEmojiFactory, makeEmojiMap } from './custom_emoji'; import type { CustomEmoji, EmojiMap } from './custom_emoji'; interface PollOptionTranslation { title: string; titleHtml: string; } export interface PollOption extends ApiPollOptionJSON { voted: boolean; titleHtml: string; translation: PollOptionTranslation | null; } export function createPollOptionTranslationFromServerJSON( translation: { title: string }, emojiMap: EmojiMap, ) { return { ...translation, titleHtml: emojify( escapeTextContentForBrowser(translation.title), emojiMap, ), } as PollOptionTranslation; } export interface Poll extends Omit { emojis: CustomEmoji[]; options: PollOption[]; own_votes?: number[]; } const pollDefaultValues = { expired: false, multiple: false, voters_count: 0, votes_count: 0, voted: false, own_votes: [], }; export function createPollFromServerJSON( serverJSON: ApiPollJSON, previousPoll?: Poll, ) { const emojiMap = makeEmojiMap(serverJSON.emojis); return { ...pollDefaultValues, ...serverJSON, emojis: serverJSON.emojis.map((emoji) => CustomEmojiFactory(emoji)), options: serverJSON.options.map((optionJSON, index) => { const option = { ...optionJSON, voted: serverJSON.own_votes?.includes(index) || false, titleHtml: emojify( escapeTextContentForBrowser(optionJSON.title), emojiMap, ), } as PollOption; const prevOption = previousPoll?.options[index]; if (prevOption?.translation && prevOption.title === option.title) { const { translation } = prevOption; option.translation = createPollOptionTranslationFromServerJSON( translation, emojiMap, ); } return option; }), } as Poll; }