feat: fetch media draft
This commit is contained in:
+29
-3
@@ -24,6 +24,7 @@ export default function MessagesSection({
|
||||
}: Props) {
|
||||
const { client, isReady } = useWAClient();
|
||||
const [message, setMessage] = useState("");
|
||||
const [isPending, setPending] = useState(false);
|
||||
|
||||
const { data: contacts } = useQuery({
|
||||
queryKey: ["contacts"],
|
||||
@@ -32,7 +33,7 @@ export default function MessagesSection({
|
||||
});
|
||||
|
||||
const chatId = getId(chat.id);
|
||||
const { data: messages } = useQuery({
|
||||
const { data: messages, refetch } = useQuery({
|
||||
queryKey: ["messages", chatId],
|
||||
queryFn: () =>
|
||||
client.getMessages({ chatId, count: 50 }).then((res) =>
|
||||
@@ -60,10 +61,33 @@ export default function MessagesSection({
|
||||
?.reverse();
|
||||
}, [messages, contacts]);
|
||||
|
||||
function sendMessage() {
|
||||
async function sendMessage() {
|
||||
const text = message.trim();
|
||||
if (!text) 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);
|
||||
}
|
||||
}
|
||||
|
||||
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 (
|
||||
@@ -156,11 +180,13 @@ export default function MessagesSection({
|
||||
) : 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 === "chat" || item.caption ? (
|
||||
@@ -227,7 +253,7 @@ export default function MessagesSection({
|
||||
aria-label="Send message"
|
||||
onClick={sendMessage}
|
||||
className="grid size-10 shrink-0 place-items-center rounded-full bg-primary text-primary-foreground shadow-sm transition hover:bg-primary/90 disabled:cursor-not-allowed disabled:opacity-50"
|
||||
disabled={!message.trim()}
|
||||
disabled={!message.trim() || isPending}
|
||||
>
|
||||
<SendIcon size={17} />
|
||||
</button>
|
||||
|
||||
+3
-91
@@ -12,96 +12,6 @@ import { useQuery } from "@tanstack/react-query";
|
||||
import { cn, getId, getInitial } from "@/lib/utils";
|
||||
import MessagesSection from "./messages";
|
||||
|
||||
// type Chat = {
|
||||
// id: number;
|
||||
// name: string;
|
||||
// initials: string;
|
||||
// color: string;
|
||||
// preview: string;
|
||||
// time: string;
|
||||
// unread?: number;
|
||||
// online?: boolean;
|
||||
// messages: { text: string; time: string; fromMe?: boolean; read?: boolean }[];
|
||||
// };
|
||||
|
||||
// const chats: Chat[] = [
|
||||
// {
|
||||
// id: 1,
|
||||
// name: "Maya Chen",
|
||||
// initials: "MC",
|
||||
// color: "bg-rose-200 text-rose-800",
|
||||
// preview: "That sounds perfect. See you then!",
|
||||
// time: "10:42 AM",
|
||||
// online: true,
|
||||
// messages: [
|
||||
// { text: "Hey! Are we still on for coffee tomorrow?", time: "10:38 AM" },
|
||||
// {
|
||||
// text: "Absolutely. I found a new spot near the park.",
|
||||
// time: "10:40 AM",
|
||||
// fromMe: true,
|
||||
// read: true,
|
||||
// },
|
||||
// { text: "That sounds perfect. See you then!", time: "10:42 AM" },
|
||||
// ],
|
||||
// },
|
||||
// {
|
||||
// id: 2,
|
||||
// name: "Design team",
|
||||
// initials: "DT",
|
||||
// color: "bg-violet-200 text-violet-800",
|
||||
// preview: "Jon: The new explorations are ready",
|
||||
// time: "9:16 AM",
|
||||
// unread: 3,
|
||||
// messages: [
|
||||
// { text: "Jon: The new explorations are ready", time: "9:16 AM" },
|
||||
// ],
|
||||
// },
|
||||
// {
|
||||
// id: 3,
|
||||
// name: "Alex Morgan",
|
||||
// initials: "AM",
|
||||
// color: "bg-amber-200 text-amber-800",
|
||||
// preview: "You: Thanks for sending that over",
|
||||
// time: "Yesterday",
|
||||
// messages: [
|
||||
// {
|
||||
// text: "Thanks for sending that over",
|
||||
// time: "Yesterday",
|
||||
// fromMe: true,
|
||||
// read: true,
|
||||
// },
|
||||
// ],
|
||||
// },
|
||||
// {
|
||||
// id: 4,
|
||||
// name: "Weekend plans",
|
||||
// initials: "WP",
|
||||
// color: "bg-emerald-200 text-emerald-800",
|
||||
// preview: "Priya: I can bring the snacks",
|
||||
// time: "Yesterday",
|
||||
// unread: 8,
|
||||
// messages: [{ text: "Priya: I can bring the snacks", time: "Yesterday" }],
|
||||
// },
|
||||
// {
|
||||
// id: 5,
|
||||
// name: "Noah Williams",
|
||||
// initials: "NW",
|
||||
// color: "bg-sky-200 text-sky-800",
|
||||
// preview: "Voice message",
|
||||
// time: "Tuesday",
|
||||
// messages: [{ text: "Voice message", time: "Tuesday" }],
|
||||
// },
|
||||
// {
|
||||
// id: 6,
|
||||
// name: "Sofia Patel",
|
||||
// initials: "SP",
|
||||
// color: "bg-orange-200 text-orange-800",
|
||||
// preview: "See you at the studio!",
|
||||
// time: "Monday",
|
||||
// messages: [{ text: "See you at the studio!", time: "Monday" }],
|
||||
// },
|
||||
// ];
|
||||
|
||||
export default function Page() {
|
||||
const [selectedId, setSelectedId] = useState<string>();
|
||||
const [query, setQuery] = useState("");
|
||||
@@ -234,7 +144,9 @@ export default function Page() {
|
||||
</div>
|
||||
<div className="mt-1 flex items-center justify-between gap-2">
|
||||
<p className="truncate text-xs text-muted-foreground">
|
||||
{chat.lastMessage?.body?.substring(0, 50)}
|
||||
{chat.previewMessage?.type === "chat"
|
||||
? chat.previewMessage?.body?.substring(0, 50)
|
||||
: null}
|
||||
</p>
|
||||
{/* {chat.unread && (
|
||||
<span className="grid size-5 shrink-0 place-items-center rounded-full bg-primary text-[10px] font-bold text-primary-foreground">
|
||||
|
||||
+2
-10
@@ -15,13 +15,7 @@ export function useWAClient() {
|
||||
return ctx;
|
||||
}
|
||||
|
||||
export function WAProvider({
|
||||
children,
|
||||
url,
|
||||
}: {
|
||||
children: React.ReactNode;
|
||||
url?: string;
|
||||
}) {
|
||||
export function WAProvider({ children }: { children: React.ReactNode }) {
|
||||
const isInitialized = useRef(false);
|
||||
const [isConnected, setConnected] = useState(false);
|
||||
|
||||
@@ -38,9 +32,7 @@ export function WAProvider({
|
||||
isInitialized.current = true;
|
||||
|
||||
wa.on("status", setConnected);
|
||||
}, [url]);
|
||||
|
||||
console.log("status", status);
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<WAContext.Provider
|
||||
|
||||
+1
-1
@@ -10,7 +10,7 @@ const queryCLient = new QueryClient();
|
||||
createRoot(document.getElementById("root")!).render(
|
||||
<StrictMode>
|
||||
<QueryClientProvider client={queryCLient}>
|
||||
<WAProvider url={import.meta.env.VITE_WHATSAPP_URL}>
|
||||
<WAProvider>
|
||||
<App />
|
||||
</WAProvider>
|
||||
</QueryClientProvider>
|
||||
|
||||
Reference in New Issue
Block a user