aboutsummaryrefslogtreecommitdiff
path: root/src/client/views/nodes/generativeFill/GenerativeFill.tsx
diff options
context:
space:
mode:
Diffstat (limited to 'src/client/views/nodes/generativeFill/GenerativeFill.tsx')
-rw-r--r--src/client/views/nodes/generativeFill/GenerativeFill.tsx103
1 files changed, 51 insertions, 52 deletions
diff --git a/src/client/views/nodes/generativeFill/GenerativeFill.tsx b/src/client/views/nodes/generativeFill/GenerativeFill.tsx
index 2b3cfb920..f8f9fe077 100644
--- a/src/client/views/nodes/generativeFill/GenerativeFill.tsx
+++ b/src/client/views/nodes/generativeFill/GenerativeFill.tsx
@@ -3,21 +3,19 @@ import React = require('react');
import { useEffect, useRef, useState } from 'react';
import { APISuccess, ImageUtility } from './generativeFillUtils/ImageHandler';
import { BrushHandler } from './generativeFillUtils/BrushHandler';
-import { IconButton, TextField } from '@mui/material';
+import { Box, IconButton, Slider, TextField } from '@mui/material';
import { CursorData, Point } from './generativeFillUtils/generativeFillInterfaces';
import { activeColor, canvasSize, eraserColor, freeformRenderSize, newCollectionSize, offsetDistanceY, offsetX } from './generativeFillUtils/generativeFillConstants';
import { PointerHandler } from './generativeFillUtils/PointerHandler';
-import { BsBrush, BsEraser, BsX } from 'react-icons/bs';
-import { AiOutlineUpload } from 'react-icons/ai';
+import { BsEraser, BsX } from 'react-icons/bs';
import { CiUndo, CiRedo } from 'react-icons/ci';
import Buttons from './GenerativeFillButtons';
-import { EditableText } from 'browndash-components';
import { MainView } from '../../MainView';
import { Doc } from '../../../../fields/Doc';
import { Networking } from '../../../Network';
import { Utils } from '../../../../Utils';
import { DocUtils, Docs } from '../../../documents/Documents';
-import { DocCast, NumCast } from '../../../../fields/Types';
+import { Cast, DocCast, NumCast } from '../../../../fields/Types';
import { CollectionDockingView } from '../../collections/CollectionDockingView';
import { OpenWhere, OpenWhereMod } from '../DocumentView';
import { Oval } from 'react-loader-spinner';
@@ -25,12 +23,11 @@ import { Oval } from 'react-loader-spinner';
/**
* For images not 1024x1024 fill in the rest in solid black, or a
* reflected version of the image.
+ *
+ * add a branch from image directly checkbox
*/
/**
- * TODO: Look into img onload, sometimes the canvas doesn't update properly
- *
- * Ref:
*
*
* CollectionDockingView.AddSplit(Doc.MakeCopy(DocCast(Doc.UserDoc().emptyPane)), OpenWhereMod.right);
@@ -88,12 +85,13 @@ const GenerativeFill = ({ imageEditorOpen, imageEditorSource, imageRootDoc, addD
const freeformPosition = useRef<number[]>([0, 0]);
// which urls were already saved to canvas
- const savedSrcs = useRef<string[]>([]);
+ const savedSrcs = useRef<Set<string>>(new Set());
// references to keep track of tree structure
const newCollectionRef = useRef<Doc | null>(null);
const parentDoc = useRef<Doc | null>(null);
const childrenDocs = useRef<Doc[]>([]);
+ const addToExistingCollection = useRef<boolean>(false);
// Undo and Redo
const handleUndo = () => {
@@ -250,18 +248,6 @@ const GenerativeFill = ({ imageEditorOpen, imageEditorSource, imageRootDoc, addD
}));
};
- // File upload
- const uploadImg = (e: React.ChangeEvent<HTMLInputElement>) => {
- if (e.target.files) {
- const file = e.target.files[0];
- const image = new Image();
- const imgUrl = URL.createObjectURL(file);
- image.src = imgUrl;
- ImageUtility.drawImgToCanvas(image, canvasRef);
- currImg.current = image;
- }
- };
-
// Get AI Edit
const getEdit = async () => {
const img = currImg.current;
@@ -280,6 +266,8 @@ const GenerativeFill = ({ imageEditorOpen, imageEditorSource, imageRootDoc, addD
// create first image
if (!newCollectionRef.current) {
+ if (addToExistingCollection.current) {
+ }
if (!(originalImg.current && imageRootDoc)) return;
console.log('creating first image');
// create new collection and add it to the view
@@ -292,7 +280,7 @@ const GenerativeFill = ({ imageEditorOpen, imageEditorSource, imageRootDoc, addD
});
DocUtils.MakeLink(imageRootDoc, newCollectionRef.current, { link_relationship: 'Image Edit Version History', link_displayLine: false });
// add the doc to the main freeform
- addDoc?.(newCollectionRef.current);
+ // addDoc?.(newCollectionRef.current);
await createNewImgDoc(originalImg.current, true);
} else {
parentDoc.current = childrenDocs.current[childrenDocs.current.length - 1];
@@ -321,7 +309,6 @@ const GenerativeFill = ({ imageEditorOpen, imageEditorSource, imageRootDoc, addD
if (!parentDoc.current) return;
const startY = NumCast(parentDoc.current.y);
const len = childrenDocs.current.length;
- console.log(len);
let initialYPositions: number[] = [];
for (let i = 0; i < len; i++) {
initialYPositions.push(startY + i * offsetDistanceY);
@@ -398,9 +385,10 @@ const GenerativeFill = ({ imageEditorOpen, imageEditorSource, imageRootDoc, addD
};
const handleViewClose = () => {
- // if (newCollectionRef.current) {
- // CollectionDockingView.AddSplit(newCollectionRef.current, OpenWhereMod.right);
- // }
+ if (newCollectionRef.current) {
+ newCollectionRef.current.fitContentOnce = true;
+ CollectionDockingView.AddSplit(newCollectionRef.current, OpenWhereMod.right);
+ }
MainView.Instance.setImageEditorOpen(false);
MainView.Instance.setImageEditorSource('');
setEdits([]);
@@ -409,12 +397,17 @@ const GenerativeFill = ({ imageEditorOpen, imageEditorSource, imageRootDoc, addD
return (
<div className="generativeFillContainer" style={{ display: imageEditorOpen ? 'flex' : 'none' }}>
<div className="generativeFillControls">
- <h1>Generative Fill</h1>
+ <h1>AI Image Editor</h1>
<div style={{ display: 'flex', alignItems: 'center', gap: '1.5rem' }}>
<Buttons canvasRef={canvasRef} currImg={currImg} getEdit={getEdit} loading={loading} onSave={onSave} onReset={handleReset} />
<IconButton onClick={handleViewClose}>
<BsX color={activeColor} />
</IconButton>
+ {saveLoading && (
+ <span style={{ height: '100%', display: 'flex', alignItems: 'center', gap: '8px' }}>
+ Saving image... <Oval height={20} width={20} color="#000000" visible={true} ariaLabel="oval-loading" secondaryColor="#ffffff89" strokeWidth={3} strokeWidthSecondary={3} />
+ </span>
+ )}
</div>
</div>
{/* Main canvas for editing */}
@@ -439,20 +432,11 @@ const GenerativeFill = ({ imageEditorOpen, imageEditorSource, imageRootDoc, addD
</div>
{/* Icons */}
<div className="iconContainer">
- <input ref={fileRef} type="file" accept="image/*" onChange={uploadImg} style={{ display: 'none' }} />
- <IconButton
- onClick={() => {
- if (fileRef.current) {
- fileRef.current.click();
- }
- }}>
- <AiOutlineUpload />
- </IconButton>
<IconButton
onClick={() => {
setBrushStyle(BrushStyle.ADD);
}}>
- <BsBrush color={brushStyle === BrushStyle.ADD ? activeColor : 'inherit'} />
+ <BsEraser color={brushStyle === BrushStyle.ADD ? activeColor : 'inherit'} />
</IconButton>
{/* Undo and Redo */}
<IconButton
@@ -475,6 +459,28 @@ const GenerativeFill = ({ imageEditorOpen, imageEditorSource, imageRootDoc, addD
}}>
<CiRedo />
</IconButton>
+ <Box
+ sx={{
+ height: 225,
+ width: '100%',
+ display: 'flex',
+ justifyContent: 'center',
+ }}>
+ <Slider
+ sx={{
+ '& input[type="range"]': {
+ WebkitAppearance: 'slider-vertical',
+ },
+ }}
+ orientation="vertical"
+ min={10}
+ max={500}
+ defaultValue={150}
+ onChange={(e, val) => {
+ setCursorData(prev => ({ ...prev, width: val as number }));
+ }}
+ />
+ </Box>
</div>
{/* Edits thumbnails*/}
<div className="editsBox">
@@ -484,12 +490,14 @@ const GenerativeFill = ({ imageEditorOpen, imageEditorSource, imageRootDoc, addD
width={100}
height={100}
src={edit}
- onClick={() => {
+ onClick={async () => {
+ // if (savedSrcs.current.has(edit)) return;
const img = new Image();
img.src = edit;
ImageUtility.drawImgToCanvas(img, canvasRef);
currImg.current = img;
- onSave();
+ savedSrcs.current.add(edit);
+ await onSave();
}}
/>
))}
@@ -521,14 +529,6 @@ const GenerativeFill = ({ imageEditorOpen, imageEditorSource, imageRootDoc, addD
currImg.current = img;
}}
/>
- <div
- style={{
- position: 'absolute',
- top: 10,
- right: 10,
- }}>
- {saveLoading && <Oval height={20} width={20} color="#ffffff" visible={true} ariaLabel="oval-loading" secondaryColor="#ffffff89" strokeWidth={3} strokeWidthSecondary={3} />}
- </div>
</div>
)}
</div>
@@ -541,15 +541,14 @@ const GenerativeFill = ({ imageEditorOpen, imageEditorSource, imageRootDoc, addD
type="text"
label="Prompt"
placeholder="Prompt..."
- InputLabelProps={{ style: { fontSize: '1.5rem' } }}
- inputProps={{ style: { fontSize: '1.5rem' } }}
+ InputLabelProps={{ style: { fontSize: '16px' } }}
+ inputProps={{ style: { fontSize: '16px' } }}
sx={{
backgroundColor: '#ffffff',
position: 'absolute',
- bottom: '1rem',
+ bottom: '16px',
transform: 'translateX(calc(50vw - 50%))',
- width: 'calc(100vw - 4rem)',
- scale: 1.2,
+ width: 'calc(100vw - 64px)',
}}
/>
</div>