fix: poll multiple-choice toggle + Sentry JAVASCRIPT-REACT-N
PollCreator: replace maxSelections/options.length stale-closure pattern with isMultiple: boolean state. max_selections computed from filledOptions at submit time. Radio inputs replaced with styled toggle buttons that visually highlight the active selection. PollContent: catch getPendingEvents error (Sentry JAVASCRIPT-REACT-N). SDK throws Cannot call getPendingEvents with pendingEventOrdering == chronological when sending poll vote events with m.reference relation. Silently catch so optimistic UI update stands — vote will retry on next sync if needed. Fixes JAVASCRIPT-REACT-N Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -203,12 +203,12 @@ export function PollContent({
|
||||
mx.sendEvent(roomId, 'm.poll.response' as any, {
|
||||
'm.relates_to': { rel_type: 'm.reference', event_id: eventId },
|
||||
'm.selections': [answerId],
|
||||
});
|
||||
}).catch(() => undefined);
|
||||
} else {
|
||||
mx.sendEvent(roomId, 'org.matrix.msc3381.poll.response' as any, {
|
||||
'm.relates_to': { rel_type: 'm.reference', event_id: eventId },
|
||||
'org.matrix.msc3381.poll.response': { answers: [answerId] },
|
||||
});
|
||||
}).catch(() => undefined);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -13,7 +13,7 @@ export function PollCreator({ roomId, onClose }: PollCreatorProps) {
|
||||
const mx = useMatrixClient();
|
||||
const [question, setQuestion] = useState('');
|
||||
const [options, setOptions] = useState<string[]>(['', '']);
|
||||
const [maxSelections, setMaxSelections] = useState<number>(1);
|
||||
const [isMultiple, setIsMultiple] = useState(false);
|
||||
const [submitting, setSubmitting] = useState(false);
|
||||
const [error, setError] = useState<string | null>(null);
|
||||
|
||||
@@ -54,7 +54,7 @@ export function PollCreator({ roomId, onClose }: PollCreatorProps) {
|
||||
'm.poll': {
|
||||
question: { 'm.text': trimmedQuestion },
|
||||
answers: filledOptions.map((o, i) => ({ 'm.id': `${i}`, 'm.text': o })),
|
||||
max_selections: maxSelections,
|
||||
max_selections: isMultiple ? filledOptions.length : 1,
|
||||
kind: 'm.poll.undisclosed',
|
||||
},
|
||||
body: trimmedQuestion,
|
||||
@@ -196,42 +196,29 @@ export function PollCreator({ roomId, onClose }: PollCreatorProps) {
|
||||
<div style={{ display: 'flex', flexDirection: 'column', gap: config.space.S100 }}>
|
||||
<Text size="L400">Selection Type</Text>
|
||||
<div style={{ display: 'flex', gap: config.space.S200 }}>
|
||||
<label
|
||||
style={{
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
gap: config.space.S100,
|
||||
cursor: 'pointer',
|
||||
fontSize: '14px',
|
||||
color: 'var(--tc-surface-high)',
|
||||
}}
|
||||
>
|
||||
<input
|
||||
type="radio"
|
||||
name="pollType"
|
||||
checked={maxSelections === 1}
|
||||
onChange={() => setMaxSelections(1)}
|
||||
/>
|
||||
Single choice
|
||||
</label>
|
||||
<label
|
||||
style={{
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
gap: config.space.S100,
|
||||
cursor: 'pointer',
|
||||
fontSize: '14px',
|
||||
color: 'var(--tc-surface-high)',
|
||||
}}
|
||||
>
|
||||
<input
|
||||
type="radio"
|
||||
name="pollType"
|
||||
checked={maxSelections !== 1}
|
||||
onChange={() => setMaxSelections(options.length)}
|
||||
/>
|
||||
Multiple choice
|
||||
</label>
|
||||
{(['single', 'multiple'] as const).map((type) => {
|
||||
const active = type === 'multiple' ? isMultiple : !isMultiple;
|
||||
return (
|
||||
<button
|
||||
key={type}
|
||||
type="button"
|
||||
onClick={() => setIsMultiple(type === 'multiple')}
|
||||
style={{
|
||||
padding: `${config.space.S100} ${config.space.S300}`,
|
||||
borderRadius: config.radii.R300,
|
||||
border: `1px solid ${active ? 'var(--bg-primary-main)' : 'var(--bg-surface-border)'}`,
|
||||
background: active ? 'var(--bg-primary-main)' : 'transparent',
|
||||
color: active ? 'var(--tc-primary-on-primary)' : 'var(--tc-surface-high)',
|
||||
cursor: 'pointer',
|
||||
fontSize: '13px',
|
||||
fontWeight: active ? 600 : 400,
|
||||
transition: 'all 0.15s ease',
|
||||
}}
|
||||
>
|
||||
{type === 'single' ? 'Single choice' : 'Multiple choice'}
|
||||
</button>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user