+
+ {message.senderName}
+
+ {new Date(Number(message.sentAt.microsSinceUnixEpoch / 1000n)).toLocaleTimeString()}
+
+ {message.editedAt && (
+ (edited)
+ )}
+ {message.isEphemeral && (
+
+ (disappears in {Math.max(0, Math.ceil((Number(message.ephemeralExpiresAt?.microsSinceUnixEpoch || 0n) - Date.now() * 1000) / 1000000))}s)
+
+ )}
+
+
+ {editingMessageId === message.id ? (
+
+ setEditInput(e.target.value)}
+ onKeyDown={(e) => {
+ if (e.key === 'Enter') handleEditMessage();
+ if (e.key === 'Escape') cancelEditing();
+ }}
+ style={{ width: '100%', marginBottom: '4px' }}
+ />
+
+
+
+ ) : (
+ message.content
+ )}
+
+
+ {/* Reactions */}
+ {Object.keys(reactions).length > 0 && (
+
+ {Object.entries(reactions).map(([emoji, data]) => (
+
handleToggleReaction(message.id, emoji)}
+ >
+ {emoji} {data.count}
+
+ ))}
+
+ )}
+
+ {/* Edit history */}
+ {editHistory.length > 0 && showEditHistory === message.id && (
+
+ {editHistory.map(edit => (
+
+ {getUserName(edit.editedBy)} edited at{' '}
+ {new Date(Number(edit.editedAt.microsSinceUnixEpoch / 1000n)).toLocaleTimeString()}
+
+ {edit.previousContent}
+ {' → '}
+ {edit.newContent}
+
+ ))}
+
+ )}
+
+ {/* Message actions */}
+ {isOwnMessage && editingMessageId !== message.id && (
+
+
+ {editHistory.length > 0 && (
+
+ )}
+
+ )}
+
+ {/* Add reaction */}
+
+ {['👍', '❤️', '😂', '😮', '😢'].map(emoji => (
+
+ ))}
+
+
+ {/* Read receipts */}
+ {readReceipts.length > 0 && (
+
+ Seen by {readReceipts.map(r => getUserName(r.userId)).join(', ')}
+
+ )}
+