diff --git a/frontend/src/App.tsx b/frontend/src/App.tsx index b9f7866..4b7c935 100644 --- a/frontend/src/App.tsx +++ b/frontend/src/App.tsx @@ -20,7 +20,7 @@ import { Textarea } from "@/components/ui/textarea"; import { Tabs, TabsContent, TabsList, TabsTrigger } from "./components/ui/tabs"; import CodeMirror from "./components/CodeMirror"; import SettingsDialog from "./components/SettingsDialog"; -import { AppState, Settings } from "./types"; +import { Settings, EditorTheme, AppState } from "./types"; import { IS_RUNNING_ON_CLOUD } from "./config"; import { PicoBadge } from "./components/PicoBadge"; import { OnboardingNote } from "./components/OnboardingNote"; @@ -41,7 +41,7 @@ function App() { openAiApiKey: null, screenshotOneApiKey: null, isImageGenerationEnabled: true, - editorTheme: "cobalt", + editorTheme: EditorTheme.COBALT, }, "setting" ); @@ -266,6 +266,7 @@ function App() { void; } -function CodeMirror({ code, editorTheme }: Props) { +function CodeMirror({ code, editorTheme, onCodeChange }: Props) { const ref = useRef(null); const view = useRef(null); - - useEffect(() => { - let selectedTheme = cobalt; - if (editorTheme === "espresso") { - selectedTheme = espresso; - } - view.current = new EditorView({ - state: EditorState.create({ - doc: code, - extensions: [ - history(), - keymap.of([ - ...defaultKeymap, - indentWithTab, - { key: "Mod-z", run: undo, preventDefault: true }, - { key: "Mod-Shift-z", run: redo, preventDefault: true }, - ]), - lineNumbers(), - bracketMatching(), - html(), - selectedTheme, - EditorView.lineWrapping, - ], + const editorState = useMemo(() => EditorState.create({ + extensions: [ + history(), + keymap.of([ + ...defaultKeymap, + indentWithTab, + { key: "Mod-z", run: undo, preventDefault: true }, + { key: "Mod-Shift-z", run: redo, preventDefault: true }, + ]), + lineNumbers(), + bracketMatching(), + html(), + editorTheme === EditorTheme.ESPRESSO ? espresso : cobalt, + EditorView.lineWrapping, + EditorView.updateListener.of((update: ViewUpdate) => { + if (update.docChanged) { + const updatedCode = update.state.doc.toString(); + onCodeChange(updatedCode); + } }), + ], + }), [editorTheme]); + useEffect(() => { + view.current = new EditorView({ + state: editorState, parent: ref.current as Element, }); @@ -53,7 +56,7 @@ function CodeMirror({ code, editorTheme }: Props) { view.current = null; } }; - }, [code, editorTheme]); + }, []); useEffect(() => { if (view.current && view.current.state.doc.toString() !== code) { @@ -69,3 +72,4 @@ function CodeMirror({ code, editorTheme }: Props) { } export default CodeMirror; + diff --git a/frontend/src/components/Preview.tsx b/frontend/src/components/Preview.tsx index de0134f..3a603ff 100644 --- a/frontend/src/components/Preview.tsx +++ b/frontend/src/components/Preview.tsx @@ -1,3 +1,4 @@ +import { useEffect, useRef } from 'react'; import classNames from "classnames"; import useThrottle from "../hooks/useThrottle"; @@ -8,12 +9,22 @@ interface Props { function Preview({ code, device }: Props) { const throttledCode = useThrottle(code, 200); + const iframeRef = useRef(null); + + useEffect(() => { + const iframe = iframeRef.current; + if (iframe && iframe.contentDocument) { + iframe.contentDocument.open(); + iframe.contentDocument.write(throttledCode); + iframe.contentDocument.close(); + } + }, [throttledCode]); return (