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 the open source text-to-image generator. It provides a streamlined
process with various new features and options to aid the image process with various new features and options to aid the image
generation process. It runs on Windows, Mac and Linux machines, with 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. Web interface, and an easy-to-use command-line interface.
_Note: This fork is rapidly evolving. Please use the _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 cd InvokeAI
### WAIT FOR THE CHECKPOINT FILE TO DOWNLOAD, THEN PROCEED ### ### 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, # 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 # 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" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>InvokeAI - A Stable Diffusion Toolkit</title> <title>InvokeAI - A Stable Diffusion Toolkit</title>
<link rel="shortcut icon" type="icon" href="/assets/favicon.0d253ced.ico" /> <link rel="shortcut icon" type="icon" href="/assets/favicon.0d253ced.ico" />
<script type="module" crossorigin src="/assets/index.f85957e3.js"></script> <script type="module" crossorigin src="/assets/index.6cdae835.js"></script>
<link rel="stylesheet" href="/assets/index.c04b2fd8.css"> <link rel="stylesheet" href="/assets/index.4ceb640a.css">
</head> </head>
<body> <body>

View File

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

View File

@ -71,7 +71,7 @@
.next-prev-button-trigger-area { .next-prev-button-trigger-area {
width: 7rem; width: 7rem;
height: 100%; height: 100%;
width: 100%; width: 15%;
display: grid; display: grid;
align-items: center; align-items: center;
pointer-events: auto; 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 { import { Box, Icon, IconButton, Image, Tooltip } from '@chakra-ui/react';
Box,
Flex,
Icon,
IconButton,
Image,
Tooltip,
useColorModeValue,
} from '@chakra-ui/react';
import { RootState, useAppDispatch, useAppSelector } from '../../app/store'; import { RootState, useAppDispatch, useAppSelector } from '../../app/store';
import { setCurrentImage } from './gallerySlice'; import { setCurrentImage } from './gallerySlice';
import { FaCheck, FaImage, FaSeedling, FaTrashAlt } from 'react-icons/fa'; import { FaCheck, FaImage, FaSeedling, FaTrashAlt } from 'react-icons/fa';
@ -42,13 +34,6 @@ const HoverableImage = memo((props: HoverableImageProps) => {
(state: RootState) => state.options.activeTab (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 { image, isSelected } = props;
const { url, uuid, metadata } = image; const { url, uuid, metadata } = image;
@ -76,43 +61,33 @@ const HoverableImage = memo((props: HoverableImageProps) => {
const handleClickImage = () => dispatch(setCurrentImage(image)); const handleClickImage = () => dispatch(setCurrentImage(image));
return ( return (
<Box position={'relative'} key={uuid}> <Box
position={'relative'}
key={uuid}
className="hoverable-image"
onMouseOver={handleMouseOver}
onMouseOut={handleMouseOut}
>
<Image <Image
width={120}
height={120}
objectFit="cover" objectFit="cover"
rounded={'md'} rounded={'md'}
src={url} src={url}
loading={'lazy'} loading={'lazy'}
backgroundColor={bgColor} className="hoverable-image-image"
/> />
<Flex <div className="hoverable-image-content" onClick={handleClickImage}>
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}
>
{isSelected && ( {isSelected && (
<Icon fill={checkColor} width={'50%'} height={'50%'} as={FaCheck} /> <Icon
width={'50%'}
height={'50%'}
as={FaCheck}
className="hoverable-image-check"
/>
)} )}
</div>
{isHovered && ( {isHovered && (
<Flex <div className="hoverable-image-icons">
direction={'column'} <Tooltip label={'Delete image'} hasArrow>
gap={1}
position={'absolute'}
top={1}
right={1}
>
<Tooltip label={'Delete image'}>
<DeleteImageModal image={image}> <DeleteImageModal image={image}>
<IconButton <IconButton
colorScheme="red" colorScheme="red"
@ -125,9 +100,9 @@ const HoverableImage = memo((props: HoverableImageProps) => {
</DeleteImageModal> </DeleteImageModal>
</Tooltip> </Tooltip>
{['txt2img', 'img2img'].includes(image?.metadata?.image?.type) && ( {['txt2img', 'img2img'].includes(image?.metadata?.image?.type) && (
<Tooltip label="Use all parameters"> <Tooltip label="Use All Parameters" hasArrow>
<IconButton <IconButton
aria-label="Use all parameters" aria-label="Use All Parameters"
icon={<IoArrowUndoCircleOutline />} icon={<IoArrowUndoCircleOutline />}
size="xs" size="xs"
fontSize={18} fontSize={18}
@ -137,9 +112,9 @@ const HoverableImage = memo((props: HoverableImageProps) => {
</Tooltip> </Tooltip>
)} )}
{image?.metadata?.image?.seed !== undefined && ( {image?.metadata?.image?.seed !== undefined && (
<Tooltip label="Use seed"> <Tooltip label="Use Seed" hasArrow>
<IconButton <IconButton
aria-label="Use seed" aria-label="Use Seed"
icon={<FaSeedling />} icon={<FaSeedling />}
size="xs" size="xs"
fontSize={16} fontSize={16}
@ -148,7 +123,7 @@ const HoverableImage = memo((props: HoverableImageProps) => {
/> />
</Tooltip> </Tooltip>
)} )}
<Tooltip label="Send To Image To Image"> <Tooltip label="Send To Image To Image" hasArrow>
<IconButton <IconButton
aria-label="Send To Image To Image" aria-label="Send To Image To Image"
icon={<FaImage />} icon={<FaImage />}
@ -158,9 +133,8 @@ const HoverableImage = memo((props: HoverableImageProps) => {
onClickCapture={handleSetInitImage} onClickCapture={handleSetInitImage}
/> />
</Tooltip> </Tooltip>
</Flex> </div>
)} )}
</Flex>
</Box> </Box>
); );
}, memoEqualityCheck); }, memoEqualityCheck);

View File

@ -55,12 +55,31 @@
@include HideScrollbar; @include HideScrollbar;
} }
.image-gallery { .masonry-grid {
display: grid; display: -webkit-box; /* Not needed if autoprefixing */
grid-template-columns: repeat(auto-fill, minmax(120px, auto)); display: -ms-flexbox; /* Not needed if autoprefixing */
gap: 0.6rem; display: flex;
justify-items: center; 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 { .image-gallery-load-more-btn {
background-color: var(--btn-load-more) !important; background-color: var(--btn-load-more) !important;

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -26,6 +26,7 @@
// gallery // gallery
@use '../features/gallery/CurrentImageDisplay.scss'; @use '../features/gallery/CurrentImageDisplay.scss';
@use '../features/gallery/ImageGallery.scss'; @use '../features/gallery/ImageGallery.scss';
@use '../features/gallery/HoverableImage.scss';
@use '../features/gallery/InvokePopover.scss'; @use '../features/gallery/InvokePopover.scss';
@use '../features/gallery/ImageMetaDataViewer/ImageMetadataViewer.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" resolved "https://registry.yarnpkg.com/react-is/-/react-is-18.2.0.tgz#199431eeaaa2e09f86427efbb4f1473edb47609b"
integrity sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w== 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: react-redux@^8.0.2:
version "8.0.2" version "8.0.2"
resolved "https://registry.yarnpkg.com/react-redux/-/react-redux-8.0.2.tgz#bc2a304bb21e79c6808e3e47c50fe1caf62f7aad" resolved "https://registry.yarnpkg.com/react-redux/-/react-redux-8.0.2.tgz#bc2a304bb21e79c6808e3e47c50fe1caf62f7aad"