[WebUI] Masonry Layout for Gallery

This commit is contained in:
blessedcoolant 2022-10-09 14:08:46 +13:00 committed by Lincoln Stein
parent 3046dabde2
commit 3170c83d8d
13 changed files with 553 additions and 513 deletions

483
frontend/dist/assets/index.27eefde8.js vendored Normal file

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

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.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>

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

@ -17,6 +17,8 @@
.hoverable-image-image {
width: 100%;
height: 100%;
object-fit: cover;
max-width: 100%;
max-height: 100%;
}

View File

@ -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;

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;
@ -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;

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

@ -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"