mirror of
https://github.com/easydiffusion/easydiffusion.git
synced 2025-01-13 01:38:19 +01:00
commit
4fbc46b3b3
@ -31,15 +31,13 @@ export const getSaveDirectory = async () => {
|
|||||||
return data[0];
|
return data[0];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
export const getConfig = async () => {
|
export const getConfig = async () => {
|
||||||
const response = await fetch(`${API_URL}/app_config`);
|
const response = await fetch(`${API_URL}/app_config`);
|
||||||
console.log('getConfig response', response);
|
console.log("getConfig response", response);
|
||||||
const data = await response.json();
|
const data = await response.json();
|
||||||
return data;
|
return data;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* post a new request for an image
|
* post a new request for an image
|
||||||
*/
|
*/
|
||||||
|
@ -0,0 +1,22 @@
|
|||||||
|
import { style, globalStyle } from "@vanilla-extract/css";
|
||||||
|
|
||||||
|
export const DrawImageMain = style({
|
||||||
|
position: "relative",
|
||||||
|
});
|
||||||
|
|
||||||
|
globalStyle(`${DrawImageMain} > canvas`, {
|
||||||
|
position: "absolute",
|
||||||
|
top: "0",
|
||||||
|
left: "0",
|
||||||
|
width: "100%",
|
||||||
|
height: "100%",
|
||||||
|
});
|
||||||
|
|
||||||
|
globalStyle(`${DrawImageMain} > canvas:first-of-type`, {
|
||||||
|
opacity: ".7",
|
||||||
|
});
|
||||||
|
|
||||||
|
globalStyle(`${DrawImageMain} > img`, {
|
||||||
|
top: "0",
|
||||||
|
left: "0",
|
||||||
|
});
|
@ -1,91 +1,176 @@
|
|||||||
// @ts-nocheck
|
// @ts-nocheck
|
||||||
import React, { useRef, useEffect } from "react";
|
import React, { useRef, useState, useEffect } from "react";
|
||||||
|
|
||||||
// https://github.com/embiem/react-canvas-draw
|
// https://github.com/embiem/react-canvas-draw
|
||||||
|
|
||||||
type DrawImageProps = {
|
type DrawImageProps = {
|
||||||
imageData: string;
|
imageData: string;
|
||||||
|
brushSize: string;
|
||||||
|
|
||||||
|
brushShape: string;
|
||||||
|
brushColor: string;
|
||||||
|
isErasing: boolean;
|
||||||
};
|
};
|
||||||
|
|
||||||
export default function DrawImage({ imageData }: DrawImageProps) {
|
import {
|
||||||
const canvasRef = useRef<HTMLCanvasElement>(null);
|
DrawImageMain, //@ts-ignore
|
||||||
|
} from "./drawImage.css.ts";
|
||||||
|
|
||||||
const draw = (ctx: CanvasRenderingContext2D) => {
|
export default function DrawImage({
|
||||||
ctx.fillStyle = "red";
|
imageData,
|
||||||
ctx.fillRect(0, 0, 100, 100);
|
brushSize,
|
||||||
};
|
brushShape,
|
||||||
|
brushColor,
|
||||||
|
isErasing,
|
||||||
|
}: DrawImageProps) {
|
||||||
|
const drawingRef = useRef<HTMLCanvasElement>(null);
|
||||||
|
const cursorRef = useRef<HTMLCanvasElement>(null);
|
||||||
|
const [isUpdating, setIsUpdating] = useState(false);
|
||||||
|
|
||||||
|
const [canvasWidth, setCanvasWidth] = useState(512);
|
||||||
|
const [canvasHeight, setCanvasHeight] = useState(512);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const canvas = canvasRef.current;
|
console.log(imageData);
|
||||||
if (canvas) {
|
const img = new Image();
|
||||||
if (imageData) {
|
img.onload = () => {
|
||||||
const ctx = canvas.getContext("2d");
|
setCanvasWidth(img.width);
|
||||||
if (ctx) {
|
setCanvasHeight(img.height);
|
||||||
const img = new Image();
|
};
|
||||||
img.onload = () => {
|
img.src = imageData;
|
||||||
ctx.drawImage(img, 0, 0);
|
}, [imageData]);
|
||||||
};
|
|
||||||
img.src = imageData;
|
useEffect(() => {
|
||||||
}
|
// when the brush color changes, change the color of all the
|
||||||
} else {
|
// drawn pixels to the new color
|
||||||
const ctx = canvas.getContext("2d");
|
if (drawingRef.current) {
|
||||||
if (ctx) {
|
const ctx = drawingRef.current.getContext("2d");
|
||||||
draw(ctx);
|
const imageData = ctx.getImageData(0, 0, canvasWidth, canvasHeight);
|
||||||
|
const data = imageData.data;
|
||||||
|
for (let i = 0; i < data.length; i += 4) {
|
||||||
|
if (data[i + 3] > 0) {
|
||||||
|
data[i] = parseInt(brushColor, 16);
|
||||||
|
data[i + 1] = parseInt(brushColor, 16);
|
||||||
|
data[i + 2] = parseInt(brushColor, 16);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
ctx.putImageData(imageData, 0, 0);
|
||||||
console.log("canvas is null");
|
|
||||||
}
|
}
|
||||||
}, [imageData, draw]);
|
}, [brushColor]);
|
||||||
|
|
||||||
const _handleMouseDown = (
|
const _handleMouseDown = (
|
||||||
e: React.MouseEvent<HTMLCanvasElement, MouseEvent>
|
e: React.MouseEvent<HTMLCanvasElement, MouseEvent>
|
||||||
) => {
|
) => {
|
||||||
console.log("mouse down", e);
|
console.log("mouse down", e);
|
||||||
const canvas = canvasRef.current;
|
|
||||||
if (canvas) {
|
|
||||||
const ctx = canvas.getContext("2d");
|
|
||||||
ctx.strokeStyle = "#ff0000";
|
|
||||||
const {
|
|
||||||
nativeEvent: { x, y },
|
|
||||||
} = e;
|
|
||||||
|
|
||||||
console.log("x: " + x + " y: " + y);
|
const {
|
||||||
|
nativeEvent: { offsetX, offsetY },
|
||||||
|
} = e;
|
||||||
|
|
||||||
ctx.moveTo(x, y);
|
setIsUpdating(true);
|
||||||
ctx.lineTo(x + 1, y + 1);
|
|
||||||
ctx.stroke();
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const _handleMouseUp = (
|
const _handleMouseUp = (
|
||||||
e: React.MouseEvent<HTMLCanvasElement, MouseEvent>
|
e: React.MouseEvent<HTMLCanvasElement, MouseEvent>
|
||||||
) => {
|
) => {
|
||||||
console.log("mouse up");
|
setIsUpdating(false);
|
||||||
const canvas = canvasRef.current;
|
const canvas = drawingRef.current;
|
||||||
|
if (canvas) {
|
||||||
|
const data = canvas.toDataURL();
|
||||||
|
// TODO: SEND THIS TO THE STATE
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const _drawCanvas = (x, y, brushSize, brushShape, brushColor) => {
|
||||||
|
const canvas = drawingRef.current;
|
||||||
if (canvas) {
|
if (canvas) {
|
||||||
const ctx = canvas.getContext("2d");
|
const ctx = canvas.getContext("2d");
|
||||||
// if (ctx) {
|
if (isErasing) {
|
||||||
// draw(ctx);
|
// stack overflow https://stackoverflow.com/questions/10396991/clearing-circular-regions-from-html5-canvas
|
||||||
// }
|
|
||||||
const {
|
const offset = brushSize / 2;
|
||||||
nativeEvent: { x, y },
|
ctx.clearRect(x - offset, y - offset, brushSize, brushSize);
|
||||||
} = e;
|
} else {
|
||||||
ctx.moveTo(x, y);
|
ctx.beginPath();
|
||||||
ctx.lineTo(x + 1, y + 1);
|
ctx.lineWidth = brushSize;
|
||||||
ctx.stroke();
|
ctx.lineCap = brushShape;
|
||||||
ctx.closePath();
|
ctx.strokeStyle = brushColor;
|
||||||
|
ctx.moveTo(x, y);
|
||||||
|
ctx.lineTo(x, y);
|
||||||
|
ctx.stroke();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const _drawCursor = (x, y, brushSize, brushShape, brushColor) => {
|
||||||
|
const canvas = cursorRef.current;
|
||||||
|
if (canvas) {
|
||||||
|
const ctx = canvas.getContext("2d");
|
||||||
|
ctx.beginPath();
|
||||||
|
ctx.clearRect(0, 0, canvas.width, canvas.height);
|
||||||
|
|
||||||
|
if (isErasing) {
|
||||||
|
const offset = brushSize / 2;
|
||||||
|
// draw a quare
|
||||||
|
ctx.lineWidth = 2;
|
||||||
|
ctx.lineCap = "butt";
|
||||||
|
ctx.strokeStyle = brushColor;
|
||||||
|
ctx.moveTo(x - offset, y - offset);
|
||||||
|
ctx.lineTo(x + offset, y - offset);
|
||||||
|
ctx.lineTo(x + offset, y + offset);
|
||||||
|
ctx.lineTo(x - offset, y + offset);
|
||||||
|
ctx.lineTo(x - offset, y - offset);
|
||||||
|
ctx.stroke();
|
||||||
|
} else {
|
||||||
|
ctx.lineWidth = brushSize;
|
||||||
|
ctx.lineCap = brushShape;
|
||||||
|
ctx.strokeStyle = brushColor;
|
||||||
|
ctx.moveTo(x, y);
|
||||||
|
ctx.lineTo(x, y);
|
||||||
|
ctx.stroke();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const _handleMouseMove = (
|
||||||
|
e: React.MouseEvent<HTMLCanvasElement, MouseEvent>
|
||||||
|
) => {
|
||||||
|
const {
|
||||||
|
nativeEvent: { offsetX: x, offsetY: y },
|
||||||
|
} = e;
|
||||||
|
|
||||||
|
_drawCursor(x, y, brushSize, brushShape, brushColor);
|
||||||
|
|
||||||
|
if (isUpdating) {
|
||||||
|
_drawCanvas(x, y, brushSize, brushShape, brushColor);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// function for external use
|
||||||
|
const fillCanvas = () => {
|
||||||
|
const canvas = drawingRef.current;
|
||||||
|
if (canvas) {
|
||||||
|
const ctx = canvas.getContext("2d");
|
||||||
|
ctx.fillStyle = brushColor;
|
||||||
|
ctx.fillRect(0, 0, canvas.width, canvas.height);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div>
|
<div className={DrawImageMain}>
|
||||||
|
<img src={imageData} />
|
||||||
<canvas
|
<canvas
|
||||||
ref={canvasRef}
|
ref={drawingRef}
|
||||||
width={512}
|
width={canvasWidth}
|
||||||
height={512}
|
height={canvasHeight}
|
||||||
|
></canvas>
|
||||||
|
<canvas
|
||||||
|
ref={cursorRef}
|
||||||
|
width={canvasWidth}
|
||||||
|
height={canvasHeight}
|
||||||
onMouseDown={_handleMouseDown}
|
onMouseDown={_handleMouseDown}
|
||||||
onMouseUp={_handleMouseUp}
|
onMouseUp={_handleMouseUp}
|
||||||
|
onMouseMove={_handleMouseMove}
|
||||||
></canvas>
|
></canvas>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
@ -18,6 +18,9 @@ export default function SeedImage(_props: any) {
|
|||||||
const init_image = useImageCreate((state) =>
|
const init_image = useImageCreate((state) =>
|
||||||
state.getValueForRequestKey("init_image")
|
state.getValueForRequestKey("init_image")
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const isInPaintingMode = useImageCreate((state) => state.isInpainting);
|
||||||
|
|
||||||
const setRequestOption = useImageCreate((state) => state.setRequestOptions);
|
const setRequestOption = useImageCreate((state) => state.setRequestOptions);
|
||||||
|
|
||||||
const _startFileSelect = () => {
|
const _startFileSelect = () => {
|
||||||
@ -38,8 +41,14 @@ export default function SeedImage(_props: any) {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const toggleInpainting = useImageCreate((state) => state.toggleInpainting);
|
||||||
|
|
||||||
const _handleClearImage = () => {
|
const _handleClearImage = () => {
|
||||||
setRequestOption("init_image", undefined);
|
setRequestOption("init_image", undefined);
|
||||||
|
|
||||||
|
if (isInPaintingMode) {
|
||||||
|
toggleInpainting();
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@ -63,10 +72,22 @@ export default function SeedImage(_props: any) {
|
|||||||
<div className={ImageFixer}>
|
<div className={ImageFixer}>
|
||||||
{init_image && (
|
{init_image && (
|
||||||
<>
|
<>
|
||||||
<img src={init_image} width="100" height="100" />
|
<div>
|
||||||
<button className={XButton} onClick={_handleClearImage}>
|
<img src={init_image} width="100" height="100" />
|
||||||
X
|
<button className={XButton} onClick={_handleClearImage}>
|
||||||
</button>
|
X
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
<label>
|
||||||
|
<input
|
||||||
|
type="checkbox"
|
||||||
|
onChange={(e) => {
|
||||||
|
toggleInpainting();
|
||||||
|
}}
|
||||||
|
checked={isInPaintingMode}
|
||||||
|
></input>
|
||||||
|
Use for Inpainting
|
||||||
|
</label>
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
@ -5,4 +5,13 @@ export const CreationPaneMain = style({
|
|||||||
width: "100%",
|
width: "100%",
|
||||||
height: "100%",
|
height: "100%",
|
||||||
padding: "0 10px",
|
padding: "0 10px",
|
||||||
|
overflowY: "auto",
|
||||||
|
});
|
||||||
|
|
||||||
|
export const InpaintingSlider = style({
|
||||||
|
position: "absolute",
|
||||||
|
top: "10px",
|
||||||
|
left: "400px",
|
||||||
|
zIndex: 1,
|
||||||
|
backgroundColor: "rgba(0, 0, 0, 0.5)",
|
||||||
});
|
});
|
||||||
|
@ -1,22 +1,35 @@
|
|||||||
import React, { ChangeEvent } from "react";
|
import React, { ChangeEvent } from "react";
|
||||||
|
|
||||||
import MakeButton from "./basicCreation/makeButton";
|
|
||||||
import AdvancedSettings from "./advancedSettings";
|
import AdvancedSettings from "./advancedSettings";
|
||||||
import ImageModifiers from "./imageModifiers";
|
import ImageModifiers from "./imageModifiers";
|
||||||
|
import InpaintingPanel from "./inpaintingPanel";
|
||||||
|
|
||||||
|
import { useImageCreate } from "../../../stores/imageCreateStore";
|
||||||
|
|
||||||
import "./creationPanel.css";
|
import "./creationPanel.css";
|
||||||
|
|
||||||
// @ts-ignore
|
import {
|
||||||
import { CreationPaneMain } from "./creationpane.css.ts";
|
CreationPaneMain,
|
||||||
|
InpaintingSlider, // @ts-ignore
|
||||||
|
} from "./creationpane.css.ts";
|
||||||
|
|
||||||
import BasicCreation from "./basicCreation";
|
import BasicCreation from "./basicCreation";
|
||||||
|
|
||||||
export default function CreationPanel() {
|
export default function CreationPanel() {
|
||||||
|
const isInPaintingMode = useImageCreate((state) => state.isInpainting);
|
||||||
return (
|
return (
|
||||||
<div className={CreationPaneMain}>
|
<>
|
||||||
<BasicCreation></BasicCreation>
|
<div className={CreationPaneMain}>
|
||||||
<AdvancedSettings></AdvancedSettings>
|
<BasicCreation></BasicCreation>
|
||||||
<ImageModifiers></ImageModifiers>
|
<AdvancedSettings></AdvancedSettings>
|
||||||
</div>
|
<ImageModifiers></ImageModifiers>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{isInPaintingMode && (
|
||||||
|
<div className={InpaintingSlider}>
|
||||||
|
<InpaintingPanel></InpaintingPanel>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,114 @@
|
|||||||
|
import React, { useRef, useState, ChangeEvent, MouseEventHandler } from "react";
|
||||||
|
import DrawImage from "../../../molecules/drawImage";
|
||||||
|
|
||||||
|
import { useImageCreate } from "../../../../stores/imageCreateStore";
|
||||||
|
|
||||||
|
import {
|
||||||
|
InpaintingPanelMain,
|
||||||
|
InpaintingControls,
|
||||||
|
InpaintingControlRow, // @ts-ignore
|
||||||
|
} from "./inpaintingPanel.css.ts";
|
||||||
|
|
||||||
|
export default function InpaintingPanel() {
|
||||||
|
// no idea if this is the right typing
|
||||||
|
const drawingRef = useRef(null);
|
||||||
|
|
||||||
|
const [brushSize, setBrushSize] = useState("20");
|
||||||
|
const [brushShape, setBrushShape] = useState("round");
|
||||||
|
const [brushColor, setBrushColor] = useState("#fff");
|
||||||
|
const [isErasing, setIsErasing] = useState(false);
|
||||||
|
|
||||||
|
const init_image = useImageCreate((state) =>
|
||||||
|
state.getValueForRequestKey("init_image")
|
||||||
|
);
|
||||||
|
|
||||||
|
const _handleBrushMask = () => {
|
||||||
|
setIsErasing(false);
|
||||||
|
};
|
||||||
|
|
||||||
|
const _handleBrushErase = () => {
|
||||||
|
setIsErasing(true);
|
||||||
|
};
|
||||||
|
|
||||||
|
const _handleFillMask = () => {
|
||||||
|
console.log("fill mask!!", drawingRef);
|
||||||
|
|
||||||
|
// drawingRef.current?.fillCanvas();
|
||||||
|
};
|
||||||
|
|
||||||
|
const _handleClearAll = () => {
|
||||||
|
console.log("clear all");
|
||||||
|
};
|
||||||
|
|
||||||
|
const _handleBrushSize = (event: ChangeEvent<HTMLInputElement>) => {
|
||||||
|
setBrushSize(event.target.value);
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className={InpaintingPanelMain}>
|
||||||
|
<DrawImage
|
||||||
|
// ref={drawingRef}
|
||||||
|
imageData={init_image}
|
||||||
|
brushSize={brushSize}
|
||||||
|
brushShape={brushShape}
|
||||||
|
brushColor={brushColor}
|
||||||
|
isErasing={isErasing}
|
||||||
|
/>
|
||||||
|
<div className={InpaintingControls}>
|
||||||
|
<div className={InpaintingControlRow}>
|
||||||
|
<button onClick={_handleBrushMask}>Mask</button>
|
||||||
|
<button onClick={_handleBrushErase}>Erase</button>
|
||||||
|
<button disabled onClick={_handleFillMask}>
|
||||||
|
Fill
|
||||||
|
</button>
|
||||||
|
<button disabled onClick={_handleClearAll}>
|
||||||
|
Clear
|
||||||
|
</button>
|
||||||
|
|
||||||
|
<label>
|
||||||
|
Brush Size
|
||||||
|
<input
|
||||||
|
type="range"
|
||||||
|
min="1"
|
||||||
|
max="100"
|
||||||
|
value={brushSize}
|
||||||
|
onChange={_handleBrushSize}
|
||||||
|
></input>
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className={InpaintingControlRow}>
|
||||||
|
<button
|
||||||
|
onClick={() => {
|
||||||
|
setBrushShape("round");
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
Cirle Brush
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
onClick={() => {
|
||||||
|
setBrushShape("square");
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
Square Brush
|
||||||
|
</button>
|
||||||
|
|
||||||
|
<button
|
||||||
|
onClick={() => {
|
||||||
|
setBrushColor("#000");
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
Dark Brush
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
onClick={() => {
|
||||||
|
setBrushColor("#fff");
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
Light Brush
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
@ -0,0 +1,27 @@
|
|||||||
|
import { style } from "@vanilla-extract/css";
|
||||||
|
|
||||||
|
export const InpaintingPanelMain = style({
|
||||||
|
position: "relative",
|
||||||
|
width: "100%",
|
||||||
|
height: "100%",
|
||||||
|
padding: "10px 10px",
|
||||||
|
});
|
||||||
|
|
||||||
|
export const InpaintingControls = style({
|
||||||
|
display: "flex",
|
||||||
|
flexDirection: "row",
|
||||||
|
width: "100%",
|
||||||
|
flexWrap: "wrap",
|
||||||
|
});
|
||||||
|
|
||||||
|
export const InpaintingControlRow = style({
|
||||||
|
display: "flex",
|
||||||
|
flexDirection: "row",
|
||||||
|
justifyContent: "space-evenly",
|
||||||
|
alignItems: "center",
|
||||||
|
width: "100%",
|
||||||
|
|
||||||
|
":first-of-type": {
|
||||||
|
margin: "10px 0",
|
||||||
|
},
|
||||||
|
});
|
@ -25,10 +25,13 @@ type CompletedImagesType = {
|
|||||||
data: string;
|
data: string;
|
||||||
info: ImageRequest;
|
info: ImageRequest;
|
||||||
};
|
};
|
||||||
|
|
||||||
export default function DisplayPanel() {
|
export default function DisplayPanel() {
|
||||||
const dingRef = useRef<HTMLAudioElement>(null);
|
const dingRef = useRef<HTMLAudioElement>(null);
|
||||||
const isSoundEnabled = useImageCreate((state) => state.isSoundEnabled());
|
const isSoundEnabled = useImageCreate((state) => state.isSoundEnabled());
|
||||||
|
|
||||||
|
const isInPaintingMode = useImageCreate((state) => state.isInpainting);
|
||||||
|
|
||||||
/* FETCHING */
|
/* FETCHING */
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
const { id, options } = useImageQueue((state) => state.firstInQueue());
|
const { id, options } = useImageQueue((state) => state.firstInQueue());
|
||||||
@ -62,6 +65,10 @@ export default function DisplayPanel() {
|
|||||||
);
|
);
|
||||||
const completedIds = useImageQueue((state) => state.completedImageIds);
|
const completedIds = useImageQueue((state) => state.completedImageIds);
|
||||||
|
|
||||||
|
const init_image = useImageCreate((state) =>
|
||||||
|
state.getValueForRequestKey("init_image")
|
||||||
|
);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const testReq = {} as ImageRequest;
|
const testReq = {} as ImageRequest;
|
||||||
const completedQueries = completedIds.map((id) => {
|
const completedQueries = completedIds.map((id) => {
|
||||||
@ -98,42 +105,43 @@ export default function DisplayPanel() {
|
|||||||
return (
|
return (
|
||||||
<div className={displayPanel}>
|
<div className={displayPanel}>
|
||||||
<AudioDing ref={dingRef}></AudioDing>
|
<AudioDing ref={dingRef}></AudioDing>
|
||||||
{completedImages.length > 0 && (
|
<div className={displayContainer}>
|
||||||
<div className={displayContainer}>
|
{/* {isInPaintingMode && <DrawImage imageData={init_image}></DrawImage>} */}
|
||||||
<div className={CurrentDisplay}>
|
|
||||||
{/* TODO Put the in painting controls here */}
|
|
||||||
{/* <DrawImage imageData={completedImages[0].data}></DrawImage> */}
|
|
||||||
|
|
||||||
<GeneratedImage
|
{completedImages.length > 0 && (
|
||||||
key={completedImages[0].id}
|
<>
|
||||||
imageData={completedImages[0].data}
|
<div className={CurrentDisplay}>
|
||||||
metadata={completedImages[0].info}
|
<GeneratedImage
|
||||||
/>
|
key={completedImages[0].id}
|
||||||
</div>
|
imageData={completedImages[0].data}
|
||||||
|
metadata={completedImages[0].info}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div className={previousImages}>
|
<div className={previousImages}>
|
||||||
{completedImages.map((image, index) => {
|
{completedImages.map((image, index) => {
|
||||||
if (void 0 !== image) {
|
if (void 0 !== image) {
|
||||||
if (index == 0) {
|
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;
|
return null;
|
||||||
}
|
}
|
||||||
|
})}
|
||||||
return (
|
</div>
|
||||||
<GeneratedImage
|
</>
|
||||||
className={previousImage}
|
)}
|
||||||
key={image.id}
|
</div>
|
||||||
imageData={image.data}
|
|
||||||
metadata={image.info}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
console.warn("image is undefined", image, index);
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
})}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -12,4 +12,3 @@ globalStyle(`${HeaderDisplayMain} > h1`, {
|
|||||||
fontWeight: "bold",
|
fontWeight: "bold",
|
||||||
marginRight: "10px",
|
marginRight: "10px",
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -6,42 +6,37 @@ import { getConfig } from "../../../api";
|
|||||||
import StatusDisplay from "./statusDisplay";
|
import StatusDisplay from "./statusDisplay";
|
||||||
|
|
||||||
import {
|
import {
|
||||||
HeaderDisplayMain
|
HeaderDisplayMain, //@ts-ignore
|
||||||
} from //@ts-ignore
|
} from "./headerDisplay.css.ts";
|
||||||
'./headerDisplay.css.ts'
|
|
||||||
|
|
||||||
|
|
||||||
export default function HeaderDisplay() {
|
export default function HeaderDisplay() {
|
||||||
|
|
||||||
// but this will be moved to the status display when it is created
|
// but this will be moved to the status display when it is created
|
||||||
const { status, data } = useQuery(["config"], getConfig)
|
const { status, data } = useQuery(["config"], getConfig);
|
||||||
|
|
||||||
const [version, setVersion] = useState("2.1.0");
|
const [version, setVersion] = useState("2.1.0");
|
||||||
const [release, setRelease] = useState('');
|
const [release, setRelease] = useState("");
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
if (status === "success") {
|
||||||
if (status === 'success') {
|
|
||||||
// TODO also pass down the actual version
|
// TODO also pass down the actual version
|
||||||
const { update_branch } = data;
|
const { update_branch } = data;
|
||||||
|
|
||||||
// just hard coded for now
|
// just hard coded for now
|
||||||
setVersion('v2.1');
|
setVersion("v2.1");
|
||||||
|
|
||||||
if (update_branch === 'main') {
|
if (update_branch === "main") {
|
||||||
setRelease('(stable)')
|
setRelease("(stable)");
|
||||||
}
|
} else {
|
||||||
else {
|
setRelease("(beta)");
|
||||||
setRelease('(beta)')
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}, [status, data, setVersion, setVersion]);
|
||||||
}, [status, data, setVersion, setVersion])
|
|
||||||
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={HeaderDisplayMain}>
|
<div className={HeaderDisplayMain}>
|
||||||
<h1>Stable Diffusion UI {version} {release} </h1>
|
<h1>
|
||||||
|
Stable Diffusion UI {version} {release}{" "}
|
||||||
|
</h1>
|
||||||
<StatusDisplay className="status-display"></StatusDisplay>
|
<StatusDisplay className="status-display"></StatusDisplay>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
import { style } from "@vanilla-extract/css";
|
import { style } from "@vanilla-extract/css";
|
||||||
|
|
||||||
|
|
||||||
// TODO MOVE TO GLOBAL CSS
|
// TODO MOVE TO GLOBAL CSS
|
||||||
export const StartingStatus = style({
|
export const StartingStatus = style({
|
||||||
color: "#f0ad4e",
|
color: "#f0ad4e",
|
||||||
|
@ -6,7 +6,6 @@ import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
|
|||||||
import { ReactQueryDevtools } from "@tanstack/react-query-devtools";
|
import { ReactQueryDevtools } from "@tanstack/react-query-devtools";
|
||||||
|
|
||||||
import { enableMapSet } from "immer";
|
import { enableMapSet } from "immer";
|
||||||
import Editor from "./pages/Home";
|
|
||||||
|
|
||||||
import App from "./app";
|
import App from "./app";
|
||||||
|
|
||||||
|
@ -35,7 +35,7 @@ export const HeaderLayout = style({
|
|||||||
|
|
||||||
export const CreateLayout = style({
|
export const CreateLayout = style({
|
||||||
gridArea: "create",
|
gridArea: "create",
|
||||||
overflow: "auto",
|
position: "relative",
|
||||||
});
|
});
|
||||||
|
|
||||||
export const DisplayLayout = style({
|
export const DisplayLayout = style({
|
||||||
|
@ -5,8 +5,6 @@ import { devtools } from "zustand/middleware";
|
|||||||
import { useRandomSeed } from "../utils";
|
import { useRandomSeed } from "../utils";
|
||||||
|
|
||||||
export type ImageCreationUiOptions = {
|
export type ImageCreationUiOptions = {
|
||||||
// isCheckedUseUpscaling: boolean;
|
|
||||||
// isCheckUseFaceCorrection: boolean;
|
|
||||||
isUseRandomSeed: boolean;
|
isUseRandomSeed: boolean;
|
||||||
isUseAutoSave: boolean;
|
isUseAutoSave: boolean;
|
||||||
isSoundEnabled: boolean;
|
isSoundEnabled: boolean;
|
||||||
@ -71,6 +69,7 @@ interface ImageCreateState {
|
|||||||
requestOptions: ImageRequest;
|
requestOptions: ImageRequest;
|
||||||
allModifiers: ModifiersOptionList;
|
allModifiers: ModifiersOptionList;
|
||||||
tags: string[];
|
tags: string[];
|
||||||
|
isInpainting: boolean;
|
||||||
|
|
||||||
setParallelCount: (count: number) => void;
|
setParallelCount: (count: number) => void;
|
||||||
setRequestOptions: (key: keyof ImageRequest, value: any) => void;
|
setRequestOptions: (key: keyof ImageRequest, value: any) => void;
|
||||||
@ -94,6 +93,7 @@ interface ImageCreateState {
|
|||||||
isUseAutoSave: () => boolean;
|
isUseAutoSave: () => boolean;
|
||||||
toggleSoundEnabled: () => void;
|
toggleSoundEnabled: () => void;
|
||||||
isSoundEnabled: () => boolean;
|
isSoundEnabled: () => boolean;
|
||||||
|
toggleInpainting: () => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
// devtools breaks TS
|
// devtools breaks TS
|
||||||
@ -134,6 +134,8 @@ export const useImageCreate = create<ImageCreateState>(
|
|||||||
|
|
||||||
allModifiers: [[[]]] as ModifiersOptionList,
|
allModifiers: [[[]]] as ModifiersOptionList,
|
||||||
|
|
||||||
|
isInpainting: false,
|
||||||
|
|
||||||
setParallelCount: (count: number) =>
|
setParallelCount: (count: number) =>
|
||||||
set(
|
set(
|
||||||
produce((state) => {
|
produce((state) => {
|
||||||
@ -280,5 +282,13 @@ export const useImageCreate = create<ImageCreateState>(
|
|||||||
isSoundEnabled: () => {
|
isSoundEnabled: () => {
|
||||||
return get().uiOptions.isSoundEnabled;
|
return get().uiOptions.isSoundEnabled;
|
||||||
},
|
},
|
||||||
|
|
||||||
|
toggleInpainting: () => {
|
||||||
|
set(
|
||||||
|
produce((state) => {
|
||||||
|
state.isInpainting = !state.isInpainting;
|
||||||
|
})
|
||||||
|
);
|
||||||
|
},
|
||||||
}))
|
}))
|
||||||
);
|
);
|
||||||
|
2
ui/frontend/dist/index.css
vendored
2
ui/frontend/dist/index.css
vendored
@ -1 +1 @@
|
|||||||
._1qevocv0{position:relative;width:100%;height:100%;pointer-events:auto;display:grid;background-color:#202124;grid-template-columns:400px 1fr;grid-template-rows:100px 1fr 50px;grid-template-areas:"header header header" "create display display" "create footer footer"}._1qevocv1{grid-area:header}._1qevocv2{grid-area:create;overflow:auto}._1qevocv3{grid-area:display;overflow:auto}._1qevocv4{grid-area:footer}@media screen and (max-width: 800px){._1qevocv0{grid-template-columns:1fr;grid-template-rows:100px 1fr 1fr 50px;grid-template-areas:"header" "create" "display" "footer"}}.starting{color:#f0ad4e}.error{color:#d9534f}.success{color:#5cb85c}.header-display{color:#fff;display:flex;align-items:center;justify-content:center}.status-display{margin-left:10px}._11d5x3d0{font-size:9pt;margin-bottom:5px;padding-left:10px;list-style-type:none}._11d5x3d1{padding-bottom:5px}._11d5x3d2{display:block;width:100%;text-align:left;background-color:transparent;color:#fff;border:0 none;cursor:pointer;padding:0;margin-bottom:10px}._11d5x3d2>h4{color:#e7ba71;margin-top:5px!important}.create-layout{padding:10px}.panel-box-toggle-btn{display:block;width:100%;text-align:left;background-color:transparent;color:#fff;border:0 none;cursor:pointer}.selected-tags{margin:10px 0}.selected-tags ul{margin:0;padding:0;display:flex;flex-wrap:wrap}li{list-style:none}.modifier-list{display:flex;flex-wrap:wrap;margin:0;padding:0}.modifierTag{display:inline-block;padding:6px;background-color:#264d8d;color:#fff;border-radius:5px;margin:5px}.modifierTag.selected{background-color:#830b79}.modifierTag p{margin:0}input[type=file]{color:transparent}.cjcdm20{position:relative;width:100%;height:100%;padding:0 10px}._1how28i0{position:relative;width:100%}._1how28i0>*{margin-bottom:10px}._1how28i1>p{font-size:1.5em;font-weight:700;margin-bottom:10px}._1how28i1>textarea{font-size:1.2em;font-weight:700;font-family:Arial;width:100%;resize:vertical;height:100px}._1rn4m8a0{display:flex}._1rn4m8a1{margin-bottom:5px;display:block}._1rn4m8a2{display:none}._1rn4m8a3{background-color:#264d8d;font-size:1.2em;font-weight:700;color:#fff;padding:8px;border-radius:5px}._1rn4m8a4{margin-left:20px}._1rn4m8a5{position:absolute;transform:translate(-50%) translateY(-35%);background:black;color:#fff;border:2pt solid #ccc;padding:0;cursor:pointer;outline:inherit;border-radius:8pt;width:16pt;height:16pt;font-family:Verdana;font-size:8pt}._1hnlbmt0{width:100%;background-color:#264d8d;font-size:1.5em;font-weight:700;color:#fff;padding:8px;border-radius:5px}._1hnlbmt0:disabled{background-color:#264d8d80}._1yvg52n0{position:relative;width:512px;height:512px}._1yvg52n1{width:512px;height:512px;background-color:#000;display:flex;justify-content:center;align-items:center}._1yvg52n2{width:512px;height:512px;object-fit:contain}._1yvg52n3{position:absolute;bottom:10px;left:10px}._1yvg52n4{position:absolute;bottom:10px;right:10px}._688lcr0{padding:10px}._688lcr1{display:flex;flex-direction:row;height:100%;width:100%;overflow:hidden}._688lcr2{width:512px;height:100%}._688lcr3{margin-left:30px;display:flex;flex:auto;flex-wrap:wrap}._688lcr4{margin:0 10px}.footer-display{color:#fff;display:flex;flex-direction:column;align-items:center;justify-content:center}body{margin:0;min-width:320px;min-height:100vh}#root{position:absolute;top:0;left:0;width:100vw;height:100vh;overflow:hidden}*{box-sizing:border-box}p,h3,h4{margin:0}textarea{margin:0;padding:0;border:none}
|
._1qevocv0{position:relative;width:100%;height:100%;pointer-events:auto;display:grid;background-color:#202124;grid-template-columns:400px 1fr;grid-template-rows:100px 1fr 50px;grid-template-areas:"header header header" "create display display" "create footer footer"}._1qevocv1{grid-area:header}._1qevocv2{grid-area:create;position:relative}._1qevocv3{grid-area:display;overflow:auto}._1qevocv4{grid-area:footer}@media screen and (max-width: 800px){._1qevocv0{grid-template-columns:1fr;grid-template-rows:100px 1fr 1fr 50px;grid-template-areas:"header" "create" "display" "footer"}}._1jo75h0{color:#f0ad4e}._1jo75h1{color:#d9534f}._1jo75h2{color:#5cb85c}._1v2cc580{color:#fff;display:flex;align-items:center;justify-content:center}._1v2cc580>h1{font-size:1.5em;font-weight:700;margin-right:10px}._11d5x3d0{font-size:9pt;margin-bottom:5px;padding-left:10px;list-style-type:none}._11d5x3d1{padding-bottom:5px}._11d5x3d2{display:block;width:100%;text-align:left;background-color:transparent;color:#fff;border:0 none;cursor:pointer;padding:0;margin-bottom:10px}._11d5x3d2>h4{color:#e7ba71;margin-top:5px!important}.fma0ug0{position:relative}.fma0ug0>canvas{position:absolute;top:0;left:0;width:100%;height:100%}.fma0ug0>canvas:first-of-type{opacity:.7}.fma0ug0>img{top:0;left:0}._2yyo4x0{position:relative;width:100%;height:100%;padding:10px}._2yyo4x1{display:flex;flex-direction:row;width:100%;flex-wrap:wrap}._2yyo4x2{display:flex;flex-direction:row;justify-content:space-evenly;align-items:center;width:100%}._2yyo4x2:first-of-type{margin:10px 0}.create-layout{padding:10px}.panel-box-toggle-btn{display:block;width:100%;text-align:left;background-color:transparent;color:#fff;border:0 none;cursor:pointer}.selected-tags{margin:10px 0}.selected-tags ul{margin:0;padding:0;display:flex;flex-wrap:wrap}li{list-style:none}.modifier-list{display:flex;flex-wrap:wrap;margin:0;padding:0}.modifierTag{display:inline-block;padding:6px;background-color:#264d8d;color:#fff;border-radius:5px;margin:5px}.modifierTag.selected{background-color:#830b79}.modifierTag p{margin:0}input[type=file]{color:transparent}.cjcdm20{position:relative;width:100%;height:100%;padding:0 10px;overflow-y:auto}.cjcdm21{position:absolute;top:10px;left:400px;z-index:1;background-color:#00000080}._1how28i0{position:relative;width:100%}._1how28i0>*{margin-bottom:10px}._1how28i1>p{font-size:1.5em;font-weight:700;margin-bottom:10px}._1how28i1>textarea{font-size:1.2em;font-weight:700;font-family:Arial;width:100%;resize:vertical;height:100px}._1rn4m8a0{display:flex}._1rn4m8a1{margin-bottom:5px;display:block}._1rn4m8a2{display:none}._1rn4m8a3{background-color:#264d8d;font-size:1.2em;font-weight:700;color:#fff;padding:8px;border-radius:5px}._1rn4m8a4{margin-left:20px}._1rn4m8a5{position:absolute;transform:translate(-50%) translateY(-35%);background:black;color:#fff;border:2pt solid #ccc;padding:0;cursor:pointer;outline:inherit;border-radius:8pt;width:16pt;height:16pt;font-family:Verdana;font-size:8pt}._1hnlbmt0{width:100%;background-color:#264d8d;font-size:1.5em;font-weight:700;color:#fff;padding:8px;border-radius:5px}._1hnlbmt0:disabled{background-color:#264d8d80}._1yvg52n0{position:relative;width:512px;height:512px}._1yvg52n1{width:512px;height:512px;background-color:#000;display:flex;justify-content:center;align-items:center}._1yvg52n2{width:512px;height:512px;object-fit:contain}._1yvg52n3{position:absolute;bottom:10px;left:10px}._1yvg52n4{position:absolute;bottom:10px;right:10px}._688lcr0{padding:10px}._688lcr1{display:flex;flex-direction:row;height:100%;width:100%;overflow:hidden}._688lcr2{width:512px;height:100%}._688lcr3{margin-left:30px;display:flex;flex:auto;flex-wrap:wrap}._688lcr4{margin:0 10px}.footer-display{color:#fff;display:flex;flex-direction:column;align-items:center;justify-content:center}body{margin:0;min-width:320px;min-height:100vh}#root{position:absolute;top:0;left:0;width:100vw;height:100vh;overflow:hidden}*{box-sizing:border-box}p,h3,h4{margin:0}textarea{margin:0;padding:0;border:none}
|
||||||
|
34
ui/frontend/dist/index.js
vendored
34
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