feat: update ui
This commit is contained in:
+75
-24
@@ -5,6 +5,8 @@ import { useQuery } from "@tanstack/react-query";
|
||||
import { cn } from "cn";
|
||||
import {
|
||||
ArrowLeftIcon,
|
||||
CheckCheckIcon,
|
||||
CheckIcon,
|
||||
PaperclipIcon,
|
||||
PhoneCallIcon,
|
||||
SendIcon,
|
||||
@@ -14,6 +16,8 @@ import dayjs from "dayjs";
|
||||
import relativeTime from "dayjs/plugin/relativeTime";
|
||||
import MessageMedia from "@/components/message-media";
|
||||
import Avatar from "@/components/ui/avatar";
|
||||
import { useContacts } from "@/hooks/useContact";
|
||||
import { useMessageEvent } from "@/hooks/useMessageEvent";
|
||||
|
||||
dayjs.extend(relativeTime);
|
||||
|
||||
@@ -32,11 +36,7 @@ export default function MessagesSection({
|
||||
const [message, setMessage] = useState("");
|
||||
const [isPending, setPending] = useState(false);
|
||||
|
||||
const { data: contacts } = useQuery({
|
||||
queryKey: ["contacts"],
|
||||
queryFn: () => client.listContacts(),
|
||||
refetchOnWindowFocus: false,
|
||||
});
|
||||
const { data: contacts } = useContacts();
|
||||
|
||||
const chatId = getId(chat.id);
|
||||
const { data: messages, refetch } = useQuery({
|
||||
@@ -46,17 +46,35 @@ export default function MessagesSection({
|
||||
refetchInterval: 10_1000,
|
||||
});
|
||||
|
||||
useMessageEvent((data) => {
|
||||
if (data.chatId === chatId) refetch();
|
||||
});
|
||||
|
||||
const messageList = useMemo(() => {
|
||||
return messages
|
||||
?.filter((i) => !["revoked"].includes(i.type as never))
|
||||
?.map((message) => {
|
||||
?.map((i) => {
|
||||
const from = contacts?.find(
|
||||
(c) => getId(c.id) === getId(message.author || message.from),
|
||||
(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 {
|
||||
...message,
|
||||
id: getId(message.id),
|
||||
...i,
|
||||
id: getId(i.id),
|
||||
from,
|
||||
quotedMsg,
|
||||
};
|
||||
})
|
||||
?.reverse();
|
||||
@@ -135,6 +153,7 @@ export default function MessagesSection({
|
||||
|
||||
{messageList?.map((item, index) => (
|
||||
<div
|
||||
id={item.id}
|
||||
key={`${item.timestamp}-${index}`}
|
||||
className={`mb-3 flex ${item.fromMe ? "justify-end" : "justify-start"}`}
|
||||
>
|
||||
@@ -151,23 +170,48 @@ export default function MessagesSection({
|
||||
</p>
|
||||
) : null}
|
||||
|
||||
{item.quotedMsg && item.quotedMsg.type === "chat" ? (
|
||||
<div
|
||||
{/* <pre className="overflow-y-auto max-h-80">
|
||||
{JSON.stringify(item, null, 2)}
|
||||
</pre> */}
|
||||
|
||||
{item.quotedMsg &&
|
||||
["chat", "image", "document"].includes(
|
||||
item.quotedMsg.type as string,
|
||||
) ? (
|
||||
<a
|
||||
href="#"
|
||||
onClick={(e) => {
|
||||
e.preventDefault();
|
||||
const el = document.getElementById(
|
||||
getId(item.quotedMsgId),
|
||||
);
|
||||
if (el) {
|
||||
el.scrollIntoView({ behavior: "smooth" });
|
||||
}
|
||||
}}
|
||||
className={cn(
|
||||
"bg-card/30 px-2 py-1.5 rounded-lg mb-2 mt-1",
|
||||
"bg-card/30 px-2 py-1.5 rounded-lg mb-2 mt-1 cursor-pointer block",
|
||||
!item.fromMe && "bg-[#d8f5e8]/30 dark:bg-[#26855c]/30",
|
||||
)}
|
||||
>
|
||||
<p className="whitespace-pre-wrap wrap-break-word">
|
||||
{item.quotedMsg.body}
|
||||
<p className="text-xs text-muted-foreground">
|
||||
{getFormattedName(item.quotedMsg.from)}
|
||||
</p>
|
||||
</div>
|
||||
<p className="whitespace-pre-wrap wrap-break-word">
|
||||
{item.quotedMsg.filename ||
|
||||
item.quotedMsg.caption ||
|
||||
(item.quotedMsg.type === "chat"
|
||||
? item.quotedMsg.body
|
||||
: "Quoted")}
|
||||
</p>
|
||||
</a>
|
||||
) : null}
|
||||
|
||||
{item.type === "image" ||
|
||||
item.type === "sticker" ||
|
||||
item.type === "document" ? (
|
||||
<MessageMedia data={item} />
|
||||
item.type === "document" ||
|
||||
item.type === "ptt" ? (
|
||||
<MessageMedia data={item as never} />
|
||||
) : null}
|
||||
|
||||
{item.type === "chat" || item.caption ? (
|
||||
@@ -187,12 +231,19 @@ export default function MessagesSection({
|
||||
className={`mt-1 flex items-center justify-end gap-1 text-[10px] ${item.fromMe ? "text-primary" : "text-muted-foreground"}`}
|
||||
>
|
||||
<span>{dayjs((item.timestamp ?? 0) * 1000).fromNow()}</span>
|
||||
{/* {item.fromMe &&
|
||||
(item.read ? (
|
||||
<CheckCheck size={14} />
|
||||
) : (
|
||||
<Check size={13} />
|
||||
))} */}
|
||||
|
||||
{item.fromMe && (
|
||||
<>
|
||||
{item.ack && item.ack >= 2 ? (
|
||||
<CheckCheckIcon
|
||||
size={14}
|
||||
className={item.ack === 3 ? "text-blue-300" : ""}
|
||||
/>
|
||||
) : (
|
||||
<CheckIcon size={13} />
|
||||
)}
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -232,7 +283,7 @@ export default function MessagesSection({
|
||||
}}
|
||||
placeholder="Write a message..."
|
||||
rows={1}
|
||||
className="max-h-24 min-h-10 flex-1 resize-none bg-transparent py-2.5 text-sm outline-none placeholder:text-muted-foreground"
|
||||
className="max-h-24 min-h-10 flex-1 resize-none field-sizing-content bg-transparent py-2.5 text-sm outline-none placeholder:text-muted-foreground"
|
||||
/>
|
||||
</div>
|
||||
<button
|
||||
|
||||
Reference in New Issue
Block a user