import React from 'react' export default function ConversationList({ conversations, loading, activeId, currentUserId, onSelect }) { return (

Conversations

Recent threads and group rooms

{conversations.length}
) } function ConversationRow({ conv, isActive, currentUserId, onClick }) { const label = convLabel(conv, currentUserId) const lastMsg = Array.isArray(conv.latest_message) ? conv.latest_message[0] : conv.latest_message const preview = lastMsg?.body ? truncate(lastMsg.body, 88) : 'No messages yet' const unread = conv.unread_count ?? 0 const myParticipant = conv.all_participants?.find((participant) => participant.user_id === currentUserId) const isArchived = myParticipant?.is_archived ?? false const isPinned = myParticipant?.is_pinned ?? false const activeMembers = conv.all_participants?.filter((participant) => !participant.left_at).length ?? 0 const typeLabel = conv.type === 'group' ? `${activeMembers} members` : 'Direct message' const senderLabel = lastMsg?.sender?.username ? `@${lastMsg.sender.username}` : null const initials = label .split(/\s+/) .filter(Boolean) .slice(0, 2) .map((part) => part.charAt(0).toUpperCase()) .join('') || 'M' return (
  • ) } function convLabel(conv, currentUserId) { if (conv.type === 'group') return conv.title ?? 'Group' const other = conv.all_participants?.find((participant) => participant.user_id !== currentUserId) return other?.user?.username ?? 'Direct message' } function truncate(str, max) { if (!str) return '' return str.length > max ? `${str.slice(0, max)}…` : str } function relativeTime(iso) { if (!iso) return 'No activity' const diff = (Date.now() - new Date(iso).getTime()) / 1000 if (diff < 60) return 'Now' if (diff < 3600) return `${Math.floor(diff / 60)}m` if (diff < 86400) return `${Math.floor(diff / 3600)}h` return `${Math.floor(diff / 86400)}d` }