mirror of
https://github.com/invoke-ai/InvokeAI
synced 2024-08-30 20:32:17 +00:00
[WebUI] Masonry Layout for Gallery
This commit is contained in:
parent
3046dabde2
commit
3170c83d8d
483
frontend/dist/assets/index.27eefde8.js
vendored
Normal file
483
frontend/dist/assets/index.27eefde8.js
vendored
Normal file
File diff suppressed because one or more lines are too long
483
frontend/dist/assets/index.a564edff.js
vendored
483
frontend/dist/assets/index.a564edff.js
vendored
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
4
frontend/dist/index.html
vendored
4
frontend/dist/index.html
vendored
@ -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.a564edff.js"></script>
|
||||
<link rel="stylesheet" href="/assets/index.787a8262.css">
|
||||
<script type="module" crossorigin src="/assets/index.27eefde8.js"></script>
|
||||
<link rel="stylesheet" href="/assets/index.c04b2fd8.css">
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
@ -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",
|
||||
|
@ -17,6 +17,8 @@
|
||||
|
||||
.hoverable-image-image {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
object-fit: cover;
|
||||
max-width: 100%;
|
||||
max-height: 100%;
|
||||
}
|
||||
|
@ -55,12 +55,31 @@
|
||||
@include HideScrollbar;
|
||||
}
|
||||
|
||||
.image-gallery {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fill, minmax(80px, auto));
|
||||
gap: 0.5rem;
|
||||
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;
|
||||
|
@ -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 />
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
@ -279,6 +281,9 @@ export const optionsSlice = createSlice({
|
||||
setShouldShowImageDetails: (state, action: PayloadAction<boolean>) => {
|
||||
state.shouldShowImageDetails = action.payload;
|
||||
},
|
||||
setShouldShowGallery: (state, action: PayloadAction<boolean>) => {
|
||||
state.shouldShowGallery = action.payload;
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
@ -315,6 +320,7 @@ export const {
|
||||
setShowAdvancedOptions,
|
||||
setActiveTab,
|
||||
setShouldShowImageDetails,
|
||||
setShouldShowGallery,
|
||||
} = optionsSlice.actions;
|
||||
|
||||
export default optionsSlice.reducer;
|
||||
|
@ -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 (
|
||||
|
@ -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 (
|
||||
|
@ -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"
|
||||
|
Loading…
Reference in New Issue
Block a user