Merge branch 'main' into hosted
This commit is contained in:
commit
1cdfd7d1ac
@ -12,6 +12,7 @@ See the [Examples](#-examples) section below for more demos.
|
|||||||
|
|
||||||
## 🌟 Recent Updates
|
## 🌟 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
|
- 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 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
|
- Nov 28 - 🔥 🔥 🔥 Customize your stack: React or Bootstrap or TailwindCSS
|
||||||
|
|||||||
5
design-docs.md
Normal file
5
design-docs.md
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
## Version History
|
||||||
|
|
||||||
|
Version history is stored as a tree on the client-side.
|
||||||
|
|
||||||
|

|
||||||
@ -2,7 +2,7 @@ import { useEffect, useRef, useState } from "react";
|
|||||||
import ImageUpload from "./components/ImageUpload";
|
import ImageUpload from "./components/ImageUpload";
|
||||||
import CodePreview from "./components/CodePreview";
|
import CodePreview from "./components/CodePreview";
|
||||||
import Preview from "./components/Preview";
|
import Preview from "./components/Preview";
|
||||||
import { CodeGenerationParams, generateCode } from "./generateCode";
|
import { generateCode } from "./generateCode";
|
||||||
import Spinner from "./components/Spinner";
|
import Spinner from "./components/Spinner";
|
||||||
import classNames from "classnames";
|
import classNames from "classnames";
|
||||||
import {
|
import {
|
||||||
@ -18,7 +18,13 @@ import { Button } from "@/components/ui/button";
|
|||||||
import { Textarea } from "@/components/ui/textarea";
|
import { Textarea } from "@/components/ui/textarea";
|
||||||
import { Tabs, TabsContent, TabsList, TabsTrigger } from "./components/ui/tabs";
|
import { Tabs, TabsContent, TabsList, TabsTrigger } from "./components/ui/tabs";
|
||||||
import SettingsDialog from "./components/SettingsDialog";
|
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 { IS_RUNNING_ON_CLOUD } from "./config";
|
||||||
import { PicoBadge } from "./components/PicoBadge";
|
import { PicoBadge } from "./components/PicoBadge";
|
||||||
import { OnboardingNote } from "./components/OnboardingNote";
|
import { OnboardingNote } from "./components/OnboardingNote";
|
||||||
@ -127,10 +133,21 @@ function App() {
|
|||||||
setIsImportedFromCode(false);
|
setIsImportedFromCode(false);
|
||||||
};
|
};
|
||||||
|
|
||||||
const stop = () => {
|
const cancelCodeGeneration = () => {
|
||||||
wsRef.current?.close?.(USER_CLOSE_WEB_SOCKET_CODE);
|
wsRef.current?.close?.(USER_CLOSE_WEB_SOCKET_CODE);
|
||||||
// make sure stop can correct the state even if the websocket is already closed
|
// make sure stop can correct the state even if the websocket is already closed
|
||||||
|
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);
|
setAppState(AppState.CODE_READY);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
function doGenerateCode(
|
function doGenerateCode(
|
||||||
@ -187,6 +204,11 @@ function App() {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
(line) => setExecutionConsole((prev) => [...prev, line]),
|
(line) => setExecutionConsole((prev) => [...prev, line]),
|
||||||
|
// On cancel
|
||||||
|
() => {
|
||||||
|
cancelCodeGenerationAndReset();
|
||||||
|
},
|
||||||
|
// On complete
|
||||||
() => {
|
() => {
|
||||||
setAppState(AppState.CODE_READY);
|
setAppState(AppState.CODE_READY);
|
||||||
}
|
}
|
||||||
@ -343,10 +365,10 @@ function App() {
|
|||||||
</div>
|
</div>
|
||||||
<div className="flex mt-4 w-full">
|
<div className="flex mt-4 w-full">
|
||||||
<Button
|
<Button
|
||||||
onClick={stop}
|
onClick={cancelCodeGeneration}
|
||||||
className="w-full dark:text-white dark:bg-gray-700"
|
className="w-full dark:text-white dark:bg-gray-700"
|
||||||
>
|
>
|
||||||
Stop
|
Cancel
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
<CodePreview code={generatedCode} />
|
<CodePreview code={generatedCode} />
|
||||||
|
|||||||
@ -1,27 +1,20 @@
|
|||||||
import toast from "react-hot-toast";
|
import toast from "react-hot-toast";
|
||||||
import { WS_BACKEND_URL } from "./config";
|
import { WS_BACKEND_URL } from "./config";
|
||||||
import { USER_CLOSE_WEB_SOCKET_CODE } from "./constants";
|
import { USER_CLOSE_WEB_SOCKET_CODE } from "./constants";
|
||||||
|
import { FullGenerationSettings } from "./types";
|
||||||
|
|
||||||
const ERROR_MESSAGE =
|
const ERROR_MESSAGE =
|
||||||
"Error generating code. Check the Developer Console AND the backend logs for details. Feel free to open a Github issue.";
|
"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";
|
const CANCEL_MESSAGE = "Code generation cancelled";
|
||||||
|
|
||||||
export interface CodeGenerationParams {
|
|
||||||
generationType: "create" | "update";
|
|
||||||
image: string;
|
|
||||||
resultImage?: string;
|
|
||||||
history?: string[];
|
|
||||||
isImportedFromCode?: boolean;
|
|
||||||
// isImageGenerationEnabled: boolean; // TODO: Merge with Settings type in types.ts
|
|
||||||
}
|
|
||||||
|
|
||||||
export function generateCode(
|
export function generateCode(
|
||||||
wsRef: React.MutableRefObject<WebSocket | null>,
|
wsRef: React.MutableRefObject<WebSocket | null>,
|
||||||
params: CodeGenerationParams,
|
params: FullGenerationSettings,
|
||||||
onChange: (chunk: string) => void,
|
onChange: (chunk: string) => void,
|
||||||
onSetCode: (code: string) => void,
|
onSetCode: (code: string) => void,
|
||||||
onStatusUpdate: (status: string) => void,
|
onStatusUpdate: (status: string) => void,
|
||||||
|
onCancel: () => void,
|
||||||
onComplete: () => void
|
onComplete: () => void
|
||||||
) {
|
) {
|
||||||
const wsUrl = `${WS_BACKEND_URL}/generate-code`;
|
const wsUrl = `${WS_BACKEND_URL}/generate-code`;
|
||||||
@ -47,15 +40,18 @@ export function generateCode(
|
|||||||
toast.error(response.value);
|
toast.error(response.value);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
ws.addEventListener("close", (event) => {
|
ws.addEventListener("close", (event) => {
|
||||||
console.log("Connection closed", event.code, event.reason);
|
console.log("Connection closed", event.code, event.reason);
|
||||||
if (event.code === USER_CLOSE_WEB_SOCKET_CODE) {
|
if (event.code === USER_CLOSE_WEB_SOCKET_CODE) {
|
||||||
toast.success(STOP_MESSAGE);
|
toast.success(CANCEL_MESSAGE);
|
||||||
|
onCancel();
|
||||||
} else if (event.code !== 1000) {
|
} else if (event.code !== 1000) {
|
||||||
console.error("WebSocket error code", event);
|
console.error("WebSocket error code", event);
|
||||||
toast.error(ERROR_MESSAGE);
|
toast.error(ERROR_MESSAGE);
|
||||||
}
|
} else {
|
||||||
onComplete();
|
onComplete();
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
ws.addEventListener("error", (error) => {
|
ws.addEventListener("error", (error) => {
|
||||||
|
|||||||
@ -28,3 +28,13 @@ export enum AppState {
|
|||||||
CODING = "CODING",
|
CODING = "CODING",
|
||||||
CODE_READY = "CODE_READY",
|
CODE_READY = "CODE_READY",
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface CodeGenerationParams {
|
||||||
|
generationType: "create" | "update";
|
||||||
|
image: string;
|
||||||
|
resultImage?: string;
|
||||||
|
history?: string[];
|
||||||
|
isImportedFromCode?: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
export type FullGenerationSettings = CodeGenerationParams & Settings;
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user