import { useEffect, useRef, useState } from "react"; import { ActionIcon, Avatar, Box, Center, Divider, Group, ScrollArea, Stack, Text, TextInput, Tooltip, } from "@mantine/core"; import { IconSend, IconLock, IconHash, IconDotsVertical, IconPaperclip, } from "@tabler/icons-react"; import type { Message, Room, User } from "./types"; function initials(s: string) { return s.replace(/[^a-z0-9]/gi, "").slice(0, 2).toUpperCase() || "?"; } function timeShort(ts: number) { const d = new Date(ts); return `${String(d.getHours()).padStart(2, "0")}:${String( d.getMinutes(), ).padStart(2, "0")}`; } function MessageRow({ msg }: { msg: Message }) { return ( {initials(msg.sender)} {msg.sender} {timeShort(msg.ts)} {msg.body} ); } export function ChatPanel({ room, user, }: { room: Room | undefined; user: User; }) { const [draft, setDraft] = useState(""); const [extra, setExtra] = useState>({}); const viewport = useRef(null); const msgs = room ? [...room.messages, ...(extra[room.id] ?? [])] : []; useEffect(() => { viewport.current?.scrollTo({ top: viewport.current.scrollHeight }); }, [room?.id, msgs.length]); if (!room) { return (
Selecciona una conversación
); } const send = () => { const body = draft.trim(); if (!body) return; const msg: Message = { id: `local-${Date.now()}`, sender: user.handle, body, ts: Date.now(), mine: true, }; setExtra((e) => ({ ...e, [room.id]: [...(e[room.id] ?? []), msg] })); setDraft(""); }; return ( {initials(room.name)} {room.name} {room.encrypted ? ( ) : ( )} {room.encrypted ? "cifrada · E2E" : "abierta · cleartext"} {msgs.map((m) => ( ))} setDraft(e.currentTarget.value)} onKeyDown={(e) => e.key === "Enter" && send()} /> ); }