Adds pagination & refresh on re-connect to gallery

This commit is contained in:
psychedelicious
2022-09-26 11:50:47 +10:00
parent db537f154e
commit 460dc897ad
13 changed files with 263 additions and 139 deletions

View File

@@ -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'}>

View File

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

View File

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

View File

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