mirror of
https://github.com/invoke-ai/InvokeAI
synced 2024-08-30 20:32:17 +00:00
Merge remote-tracking branch 'origin/user-image-uploads' into inpainting-rebase
This commit is contained in:
commit
0b046c95ef
@ -17,7 +17,7 @@ interface Props extends IconButtonProps {
|
||||
const IAIIconButton = (props: Props) => {
|
||||
const {
|
||||
tooltip = '',
|
||||
tooltipPlacement = 'top',
|
||||
tooltipPlacement = 'bottom',
|
||||
styleClass,
|
||||
onClick,
|
||||
cursor,
|
||||
|
@ -24,7 +24,14 @@
|
||||
.image-upload-child {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
row-gap: 3rem;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
text-align: center;
|
||||
|
||||
svg {
|
||||
width: 4rem !important;
|
||||
}
|
||||
h2 {
|
||||
font-size: 1.2rem !important;
|
||||
}
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { Button, Heading, useToast } from '@chakra-ui/react';
|
||||
import { Heading, useToast } from '@chakra-ui/react';
|
||||
import { useCallback } from 'react';
|
||||
import { FileRejection } from 'react-dropzone';
|
||||
import { FaUpload } from 'react-icons/fa';
|
||||
@ -42,7 +42,11 @@ export default function InvokeImageUploader(props: InvokeImageUploaderProps) {
|
||||
<ImageUploader
|
||||
fileAcceptedCallback={fileAcceptedCallback}
|
||||
fileRejectionCallback={fileRejectionCallback}
|
||||
styleClass={`${styleClass} image-upload-child-wrapper`}
|
||||
styleClass={
|
||||
styleClass
|
||||
? `${styleClass} image-upload-child-wrapper`
|
||||
: `image-upload-child-wrapper`
|
||||
}
|
||||
>
|
||||
<div className="image-upload-child">
|
||||
<FaUpload size={'7rem'} />
|
||||
|
@ -140,7 +140,8 @@ const CurrentImageButtons = ({ image }: CurrentImageButtonsProps) => {
|
||||
[image]
|
||||
);
|
||||
|
||||
const handleClickUseSeed = () => image.metadata && dispatch(setSeed(image.metadata.image.seed));
|
||||
const handleClickUseSeed = () =>
|
||||
image.metadata && dispatch(setSeed(image.metadata.image.seed));
|
||||
useHotkeys(
|
||||
's',
|
||||
() => {
|
||||
|
@ -18,6 +18,10 @@
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
column-gap: 0.5rem;
|
||||
|
||||
.chakra-popover__popper {
|
||||
z-index: 11;
|
||||
}
|
||||
}
|
||||
|
||||
.current-image-viewer {
|
||||
|
@ -89,10 +89,12 @@
|
||||
|
||||
.image-gallery-container-placeholder {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
background-color: var(--background-color-secondary);
|
||||
border-radius: 0.5rem;
|
||||
place-items: center;
|
||||
padding: 2rem 0;
|
||||
padding: 2rem;
|
||||
text-align: center;
|
||||
|
||||
p {
|
||||
color: var(--subtext-color-bright);
|
||||
|
@ -21,7 +21,7 @@ import {
|
||||
} from './gallerySlice';
|
||||
import HoverableImage from './HoverableImage';
|
||||
import { setShouldShowGallery } from '../gallery/gallerySlice';
|
||||
import { ButtonGroup, Spacer, useToast } from '@chakra-ui/react';
|
||||
import { ButtonGroup, useToast } from '@chakra-ui/react';
|
||||
import { CSSTransition } from 'react-transition-group';
|
||||
import { Direction } from 're-resizable/lib/resizer';
|
||||
import { imageGallerySelector } from './gallerySliceSelectors';
|
||||
@ -77,6 +77,13 @@ export default function ImageGallery() {
|
||||
setGallerySize((prevSize) => {
|
||||
return { ...prevSize, width: Math.min(Number(prevSize.width), 200) };
|
||||
});
|
||||
} else if (activeTabName === 'img2img' && shouldPinGallery) {
|
||||
setGalleryMaxSize((prevSize) => {
|
||||
return { ...prevSize, width: '490', height: '100%' };
|
||||
});
|
||||
setGallerySize((prevSize) => {
|
||||
return { ...prevSize, width: Math.min(Number(prevSize.width), 490) };
|
||||
});
|
||||
} else {
|
||||
setGalleryMaxSize((prevSize) => {
|
||||
return { ...prevSize, width: '590', height: '100%' };
|
||||
@ -319,12 +326,6 @@ export default function ImageGallery() {
|
||||
}}
|
||||
>
|
||||
<div className="image-gallery-header">
|
||||
{/*{activeTabName !== 'inpainting' ? (
|
||||
<>
|
||||
<h1>Your Invocations</h1>
|
||||
<Spacer />
|
||||
</>
|
||||
) : null}*/}
|
||||
<div>
|
||||
<ButtonGroup
|
||||
size="sm"
|
||||
@ -351,6 +352,7 @@ export default function ImageGallery() {
|
||||
<IAIPopover
|
||||
trigger="hover"
|
||||
hasArrow={activeTabName === 'inpainting' ? false : true}
|
||||
placement={'left'}
|
||||
triggerComponent={
|
||||
<IAIIconButton
|
||||
size={'sm'}
|
||||
|
@ -33,7 +33,7 @@ const ModelListItem = (props: ModelListItemProps) => {
|
||||
};
|
||||
return (
|
||||
<div className="model-list-item">
|
||||
<Tooltip label={description} hasArrow placement="top">
|
||||
<Tooltip label={description} hasArrow placement="bottom">
|
||||
<div className="model-list-item-name">{name}</div>
|
||||
</Tooltip>
|
||||
<Spacer />
|
||||
|
@ -49,7 +49,6 @@
|
||||
img {
|
||||
border-radius: 0.5rem;
|
||||
object-fit: contain;
|
||||
width: auto;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -27,7 +27,7 @@ const ImageToImageDisplay = () => {
|
||||
|
||||
return (
|
||||
<div className="workarea-split-view">
|
||||
<div className="workarea-split-view-left">{imageToImageComponent} </div>
|
||||
<div className="workarea-split-view-left">{imageToImageComponent}</div>
|
||||
{currentImage && (
|
||||
<div className="workarea-split-view-right">
|
||||
<CurrentImageDisplay />
|
||||
|
@ -19,6 +19,16 @@
|
||||
column-gap: 0.5rem;
|
||||
}
|
||||
|
||||
.inpainting-button-dropdown {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
row-gap: 0.5rem;
|
||||
}
|
||||
|
||||
.inpainting-color-picker {
|
||||
margin-left: 1rem !important;
|
||||
}
|
||||
|
||||
.inpainting-slider-numberinput {
|
||||
display: flex;
|
||||
column-gap: 1rem;
|
||||
@ -80,10 +90,4 @@
|
||||
inset: 0 auto auto -75px !important;
|
||||
}
|
||||
}
|
||||
|
||||
.current-image-options {
|
||||
.chakra-popover__popper {
|
||||
z-index: 11;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -2,6 +2,7 @@ import { useToast } from '@chakra-ui/react';
|
||||
import { useHotkeys } from 'react-hotkeys-hook';
|
||||
import {
|
||||
FaEraser,
|
||||
FaMask,
|
||||
FaPaintBrush,
|
||||
FaPalette,
|
||||
FaPlus,
|
||||
@ -36,6 +37,7 @@ import IAIPopover from '../../../common/components/IAIPopover';
|
||||
import IAIColorPicker from '../../../common/components/IAIColorPicker';
|
||||
import { RgbaColor } from 'react-colorful';
|
||||
import { setShowDualDisplay } from '../../options/optionsSlice';
|
||||
import { useState } from 'react';
|
||||
|
||||
const InpaintingControls = () => {
|
||||
const {
|
||||
@ -54,6 +56,9 @@ const InpaintingControls = () => {
|
||||
const dispatch = useAppDispatch();
|
||||
const toast = useToast();
|
||||
|
||||
// Button State Controllers
|
||||
const [maskOptionsOpen, setMaskOptionsOpen] = useState<boolean>(false);
|
||||
|
||||
/**
|
||||
* Hotkeys
|
||||
*/
|
||||
@ -334,39 +339,71 @@ const InpaintingControls = () => {
|
||||
</div>
|
||||
<div className="inpainting-buttons-group">
|
||||
<IAIPopover
|
||||
trigger="hover"
|
||||
trigger="click"
|
||||
onOpen={() => setMaskOptionsOpen(true)}
|
||||
onClose={() => setMaskOptionsOpen(false)}
|
||||
triggerComponent={
|
||||
<IAIIconButton
|
||||
aria-label="Mask Color"
|
||||
tooltip="Mask Color"
|
||||
icon={<FaPalette />}
|
||||
isDisabled={!shouldShowMask}
|
||||
aria-label="Mask Options"
|
||||
tooltip="Mask Options"
|
||||
icon={<FaMask />}
|
||||
cursor={'pointer'}
|
||||
isDisabled={isMaskEmpty}
|
||||
data-selected={maskOptionsOpen}
|
||||
/>
|
||||
}
|
||||
>
|
||||
<IAIColorPicker color={maskColor} onChange={handleChangeMaskColor} />
|
||||
<div className="inpainting-button-dropdown">
|
||||
<IAIIconButton
|
||||
aria-label="Hide/Show Mask (H)"
|
||||
tooltip="Hide/Show Mask (H)"
|
||||
data-selected={!shouldShowMask}
|
||||
icon={
|
||||
shouldShowMask ? <BiShow size={22} /> : <BiHide size={22} />
|
||||
}
|
||||
onClick={handleToggleShouldShowMask}
|
||||
/>
|
||||
<IAIIconButton
|
||||
tooltip="Invert Mask Display (Shift+M)"
|
||||
aria-label="Invert Mask Display (Shift+M)"
|
||||
data-selected={shouldInvertMask}
|
||||
icon={
|
||||
shouldInvertMask ? (
|
||||
<MdInvertColors size={22} />
|
||||
) : (
|
||||
<MdInvertColorsOff size={22} />
|
||||
)
|
||||
}
|
||||
onClick={handleToggleShouldInvertMask}
|
||||
isDisabled={!shouldShowMask}
|
||||
/>
|
||||
<IAIPopover
|
||||
trigger="hover"
|
||||
placement="right"
|
||||
styleClass="inpainting-color-picker"
|
||||
triggerComponent={
|
||||
<IAIIconButton
|
||||
aria-label="Mask Color"
|
||||
tooltip="Mask Color"
|
||||
icon={<FaPalette />}
|
||||
isDisabled={!shouldShowMask}
|
||||
cursor={'pointer'}
|
||||
/>
|
||||
}
|
||||
>
|
||||
<IAIColorPicker
|
||||
color={maskColor}
|
||||
onChange={handleChangeMaskColor}
|
||||
/>
|
||||
</IAIPopover>
|
||||
</div>
|
||||
</IAIPopover>
|
||||
<IAIIconButton
|
||||
aria-label="Hide/Show Mask (H)"
|
||||
tooltip="Hide/Show Mask (H)"
|
||||
data-selected={!shouldShowMask}
|
||||
icon={shouldShowMask ? <BiShow size={22} /> : <BiHide size={22} />}
|
||||
onClick={handleToggleShouldShowMask}
|
||||
/>
|
||||
<IAIIconButton
|
||||
tooltip="Invert Mask Display (Shift+M)"
|
||||
aria-label="Invert Mask Display (Shift+M)"
|
||||
data-selected={shouldInvertMask}
|
||||
icon={
|
||||
shouldInvertMask ? (
|
||||
<MdInvertColors size={22} />
|
||||
) : (
|
||||
<MdInvertColorsOff size={22} />
|
||||
)
|
||||
}
|
||||
onClick={handleToggleShouldInvertMask}
|
||||
isDisabled={!shouldShowMask}
|
||||
aria-label="Clear Mask (Shift+C)"
|
||||
tooltip="Clear Mask (Shift+C)"
|
||||
icon={<FaPlus size={18} style={{ transform: 'rotate(45deg)' }} />}
|
||||
onClick={handleClearMask}
|
||||
isDisabled={isMaskEmpty || !shouldShowMask}
|
||||
/>
|
||||
</div>
|
||||
<div className="inpainting-buttons-group">
|
||||
@ -384,28 +421,23 @@ const InpaintingControls = () => {
|
||||
onClick={handleRedo}
|
||||
isDisabled={!canRedo || !shouldShowMask}
|
||||
/>
|
||||
<IAIIconButton
|
||||
aria-label="Clear Mask Canvas (Shift + C)"
|
||||
tooltip="Clear Mask Canvas (Shift + C)"
|
||||
icon={<FaPlus size={18} style={{ transform: 'rotate(45deg)' }} />}
|
||||
onClick={handleClearMask}
|
||||
isDisabled={isMaskEmpty || !shouldShowMask}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className="inpainting-buttons-group">
|
||||
<IAIIconButton
|
||||
aria-label="Clear Image"
|
||||
tooltip="Clear Image"
|
||||
icon={<FaTrash size={18} />}
|
||||
icon={<FaTrash size={16} />}
|
||||
onClick={handleClearImage}
|
||||
// isDisabled={}
|
||||
/>
|
||||
<IAIIconButton
|
||||
aria-label="Split Layout (Shift+J)"
|
||||
tooltip="Split Layout (Shift+J)"
|
||||
icon={<VscSplitHorizontal />}
|
||||
data-selected={showDualDisplay}
|
||||
onClick={handleDualDisplay}
|
||||
/>
|
||||
</div>
|
||||
<IAIIconButton
|
||||
aria-label="Split Layout (Shift+J)"
|
||||
tooltip="Split Layout (Shift+J)"
|
||||
icon={<VscSplitHorizontal />}
|
||||
data-selected={showDualDisplay}
|
||||
onClick={handleDualDisplay}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
@ -4,7 +4,10 @@ import InvokeWorkarea from '../InvokeWorkarea';
|
||||
|
||||
export default function InpaintingWorkarea() {
|
||||
return (
|
||||
<InvokeWorkarea optionsPanel={<InpaintingPanel />}>
|
||||
<InvokeWorkarea
|
||||
optionsPanel={<InpaintingPanel />}
|
||||
styleClass="inpainting-workarea-overrides"
|
||||
>
|
||||
<InpaintingDisplay />
|
||||
</InvokeWorkarea>
|
||||
);
|
||||
|
@ -42,13 +42,5 @@
|
||||
border-radius: 0.5rem;
|
||||
padding: 1rem;
|
||||
}
|
||||
|
||||
.workarea-split-view-left {
|
||||
padding-right: 0.5rem;
|
||||
}
|
||||
|
||||
.workarea-split-view-right {
|
||||
padding-left: 0.5rem;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -6,16 +6,21 @@ import ShowHideGalleryButton from '../gallery/ShowHideGalleryButton';
|
||||
type InvokeWorkareaProps = {
|
||||
optionsPanel: ReactNode;
|
||||
children: ReactNode;
|
||||
styleClass?: string;
|
||||
};
|
||||
|
||||
const InvokeWorkarea = (props: InvokeWorkareaProps) => {
|
||||
const { optionsPanel, children } = props;
|
||||
const { optionsPanel, children, styleClass } = props;
|
||||
|
||||
const { shouldShowGallery, shouldHoldGalleryOpen, shouldPinGallery } =
|
||||
useAppSelector((state: RootState) => state.gallery);
|
||||
|
||||
return (
|
||||
<div className="workarea-wrapper">
|
||||
<div
|
||||
className={
|
||||
styleClass ? `workarea-wrapper ${styleClass}` : `workarea-wrapper`
|
||||
}
|
||||
>
|
||||
<div className="workarea-main">
|
||||
<div className="workarea-options-panel">{optionsPanel}</div>
|
||||
{children}
|
||||
|
Loading…
Reference in New Issue
Block a user