mirror of
https://github.com/invoke-ai/InvokeAI
synced 2024-08-30 20:32:17 +00:00
chore(ui): clean up gallerySlice
This commit is contained in:
parent
b7b5bd1b46
commit
f9e78d3c64
@ -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,
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -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,
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -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') {
|
||||||
|
@ -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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
@ -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;
|
||||||
|
Loading…
Reference in New Issue
Block a user