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()}
/>
);
}