Merge branch 'main' into hosted

This commit is contained in:
Abi Raja 2023-12-11 18:56:29 -05:00
commit 1cdfd7d1ac
5 changed files with 53 additions and 19 deletions

View File

@ -12,6 +12,7 @@ See the [Examples](#-examples) section below for more demos.
## 🌟 Recent Updates
- Dec 11 - Start a new project from existing code (allows you to come back to an older project)
- Dec 7 - 🔥 🔥 🔥 View a history of your edits, and branch off them
- Nov 30 - Dark mode, output code in Ionic (thanks [@dialmedu](https://github.com/dialmedu)), set OpenAI base URL
- Nov 28 - 🔥 🔥 🔥 Customize your stack: React or Bootstrap or TailwindCSS

5
design-docs.md Normal file
View File

@ -0,0 +1,5 @@
## Version History
Version history is stored as a tree on the client-side.
![Screenshot to Code](https://github.com/abi/screenshot-to-code/assets/23818/e35644aa-b90a-4aa7-8027-b8732796fd7c)

View File

@ -2,7 +2,7 @@ import { useEffect, useRef, useState } from "react";
import ImageUpload from "./components/ImageUpload";
import CodePreview from "./components/CodePreview";
import Preview from "./components/Preview";
import { CodeGenerationParams, generateCode } from "./generateCode";
import { generateCode } from "./generateCode";
import Spinner from "./components/Spinner";
import classNames from "classnames";
import {
@ -18,7 +18,13 @@ import { Button } from "@/components/ui/button";
import { Textarea } from "@/components/ui/textarea";
import { Tabs, TabsContent, TabsList, TabsTrigger } from "./components/ui/tabs";
import SettingsDialog from "./components/SettingsDialog";
import { Settings, EditorTheme, AppState, GeneratedCodeConfig } from "./types";
import {
AppState,
CodeGenerationParams,
EditorTheme,
GeneratedCodeConfig,
Settings,
} from "./types";
import { IS_RUNNING_ON_CLOUD } from "./config";
import { PicoBadge } from "./components/PicoBadge";
import { OnboardingNote } from "./components/OnboardingNote";
@ -127,10 +133,21 @@ function App() {
setIsImportedFromCode(false);
};
const stop = () => {
const cancelCodeGeneration = () => {
wsRef.current?.close?.(USER_CLOSE_WEB_SOCKET_CODE);
// make sure stop can correct the state even if the websocket is already closed
setAppState(AppState.CODE_READY);
cancelCodeGenerationAndReset();
};
const cancelCodeGenerationAndReset = () => {
// When this is the first version, reset the entire app state
if (currentVersion === null) {
reset();
} else {
// Otherwise, revert to the last version
setGeneratedCode(appHistory[currentVersion].code);
setAppState(AppState.CODE_READY);
}
};
function doGenerateCode(
@ -187,6 +204,11 @@ function App() {
}
},
(line) => setExecutionConsole((prev) => [...prev, line]),
// On cancel
() => {
cancelCodeGenerationAndReset();
},
// On complete
() => {
setAppState(AppState.CODE_READY);
}
@ -343,10 +365,10 @@ function App() {
</div>
<div className="flex mt-4 w-full">
<Button
onClick={stop}
onClick={cancelCodeGeneration}
className="w-full dark:text-white dark:bg-gray-700"
>
Stop
Cancel
</Button>
</div>
<CodePreview code={generatedCode} />

View File

@ -1,27 +1,20 @@
import toast from "react-hot-toast";
import { WS_BACKEND_URL } from "./config";
import { USER_CLOSE_WEB_SOCKET_CODE } from "./constants";
import { FullGenerationSettings } from "./types";
const ERROR_MESSAGE =
"Error generating code. Check the Developer Console AND the backend logs for details. Feel free to open a Github issue.";
const STOP_MESSAGE = "Code generation stopped";
export interface CodeGenerationParams {
generationType: "create" | "update";
image: string;
resultImage?: string;
history?: string[];
isImportedFromCode?: boolean;
// isImageGenerationEnabled: boolean; // TODO: Merge with Settings type in types.ts
}
const CANCEL_MESSAGE = "Code generation cancelled";
export function generateCode(
wsRef: React.MutableRefObject<WebSocket | null>,
params: CodeGenerationParams,
params: FullGenerationSettings,
onChange: (chunk: string) => void,
onSetCode: (code: string) => void,
onStatusUpdate: (status: string) => void,
onCancel: () => void,
onComplete: () => void
) {
const wsUrl = `${WS_BACKEND_URL}/generate-code`;
@ -47,15 +40,18 @@ export function generateCode(
toast.error(response.value);
}
});
ws.addEventListener("close", (event) => {
console.log("Connection closed", event.code, event.reason);
if (event.code === USER_CLOSE_WEB_SOCKET_CODE) {
toast.success(STOP_MESSAGE);
toast.success(CANCEL_MESSAGE);
onCancel();
} else if (event.code !== 1000) {
console.error("WebSocket error code", event);
toast.error(ERROR_MESSAGE);
} else {
onComplete();
}
onComplete();
});
ws.addEventListener("error", (error) => {

View File

@ -28,3 +28,13 @@ export enum AppState {
CODING = "CODING",
CODE_READY = "CODE_READY",
}
export interface CodeGenerationParams {
generationType: "create" | "update";
image: string;
resultImage?: string;
history?: string[];
isImportedFromCode?: boolean;
}
export type FullGenerationSettings = CodeGenerationParams & Settings;