mirror of
https://github.com/easydiffusion/easydiffusion.git
synced 2025-01-12 17:28:56 +01:00
Merge pull request #24 from caranicas/beta-react-display-loading
Beta react display loading
This commit is contained in:
commit
51f1759323
13
ui/frontend/build_src/package-lock.json
generated
13
ui/frontend/build_src/package-lock.json
generated
@ -21,6 +21,7 @@
|
||||
"zustand": "^4.1.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/node": "^18.7.18",
|
||||
"@types/react": "^18.0.17",
|
||||
"@types/react-dom": "^18.0.6",
|
||||
"@types/uuid": "^8.3.4",
|
||||
@ -613,6 +614,12 @@
|
||||
"react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@types/node": {
|
||||
"version": "18.7.18",
|
||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-18.7.18.tgz",
|
||||
"integrity": "sha512-m+6nTEOadJZuTPkKR/SYK3A2d7FZrgElol9UP1Kae90VVU4a6mxnPuLiIW1m4Cq4gZ/nWb9GrdVXJCoCazDAbg==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/@types/prop-types": {
|
||||
"version": "15.7.5",
|
||||
"resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.5.tgz",
|
||||
@ -2361,6 +2368,12 @@
|
||||
"use-sync-external-store": "^1.2.0"
|
||||
}
|
||||
},
|
||||
"@types/node": {
|
||||
"version": "18.7.18",
|
||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-18.7.18.tgz",
|
||||
"integrity": "sha512-m+6nTEOadJZuTPkKR/SYK3A2d7FZrgElol9UP1Kae90VVU4a6mxnPuLiIW1m4Cq4gZ/nWb9GrdVXJCoCazDAbg==",
|
||||
"dev": true
|
||||
},
|
||||
"@types/prop-types": {
|
||||
"version": "15.7.5",
|
||||
"resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.5.tgz",
|
||||
|
@ -23,6 +23,7 @@
|
||||
"zustand": "^4.1.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/node": "^18.7.18",
|
||||
"@types/react": "^18.0.17",
|
||||
"@types/react-dom": "^18.0.6",
|
||||
"@types/uuid": "^8.3.4",
|
||||
|
@ -60,7 +60,6 @@ export default function DrawImage({
|
||||
const _handleMouseDown = (
|
||||
e: React.MouseEvent<HTMLCanvasElement, MouseEvent>
|
||||
) => {
|
||||
|
||||
const {
|
||||
nativeEvent: { offsetX, offsetY },
|
||||
} = e;
|
||||
|
@ -1,34 +1,20 @@
|
||||
import { style } from "@vanilla-extract/css";
|
||||
|
||||
export const generatedImage = style({
|
||||
export const generatedImageMain = style({
|
||||
position: "relative",
|
||||
width: "512px",
|
||||
height: "512px",
|
||||
});
|
||||
|
||||
export const imageContain = style({
|
||||
width: "512px",
|
||||
height: "512px",
|
||||
backgroundColor: "black",
|
||||
display: "flex",
|
||||
justifyContent: "center",
|
||||
alignItems: "center",
|
||||
});
|
||||
// export const imageContain = style({
|
||||
// width: "512px",
|
||||
// height: "512px",
|
||||
// backgroundColor: "black",
|
||||
// display: "flex",
|
||||
// justifyContent: "center",
|
||||
// alignItems: "center",
|
||||
// });
|
||||
|
||||
export const image = style({
|
||||
width: "512px",
|
||||
height: "512px",
|
||||
objectFit: "contain",
|
||||
});
|
||||
|
||||
export const saveButton = style({
|
||||
position: "absolute",
|
||||
bottom: "10px",
|
||||
left: "10px",
|
||||
});
|
||||
|
||||
export const useButton = style({
|
||||
position: "absolute",
|
||||
bottom: "10px",
|
||||
right: "10px",
|
||||
// width: "512px",
|
||||
// height: "512px",
|
||||
// objectFit: "contain",
|
||||
});
|
||||
|
@ -3,17 +3,15 @@ import React, { useCallback } from "react";
|
||||
import { ImageRequest, useImageCreate } from "../../../stores/imageCreateStore";
|
||||
|
||||
import {
|
||||
generatedImage,
|
||||
imageContain,
|
||||
image,
|
||||
saveButton,
|
||||
useButton, //@ts-ignore
|
||||
generatedImageMain,
|
||||
image, //@ts-ignore
|
||||
} from "./generatedImage.css.ts";
|
||||
|
||||
type GeneretaedImageProps = {
|
||||
imageData: string;
|
||||
metadata: ImageRequest;
|
||||
className?: string;
|
||||
// children: never[];
|
||||
};
|
||||
|
||||
export default function GeneratedImage({
|
||||
@ -21,65 +19,9 @@ export default function GeneratedImage({
|
||||
metadata,
|
||||
className,
|
||||
}: GeneretaedImageProps) {
|
||||
const setRequestOption = useImageCreate((state) => state.setRequestOptions);
|
||||
|
||||
const createFileName = () => {
|
||||
const {
|
||||
prompt,
|
||||
seed,
|
||||
num_inference_steps,
|
||||
guidance_scale,
|
||||
use_face_correction,
|
||||
use_upscale,
|
||||
width,
|
||||
height,
|
||||
} = metadata;
|
||||
|
||||
//Most important information is the prompt
|
||||
let underscoreName = prompt.replace(/[^a-zA-Z0-9]/g, "_");
|
||||
underscoreName = underscoreName.substring(0, 100);
|
||||
// name and the top level metadata
|
||||
let fileName = `${underscoreName}_Seed-${seed}_Steps-${num_inference_steps}_Guidance-${guidance_scale}`;
|
||||
// Add the face correction and upscale
|
||||
if (use_face_correction) {
|
||||
fileName += `_FaceCorrection-${use_face_correction}`;
|
||||
}
|
||||
if (use_upscale) {
|
||||
fileName += `_Upscale-${use_upscale}`;
|
||||
}
|
||||
// Add the width and height
|
||||
fileName += `_${width}x${height}`;
|
||||
// add the file extension
|
||||
fileName += `.png`;
|
||||
// return fileName
|
||||
return fileName;
|
||||
};
|
||||
|
||||
const _handleSave = () => {
|
||||
const link = document.createElement("a");
|
||||
link.download = createFileName();
|
||||
link.href = imageData;
|
||||
link.click();
|
||||
};
|
||||
|
||||
const _handleUseAsInput = () => {
|
||||
setRequestOption("init_image", imageData);
|
||||
};
|
||||
|
||||
// className={[statusClass, className].join(" ")}
|
||||
|
||||
return (
|
||||
<div className={[generatedImage, className].join(" ")}>
|
||||
<p>{metadata.prompt}</p>
|
||||
<div className={imageContain}>
|
||||
<img className={image} src={imageData} alt="generated" />
|
||||
<button className={saveButton} onClick={_handleSave}>
|
||||
Save
|
||||
</button>
|
||||
<button className={useButton} onClick={_handleUseAsInput}>
|
||||
Use as Input
|
||||
</button>
|
||||
</div>
|
||||
<div className={[generatedImageMain, className].join(" ")}>
|
||||
<img className={image} src={imageData} alt={metadata.prompt} />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
@ -4,6 +4,9 @@ import AdvancedSettings from "./advancedSettings";
|
||||
import ImageModifiers from "./imageModifiers";
|
||||
import InpaintingPanel from "./inpaintingPanel";
|
||||
|
||||
// this works but causes type errors so its not worth it for now
|
||||
// import { useImageCreate } from "@stores/imageCreateStore.ts";
|
||||
|
||||
import { useImageCreate } from "../../../stores/imageCreateStore";
|
||||
|
||||
import "./creationPanel.css";
|
||||
|
@ -0,0 +1,38 @@
|
||||
import { style, globalStyle } from "@vanilla-extract/css";
|
||||
|
||||
// @ts-ignore
|
||||
import { vars } from "../../../../styles/theme/index.css.ts";
|
||||
|
||||
export const completedImagesMain = style({
|
||||
display: "flex",
|
||||
flexDirection: "row",
|
||||
flexWrap: "nowrap",
|
||||
height: "100%",
|
||||
width: "100%",
|
||||
overflow: "auto",
|
||||
paddingBottom: vars.spacing.medium,
|
||||
});
|
||||
|
||||
export const imageContain = style({
|
||||
width: "112px",
|
||||
backgroundColor: "black",
|
||||
display: "flex",
|
||||
justifyContent: "center",
|
||||
alignItems: "center",
|
||||
flexShrink: 0,
|
||||
border: "0 none",
|
||||
padding: "0",
|
||||
});
|
||||
|
||||
globalStyle(`${imageContain} img`, {
|
||||
width: "100%",
|
||||
objectFit: "contain",
|
||||
});
|
||||
|
||||
globalStyle(`${completedImagesMain} > ${imageContain}:first-of-type`, {
|
||||
marginLeft: vars.spacing.medium,
|
||||
});
|
||||
|
||||
globalStyle(`${imageContain} > ${imageContain}:last-of-type`, {
|
||||
marginRight: 0,
|
||||
});
|
@ -1,18 +1,58 @@
|
||||
export const CompletedImages = () => {
|
||||
import React from "react";
|
||||
|
||||
import { CompletedImagesType } from "../index";
|
||||
|
||||
type CurrentDisplayProps = {
|
||||
images: CompletedImagesType[] | null;
|
||||
setCurrentDisplay: (image: CompletedImagesType) => void;
|
||||
};
|
||||
|
||||
import {
|
||||
completedImagesMain,
|
||||
imageContain, //@ts-ignore
|
||||
} from "./completedImages.css.ts";
|
||||
|
||||
export default function CompletedImages({
|
||||
images,
|
||||
setCurrentDisplay,
|
||||
}: CurrentDisplayProps) {
|
||||
const _handleSetCurrentDisplay = (index: number) => {
|
||||
debugger;
|
||||
const image = images![index];
|
||||
setCurrentDisplay(image);
|
||||
};
|
||||
|
||||
console.log("COMP{LETED IMAGES", images);
|
||||
return (
|
||||
<div className="completed-images">
|
||||
<h1>Completed Images</h1>
|
||||
<div className={completedImagesMain}>
|
||||
{images &&
|
||||
images.map((image, index) => {
|
||||
// if (void 0 !== image) {
|
||||
// return null;
|
||||
// }
|
||||
|
||||
return (
|
||||
// <div className={imageContain} key={index} value={index} onClick={() => {
|
||||
// debugger;
|
||||
// const image = images[index];
|
||||
// _handleSetCurrentDisplay(image);
|
||||
// }}>
|
||||
// <img src={image.data} alt={image.info.prompt} />
|
||||
// </div>
|
||||
|
||||
<button
|
||||
key={index}
|
||||
className={imageContain}
|
||||
onClick={() => {
|
||||
console.log("CLICKED", index);
|
||||
debugger;
|
||||
_handleSetCurrentDisplay(index);
|
||||
}}
|
||||
>
|
||||
<img src={image.data} alt={image.info.prompt} />
|
||||
</button>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
);
|
||||
// const { data } = useQuery("completedImages", getCompletedImages);
|
||||
// return (
|
||||
// <div className="completed-images">
|
||||
// <h2>Completed Images</h2>
|
||||
// <div className="completed-images-list">
|
||||
// {data?.map((image) => (
|
||||
// <GeneratedImage imageData={image.data} key={image.id} />
|
||||
// ))}
|
||||
// </div>
|
||||
// </div>
|
||||
// );
|
||||
};
|
||||
}
|
||||
|
@ -0,0 +1,78 @@
|
||||
import React from "react";
|
||||
import GeneratedImage from "../../../molecules/generatedImage";
|
||||
import {
|
||||
ImageRequest,
|
||||
useImageCreate,
|
||||
} from "../../../../stores/imageCreateStore";
|
||||
|
||||
import { CompletedImagesType } from "../index";
|
||||
|
||||
type CurrentDisplayProps = {
|
||||
image: CompletedImagesType | null;
|
||||
};
|
||||
|
||||
export default function CurrentDisplay({ image }: CurrentDisplayProps) {
|
||||
const { info, data } = image || { info: null, data: null };
|
||||
|
||||
const setRequestOption = useImageCreate((state) => state.setRequestOptions);
|
||||
|
||||
const createFileName = () => {
|
||||
const {
|
||||
prompt,
|
||||
seed,
|
||||
num_inference_steps,
|
||||
guidance_scale,
|
||||
use_face_correction,
|
||||
use_upscale,
|
||||
width,
|
||||
height,
|
||||
} = info!;
|
||||
|
||||
//Most important information is the prompt
|
||||
let underscoreName = prompt.replace(/[^a-zA-Z0-9]/g, "_");
|
||||
underscoreName = underscoreName.substring(0, 100);
|
||||
// name and the top level metadata
|
||||
let fileName = `${underscoreName}_Seed-${seed}_Steps-${num_inference_steps}_Guidance-${guidance_scale}`;
|
||||
// Add the face correction and upscale
|
||||
if (use_face_correction) {
|
||||
fileName += `_FaceCorrection-${use_face_correction}`;
|
||||
}
|
||||
if (use_upscale) {
|
||||
fileName += `_Upscale-${use_upscale}`;
|
||||
}
|
||||
// Add the width and height
|
||||
fileName += `_${width}x${height}`;
|
||||
// add the file extension
|
||||
fileName += `.png`;
|
||||
// return fileName
|
||||
return fileName;
|
||||
};
|
||||
|
||||
const _handleSave = () => {
|
||||
const link = document.createElement("a");
|
||||
link.download = createFileName();
|
||||
link.href = data!;
|
||||
link.click();
|
||||
};
|
||||
|
||||
const _handleUseAsInput = () => {
|
||||
setRequestOption("init_image", data);
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="current-display">
|
||||
{image && (
|
||||
<div>
|
||||
<p> {info!.prompt}</p>
|
||||
<GeneratedImage imageData={data!} metadata={info!}></GeneratedImage>
|
||||
|
||||
<div>
|
||||
<button onClick={_handleSave}>Save</button>
|
||||
<button onClick={_handleUseAsInput}>Use as Input</button>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
<div></div>
|
||||
</div>
|
||||
);
|
||||
}
|
@ -4,29 +4,19 @@ import { style } from "@vanilla-extract/css";
|
||||
import { vars } from "../../../styles/theme/index.css.ts";
|
||||
|
||||
export const displayPanel = style({
|
||||
padding: vars.spacing.medium,
|
||||
height: "100%",
|
||||
display: "flex",
|
||||
flexDirection: "column",
|
||||
});
|
||||
|
||||
export const displayContainer = style({
|
||||
flexGrow: 1,
|
||||
display: "flex",
|
||||
flexDirection: "row",
|
||||
height: "100%",
|
||||
width: "100%",
|
||||
overflow: "hidden",
|
||||
});
|
||||
|
||||
export const CurrentDisplay = style({
|
||||
width: "512px",
|
||||
height: "100%",
|
||||
flexDirection: "column",
|
||||
justifyContent: "center",
|
||||
alignItems: "center",
|
||||
});
|
||||
|
||||
export const previousImages = style({
|
||||
marginLeft: vars.spacing.large,
|
||||
display: "flex",
|
||||
flex: "auto",
|
||||
flexWrap: "wrap",
|
||||
});
|
||||
|
||||
export const previousImage = style({
|
||||
margin: `0 ${vars.spacing.small}`,
|
||||
height: "150px",
|
||||
});
|
||||
|
@ -9,18 +9,21 @@ import { doMakeImage, MakeImageKey } from "../../../api";
|
||||
|
||||
import AudioDing from "./audioDing";
|
||||
|
||||
import GeneratedImage from "../../molecules/generatedImage";
|
||||
// import GeneratedImage from "../../molecules/generatedImage";
|
||||
// import DrawImage from "../../molecules/drawImage";
|
||||
|
||||
import CurrentDisplay from "./currentDisplay";
|
||||
import CompletedImages from "./completedImages";
|
||||
|
||||
import {
|
||||
displayPanel,
|
||||
displayContainer,
|
||||
CurrentDisplay,
|
||||
// CurrentDisplay,
|
||||
previousImages,
|
||||
previousImage, //@ts-ignore
|
||||
} from "./displayPanel.css.ts";
|
||||
|
||||
type CompletedImagesType = {
|
||||
export type CompletedImagesType = {
|
||||
id: string;
|
||||
data: string;
|
||||
info: ImageRequest;
|
||||
@ -29,13 +32,13 @@ type CompletedImagesType = {
|
||||
export default function DisplayPanel() {
|
||||
const dingRef = useRef<HTMLAudioElement>(null);
|
||||
const isSoundEnabled = useImageCreate((state) => state.isSoundEnabled());
|
||||
|
||||
const isInPaintingMode = useImageCreate((state) => state.isInpainting);
|
||||
|
||||
/* FETCHING */
|
||||
// @ts-ignore
|
||||
const { id, options } = useImageQueue((state) => state.firstInQueue());
|
||||
const removeFirstInQueue = useImageQueue((state) => state.removeFirstInQueue);
|
||||
const [currentImage, setCurrentImage] = useState<CompletedImagesType | null>(
|
||||
null
|
||||
);
|
||||
|
||||
const { status, data } = useQuery(
|
||||
[MakeImageKey, id],
|
||||
() => doMakeImage(options),
|
||||
@ -58,16 +61,15 @@ export default function DisplayPanel() {
|
||||
}, [status, data, removeFirstInQueue, dingRef, isSoundEnabled]);
|
||||
|
||||
/* COMPLETED IMAGES */
|
||||
|
||||
const queryClient = useQueryClient();
|
||||
const [completedImages, setCompletedImages] = useState<CompletedImagesType[]>(
|
||||
[]
|
||||
);
|
||||
const completedIds = useImageQueue((state) => state.completedImageIds);
|
||||
|
||||
const init_image = useImageCreate((state) =>
|
||||
state.getValueForRequestKey("init_image")
|
||||
);
|
||||
// const init_image = useImageCreate((state) =>
|
||||
// state.getValueForRequestKey("init_image")
|
||||
// );
|
||||
|
||||
useEffect(() => {
|
||||
const testReq = {} as ImageRequest;
|
||||
@ -97,50 +99,24 @@ export default function DisplayPanel() {
|
||||
.flat()
|
||||
.reverse();
|
||||
setCompletedImages(temp);
|
||||
setCurrentImage(temp[0] || null);
|
||||
} else {
|
||||
setCompletedImages([]);
|
||||
setCurrentImage(null);
|
||||
}
|
||||
}, [setCompletedImages, queryClient, completedIds]);
|
||||
}, [setCompletedImages, setCurrentImage, queryClient, completedIds]);
|
||||
|
||||
return (
|
||||
<div className={displayPanel}>
|
||||
<AudioDing ref={dingRef}></AudioDing>
|
||||
<div className={displayContainer}>
|
||||
{/* {isInPaintingMode && <DrawImage imageData={init_image}></DrawImage>} */}
|
||||
|
||||
{completedImages.length > 0 && (
|
||||
<>
|
||||
<div className={CurrentDisplay}>
|
||||
<GeneratedImage
|
||||
key={completedImages[0].id}
|
||||
imageData={completedImages[0].data}
|
||||
metadata={completedImages[0].info}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className={previousImages}>
|
||||
{completedImages.map((image, index) => {
|
||||
if (void 0 !== image) {
|
||||
if (index == 0) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return (
|
||||
<GeneratedImage
|
||||
className={previousImage}
|
||||
key={image.id}
|
||||
imageData={image.data}
|
||||
metadata={image.info}
|
||||
/>
|
||||
);
|
||||
} else {
|
||||
console.warn("image is undefined", image, index);
|
||||
return null;
|
||||
}
|
||||
})}
|
||||
</div>
|
||||
</>
|
||||
)}
|
||||
<CurrentDisplay image={currentImage}></CurrentDisplay>
|
||||
</div>
|
||||
<div className={previousImages}>
|
||||
<CompletedImages
|
||||
images={completedImages}
|
||||
setCurrentDisplay={setCurrentImage}
|
||||
></CompletedImages>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
@ -1,5 +1,10 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"baseUrl": "./",
|
||||
"paths": {
|
||||
"@stores": ["src/stores"]
|
||||
},
|
||||
|
||||
"target": "ESNext",
|
||||
"useDefineForClassFields": true,
|
||||
"lib": ["DOM", "DOM.Iterable", "ESNext"],
|
||||
|
@ -2,14 +2,24 @@ import { defineConfig } from "vite";
|
||||
import react from "@vitejs/plugin-react";
|
||||
import { vanillaExtractPlugin } from "@vanilla-extract/vite-plugin";
|
||||
|
||||
import path from "path";
|
||||
// https://vitejs.dev/config/
|
||||
export default defineConfig({
|
||||
resolve: {
|
||||
alias: {
|
||||
// TODO figure out why vs code complains about this even though it works
|
||||
"@stores": path.resolve(__dirname, "./src/stores"),
|
||||
// TODO - add more aliases
|
||||
},
|
||||
},
|
||||
|
||||
plugins: [
|
||||
react(),
|
||||
vanillaExtractPlugin({
|
||||
// configuration
|
||||
}),
|
||||
],
|
||||
|
||||
server: {
|
||||
port: 9001,
|
||||
},
|
||||
|
2
ui/frontend/dist/index.css
vendored
2
ui/frontend/dist/index.css
vendored
File diff suppressed because one or more lines are too long
26
ui/frontend/dist/index.js
vendored
26
ui/frontend/dist/index.js
vendored
File diff suppressed because one or more lines are too long
Loading…
Reference in New Issue
Block a user