/* eslint-disable @typescript-eslint/no-explicit-any */ import { useState } from "react"; import { RiSparkling2Fill } from "react-icons/ri"; import { GrSend } from "react-icons/gr"; import classNames from "classnames"; import { toast } from "react-toastify"; import { useLocalStorage } from "react-use"; import { MdPreview } from "react-icons/md"; import Login from "../login/login"; import { defaultHTML } from "./../../../utils/consts"; import SuccessSound from "./../../assets/success.mp3"; import Settings from "../settings/settings"; import ProModal from "../pro-modal/pro-modal"; // import SpeechPrompt from "../speech-prompt/speech-prompt"; function AskAI({ html, setHtml, onScrollToBottom, isAiWorking, setisAiWorking, setView, }: { html: string; setHtml: (html: string) => void; onScrollToBottom: () => void; isAiWorking: boolean; setView: React.Dispatch>; setisAiWorking: React.Dispatch>; }) { const [open, setOpen] = useState(false); const [prompt, setPrompt] = useState(""); const [hasAsked, setHasAsked] = useState(false); const [previousPrompt, setPreviousPrompt] = useState(""); const [provider, setProvider] = useLocalStorage("provider", "auto"); const [openProvider, setOpenProvider] = useState(false); const [providerError, setProviderError] = useState(""); const [openProModal, setOpenProModal] = useState(false); const audio = new Audio(SuccessSound); audio.volume = 0.5; const callAi = async () => { if (isAiWorking || !prompt.trim()) return; setisAiWorking(true); setProviderError(""); let contentResponse = ""; let lastRenderTime = 0; try { const request = await fetch("/api/ask-ai", { method: "POST", body: JSON.stringify({ prompt, provider, ...(html === defaultHTML ? {} : { html }), ...(previousPrompt ? { previousPrompt } : {}), }), headers: { "Content-Type": "application/json", }, }); if (request && request.body) { if (!request.ok) { const res = await request.json(); if (res.openLogin) { setOpen(true); } else if (res.openSelectProvider) { setOpenProvider(true); setProviderError(res.message); } else if (res.openProModal) { setOpenProModal(true); } else { toast.error(res.message); } setisAiWorking(false); return; } const reader = request.body.getReader(); const decoder = new TextDecoder("utf-8"); const read = async () => { const { done, value } = await reader.read(); if (done) { toast.success("AI responded successfully"); setPrompt(""); setPreviousPrompt(prompt); setisAiWorking(false); setHasAsked(true); audio.play(); setView("preview"); // Now we have the complete HTML including , so set it to be sure const finalDoc = contentResponse.match( /[\s\S]*<\/html>/ )?.[0]; if (finalDoc) { setHtml(finalDoc); } return; } const chunk = decoder.decode(value, { stream: true }); contentResponse += chunk; const newHtml = contentResponse.match(/[\s\S]*/)?.[0]; if (newHtml) { // Force-close the HTML tag so the iframe doesn't render half-finished markup let partialDoc = newHtml; if (!partialDoc.includes("")) { partialDoc += "\n"; } // Throttle the re-renders to avoid flashing/flicker const now = Date.now(); if (now - lastRenderTime > 300) { setHtml(partialDoc); lastRenderTime = now; } if (partialDoc.length > 200) { onScrollToBottom(); } } read(); }; read(); } // eslint-disable-next-line @typescript-eslint/no-explicit-any } catch (error: any) { setisAiWorking(false); toast.error(error.message); if (error.openLogin) { setOpen(true); } } }; return (
{defaultHTML !== html && ( )}
setPrompt(e.target.value)} onKeyDown={(e) => { if (e.key === "Enter") { callAi(); } }} />
{/* */}
setOpen(false)} >

You reached the limit of free AI usage. Please login to continue.

setOpenProModal(false)} />
); } export default AskAI;