feat: add media storage
This commit is contained in:
+14
-35
@@ -1,4 +1,4 @@
|
||||
import { useWAClient } from "@/lib/context";
|
||||
import { useWAClient } from "./context";
|
||||
import { getFormattedName, getId, getInitial } from "@/lib/utils";
|
||||
import type { ChatDTO } from "@shared/dto";
|
||||
import { useQuery } from "@tanstack/react-query";
|
||||
@@ -7,6 +7,7 @@ import { ArrowLeftIcon, PaperclipIcon, SendIcon } from "lucide-react";
|
||||
import React, { useMemo, useState } from "react";
|
||||
import dayjs from "dayjs";
|
||||
import relativeTime from "dayjs/plugin/relativeTime";
|
||||
import MessageMedia from "@/components/message-media";
|
||||
|
||||
dayjs.extend(relativeTime);
|
||||
|
||||
@@ -34,15 +35,9 @@ export default function MessagesSection({
|
||||
const chatId = getId(chat.id);
|
||||
const { data: messages, refetch } = useQuery({
|
||||
queryKey: ["messages", chatId],
|
||||
queryFn: () =>
|
||||
client.getMessages({ chatId, count: 50 }).then((res) =>
|
||||
res.map((i) => ({
|
||||
...i,
|
||||
id: getId(i.id),
|
||||
fromMe: i.id.fromMe || i.fromMe,
|
||||
})),
|
||||
),
|
||||
queryFn: () => client.getMessages({ chatId, count: 50 }),
|
||||
enabled: Boolean(chatId && isReady),
|
||||
refetchInterval: 10_1000,
|
||||
});
|
||||
|
||||
const messageList = useMemo(() => {
|
||||
@@ -54,6 +49,7 @@ export default function MessagesSection({
|
||||
);
|
||||
return {
|
||||
...message,
|
||||
id: getId(message.id),
|
||||
from,
|
||||
};
|
||||
})
|
||||
@@ -76,19 +72,6 @@ export default function MessagesSection({
|
||||
}
|
||||
}
|
||||
|
||||
async function fetchMedia(msgId: string) {
|
||||
const data = await client.getMedia(msgId);
|
||||
// decode from base64
|
||||
const blob = await fetch(data).then((res) => res.blob());
|
||||
// download
|
||||
const url = URL.createObjectURL(blob);
|
||||
const a = document.createElement("a");
|
||||
a.href = url;
|
||||
a.download = "media";
|
||||
a.click();
|
||||
URL.revokeObjectURL(url);
|
||||
}
|
||||
|
||||
return (
|
||||
<section
|
||||
className={`flex min-w-0 flex-1 flex-col bg-muted ${mobileChat ? "flex" : "hidden md:flex"}`}
|
||||
@@ -174,28 +157,24 @@ export default function MessagesSection({
|
||||
!item.fromMe && "bg-[#d8f5e8]/30 dark:bg-[#26855c]/30",
|
||||
)}
|
||||
>
|
||||
<p className="whitespace-pre-wrap">{item.quotedMsg.body}</p>
|
||||
<p className="whitespace-pre-wrap wrap-break-word">
|
||||
{item.quotedMsg.body}
|
||||
</p>
|
||||
</div>
|
||||
) : null}
|
||||
|
||||
{item.type === "image" && (
|
||||
<a href="#" onClick={() => fetchMedia(item.id)}>
|
||||
<img
|
||||
src={"data:image/jpeg;base64," + item.body}
|
||||
alt=""
|
||||
className="w-full"
|
||||
/>
|
||||
</a>
|
||||
)}
|
||||
{item.type === "image" ||
|
||||
item.type === "sticker" ||
|
||||
item.type === "document" ? (
|
||||
<MessageMedia data={item} />
|
||||
) : null}
|
||||
|
||||
{item.type === "chat" || item.caption ? (
|
||||
<p className="whitespace-pre-wrap">
|
||||
<p className="whitespace-pre-wrap wrap-break-word">
|
||||
{item.caption || item.body}
|
||||
</p>
|
||||
) : null}
|
||||
|
||||
{item.type === "sticker" && <p className="italic">Sticker</p>}
|
||||
|
||||
<div
|
||||
className={`mt-1 flex items-center justify-end gap-1 text-[10px] ${item.fromMe ? "text-primary" : "text-muted-foreground"}`}
|
||||
>
|
||||
|
||||
Reference in New Issue
Block a user