chore(ui): clean up gallerySlice

This commit is contained in:
psychedelicious 2023-05-16 10:16:36 +10:00
parent b7b5bd1b46
commit f9e78d3c64
5 changed files with 54 additions and 119 deletions

View File

@ -47,10 +47,7 @@ import {
FaTrash, FaTrash,
FaWrench, FaWrench,
} from 'react-icons/fa'; } from 'react-icons/fa';
import { import { gallerySelector } from '../store/gallerySelectors';
gallerySelector,
selectedImageSelector,
} from '../store/gallerySelectors';
import DeleteImageModal from './DeleteImageModal'; import DeleteImageModal from './DeleteImageModal';
import { useCallback } from 'react'; import { useCallback } from 'react';
import { requestCanvasRescale } from 'features/canvas/store/thunks/requestCanvasScale'; import { requestCanvasRescale } from 'features/canvas/store/thunks/requestCanvasScale';
@ -73,15 +70,15 @@ const currentImageButtonsSelector = createSelector(
uiSelector, uiSelector,
lightboxSelector, lightboxSelector,
activeTabNameSelector, activeTabNameSelector,
selectedImageSelector,
], ],
(system, gallery, postprocessing, ui, lightbox, activeTabName, image) => { (system, gallery, postprocessing, ui, lightbox, activeTabName) => {
const { const {
isProcessing, isProcessing,
isConnected, isConnected,
isGFPGANAvailable, isGFPGANAvailable,
isESRGANAvailable, isESRGANAvailable,
shouldConfirmOnDelete, shouldConfirmOnDelete,
progressImage,
} = system; } = system;
const { upscalingLevel, facetoolStrength } = postprocessing; const { upscalingLevel, facetoolStrength } = postprocessing;
@ -90,7 +87,7 @@ const currentImageButtonsSelector = createSelector(
const { shouldShowImageDetails, shouldHidePreview } = ui; const { shouldShowImageDetails, shouldHidePreview } = ui;
const { intermediateImage, currentImage } = gallery; const { selectedImage } = gallery;
return { return {
canDeleteImage: isConnected && !isProcessing, canDeleteImage: isConnected && !isProcessing,
@ -101,15 +98,14 @@ const currentImageButtonsSelector = createSelector(
isESRGANAvailable, isESRGANAvailable,
upscalingLevel, upscalingLevel,
facetoolStrength, facetoolStrength,
shouldDisableToolbarButtons: Boolean(intermediateImage) || !currentImage, shouldDisableToolbarButtons: Boolean(progressImage) || !selectedImage,
currentImage,
shouldShowImageDetails, shouldShowImageDetails,
activeTabName, activeTabName,
isLightboxOpen, isLightboxOpen,
shouldHidePreview, shouldHidePreview,
image, image: selectedImage,
seed: image?.metadata?.invokeai?.node?.seed, seed: selectedImage?.metadata?.invokeai?.node?.seed,
prompt: image?.metadata?.invokeai?.node?.prompt, prompt: selectedImage?.metadata?.invokeai?.node?.prompt,
}; };
}, },
{ {

View File

@ -4,18 +4,18 @@ import { useAppSelector } from 'app/store/storeHooks';
import { systemSelector } from 'features/system/store/systemSelectors'; import { systemSelector } from 'features/system/store/systemSelectors';
import { isEqual } from 'lodash-es'; import { isEqual } from 'lodash-es';
import { selectedImageSelector } from '../store/gallerySelectors'; import { gallerySelector } from '../store/gallerySelectors';
import CurrentImageButtons from './CurrentImageButtons'; import CurrentImageButtons from './CurrentImageButtons';
import CurrentImagePreview from './CurrentImagePreview'; import CurrentImagePreview from './CurrentImagePreview';
import { FaImage } from 'react-icons/fa'; import { FaImage } from 'react-icons/fa';
export const currentImageDisplaySelector = createSelector( export const currentImageDisplaySelector = createSelector(
[systemSelector, selectedImageSelector], [systemSelector, gallerySelector],
(system, selectedImage) => { (system, gallery) => {
const { progressImage } = system; const { progressImage } = system;
return { return {
hasAnImageToDisplay: selectedImage || progressImage, hasAnImageToDisplay: gallery.selectedImage || progressImage,
}; };
}, },
{ {

View File

@ -15,10 +15,7 @@ import IAICheckbox from 'common/components/IAICheckbox';
import IAIIconButton from 'common/components/IAIIconButton'; import IAIIconButton from 'common/components/IAIIconButton';
import IAIPopover from 'common/components/IAIPopover'; import IAIPopover from 'common/components/IAIPopover';
import IAISlider from 'common/components/IAISlider'; import IAISlider from 'common/components/IAISlider';
import { import { gallerySelector } from 'features/gallery/store/gallerySelectors';
gallerySelector,
imageGallerySelector,
} from 'features/gallery/store/gallerySelectors';
import { import {
setCurrentCategory, setCurrentCategory,
setGalleryImageMinimumWidth, setGalleryImageMinimumWidth,
@ -57,11 +54,12 @@ import { Virtuoso, VirtuosoGrid } from 'react-virtuoso';
import { Image as ImageType } from 'app/types/invokeai'; import { Image as ImageType } from 'app/types/invokeai';
import { defaultSelectorOptions } from 'app/store/util/defaultMemoizeOptions'; import { defaultSelectorOptions } from 'app/store/util/defaultMemoizeOptions';
import GalleryProgressImage from './GalleryProgressImage'; import GalleryProgressImage from './GalleryProgressImage';
import { uiSelector } from 'features/ui/store/uiSelectors';
const GALLERY_SHOW_BUTTONS_MIN_WIDTH = 290; const GALLERY_SHOW_BUTTONS_MIN_WIDTH = 290;
const PROGRESS_IMAGE_PLACEHOLDER = 'PROGRESS_IMAGE_PLACEHOLDER'; const PROGRESS_IMAGE_PLACEHOLDER = 'PROGRESS_IMAGE_PLACEHOLDER';
const selector = createSelector( const categorySelector = createSelector(
[(state: RootState) => state], [(state: RootState) => state],
(state) => { (state) => {
const { results, uploads, system, gallery } = state; const { results, uploads, system, gallery } = state;
@ -92,6 +90,33 @@ const selector = createSelector(
defaultSelectorOptions defaultSelectorOptions
); );
const mainSelector = createSelector(
[gallerySelector, uiSelector],
(gallery, ui) => {
const {
currentCategory,
galleryImageMinimumWidth,
galleryImageObjectFit,
shouldAutoSwitchToNewImages,
shouldUseSingleGalleryColumn,
selectedImage,
} = gallery;
const { shouldPinGallery } = ui;
return {
currentCategory,
shouldPinGallery,
galleryImageMinimumWidth,
galleryImageObjectFit,
shouldAutoSwitchToNewImages,
shouldUseSingleGalleryColumn,
selectedImage,
};
},
defaultSelectorOptions
);
const ImageGalleryContent = () => { const ImageGalleryContent = () => {
const dispatch = useAppDispatch(); const dispatch = useAppDispatch();
const { t } = useTranslation(); const { t } = useTranslation();
@ -113,7 +138,6 @@ const ImageGalleryContent = () => {
}); });
const { const {
// images,
currentCategory, currentCategory,
shouldPinGallery, shouldPinGallery,
galleryImageMinimumWidth, galleryImageMinimumWidth,
@ -121,10 +145,10 @@ const ImageGalleryContent = () => {
shouldAutoSwitchToNewImages, shouldAutoSwitchToNewImages,
shouldUseSingleGalleryColumn, shouldUseSingleGalleryColumn,
selectedImage, selectedImage,
} = useAppSelector(imageGallerySelector); } = useAppSelector(mainSelector);
const { images, areMoreImagesAvailable, isLoading } = const { images, areMoreImagesAvailable, isLoading } =
useAppSelector(selector); useAppSelector(categorySelector);
const handleClickLoadMore = () => { const handleClickLoadMore = () => {
if (currentCategory === 'results') { if (currentCategory === 'results') {

View File

@ -1,83 +1,3 @@
import { createSelector } from '@reduxjs/toolkit';
import { RootState } from 'app/store/store'; import { RootState } from 'app/store/store';
import { lightboxSelector } from 'features/lightbox/store/lightboxSelectors';
import {
activeTabNameSelector,
uiSelector,
} from 'features/ui/store/uiSelectors';
import { isEqual } from 'lodash-es';
import { selectResultsById, selectResultsEntities } from './resultsSlice';
import { selectUploadsAll, selectUploadsById } from './uploadsSlice';
export const gallerySelector = (state: RootState) => state.gallery; export const gallerySelector = (state: RootState) => state.gallery;
export const imageGallerySelector = createSelector(
[
(state: RootState) => state,
gallerySelector,
uiSelector,
lightboxSelector,
activeTabNameSelector,
],
(state, gallery, ui, lightbox, activeTabName) => {
const {
currentCategory,
galleryImageMinimumWidth,
galleryImageObjectFit,
shouldAutoSwitchToNewImages,
galleryWidth,
shouldUseSingleGalleryColumn,
selectedImage,
} = gallery;
const { shouldPinGallery } = ui;
const { isLightboxOpen } = lightbox;
const images =
currentCategory === 'results'
? selectResultsEntities(state)
: selectUploadsAll(state);
return {
shouldPinGallery,
galleryImageMinimumWidth,
galleryImageObjectFit,
galleryGridTemplateColumns: shouldUseSingleGalleryColumn
? 'auto'
: `repeat(auto-fill, minmax(${galleryImageMinimumWidth}px, auto))`,
shouldAutoSwitchToNewImages,
currentCategory,
images,
galleryWidth,
shouldEnableResize:
isLightboxOpen ||
(activeTabName === 'unifiedCanvas' && shouldPinGallery)
? false
: true,
shouldUseSingleGalleryColumn,
selectedImage,
};
},
{
memoizeOptions: {
resultEqualityCheck: isEqual,
},
}
);
export const selectedImageSelector = createSelector(
[(state: RootState) => state, gallerySelector],
(state, gallery) => {
const selectedImage = gallery.selectedImage;
if (selectedImage?.type === 'results') {
return selectResultsById(state, selectedImage.name);
}
if (selectedImage?.type === 'uploads') {
return selectUploadsById(state, selectedImage.name);
}
}
);

View File

@ -10,14 +10,10 @@ import {
type GalleryImageObjectFitType = 'contain' | 'cover'; type GalleryImageObjectFitType = 'contain' | 'cover';
export interface GalleryState { export interface GalleryState {
/**
* The selected image
*/
selectedImage?: Image; selectedImage?: Image;
galleryImageMinimumWidth: number; galleryImageMinimumWidth: number;
galleryImageObjectFit: GalleryImageObjectFitType; galleryImageObjectFit: GalleryImageObjectFitType;
shouldAutoSwitchToNewImages: boolean; shouldAutoSwitchToNewImages: boolean;
galleryWidth: number;
shouldUseSingleGalleryColumn: boolean; shouldUseSingleGalleryColumn: boolean;
currentCategory: 'results' | 'uploads'; currentCategory: 'results' | 'uploads';
} }
@ -26,7 +22,6 @@ export const initialGalleryState: GalleryState = {
galleryImageMinimumWidth: 64, galleryImageMinimumWidth: 64,
galleryImageObjectFit: 'cover', galleryImageObjectFit: 'cover',
shouldAutoSwitchToNewImages: true, shouldAutoSwitchToNewImages: true,
galleryWidth: 300,
shouldUseSingleGalleryColumn: false, shouldUseSingleGalleryColumn: false,
currentCategory: 'results', currentCategory: 'results',
}; };
@ -58,9 +53,6 @@ export const gallerySlice = createSlice({
) => { ) => {
state.currentCategory = action.payload; state.currentCategory = action.payload;
}, },
setGalleryWidth: (state, action: PayloadAction<number>) => {
state.galleryWidth = action.payload;
},
setShouldUseSingleGalleryColumn: ( setShouldUseSingleGalleryColumn: (
state, state,
action: PayloadAction<boolean> action: PayloadAction<boolean>
@ -93,24 +85,28 @@ export const gallerySlice = createSlice({
builder.addCase(receivedResultImagesPage.fulfilled, (state, action) => { builder.addCase(receivedResultImagesPage.fulfilled, (state, action) => {
// rehydrate selectedImage URL when results list comes in // rehydrate selectedImage URL when results list comes in
// solves case when outdated URL is in local storage // solves case when outdated URL is in local storage
if (state.selectedImage) { const selectedImage = state.selectedImage;
if (selectedImage) {
const selectedImageInResults = action.payload.items.find( const selectedImageInResults = action.payload.items.find(
(image) => image.image_name === state.selectedImage!.name (image) => image.image_name === selectedImage.name
); );
if (selectedImageInResults) { if (selectedImageInResults) {
state.selectedImage.url = selectedImageInResults.image_url; selectedImage.url = selectedImageInResults.image_url;
state.selectedImage = selectedImage;
} }
} }
}); });
builder.addCase(receivedUploadImagesPage.fulfilled, (state, action) => { builder.addCase(receivedUploadImagesPage.fulfilled, (state, action) => {
// rehydrate selectedImage URL when results list comes in // rehydrate selectedImage URL when results list comes in
// solves case when outdated URL is in local storage // solves case when outdated URL is in local storage
if (state.selectedImage) { const selectedImage = state.selectedImage;
if (selectedImage) {
const selectedImageInResults = action.payload.items.find( const selectedImageInResults = action.payload.items.find(
(image) => image.image_name === state.selectedImage!.name (image) => image.image_name === selectedImage.name
); );
if (selectedImageInResults) { if (selectedImageInResults) {
state.selectedImage.url = selectedImageInResults.image_url; selectedImage.url = selectedImageInResults.image_url;
state.selectedImage = selectedImage;
} }
} }
}); });
@ -122,7 +118,6 @@ export const {
setGalleryImageMinimumWidth, setGalleryImageMinimumWidth,
setGalleryImageObjectFit, setGalleryImageObjectFit,
setShouldAutoSwitchToNewImages, setShouldAutoSwitchToNewImages,
setGalleryWidth,
setShouldUseSingleGalleryColumn, setShouldUseSingleGalleryColumn,
setCurrentCategory, setCurrentCategory,
} = gallerySlice.actions; } = gallerySlice.actions;