From 3602f8fc2b363532848bf451b0d57cc9efbde4eb Mon Sep 17 00:00:00 2001 From: Tanish Manku <-h> Date: Thu, 20 Mar 2025 02:10:27 -0700 Subject: [PATCH] Add generation signals --- .../GenerationRootComponent.tsx | 91 +++++++++++++++++-- .../EngineUtitlities/Base64Helpers.ts | 7 ++ .../RenderingPrimitives/RealTimeDrawEngine.ts | 5 +- .../signals/generation/generationSignals.ts | 13 +++ .../realtime/src/signals/generation/index.ts | 1 + frontend/realtime/src/signals/index.ts | 1 + 6 files changed, 108 insertions(+), 10 deletions(-) create mode 100644 frontend/realtime/src/KonvaApp/EngineUtitlities/Base64Helpers.ts create mode 100644 frontend/realtime/src/signals/generation/generationSignals.ts create mode 100644 frontend/realtime/src/signals/generation/index.ts diff --git a/frontend/realtime/src/GenerationRootComponent/GenerationRootComponent.tsx b/frontend/realtime/src/GenerationRootComponent/GenerationRootComponent.tsx index 65107cfcde..ea5ef959e5 100644 --- a/frontend/realtime/src/GenerationRootComponent/GenerationRootComponent.tsx +++ b/frontend/realtime/src/GenerationRootComponent/GenerationRootComponent.tsx @@ -1,24 +1,101 @@ import { faSparkles } from "@fortawesome/pro-solid-svg-icons"; -import { Button } from "~/components/ui"; +import { useSignals } from "@preact/signals-react/runtime"; +import { Button, LoadingSpinner } from "~/components/ui"; import { useRenderCounter } from "~/hooks/useRenderCounter"; +import { GenerationLoadingState, generationSignal } from "~/signals"; +import { useRef } from "react"; export const GenerationRootComponent = () => { // This is a hook that will log the number of times the component has rerendered // Let's make sure we only log once useRenderCounter("GenerationRootComponent"); + useSignals(); - return ( - <> -
-
+ const generationState = generationSignal.value; + const inputRef = useRef(null); + + const handleGenerate = () => { + if (!inputRef.current) { + return + }; + + // TODO: For testing only!!! Remove when finished + if (generationState.loadingState === GenerationLoadingState.GENERATING) { + generationSignal.value = { loadingState: GenerationLoadingState.INIT, prompt: "" }; + return; + } + + const prompt = inputRef.current.value; + generationSignal.value = { loadingState: GenerationLoadingState.GENERATING, prompt }; + + // TODO: Write the signal change effect in generationSignals.ts + // TODO: Call the server to generate the image + }; + + let contentElement; + switch (generationState.loadingState) { + case GenerationLoadingState.INIT: + contentElement = +
Generate Image Imagine, Describe, Generate.
+ break; + case GenerationLoadingState.GENERATING: + case GenerationLoadingState.GENERATED: + contentElement = + break; + } + + // const isButtonDisabled = generationState.loadingState === GenerationLoadingState.GENERATING; + const isButtonDisabled = false; + + return ( + <> +
+ {contentElement}
- - + +
); }; + +const GenerationContent = (generationState : { + loadingState: GenerationLoadingState; + imageB64?: string; + prompt: string; +}) => { + + const imgBoxStyle = { + width: "1024px", + height: "1024px", + } + + let imgBoxContent; + if (generationState.loadingState === GenerationLoadingState.GENERATING) { + imgBoxContent = ( +
+ +
+ ) + } else if (generationState.loadingState === GenerationLoadingState.GENERATED) { + imgBoxContent = ( + Generated Image + ) + } + + return ( +
+
+ {imgBoxContent} +
+
+ {generationState.prompt} +
+ +
+ ) +} diff --git a/frontend/realtime/src/KonvaApp/EngineUtitlities/Base64Helpers.ts b/frontend/realtime/src/KonvaApp/EngineUtitlities/Base64Helpers.ts new file mode 100644 index 0000000000..8919e7d73f --- /dev/null +++ b/frontend/realtime/src/KonvaApp/EngineUtitlities/Base64Helpers.ts @@ -0,0 +1,7 @@ +const ensureBase64Prefix = (base64String: string) => { + return base64String.startsWith("data:") + ? base64String + : `data:image/png;base64,${base64String}`; +} + +export { ensureBase64Prefix }; diff --git a/frontend/realtime/src/KonvaApp/RenderingPrimitives/RealTimeDrawEngine.ts b/frontend/realtime/src/KonvaApp/RenderingPrimitives/RealTimeDrawEngine.ts index a1f151596c..38534adddd 100644 --- a/frontend/realtime/src/KonvaApp/RenderingPrimitives/RealTimeDrawEngine.ts +++ b/frontend/realtime/src/KonvaApp/RenderingPrimitives/RealTimeDrawEngine.ts @@ -25,6 +25,7 @@ import { isLoadingVisible, loadingProgress, } from "~/signals/uiEvents/loadingIndicator"; +import { ensureBase64Prefix } from "../EngineUtitlities/Base64Helpers"; interface ServerSettings { model_path: string; @@ -902,9 +903,7 @@ export class RealTimeDrawEngine { const img = document.createElement("img"); // Convert base64 to data URL if it doesn't include the prefix - const dataUrl = base64String.startsWith("data:") - ? base64String - : `data:image/png;base64,${base64String}`; + const dataUrl = ensureBase64Prefix(base64String); // Create a promise to handle the image loading return new Promise((resolve, reject) => { diff --git a/frontend/realtime/src/signals/generation/generationSignals.ts b/frontend/realtime/src/signals/generation/generationSignals.ts new file mode 100644 index 0000000000..49313698cc --- /dev/null +++ b/frontend/realtime/src/signals/generation/generationSignals.ts @@ -0,0 +1,13 @@ +import { signal } from "@preact/signals-react"; + +export enum GenerationLoadingState { + INIT, + GENERATING, + GENERATED, +} + +export const generationSignal = signal<{ + loadingState: GenerationLoadingState; + prompt: string; + imageB64?: string; +}>({ loadingState: GenerationLoadingState.INIT, prompt: "" }); \ No newline at end of file diff --git a/frontend/realtime/src/signals/generation/index.ts b/frontend/realtime/src/signals/generation/index.ts new file mode 100644 index 0000000000..f0b5f004b8 --- /dev/null +++ b/frontend/realtime/src/signals/generation/index.ts @@ -0,0 +1 @@ +export * from "./generationSignals"; \ No newline at end of file diff --git a/frontend/realtime/src/signals/index.ts b/frontend/realtime/src/signals/index.ts index 8f8707efc1..157d93dd58 100644 --- a/frontend/realtime/src/signals/index.ts +++ b/frontend/realtime/src/signals/index.ts @@ -1,3 +1,4 @@ export * from "./authentication"; export * from "./uiAccess"; export * from "./uiEvents"; +export * from "./generation"; \ No newline at end of file