mirror of
https://github.com/invoke-ai/InvokeAI.git
synced 2026-02-06 14:25:02 -05:00
Adds pagination & refresh on re-connect to gallery
This commit is contained in:
@@ -1,5 +1,6 @@
|
||||
import { Center, Flex, Text } from '@chakra-ui/react';
|
||||
import { RootState } from '../../app/store';
|
||||
import { Button, Center, Flex, Text } from '@chakra-ui/react';
|
||||
import { requestImages } from '../../app/socketio/actions';
|
||||
import { RootState, useAppDispatch } from '../../app/store';
|
||||
import { useAppSelector } from '../../app/store';
|
||||
import HoverableImage from './HoverableImage';
|
||||
|
||||
@@ -10,7 +11,7 @@ const ImageGallery = () => {
|
||||
const { images, currentImageUuid } = useAppSelector(
|
||||
(state: RootState) => state.gallery
|
||||
);
|
||||
|
||||
const dispatch = useAppDispatch();
|
||||
/**
|
||||
* I don't like that this needs to rerender whenever the current image is changed.
|
||||
* What if we have a large number of images? I suppose pagination (planned) will
|
||||
@@ -19,15 +20,22 @@ const ImageGallery = () => {
|
||||
* TODO: Refactor if performance complaints, or after migrating to new API which supports pagination.
|
||||
*/
|
||||
|
||||
const handleClickLoadMore = () => {
|
||||
dispatch(requestImages());
|
||||
};
|
||||
|
||||
return images.length ? (
|
||||
<Flex gap={2} wrap="wrap" pb={2}>
|
||||
{[...images].reverse().map((image) => {
|
||||
const { uuid } = image;
|
||||
const isSelected = currentImageUuid === uuid;
|
||||
return (
|
||||
<HoverableImage key={uuid} image={image} isSelected={isSelected} />
|
||||
);
|
||||
})}
|
||||
<Flex direction={'column'} gap={2} pb={2}>
|
||||
<Flex gap={2} wrap="wrap">
|
||||
{images.map((image) => {
|
||||
const { uuid } = image;
|
||||
const isSelected = currentImageUuid === uuid;
|
||||
return (
|
||||
<HoverableImage key={uuid} image={image} isSelected={isSelected} />
|
||||
);
|
||||
})}
|
||||
</Flex>
|
||||
<Button onClick={handleClickLoadMore}>Load more...</Button>
|
||||
</Flex>
|
||||
) : (
|
||||
<Center height={'100%'} position={'relative'}>
|
||||
|
||||
@@ -8,11 +8,15 @@ export interface GalleryState {
|
||||
currentImageUuid: string;
|
||||
images: Array<InvokeAI.Image>;
|
||||
intermediateImage?: InvokeAI.Image;
|
||||
nextPage: number;
|
||||
offset: number;
|
||||
}
|
||||
|
||||
const initialState: GalleryState = {
|
||||
currentImageUuid: '',
|
||||
images: [],
|
||||
nextPage: 1,
|
||||
offset: 0,
|
||||
};
|
||||
|
||||
export const gallerySlice = createSlice({
|
||||
@@ -50,7 +54,7 @@ export const gallerySlice = createSlice({
|
||||
* Clamp the new index to ensure it is valid..
|
||||
*/
|
||||
const newCurrentImageIndex = clamp(
|
||||
imageToDeleteIndex - 1,
|
||||
imageToDeleteIndex,
|
||||
0,
|
||||
newImages.length - 1
|
||||
);
|
||||
@@ -67,10 +71,11 @@ export const gallerySlice = createSlice({
|
||||
state.images = newImages;
|
||||
},
|
||||
addImage: (state, action: PayloadAction<InvokeAI.Image>) => {
|
||||
state.images.push(action.payload);
|
||||
state.images.unshift(action.payload);
|
||||
state.currentImageUuid = action.payload.uuid;
|
||||
state.intermediateImage = undefined;
|
||||
state.currentImage = action.payload;
|
||||
state.offset += 1
|
||||
},
|
||||
setIntermediateImage: (state, action: PayloadAction<InvokeAI.Image>) => {
|
||||
state.intermediateImage = action.payload;
|
||||
@@ -78,13 +83,24 @@ export const gallerySlice = createSlice({
|
||||
clearIntermediateImage: (state) => {
|
||||
state.intermediateImage = undefined;
|
||||
},
|
||||
setGalleryImages: (state, action: PayloadAction<Array<InvokeAI.Image>>) => {
|
||||
const newImages = action.payload;
|
||||
if (newImages.length) {
|
||||
const newCurrentImage = newImages[newImages.length - 1];
|
||||
state.images = newImages;
|
||||
addGalleryImages: (
|
||||
state,
|
||||
action: PayloadAction<{
|
||||
images: Array<InvokeAI.Image>;
|
||||
nextPage: number;
|
||||
offset: number;
|
||||
}>
|
||||
) => {
|
||||
const { images, nextPage, offset } = action.payload;
|
||||
if (images.length) {
|
||||
const newCurrentImage = images[0];
|
||||
state.images = state.images
|
||||
.concat(images)
|
||||
.sort((a, b) => b.mtime - a.mtime);
|
||||
state.currentImage = newCurrentImage;
|
||||
state.currentImageUuid = newCurrentImage.uuid;
|
||||
state.nextPage = nextPage;
|
||||
state.offset = offset;
|
||||
}
|
||||
},
|
||||
},
|
||||
@@ -95,7 +111,7 @@ export const {
|
||||
clearIntermediateImage,
|
||||
removeImage,
|
||||
setCurrentImage,
|
||||
setGalleryImages,
|
||||
addGalleryImages,
|
||||
setIntermediateImage,
|
||||
} = gallerySlice.actions;
|
||||
|
||||
|
||||
@@ -32,8 +32,16 @@ import { cloneElement, ReactElement } from 'react';
|
||||
const systemSelector = createSelector(
|
||||
(state: RootState) => state.system,
|
||||
(system: SystemState) => {
|
||||
const { shouldDisplayInProgress, shouldConfirmOnDelete, shouldDisplayGuides } = system;
|
||||
return { shouldDisplayInProgress, shouldConfirmOnDelete, shouldDisplayGuides };
|
||||
const {
|
||||
shouldDisplayInProgress,
|
||||
shouldConfirmOnDelete,
|
||||
shouldDisplayGuides,
|
||||
} = system;
|
||||
return {
|
||||
shouldDisplayInProgress,
|
||||
shouldConfirmOnDelete,
|
||||
shouldDisplayGuides,
|
||||
};
|
||||
},
|
||||
{
|
||||
memoizeOptions: { resultEqualityCheck: isEqual },
|
||||
@@ -64,8 +72,11 @@ const SettingsModal = ({ children }: SettingsModalProps) => {
|
||||
onClose: onRefreshModalClose,
|
||||
} = useDisclosure();
|
||||
|
||||
const { shouldDisplayInProgress, shouldConfirmOnDelete, shouldDisplayGuides } =
|
||||
useAppSelector(systemSelector);
|
||||
const {
|
||||
shouldDisplayInProgress,
|
||||
shouldConfirmOnDelete,
|
||||
shouldDisplayGuides,
|
||||
} = useAppSelector(systemSelector);
|
||||
|
||||
const dispatch = useAppDispatch();
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { createSlice } from '@reduxjs/toolkit';
|
||||
import type { PayloadAction } from '@reduxjs/toolkit';
|
||||
import { ExpandedIndex } from '@chakra-ui/react';
|
||||
import * as InvokeAI from '../../app/invokeai'
|
||||
import * as InvokeAI from '../../app/invokeai';
|
||||
|
||||
export type LogLevel = 'info' | 'warning' | 'error';
|
||||
|
||||
@@ -15,7 +15,9 @@ export interface Log {
|
||||
[index: number]: LogEntry;
|
||||
}
|
||||
|
||||
export interface SystemState extends InvokeAI.SystemStatus, InvokeAI.SystemConfig {
|
||||
export interface SystemState
|
||||
extends InvokeAI.SystemStatus,
|
||||
InvokeAI.SystemConfig {
|
||||
shouldDisplayInProgress: boolean;
|
||||
log: Array<LogEntry>;
|
||||
shouldShowLogViewer: boolean;
|
||||
@@ -31,7 +33,6 @@ export interface SystemState extends InvokeAI.SystemStatus, InvokeAI.SystemConfi
|
||||
totalIterations: number;
|
||||
currentStatus: string;
|
||||
currentStatusHasSteps: boolean;
|
||||
|
||||
shouldDisplayGuides: boolean;
|
||||
}
|
||||
|
||||
@@ -51,7 +52,7 @@ const initialSystemState = {
|
||||
totalSteps: 0,
|
||||
currentIteration: 0,
|
||||
totalIterations: 0,
|
||||
currentStatus: '',
|
||||
currentStatus: 'Disconnected',
|
||||
currentStatusHasSteps: false,
|
||||
model: '',
|
||||
model_id: '',
|
||||
@@ -107,6 +108,12 @@ export const systemSlice = createSlice({
|
||||
},
|
||||
setIsConnected: (state, action: PayloadAction<boolean>) => {
|
||||
state.isConnected = action.payload;
|
||||
state.isProcessing = false;
|
||||
state.currentStep = 0;
|
||||
state.totalSteps = 0;
|
||||
state.currentIteration = 0;
|
||||
state.totalIterations = 0;
|
||||
state.currentStatusHasSteps = false;
|
||||
},
|
||||
setSocketId: (state, action: PayloadAction<string>) => {
|
||||
state.socketId = action.payload;
|
||||
|
||||
Reference in New Issue
Block a user