{/* Username for others at group start */}
{!own && isNewGroup && (
setHoveredId(msg.id)}
onMouseLeave={() => setHoveredId(null)}
onContextMenu={e => { e.preventDefault(); if (canEdit) setReactMenu({ msgId: msg.id, x: e.clientX, y: e.clientY }) }}
onTouchEnd={e => {
const now = Date.now()
const lastTap = e.currentTarget.dataset.lastTap || 0
if (now - lastTap < 300 && canEdit) {
e.preventDefault()
const touch = e.changedTouches?.[0]
if (touch) setReactMenu({ msgId: msg.id, x: touch.clientX, y: touch.clientY })
}
e.currentTarget.dataset.lastTap = now
}}
>
{bigEmoji ? (
{msg.text}
) : (
{/* Inline reply quote */}
{hasReply && (
{msg.reply_username || ''}
{(msg.reply_text || '').slice(0, 80)}
)}
{hasReply ? (
) :
}
{(msg.text.match(URL_REGEX) || []).slice(0, 1).map(url => (
{ if (isAtBottom.current) setTimeout(() => scrollToBottom('smooth'), 50) }} />
))}
)}
{/* Hover actions */}
{own && canEdit && (
)}
{/* Reactions โ iMessage style floating badge */}
{msg.reactions?.length > 0 && (
)}
{/* Timestamp โ only on last message of group */}
{isLastInGroup && (