// Copyright 2025 Signal Messenger, LLC // SPDX-License-Identifier: AGPL-3.0-only import React, { memo, useState } from 'react'; import { Checkbox } from 'radix-ui'; import { tw } from '../../../axo/tw.js'; import { AxoButton } from '../../../axo/AxoButton.js'; import { AxoSymbol } from '../../../axo/AxoSymbol.js'; import type { DirectionType } from '../Message.js'; import type { PollWithResolvedVotersType } from '../../../state/selectors/message.js'; import type { LocalizerType } from '../../../types/Util.js'; import { PollVotesModal } from './PollVotesModal.js'; function VotedCheckmark({ isIncoming, i18n, }: { isIncoming: boolean; i18n: LocalizerType; }): JSX.Element { return (
); } type PollCheckboxProps = { checked: boolean; onCheckedChange: (nextChecked: boolean) => void; isIncoming: boolean; }; const PollCheckbox = memo((props: PollCheckboxProps) => { const { isIncoming } = props; return ( ); }); PollCheckbox.displayName = 'PollCheckbox'; export type PollMessageContentsProps = { poll: PollWithResolvedVotersType; direction: DirectionType; i18n: LocalizerType; }; export function PollMessageContents({ poll, direction, i18n, }: PollMessageContentsProps): JSX.Element { const [showVotesModal, setShowVotesModal] = useState(false); const isIncoming = direction === 'incoming'; const totalVotes = poll.totalNumVotes; let pollStatusText: string; if (poll.terminatedAt) { pollStatusText = i18n('icu:PollMessage--FinalResults'); } else if (poll.allowMultiple) { pollStatusText = i18n('icu:PollMessage--SelectMultiple'); } else { pollStatusText = i18n('icu:PollMessage--SelectOne'); } return (
{poll.question}
{pollStatusText}
{/* Poll Options */}
{poll.options.map((option, index) => { const pollVoteEntries = poll.votesByOption.get(index); const optionVotes = pollVoteEntries?.length ?? 0; const percentage = totalVotes > 0 ? (optionVotes / totalVotes) * 100 : 0; const weVotedForThis = (pollVoteEntries ?? []).some( vote => vote.isMe && vote.optionIndexes.includes(index) ); return ( // eslint-disable-next-line react/no-array-index-key
{poll.terminatedAt == null && ( // 3px offset: type-body-large has 14px font-size and 20px line-height, // creating 3px space above text. This aligns checkbox with text baseline.
{}} isIncoming={isIncoming} />
)}
{option} {totalVotes > 0 && (
{poll.terminatedAt != null && weVotedForThis && ( )} {optionVotes}
)}
{percentage > 0 && (
)}
); })}
{totalVotes > 0 ? (
setShowVotesModal(true)} > {i18n('icu:PollMessage__ViewVotesButton')}
) : (
{i18n('icu:PollVotesModal__noVotes')}
)} {showVotesModal && ( setShowVotesModal(false)} /> )}
); }