current and cache history

This commit is contained in:
caranicas 2022-09-18 15:19:31 -04:00
parent bad015de9a
commit c7b89a1126
12 changed files with 278 additions and 169 deletions

View File

@ -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",

View File

@ -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",

View File

@ -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",
});

View File

@ -3,17 +3,16 @@ import React, { useCallback } from "react";
import { ImageRequest, useImageCreate } from "../../../stores/imageCreateStore";
import {
generatedImage,
imageContain,
generatedImageMain,
image,
saveButton,
useButton, //@ts-ignore
} from "./generatedImage.css.ts";
} from //@ts-ignore
"./generatedImage.css.ts";
type GeneretaedImageProps = {
imageData: string;
metadata: ImageRequest;
className?: string;
children: never[];
};
export default function GeneratedImage({
@ -21,65 +20,10 @@ 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>
);
}

View File

@ -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";

View File

@ -0,0 +1,44 @@
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,
});

View File

@ -1,18 +1,61 @@
export const CompletedImages = () => {
import React from "react";
import { CompletedImagesType } from "../index";
type CurrentDisplayProps = {
images: CompletedImagesType[] | null;
setCurrentDisplay: (image: CompletedImagesType) => void;
}
import {
completedImagesMain,
imageContain
} from //@ts-ignore
"./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>
// );
};
)
};

View File

@ -0,0 +1,90 @@
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>
);
}

View File

@ -4,29 +4,21 @@ 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({
display: "flex",
flexDirection: "row",
height: "100%",
width: "100%",
overflow: "hidden",
});
export const CurrentDisplay = style({
width: "512px",
height: "100%",
flexGrow: 1,
display: 'flex',
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',
});

View File

@ -9,33 +9,36 @@ 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;
};
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,51 +99,23 @@ 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>
);
}

View File

@ -1,5 +1,10 @@
{
"compilerOptions": {
"baseUrl": "./",
"paths": {
"@stores": ["src/stores"]
},
"target": "ESNext",
"useDefineForClassFields": true,
"lib": ["DOM", "DOM.Iterable", "ESNext"],

View File

@ -2,14 +2,28 @@ 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,
},