Merge pull request #58 from clean99/feat/enable-code-edit

Feat: fix flashing issue when updating code and enable code edit
This commit is contained in:
Abi Raja 2023-11-21 22:09:15 -05:00 committed by GitHub
commit 4e219db7b2
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 58 additions and 36 deletions

View File

@ -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() {
<CodeMirror
code={generatedCode}
editorTheme={settings.editorTheme}
onCodeChange={setGeneratedCode}
/>
<span
title="Copy Code"

View File

@ -1,6 +1,6 @@
import { useRef, useEffect } from "react";
import { useRef, useEffect, useMemo } from "react";
import { EditorState } from "@codemirror/state";
import { EditorView, keymap, lineNumbers } from "@codemirror/view";
import { EditorView, keymap, lineNumbers, ViewUpdate } from "@codemirror/view";
import { espresso, cobalt } from "thememirror";
import {
defaultKeymap,
@ -11,24 +11,18 @@ import {
} from "@codemirror/commands";
import { bracketMatching } from "@codemirror/language";
import { html } from "@codemirror/lang-html";
import { EditorTheme } from "@/types";
interface Props {
code: string;
editorTheme: string;
editorTheme: EditorTheme;
onCodeChange: (code: string) => void;
}
function CodeMirror({ code, editorTheme }: Props) {
function CodeMirror({ code, editorTheme, onCodeChange }: Props) {
const ref = useRef<HTMLDivElement>(null);
const view = useRef<EditorView | null>(null);
useEffect(() => {
let selectedTheme = cobalt;
if (editorTheme === "espresso") {
selectedTheme = espresso;
}
view.current = new EditorView({
state: EditorState.create({
doc: code,
const editorState = useMemo(() => EditorState.create({
extensions: [
history(),
keymap.of([
@ -40,10 +34,19 @@ function CodeMirror({ code, editorTheme }: Props) {
lineNumbers(),
bracketMatching(),
html(),
selectedTheme,
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;

View File

@ -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<HTMLIFrameElement | null>(null);
useEffect(() => {
const iframe = iframeRef.current;
if (iframe && iframe.contentDocument) {
iframe.contentDocument.open();
iframe.contentDocument.write(throttledCode);
iframe.contentDocument.close();
}
}, [throttledCode]);
return (
<div className="flex justify-center mx-2">
<iframe
ref={iframeRef}
title="Preview"
srcDoc={throttledCode}
className={classNames(
"border-[4px] border-black rounded-[20px] shadow-lg",
"transform scale-[0.9] origin-top",
@ -26,4 +37,5 @@ function Preview({ code, device }: Props) {
</div>
);
}
export default Preview;

View File

@ -9,7 +9,7 @@ import {
DialogTrigger,
} from "@/components/ui/dialog";
import { FaCog } from "react-icons/fa";
import { Settings } from "../types";
import { EditorTheme, Settings } from "../types";
import { Switch } from "./ui/switch";
import { Label } from "./ui/label";
import { Input } from "./ui/input";
@ -21,7 +21,7 @@ interface Props {
}
function SettingsDialog({ settings, setSettings }: Props) {
const handleThemeChange = (theme: string) => {
const handleThemeChange = (theme: EditorTheme) => {
setSettings((s) => ({
...s,
editorTheme: theme,
@ -110,7 +110,7 @@ function SettingsDialog({ settings, setSettings }: Props) {
id="editor-theme"
value={settings.editorTheme}
onChange={(e: React.ChangeEvent<HTMLSelectElement>) =>
handleThemeChange(e.target.value)
handleThemeChange(e.target.value as EditorTheme)
}
>
<option value="cobalt">Cobalt</option>

View File

@ -1,8 +1,13 @@
export enum EditorTheme {
ESPRESSO = "espresso",
COBALT = "cobalt",
}
export interface Settings {
openAiApiKey: string | null;
screenshotOneApiKey: string | null;
isImageGenerationEnabled: boolean;
editorTheme: string;
editorTheme: EditorTheme;
}
export enum AppState {