import React, { useMemo, useRef, useEffect, useState, ChangeEvent, FormEvent } from "react"; import { Message, useChat } from "ai/react"; import { useAppDispatch, useAppSelector } from "../../store/hook"; import { compiler_state, initEsbuild, } from "../../store/features/compilerSlice"; import { editor_state, set_monaco_input_value, update_editor_code } from "../../store/features/editorSlice"; import { theme_state } from "../../store/features/themeSlice"; import { ModalEnum, open_modal } from "../../store/features/modalSlice"; import ConsoleLog from "./ConsoleLog"; import Iframe from "./Iframe"; import InputCodeTab from "./InputCodeTab"; import Footer from "./Footer"; import Pane from "./Pane"; import { SendIcon } from "../../constants/icon"; import ReactMarkdown from "react-markdown"; import { ChatRequestOptions } from "ai"; const Playground = () => { const dispatch = useAppDispatch(); const formRef = useRef(null); const inputRef = useRef(null); const { theme } = useAppSelector(theme_state); const { esbuildStatus, isCompiling, output } = useAppSelector(compiler_state); const { logs, editorValue, isLogTabOpen } = useAppSelector(editor_state); const [markdownCode, setMarkdownCode] = useState(''); const [prevMarkdownCode, setPrevMarkdownCode] = useState(markdownCode); const [isSystemInputVisible, setSystemInputVisible] = useState(false); const [isModelInputVisible, setModelInputVisible] = useState(false); const [selectedModel, setSelectedModel] = useState("GPT-4"); const [systemMessage, setSystemMessage] = useState( "You are a helpful AI assistant. Assist the user in writing React code, ensuring that all logic is contained within a single app component file and that the output is rendered to the DOM's root element." ); const isValidCodeBlock = (markdownCode: string) => { return markdownCode && markdownCode.length > 10 && markdownCode.includes('\n'); } useEffect(() => { const timer = setInterval(() => { if (isValidCodeBlock(markdownCode) && markdownCode !== prevMarkdownCode) { dispatch(update_editor_code({ type: 'javascript', content: markdownCode })); setPrevMarkdownCode(markdownCode); } }, 2000); return () => { clearInterval(timer); }; }, [markdownCode, prevMarkdownCode, dispatch]); const { append, messages, input, setInput, handleSubmit, ...rest } = useChat({ onError: (error) => { console.error(error); }, }); const modifiedHandleSubmit = async (e: React.FormEvent, chatRequestOptions?: ChatRequestOptions) => { e.preventDefault(); if (messages.length === 0 || messages[0].role !== "system") { const systemMessageToAdd: Message = { id: `${Date.now()}-system`, createdAt: new Date(), content: systemMessage, role: "system" }; await append(systemMessageToAdd); } await handleSubmit(e, chatRequestOptions); }; useEffect(() => { if (!esbuildStatus.isReady) { dispatch(initEsbuild()); } }, [dispatch, esbuildStatus]); useEffect(() => { dispatch(open_modal(ModalEnum.TEMPLATE)); }, [dispatch]); useEffect(() => { if(isValidCodeBlock(markdownCode)) { const newEditorValue = { name: "React", description: "By codetree", public: true, iconSrc: "/icons/reactjs.svg", tabs: { javascript: { title: "JS/JSX", entryPoints: "index.js", monacoLanguage: "javascript", data: markdownCode }, html: { title: "index.html", entryPoints: "index.html", monacoLanguage: "html", data: "" }, css: { title: "main.css", entryPoints: "main.css", monacoLanguage: "css", data: "" } } }; dispatch(set_monaco_input_value(newEditorValue as any)); } }, [markdownCode, dispatch]); return (
System Prompt Model {isSystemInputVisible && (