import type { MessageReaction } from '@chat-app/shared/chat'; import { useMemo } from 'react'; import { Pressable, StyleSheet, Text, View } from 'react-native'; import { colors } from '../theme/colors'; interface Props { reactions: MessageReaction[]; myUserId: string | null; onToggle: (emoji: string) => void; } // Renders the per-message reaction badges underneath a bubble. Pills // the current user has reacted to get a tinted background so they know // which ones to tap to un-react. export function ReactionPills({ reactions, myUserId, onToggle }: Props) { const grouped = useMemo(() => groupByEmoji(reactions, myUserId), [reactions, myUserId]); if (grouped.length === 0) return null; return ( {grouped.map((g) => ( onToggle(g.emoji)} style={[styles.pill, g.mine && styles.pillMine]} > {g.emoji} {g.count} ))} ); } function groupByEmoji( rows: MessageReaction[], myUserId: string | null, ): Array<{ emoji: string; count: number; mine: boolean }> { const m = new Map(); for (const r of rows) { const prev = m.get(r.emoji) ?? { count: 0, mine: false }; m.set(r.emoji, { count: prev.count + 1, mine: prev.mine || (myUserId !== null && r.userId === myUserId), }); } return Array.from(m.entries()).map(([emoji, v]) => ({ emoji, ...v })); } const styles = StyleSheet.create({ row: { flexDirection: 'row', flexWrap: 'wrap', gap: 4, marginTop: 4 }, pill: { flexDirection: 'row', alignItems: 'center', paddingHorizontal: 8, paddingVertical: 2, borderRadius: 12, backgroundColor: colors.surface, borderColor: colors.border, borderWidth: 1, gap: 4, }, pillMine: { backgroundColor: colors.accentMuted, borderColor: colors.accent }, emoji: { fontSize: 13 }, count: { color: colors.textMuted, fontSize: 12, fontWeight: '600' }, countMine: { color: colors.accent }, });