merge prior to backing out PR #1000

This commit is contained in:
Lincoln Stein 2022-10-09 18:24:15 -04:00
commit 3d4276439f
30 changed files with 692 additions and 124 deletions

View File

@ -46,7 +46,7 @@ This is a fork of
the open source text-to-image generator. It provides a streamlined
process with various new features and options to aid the image
generation process. It runs on Windows, Mac and Linux machines, with
GPU cards with as little as 4 GB or RAM. It provides both a polished
GPU cards with as little as 4 GB of RAM. It provides both a polished
Web interface, and an easy-to-use command-line interface.
_Note: This fork is rapidly evolving. Please use the

Binary file not shown.

After

Width:  |  Height:  |  Size: 284 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 252 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 983 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 101 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 546 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 336 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 29 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 148 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 637 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 529 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 989 KiB

View File

@ -75,7 +75,6 @@ git clone https://github.com/invoke-ai/InvokeAI.git
cd InvokeAI
### WAIT FOR THE CHECKPOINT FILE TO DOWNLOAD, THEN PROCEED ###
>>>>>>> Updates INSTALL_MAC.md
# We will leave the big checkpoint wherever you stashed it for long-term storage,
# and make a link to it from the repo's folder. This allows you to use it for

File diff suppressed because one or more lines are too long

483
frontend/dist/assets/index.6cdae835.js vendored Normal file

File diff suppressed because one or more lines are too long

View File

@ -6,8 +6,8 @@
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>InvokeAI - A Stable Diffusion Toolkit</title>
<link rel="shortcut icon" type="icon" href="/assets/favicon.0d253ced.ico" />
<script type="module" crossorigin src="/assets/index.f85957e3.js"></script>
<link rel="stylesheet" href="/assets/index.c04b2fd8.css">
<script type="module" crossorigin src="/assets/index.6cdae835.js"></script>
<link rel="stylesheet" href="/assets/index.4ceb640a.css">
</head>
<body>

View File

@ -25,6 +25,7 @@
"react-dropzone": "^14.2.2",
"react-hotkeys-hook": "^3.4.7",
"react-icons": "^4.4.0",
"react-masonry-css": "^1.0.16",
"react-redux": "^8.0.2",
"redux-persist": "^6.0.0",
"socket.io": "^4.5.2",

View File

@ -71,7 +71,7 @@
.next-prev-button-trigger-area {
width: 7rem;
height: 100%;
width: 100%;
width: 15%;
display: grid;
align-items: center;
pointer-events: auto;

View File

@ -0,0 +1,59 @@
.hoverable-image {
display: grid;
grid-template-areas: 'hoverable-image';
transition: transform 0.2s ease-out;
&:hover {
cursor: pointer;
border-radius: 0.5rem;
z-index: 2;
}
.hoverable-image-image,
.hoverable-image-content,
.hoverable-image-icons {
grid-area: hoverable-image;
}
.hoverable-image-image {
width: 100%;
height: 100%;
object-fit: cover;
max-width: 100%;
max-height: 100%;
}
.hoverable-image-content {
display: grid;
place-items: center;
.hoverable-image-check {
fill: var(--status-good-color);
}
}
.hoverable-image-icons {
grid-area: hoverable-image;
position: absolute;
bottom: -2rem;
display: grid;
grid-template-columns: repeat(2, max-content);
border-radius: 0.4rem;
background-color: var(--background-color-secondary);
padding: 0.2rem;
gap: 0.2rem;
grid-auto-rows: max-content;
place-self: center;
button {
width: 12px;
height: 12px;
border-radius: 0.2rem;
padding: 10px 0;
svg {
width: 12px;
height: 12px;
}
}
}
}

View File

@ -1,12 +1,4 @@
import {
Box,
Flex,
Icon,
IconButton,
Image,
Tooltip,
useColorModeValue,
} from '@chakra-ui/react';
import { Box, Icon, IconButton, Image, Tooltip } from '@chakra-ui/react';
import { RootState, useAppDispatch, useAppSelector } from '../../app/store';
import { setCurrentImage } from './gallerySlice';
import { FaCheck, FaImage, FaSeedling, FaTrashAlt } from 'react-icons/fa';
@ -42,13 +34,6 @@ const HoverableImage = memo((props: HoverableImageProps) => {
(state: RootState) => state.options.activeTab
);
const checkColor = useColorModeValue('green.600', 'green.300');
const bgColor = useColorModeValue('gray.200', 'gray.700');
const bgGradient = useColorModeValue(
'radial-gradient(circle, rgba(255,255,255,0.7) 0%, rgba(255,255,255,0.7) 20%, rgba(0,0,0,0) 100%)',
'radial-gradient(circle, rgba(0,0,0,0.7) 0%, rgba(0,0,0,0.7) 20%, rgba(0,0,0,0) 100%)'
);
const { image, isSelected } = props;
const { url, uuid, metadata } = image;
@ -76,91 +61,80 @@ const HoverableImage = memo((props: HoverableImageProps) => {
const handleClickImage = () => dispatch(setCurrentImage(image));
return (
<Box position={'relative'} key={uuid}>
<Box
position={'relative'}
key={uuid}
className="hoverable-image"
onMouseOver={handleMouseOver}
onMouseOut={handleMouseOut}
>
<Image
width={120}
height={120}
objectFit="cover"
rounded={'md'}
src={url}
loading={'lazy'}
backgroundColor={bgColor}
className="hoverable-image-image"
/>
<Flex
cursor={'pointer'}
position={'absolute'}
top={0}
left={0}
rounded={'md'}
width="100%"
height="100%"
alignItems={'center'}
justifyContent={'center'}
background={isSelected ? bgGradient : undefined}
onClick={handleClickImage}
onMouseOver={handleMouseOver}
onMouseOut={handleMouseOut}
>
<div className="hoverable-image-content" onClick={handleClickImage}>
{isSelected && (
<Icon fill={checkColor} width={'50%'} height={'50%'} as={FaCheck} />
<Icon
width={'50%'}
height={'50%'}
as={FaCheck}
className="hoverable-image-check"
/>
)}
{isHovered && (
<Flex
direction={'column'}
gap={1}
position={'absolute'}
top={1}
right={1}
>
<Tooltip label={'Delete image'}>
<DeleteImageModal image={image}>
<IconButton
colorScheme="red"
aria-label="Delete image"
icon={<FaTrashAlt />}
size="xs"
variant={'imageHoverIconButton'}
fontSize={14}
/>
</DeleteImageModal>
</Tooltip>
{['txt2img', 'img2img'].includes(image?.metadata?.image?.type) && (
<Tooltip label="Use all parameters">
<IconButton
aria-label="Use all parameters"
icon={<IoArrowUndoCircleOutline />}
size="xs"
fontSize={18}
variant={'imageHoverIconButton'}
onClickCapture={handleClickSetAllParameters}
/>
</Tooltip>
)}
{image?.metadata?.image?.seed !== undefined && (
<Tooltip label="Use seed">
<IconButton
aria-label="Use seed"
icon={<FaSeedling />}
size="xs"
fontSize={16}
variant={'imageHoverIconButton'}
onClickCapture={handleClickSetSeed}
/>
</Tooltip>
)}
<Tooltip label="Send To Image To Image">
</div>
{isHovered && (
<div className="hoverable-image-icons">
<Tooltip label={'Delete image'} hasArrow>
<DeleteImageModal image={image}>
<IconButton
aria-label="Send To Image To Image"
icon={<FaImage />}
colorScheme="red"
aria-label="Delete image"
icon={<FaTrashAlt />}
size="xs"
variant={'imageHoverIconButton'}
fontSize={14}
/>
</DeleteImageModal>
</Tooltip>
{['txt2img', 'img2img'].includes(image?.metadata?.image?.type) && (
<Tooltip label="Use All Parameters" hasArrow>
<IconButton
aria-label="Use All Parameters"
icon={<IoArrowUndoCircleOutline />}
size="xs"
fontSize={18}
variant={'imageHoverIconButton'}
onClickCapture={handleClickSetAllParameters}
/>
</Tooltip>
)}
{image?.metadata?.image?.seed !== undefined && (
<Tooltip label="Use Seed" hasArrow>
<IconButton
aria-label="Use Seed"
icon={<FaSeedling />}
size="xs"
fontSize={16}
variant={'imageHoverIconButton'}
onClickCapture={handleSetInitImage}
onClickCapture={handleClickSetSeed}
/>
</Tooltip>
</Flex>
)}
</Flex>
)}
<Tooltip label="Send To Image To Image" hasArrow>
<IconButton
aria-label="Send To Image To Image"
icon={<FaImage />}
size="xs"
fontSize={16}
variant={'imageHoverIconButton'}
onClickCapture={handleSetInitImage}
/>
</Tooltip>
</div>
)}
</Box>
);
}, memoEqualityCheck);

View File

@ -55,12 +55,31 @@
@include HideScrollbar;
}
.image-gallery {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(120px, auto));
gap: 0.6rem;
justify-items: center;
.masonry-grid {
display: -webkit-box; /* Not needed if autoprefixing */
display: -ms-flexbox; /* Not needed if autoprefixing */
display: flex;
margin-left: 0.5rem; /* gutter size offset */
width: auto;
}
.masonry-grid_column {
padding-left: 0.5rem; /* gutter size */
background-clip: padding-box;
}
/* Style your items */
.masonry-grid_column > .hoverable-image {
/* change div to reference your elements you put in <Masonry> */
background: var(--tab-color);
margin-bottom: 0.5rem;
}
// .image-gallery {
// display: grid;
// grid-template-columns: repeat(auto-fill, minmax(80px, auto));
// gap: 0.5rem;
// justify-items: center;
// }
.image-gallery-load-more-btn {
background-color: var(--btn-load-more) !important;

View File

@ -1,25 +1,25 @@
import { Button, IconButton } from '@chakra-ui/button';
import { Resizable } from 're-resizable';
import React from 'react';
import React, { useState } from 'react';
import { useHotkeys } from 'react-hotkeys-hook';
import { MdClear, MdPhotoLibrary } from 'react-icons/md';
import Masonry from 'react-masonry-css';
import { requestImages } from '../../app/socketio/actions';
import { RootState, useAppDispatch, useAppSelector } from '../../app/store';
import IAIIconButton from '../../common/components/IAIIconButton';
import {
selectNextImage,
selectPrevImage,
setShouldShowGallery,
} from './gallerySlice';
import { selectNextImage, selectPrevImage } from './gallerySlice';
import HoverableImage from './HoverableImage';
import { setShouldShowGallery } from '../options/optionsSlice';
export default function ImageGallery() {
const {
images,
currentImageUuid,
areMoreImagesAvailable,
shouldShowGallery,
} = useAppSelector((state: RootState) => state.gallery);
const { images, currentImageUuid, areMoreImagesAvailable } = useAppSelector(
(state: RootState) => state.gallery
);
const shouldShowGallery = useAppSelector(
(state: RootState) => state.options.shouldShowGallery
);
const activeTab = useAppSelector(
(state: RootState) => state.options.activeTab
@ -27,6 +27,12 @@ export default function ImageGallery() {
const dispatch = useAppDispatch();
const [column, setColumn] = useState<number | undefined>();
const handleResize = (event: MouseEvent | TouchEvent | any) => {
setColumn(Math.floor((window.innerWidth - event.x) / 120));
};
const handleShowGalleryToggle = () => {
dispatch(setShouldShowGallery(!shouldShowGallery));
};
@ -83,6 +89,7 @@ export default function ImageGallery() {
minWidth={'300'}
maxWidth={activeTab == 1 ? '300' : '600'}
className="image-gallery-popup"
onResize={handleResize}
>
{/* <div className="image-gallery-popup"></div> */}
<div className="image-gallery-header">
@ -97,7 +104,12 @@ export default function ImageGallery() {
</div>
<div className="image-gallery-container">
{images.length ? (
<div className="image-gallery">
<Masonry
className="masonry-grid"
columnClassName="masonry-grid_column"
breakpointCols={column}
>
{/* <div className="image-gallery"> */}
{images.map((image) => {
const { uuid } = image;
const isSelected = currentImageUuid === uuid;
@ -109,7 +121,8 @@ export default function ImageGallery() {
/>
);
})}
</div>
{/* </div> */}
</Masonry>
) : (
<div className="image-gallery-container-placeholder">
<MdPhotoLibrary />

View File

@ -11,14 +11,12 @@ export interface GalleryState {
areMoreImagesAvailable: boolean;
latest_mtime?: number;
earliest_mtime?: number;
shouldShowGallery: boolean;
}
const initialState: GalleryState = {
currentImageUuid: '',
images: [],
areMoreImagesAvailable: true,
shouldShowGallery: false,
};
export const gallerySlice = createSlice({
@ -140,9 +138,6 @@ export const gallerySlice = createSlice({
state.areMoreImagesAvailable = areMoreImagesAvailable;
}
},
setShouldShowGallery: (state, action: PayloadAction<boolean>) => {
state.shouldShowGallery = action.payload;
},
},
});
@ -155,7 +150,6 @@ export const {
setIntermediateImage,
selectNextImage,
selectPrevImage,
setShouldShowGallery,
} = gallerySlice.actions;
export default gallerySlice.reducer;

View File

@ -35,6 +35,7 @@ export interface OptionsState {
showAdvancedOptions: boolean;
activeTab: number;
shouldShowImageDetails: boolean;
shouldShowGallery: boolean;
}
const initialOptionsState: OptionsState = {
@ -66,6 +67,7 @@ const initialOptionsState: OptionsState = {
showAdvancedOptions: true,
activeTab: 0,
shouldShowImageDetails: false,
shouldShowGallery: false,
};
const initialState: OptionsState = initialOptionsState;
@ -281,6 +283,9 @@ export const optionsSlice = createSlice({
setShouldShowImageDetails: (state, action: PayloadAction<boolean>) => {
state.shouldShowImageDetails = action.payload;
},
setShouldShowGallery: (state, action: PayloadAction<boolean>) => {
state.shouldShowGallery = action.payload;
},
},
});
@ -317,6 +322,7 @@ export const {
setShowAdvancedOptions,
setActiveTab,
setShouldShowImageDetails,
setShouldShowGallery,
} = optionsSlice.actions;
export default optionsSlice.reducer;

View File

@ -21,7 +21,7 @@
.site-header-right-side {
display: grid;
grid-template-columns: repeat(6, max-content);
grid-template-columns: repeat(7, max-content);
align-items: center;
column-gap: 0.5rem;
}

View File

@ -1,7 +1,7 @@
import { IconButton, Link, Tooltip, useColorMode } from '@chakra-ui/react';
import { useHotkeys } from 'react-hotkeys-hook';
import { FaSun, FaMoon, FaGithub } from 'react-icons/fa';
import { FaSun, FaMoon, FaGithub, FaDiscord } from 'react-icons/fa';
import { MdHelp, MdKeyboard, MdSettings } from 'react-icons/md';
import InvokeAILogo from '../../assets/images/logo.png';
@ -70,7 +70,7 @@ const SiteHeader = () => {
icon={
<Link
isExternal
href="http://github.com/lstein/stable-diffusion/issues"
href="http://github.com/invoke-ai/InvokeAI/issues"
>
<MdHelp />
</Link>
@ -85,13 +85,27 @@ const SiteHeader = () => {
fontSize={20}
size={'sm'}
icon={
<Link isExternal href="http://github.com/lstein/stable-diffusion">
<Link isExternal href="http://github.com/invoke-ai/InvokeAI">
<FaGithub />
</Link>
}
/>
</Tooltip>
<Tooltip hasArrow label="Discord" placement={'bottom'}>
<IconButton
aria-label="Link to Discord Server"
variant="link"
fontSize={20}
size={'sm'}
icon={
<Link isExternal href="https://discord.gg/ZmtBAhwWhy">
<FaDiscord />
</Link>
}
/>
</Tooltip>
<Tooltip hasArrow label="Theme" placement={'bottom'}>
<IconButton
aria-label="Toggle Dark Mode"

View File

@ -6,7 +6,7 @@ import { RootState, useAppSelector } from '../../../app/store';
export default function ImageToImage() {
const shouldShowGallery = useAppSelector(
(state: RootState) => state.gallery.shouldShowGallery
(state: RootState) => state.options.shouldShowGallery
);
return (

View File

@ -6,7 +6,7 @@ import { RootState, useAppSelector } from '../../../app/store';
export default function TextToImage() {
const shouldShowGallery = useAppSelector(
(state: RootState) => state.gallery.shouldShowGallery
(state: RootState) => state.options.shouldShowGallery
);
return (

View File

@ -26,6 +26,7 @@
// gallery
@use '../features/gallery/CurrentImageDisplay.scss';
@use '../features/gallery/ImageGallery.scss';
@use '../features/gallery/HoverableImage.scss';
@use '../features/gallery/InvokePopover.scss';
@use '../features/gallery/ImageMetaDataViewer/ImageMetadataViewer.scss';

View File

@ -2850,6 +2850,11 @@ react-is@^18.0.0:
resolved "https://registry.yarnpkg.com/react-is/-/react-is-18.2.0.tgz#199431eeaaa2e09f86427efbb4f1473edb47609b"
integrity sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==
react-masonry-css@^1.0.16:
version "1.0.16"
resolved "https://registry.yarnpkg.com/react-masonry-css/-/react-masonry-css-1.0.16.tgz#72b28b4ae3484e250534700860597553a10f1a2c"
integrity sha512-KSW0hR2VQmltt/qAa3eXOctQDyOu7+ZBevtKgpNDSzT7k5LA/0XntNa9z9HKCdz3QlxmJHglTZ18e4sX4V8zZQ==
react-redux@^8.0.2:
version "8.0.2"
resolved "https://registry.yarnpkg.com/react-redux/-/react-redux-8.0.2.tgz#bc2a304bb21e79c6808e3e47c50fe1caf62f7aad"