Add generation signals

This commit is contained in:
Tanish Manku committed 2025-03-20 02:10:27 -07:00
1 parent 115c4fc60c
commit 3602f8fc2b
6 files changed
+108 -10

No files matched your search

@@ -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 (
<>
<div className="fixed flex flex-col items-center justify-center w-full h-full gap-y-32">
<div className="flex flex-col items-center justify-center">
const generationState = generationSignal.value;
const inputRef = useRef<HTMLInputElement>(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 =
<div className="flex flex-col items-center justify-center mb-32">
<span className="text-9xl font-bold">Generate Image</span>
<span className="text-3xl pt-2">Imagine, Describe, Generate.</span>
</div>
break;
case GenerationLoadingState.GENERATING:
case GenerationLoadingState.GENERATED:
contentElement = <GenerationContent loadingState={generationState.loadingState} imageB64={generationState.imageB64} prompt={generationState.prompt} />
break;
}
// const isButtonDisabled = generationState.loadingState === GenerationLoadingState.GENERATING;
const isButtonDisabled = false;
return (
<>
<div className="fixed flex flex-col items-center justify-center w-full h-full gap-y-12 transition-all duration-1000">
{contentElement}
<div className="glass p-3 rounded-xl flex w-1/2 border-ui-panel border-2">
<input type="text" placeholder="Describe what you want to see..." className="flex-1 text-lg rounded-md bg-transparent focus:outline-none" />
<Button icon={faSparkles} variant="primary" className="text-lg">Generate</Button>
<input ref={inputRef} type="text" placeholder="Describe what you want to see..." className="flex-1 text-lg rounded-md bg-transparent focus:outline-none" />
<Button icon={faSparkles} variant="primary" className="text-lg" onClick={handleGenerate} disabled={isButtonDisabled}>Generate</Button>
</div>
</div>
</>
);
};
const GenerationContent = (generationState : {
loadingState: GenerationLoadingState;
imageB64?: string;
prompt: string;
}) => {
const imgBoxStyle = {
width: "1024px",
height: "1024px",
}
let imgBoxContent;
if (generationState.loadingState === GenerationLoadingState.GENERATING) {
imgBoxContent = (
<div className="w-full h-full flex items-center justify-center">
<LoadingSpinner isShowing={true} message="Generating image..." />
</div>
)
} else if (generationState.loadingState === GenerationLoadingState.GENERATED) {
imgBoxContent = (
<img src={generationState.imageB64} alt="Generated Image" />
)
}
return (
<div className="flex flex-col items-center justify-center" >
<div style={imgBoxStyle} className="bg-ui-border rounded-lg">
{imgBoxContent}
</div>
<div className="bg-ui-panel w-full min-h-12 flex items-center justify-center">
<span className="text-lg p-4">{generationState.prompt}</span>
</div>
</div>
)
}
@@ -0,0 +1,7 @@
const ensureBase64Prefix = (base64String: string) => {
return base64String.startsWith("data:")
? base64String
: `data:image/png;base64,${base64String}`;
}
export { ensureBase64Prefix };
@@ -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) => {
@@ -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: "" });
@@ -0,0 +1 @@
export * from "./generationSignals";
+1
View File
@@ -1,3 +1,4 @@
export * from "./authentication";
export * from "./uiAccess";
export * from "./uiEvents";
export * from "./generation";