import { useWAClient } from "./context"; import { getFormattedName, getId } from "@/lib/utils"; import { useInfiniteQuery, useQueryClient } from "@tanstack/react-query"; import { cn } from "cn"; import { ArrowLeftIcon, CheckCheckIcon, CheckIcon, Loader2Icon, PaperclipIcon, PhoneCallIcon, SendIcon, } from "lucide-react"; import { useMemo, useState } from "react"; import dayjs from "dayjs"; import relativeTime from "dayjs/plugin/relativeTime"; import MessageMedia from "@/components/message-media"; import { useContacts } from "@/hooks/useContact"; import { useMessageEvent } from "@/hooks/useMessageEvent"; import { useHashRouter } from "@/hooks/useHashRouter"; import { useChats } from "@/hooks/useChats"; import Avatar from "@/components/ui/avatar"; import { useIntersection } from "@/hooks/useIntersection"; import Paragraph from "@/components/paragraph"; dayjs.extend(relativeTime); type Props = { chatId: string | null; maxCount?: number; }; export default function MessagesSection({ chatId, maxCount = 50 }: Props) { const { client, isReady } = useWAClient(); const router = useHashRouter(); const [message, setMessage] = useState(""); const [isPending, setPending] = useState(false); const queryClient = useQueryClient(); const { data: chats } = useChats(); const { data: contacts } = useContacts(); const { data: messages, isLoading, refetch, fetchNextPage, hasNextPage, isFetchingNextPage, } = useInfiniteQuery({ queryKey: ["messages", chatId], queryFn: ({ pageParam }) => client .getMessages({ chatId: chatId!, count: maxCount, direction: "before", id: pageParam, }) .then((i) => i.reverse()), initialPageParam: undefined as string | undefined, enabled: Boolean(chatId && isReady), getNextPageParam: (lastPage) => { if (lastPage.length < maxCount) return undefined; return getId(lastPage[lastPage.length - 1]?.id); }, select: (data) => data.pages.flat(), }); useMessageEvent((data) => { if (data.chatId !== chatId) return; queryClient.setQueryData(["messages", chatId], (old: any) => { if (!old) return old; return { ...old, pages: [[data, ...old.pages[0]], ...old.pages.slice(1)], }; }); }); const endScrollRef = useIntersection(() => { if (hasNextPage && !isFetchingNextPage && !isLoading) { fetchNextPage(); } }); const chat = useMemo( () => chats?.find((c) => c.id === chatId), [chats, chatId], ); const messageList = useMemo(() => { return messages ?.filter((i) => !["revoked"].includes(i.type as never)) ?.map((i) => { const from = contacts?.find( (c) => getId(c.id) === getId(i.author || i.from), ); const quotedMsg = i.quotedMsg ? { ...i.quotedMsg, from: contacts?.find((c) => { return ( getId(c.id) === getId(i.quotedMsg?.author || i.quotedMsg?.from) ); }), } : null; return { ...i, id: getId(i.id), from, quotedMsg, }; }); }, [messages, contacts]); async function sendMessage() { const text = message.trim(); if (!text || !chatId) return; try { setPending(true); await client.sendText({ chatId, text, options: { waitForAck: true } }); setTimeout(refetch, 100); setMessage(""); } catch (err) { alert((err as Error).message); } finally { setPending(false); } } return (

{chat?.formattedTitle || chat?.name}

{/*

{selected.online ? "Online now" : "Active recently"}

*/}
{/*
*/}
{/*
Today
*/} {messageList?.map((item, index) => (

{getFormattedName(item.from) || item.notifyName}

{item.isForwarded ? (

Forwarded

) : null} {/*
                  {JSON.stringify(item, null, 2)}
                
*/} {item.quotedMsg && ["chat", "image", "document"].includes( item.quotedMsg.type as string, ) ? ( ) : null} {item.type === "image" || item.type === "sticker" || item.type === "document" || item.type === "ptt" ? ( ) : null} {item.type === "chat" || item.caption ? ( ) : null} {item.type === "call_log" && (

Call log

)}
{dayjs((item.timestamp ?? 0) * 1000).fromNow()} {item.fromMe && ( <> {item.ack && item.ack >= 2 ? ( ) : ( )} )}
))}
{isLoading || (isFetchingNextPage && ( ))} {isLoading || isFetchingNextPage ? "Loading..." : "End of messages"}
{/* */}