import { useRef, useState } from "react"; import classNames from "classnames"; import { ArrowUp, ChevronDown, CircleStop, Dice6 } from "lucide-react"; import { useLocalStorage, useUpdateEffect, useMount } from "react-use"; import { toast } from "sonner"; import { useAi } from "@/hooks/useAi"; import { useEditor } from "@/hooks/useEditor"; import { EnhancedSettings, Project } from "@/types"; import { SelectedFiles } from "@/components/editor/ask-ai/selected-files"; import { SelectedHtmlElement } from "@/components/editor/ask-ai/selected-html-element"; import { AiLoading } from "@/components/editor/ask-ai/loading"; import { Button } from "@/components/ui/button"; import { Uploader } from "@/components/editor/ask-ai/uploader"; import { ReImagine } from "@/components/editor/ask-ai/re-imagine"; import { Selector } from "@/components/editor/ask-ai/selector"; import { PromptBuilder } from "@/components/editor/ask-ai/prompt-builder"; import { Context } from "@/components/editor/ask-ai/context"; import { useUser } from "@/hooks/useUser"; import { useLoginModal } from "@/components/contexts/login-context"; import { Settings } from "./settings"; import { useProModal } from "@/components/contexts/pro-context"; import { MAX_FREE_PROJECTS } from "@/lib/utils"; import { PROMPTS_FOR_AI } from "@/lib/prompts"; export const AskAi = ({ project, isNew, onScrollToBottom, }: { project?: Project; files?: string[]; isNew?: boolean; onScrollToBottom?: () => void; }) => { const { user, projects } = useUser(); const { isSameHtml, isUploading, pages, isLoadingProject } = useEditor(); const { isAiWorking, isThinking, selectedFiles, setSelectedFiles, selectedElement, setSelectedElement, callAiNewProject, callAiFollowUp, audio: hookAudio, cancelRequest, } = useAi(onScrollToBottom); const { openLoginModal } = useLoginModal(); const { openProModal } = useProModal(); const [openProvider, setOpenProvider] = useState(false); const [providerError, setProviderError] = useState(""); const refThink = useRef(null); const [enhancedSettings, setEnhancedSettings, removeEnhancedSettings] = useLocalStorage("deepsite-enhancedSettings", { isActive: false, primaryColor: undefined, secondaryColor: undefined, theme: undefined, }); const [promptStorage, , removePromptStorage] = useLocalStorage("prompt", ""); const [isFollowUp, setIsFollowUp] = useState(true); const [prompt, setPrompt] = useState( promptStorage && promptStorage.trim() !== "" ? promptStorage : "" ); const [think, setThink] = useState(""); const [openThink, setOpenThink] = useState(false); const [randomPromptLoading, setRandomPromptLoading] = useState(false); useMount(() => { if (promptStorage && promptStorage.trim() !== "") { callAi(); } }); const callAi = async (redesignMarkdown?: string) => { removePromptStorage(); if (user && !user.isPro && projects.length >= MAX_FREE_PROJECTS) return openProModal([]); if (isAiWorking) return; if (!redesignMarkdown && !prompt.trim()) return; if (isFollowUp && !redesignMarkdown && !isSameHtml) { if (!user) return openLoginModal({ prompt }); const result = await callAiFollowUp(prompt, enhancedSettings, isNew); if (result?.error) { handleError(result.error, result.message); return; } if (result?.success) { setPrompt(""); } } else { const result = await callAiNewProject( prompt, enhancedSettings, redesignMarkdown, !!user, user?.name ); if (result?.error) { handleError(result.error, result.message); return; } if (result?.success) { setPrompt(""); } } }; const handleError = (error: string, message?: string) => { switch (error) { case "login_required": openLoginModal(); break; case "provider_required": setOpenProvider(true); setProviderError(message || ""); break; case "pro_required": openProModal([]); break; case "api_error": toast.error(message || "An error occurred"); break; case "network_error": toast.error(message || "Network error occurred"); break; default: toast.error("An unexpected error occurred"); } }; useUpdateEffect(() => { if (refThink.current) { refThink.current.scrollTop = refThink.current.scrollHeight; } }, [think]); const randomPrompt = () => { setRandomPromptLoading(true); setTimeout(() => { setPrompt( PROMPTS_FOR_AI[Math.floor(Math.random() * PROMPTS_FOR_AI.length)] ); setRandomPromptLoading(false); }, 400); }; return (
{think && (
{ setOpenThink(!openThink); }} >

{isThinking ? "DeepSite is thinking..." : "DeepSite's plan"}

{think}

)} setSelectedFiles(selectedFiles.filter((f) => f !== file)) } /> {selectedElement && (
setSelectedElement(null)} />
)}
{(isAiWorking || isUploading || isThinking || isLoadingProject) && (
{isAiWorking && ( )}
)}