refactor(ui): fix delete image stuff

This commit is contained in:
psychedelicious 2024-06-16 11:36:36 +10:00
parent 3f6cf638f9
commit 5e1a6ae334
14 changed files with 109 additions and 178 deletions

View File

@ -1,7 +1,5 @@
import type { AppStartListening } from 'app/store/middleware/listenerMiddleware'; import type { AppStartListening } from 'app/store/middleware/listenerMiddleware';
import { resetCanvas } from 'features/canvas/store/canvasSlice'; import { caAllDeleted, ipaAllDeleted, layerAllDeleted } from 'features/controlLayers/store/canvasV2Slice';
import { controlAdaptersReset } from 'features/controlAdapters/store/controlAdaptersSlice';
import { allLayersDeleted } from 'features/controlLayers/store/canvasV2Slice';
import { getImageUsage } from 'features/deleteImageModal/store/selectors'; import { getImageUsage } from 'features/deleteImageModal/store/selectors';
import { nodeEditorReset } from 'features/nodes/store/nodesSlice'; import { nodeEditorReset } from 'features/nodes/store/nodesSlice';
import { imagesApi } from 'services/api/endpoints/images'; import { imagesApi } from 'services/api/endpoints/images';
@ -14,18 +12,18 @@ export const addDeleteBoardAndImagesFulfilledListener = (startAppListening: AppS
// Remove all deleted images from the UI // Remove all deleted images from the UI
let wasCanvasReset = false; let wereLayersReset = false;
let wasNodeEditorReset = false; let wasNodeEditorReset = false;
let wereControlAdaptersReset = false; let wereControlAdaptersReset = false;
let wereControlLayersReset = false; let wereIPAdaptersReset = false;
const { canvas, nodes, controlAdapters, canvasV2 } = getState(); const { nodes, canvasV2 } = getState();
deleted_images.forEach((image_name) => { deleted_images.forEach((image_name) => {
const imageUsage = getImageUsage(canvas, nodes.present, controlAdapters, canvasV2, image_name); const imageUsage = getImageUsage(nodes.present, canvasV2, image_name);
if (imageUsage.isCanvasImage && !wasCanvasReset) { if (imageUsage.isLayerImage && !wereLayersReset) {
dispatch(resetCanvas()); dispatch(layerAllDeleted());
wasCanvasReset = true; wereLayersReset = true;
} }
if (imageUsage.isNodesImage && !wasNodeEditorReset) { if (imageUsage.isNodesImage && !wasNodeEditorReset) {
@ -33,14 +31,14 @@ export const addDeleteBoardAndImagesFulfilledListener = (startAppListening: AppS
wasNodeEditorReset = true; wasNodeEditorReset = true;
} }
if (imageUsage.isControlImage && !wereControlAdaptersReset) { if (imageUsage.isControlAdapterImage && !wereControlAdaptersReset) {
dispatch(controlAdaptersReset()); dispatch(caAllDeleted());
wereControlAdaptersReset = true; wereControlAdaptersReset = true;
} }
if (imageUsage.isControlLayerImage && !wereControlLayersReset) { if (imageUsage.isIPAdapterImage && !wereIPAdaptersReset) {
dispatch(allLayersDeleted()); dispatch(ipaAllDeleted());
wereControlLayersReset = true; wereIPAdaptersReset = true;
} }
}); });
}, },

View File

@ -3,18 +3,11 @@ import type { AppStartListening } from 'app/store/middleware/listenerMiddleware'
import type { AppDispatch, RootState } from 'app/store/store'; import type { AppDispatch, RootState } from 'app/store/store';
import { resetCanvas } from 'features/canvas/store/canvasSlice'; import { resetCanvas } from 'features/canvas/store/canvasSlice';
import { import {
controlAdapterImageChanged, caImageChanged,
controlAdapterProcessedImageChanged, caProcessedImageChanged,
selectControlAdapterAll, ipaImageChanged,
} from 'features/controlAdapters/store/controlAdaptersSlice'; layerDeleted,
import { isControlNetOrT2IAdapter } from 'features/controlAdapters/store/types'; } from 'features/controlLayers/store/canvasV2Slice';
import { layerDeleted } from 'features/controlLayers/store/canvasV2Slice';
import {
isControlAdapterLayer,
isInitialImageLayer,
isIPAdapterLayer,
isRegionalGuidanceLayer,
} from 'features/controlLayers/store/types';
import { imageDeletionConfirmed } from 'features/deleteImageModal/store/actions'; import { imageDeletionConfirmed } from 'features/deleteImageModal/store/actions';
import { isModalOpenChanged } from 'features/deleteImageModal/store/slice'; import { isModalOpenChanged } from 'features/deleteImageModal/store/slice';
import { selectListImagesQueryArgs } from 'features/gallery/store/gallerySelectors'; import { selectListImagesQueryArgs } from 'features/gallery/store/gallerySelectors';
@ -48,51 +41,33 @@ const deleteNodesImages = (state: RootState, dispatch: AppDispatch, imageDTO: Im
}; };
const deleteControlAdapterImages = (state: RootState, dispatch: AppDispatch, imageDTO: ImageDTO) => { const deleteControlAdapterImages = (state: RootState, dispatch: AppDispatch, imageDTO: ImageDTO) => {
forEach(selectControlAdapterAll(state.controlAdapters), (ca) => { state.canvasV2.controlAdapters.forEach(({ id, image, processedImage }) => {
if ( if (image?.name === imageDTO.image_name || processedImage?.name === imageDTO.image_name) {
ca.controlImage === imageDTO.image_name || dispatch(caImageChanged({ id, imageDTO: null }));
(isControlNetOrT2IAdapter(ca) && ca.processedControlImage === imageDTO.image_name) dispatch(caProcessedImageChanged({ id, imageDTO: null }));
) {
dispatch(
controlAdapterImageChanged({
id: ca.id,
controlImage: null,
})
);
dispatch(
controlAdapterProcessedImageChanged({
id: ca.id,
processedControlImage: null,
})
);
} }
}); });
}; };
const deleteControlLayerImages = (state: RootState, dispatch: AppDispatch, imageDTO: ImageDTO) => { const deleteIPAdapterImages = (state: RootState, dispatch: AppDispatch, imageDTO: ImageDTO) => {
state.canvasV2.layers.forEach((l) => { state.canvasV2.ipAdapters.forEach(({ id, image }) => {
if (isRegionalGuidanceLayer(l)) { if (image?.name === imageDTO.image_name) {
if (l.ipAdapters.some((ipa) => ipa.image?.name === imageDTO.image_name)) { dispatch(ipaImageChanged({ id, imageDTO: null }));
dispatch(layerDeleted(l.id)); }
});
};
const deleteLayerImages = (state: RootState, dispatch: AppDispatch, imageDTO: ImageDTO) => {
state.canvasV2.layers.forEach(({ id, objects }) => {
let shouldDelete = false;
for (const obj of objects) {
if (obj.type === 'image' && obj.image.name === imageDTO.image_name) {
shouldDelete = true;
break;
} }
} }
if (isControlAdapterLayer(l)) { if (shouldDelete) {
if ( dispatch(layerDeleted({ id }));
l.controlAdapter.image?.name === imageDTO.image_name ||
l.controlAdapter.processedImage?.name === imageDTO.image_name
) {
dispatch(layerDeleted(l.id));
}
}
if (isIPAdapterLayer(l)) {
if (l.ipAdapter.image?.name === imageDTO.image_name) {
dispatch(layerDeleted(l.id));
}
}
if (isInitialImageLayer(l)) {
if (l.image?.name === imageDTO.image_name) {
dispatch(layerDeleted(l.id));
}
} }
}); });
}; };
@ -145,14 +120,10 @@ export const addImageDeletionListeners = (startAppListening: AppStartListening)
} }
} }
// We need to reset the features where the image is in use - none of these work if their image(s) don't exist
if (imageUsage.isCanvasImage) {
dispatch(resetCanvas());
}
deleteControlAdapterImages(state, dispatch, imageDTO);
deleteNodesImages(state, dispatch, imageDTO); deleteNodesImages(state, dispatch, imageDTO);
deleteControlLayerImages(state, dispatch, imageDTO); deleteControlAdapterImages(state, dispatch, imageDTO);
deleteIPAdapterImages(state, dispatch, imageDTO);
deleteLayerImages(state, dispatch, imageDTO);
} catch { } catch {
// no-op // no-op
} finally { } finally {
@ -189,14 +160,15 @@ export const addImageDeletionListeners = (startAppListening: AppStartListening)
// We need to reset the features where the image is in use - none of these work if their image(s) don't exist // We need to reset the features where the image is in use - none of these work if their image(s) don't exist
if (imagesUsage.some((i) => i.isCanvasImage)) { if (imagesUsage.some((i) => i.isLayerImage)) {
dispatch(resetCanvas()); dispatch(resetCanvas());
} }
imageDTOs.forEach((imageDTO) => { imageDTOs.forEach((imageDTO) => {
deleteControlAdapterImages(state, dispatch, imageDTO);
deleteNodesImages(state, dispatch, imageDTO); deleteNodesImages(state, dispatch, imageDTO);
deleteControlLayerImages(state, dispatch, imageDTO); deleteControlAdapterImages(state, dispatch, imageDTO);
deleteIPAdapterImages(state, dispatch, imageDTO);
deleteLayerImages(state, dispatch, imageDTO);
}); });
} catch { } catch {
// no-op // no-op

View File

@ -13,9 +13,10 @@ export const addImageToDeleteSelectedListener = (startAppListening: AppStartList
const imagesUsage = selectImageUsage(getState()); const imagesUsage = selectImageUsage(getState());
const isImageInUse = const isImageInUse =
imagesUsage.some((i) => i.isCanvasImage) || imagesUsage.some((i) => i.isLayerImage) ||
imagesUsage.some((i) => i.isControlImage) || imagesUsage.some((i) => i.isControlAdapterImage) ||
imagesUsage.some((i) => i.isNodesImage); imagesUsage.some((i) => i.isIPAdapterImage) ||
imagesUsage.some((i) => i.isLayerImage);
if (shouldConfirmOnDelete || isImageInUse) { if (shouldConfirmOnDelete || isImageInUse) {
dispatch(isModalOpenChanged(true)); dispatch(isModalOpenChanged(true));

View File

@ -194,11 +194,13 @@ export const {
layerLinePointAdded, layerLinePointAdded,
layerRectAdded, layerRectAdded,
layerImageAdded, layerImageAdded,
layerAllDeleted,
// IP Adapters // IP Adapters
ipaAdded, ipaAdded,
ipaRecalled, ipaRecalled,
ipaIsEnabledToggled, ipaIsEnabledToggled,
ipaDeleted, ipaDeleted,
ipaAllDeleted,
ipaImageChanged, ipaImageChanged,
ipaMethodChanged, ipaMethodChanged,
ipaModelChanged, ipaModelChanged,
@ -209,6 +211,7 @@ export const {
caAdded, caAdded,
caBboxChanged, caBboxChanged,
caDeleted, caDeleted,
caAllDeleted,
caIsEnabledToggled, caIsEnabledToggled,
caMovedBackwardOne, caMovedBackwardOne,
caMovedForwardOne, caMovedForwardOne,
@ -234,6 +237,7 @@ export const {
rgTranslated, rgTranslated,
rgBboxChanged, rgBboxChanged,
rgDeleted, rgDeleted,
rgAllDeleted,
rgGlobalOpacityChanged, rgGlobalOpacityChanged,
rgMovedForwardOne, rgMovedForwardOne,
rgMovedToFront, rgMovedToFront,

View File

@ -82,6 +82,9 @@ export const controlAdaptersReducers = {
const { id } = action.payload; const { id } = action.payload;
state.controlAdapters = state.controlAdapters.filter((ca) => ca.id !== id); state.controlAdapters = state.controlAdapters.filter((ca) => ca.id !== id);
}, },
caAllDeleted: (state) => {
state.controlAdapters = [];
},
caOpacityChanged: (state, action: PayloadAction<{ id: string; opacity: number }>) => { caOpacityChanged: (state, action: PayloadAction<{ id: string; opacity: number }>) => {
const { id, opacity } = action.payload; const { id, opacity } = action.payload;
const ca = selectCA(state, id); const ca = selectCA(state, id);

View File

@ -39,7 +39,11 @@ export const ipAdaptersReducers = {
} }
}, },
ipaDeleted: (state, action: PayloadAction<{ id: string }>) => { ipaDeleted: (state, action: PayloadAction<{ id: string }>) => {
state.ipAdapters = state.ipAdapters.filter((ipa) => ipa.id !== action.payload.id); const { id } = action.payload;
state.ipAdapters = state.ipAdapters.filter((ipa) => ipa.id !== id);
},
ipaAllDeleted: (state) => {
state.ipAdapters = [];
}, },
ipaImageChanged: (state, action: PayloadAction<{ id: string; imageDTO: ImageDTO | null }>) => { ipaImageChanged: (state, action: PayloadAction<{ id: string; imageDTO: ImageDTO | null }>) => {
const { id, imageDTO } = action.payload; const { id, imageDTO } = action.payload;

View File

@ -88,6 +88,9 @@ export const layersReducers = {
const { id } = action.payload; const { id } = action.payload;
state.layers = state.layers.filter((l) => l.id !== id); state.layers = state.layers.filter((l) => l.id !== id);
}, },
layerAllDeleted: (state) => {
state.layers = [];
},
layerOpacityChanged: (state, action: PayloadAction<{ id: string; opacity: number }>) => { layerOpacityChanged: (state, action: PayloadAction<{ id: string; opacity: number }>) => {
const { id, opacity } = action.payload; const { id, opacity } = action.payload;
const layer = selectLayer(state, id); const layer = selectLayer(state, id);

View File

@ -117,6 +117,9 @@ export const regionsReducers = {
const { id } = action.payload; const { id } = action.payload;
state.regions = state.regions.filter((ca) => ca.id !== id); state.regions = state.regions.filter((ca) => ca.id !== id);
}, },
rgAllDeleted: (state) => {
state.regions = [];
},
rgGlobalOpacityChanged: (state, action: PayloadAction<{ opacity: number }>) => { rgGlobalOpacityChanged: (state, action: PayloadAction<{ opacity: number }>) => {
const { opacity } = action.payload; const { opacity } = action.payload;
state.maskFillOpacity = opacity; state.maskFillOpacity = opacity;

View File

@ -1,8 +1,6 @@
import { ConfirmationAlertDialog, Divider, Flex, FormControl, FormLabel, Switch, Text } from '@invoke-ai/ui-library'; import { ConfirmationAlertDialog, Divider, Flex, FormControl, FormLabel, Switch, Text } from '@invoke-ai/ui-library';
import { createMemoizedSelector } from 'app/store/createMemoizedSelector'; import { createMemoizedSelector } from 'app/store/createMemoizedSelector';
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks'; import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
import { selectCanvasSlice } from 'features/canvas/store/canvasSlice';
import { selectControlAdaptersSlice } from 'features/controlAdapters/store/controlAdaptersSlice';
import { selectCanvasV2Slice } from 'features/controlLayers/store/canvasV2Slice'; import { selectCanvasV2Slice } from 'features/controlLayers/store/canvasV2Slice';
import { imageDeletionConfirmed } from 'features/deleteImageModal/store/actions'; import { imageDeletionConfirmed } from 'features/deleteImageModal/store/actions';
import { getImageUsage, selectImageUsage } from 'features/deleteImageModal/store/selectors'; import { getImageUsage, selectImageUsage } from 'features/deleteImageModal/store/selectors';
@ -22,26 +20,17 @@ import { useTranslation } from 'react-i18next';
import ImageUsageMessage from './ImageUsageMessage'; import ImageUsageMessage from './ImageUsageMessage';
const selectImageUsages = createMemoizedSelector( const selectImageUsages = createMemoizedSelector(
[ [selectDeleteImageModalSlice, selectNodesSlice, selectCanvasV2Slice, selectImageUsage],
selectDeleteImageModalSlice, (deleteImageModal, nodes, canvasV2, imagesUsage) => {
selectCanvasSlice,
selectNodesSlice,
selectControlAdaptersSlice,
selectCanvasV2Slice,
selectImageUsage,
],
(deleteImageModal, canvas, nodes, controlAdapters, controlLayers, imagesUsage) => {
const { imagesToDelete } = deleteImageModal; const { imagesToDelete } = deleteImageModal;
const allImageUsage = (imagesToDelete ?? []).map(({ image_name }) => const allImageUsage = (imagesToDelete ?? []).map(({ image_name }) => getImageUsage(nodes, canvasV2, image_name));
getImageUsage(canvas, nodes, controlAdapters, canvasV2, image_name)
);
const imageUsageSummary: ImageUsage = { const imageUsageSummary: ImageUsage = {
isCanvasImage: some(allImageUsage, (i) => i.isCanvasImage), isLayerImage: some(allImageUsage, (i) => i.isLayerImage),
isNodesImage: some(allImageUsage, (i) => i.isNodesImage), isNodesImage: some(allImageUsage, (i) => i.isNodesImage),
isControlImage: some(allImageUsage, (i) => i.isControlImage), isControlAdapterImage: some(allImageUsage, (i) => i.isControlAdapterImage),
isControlLayerImage: some(allImageUsage, (i) => i.isControlLayerImage), isIPAdapterImage: some(allImageUsage, (i) => i.isIPAdapterImage),
}; };
return { return {

View File

@ -29,10 +29,10 @@ const ImageUsageMessage = (props: Props) => {
<> <>
<Text>{topMessage}</Text> <Text>{topMessage}</Text>
<UnorderedList paddingInlineStart={6}> <UnorderedList paddingInlineStart={6}>
{imageUsage.isCanvasImage && <ListItem>{t('ui.tabs.canvasTab')}</ListItem>} {imageUsage.isLayerImage && <ListItem>{t('controlLayers.layers')}</ListItem>}
{imageUsage.isControlImage && <ListItem>{t('common.controlNet')}</ListItem>} {imageUsage.isControlAdapterImage && <ListItem>{t('controlLayers.controlAdapters')}</ListItem>}
{imageUsage.isIPAdapterImage && <ListItem>{t('controlLayers.ipAdapters')}</ListItem>}
{imageUsage.isNodesImage && <ListItem>{t('ui.tabs.workflowsTab')}</ListItem>} {imageUsage.isNodesImage && <ListItem>{t('ui.tabs.workflowsTab')}</ListItem>}
{imageUsage.isControlLayerImage && <ListItem>{t('ui.tabs.generationTab')}</ListItem>}
</UnorderedList> </UnorderedList>
<Text>{bottomMessage}</Text> <Text>{bottomMessage}</Text>
</> </>

View File

@ -1,20 +1,6 @@
import { createMemoizedSelector } from 'app/store/createMemoizedSelector'; import { createMemoizedSelector } from 'app/store/createMemoizedSelector';
import { selectCanvasSlice } from 'features/canvas/store/canvasSlice';
import type { CanvasState } from 'features/canvas/store/canvasTypes';
import {
selectControlAdapterAll,
selectControlAdaptersSlice,
} from 'features/controlAdapters/store/controlAdaptersSlice';
import type { ControlAdaptersState } from 'features/controlAdapters/store/types';
import { isControlNetOrT2IAdapter } from 'features/controlAdapters/store/types';
import { selectCanvasV2Slice } from 'features/controlLayers/store/canvasV2Slice'; import { selectCanvasV2Slice } from 'features/controlLayers/store/canvasV2Slice';
import type { CanvasV2State } from 'features/controlLayers/store/types'; import type { CanvasV2State } from 'features/controlLayers/store/types';
import {
isControlAdapterLayer,
isInitialImageLayer,
isIPAdapterLayer,
isRegionalGuidanceLayer,
} from 'features/controlLayers/store/types';
import { selectDeleteImageModalSlice } from 'features/deleteImageModal/store/slice'; import { selectDeleteImageModalSlice } from 'features/deleteImageModal/store/slice';
import { selectNodesSlice } from 'features/nodes/store/nodesSlice'; import { selectNodesSlice } from 'features/nodes/store/nodesSlice';
import type { NodesState } from 'features/nodes/store/types'; import type { NodesState } from 'features/nodes/store/types';
@ -24,47 +10,28 @@ import { some } from 'lodash-es';
import type { ImageUsage } from './types'; import type { ImageUsage } from './types';
export const getImageUsage = ( export const getImageUsage = (nodes: NodesState, canvasV2: CanvasV2State, image_name: string) => {
canvas: CanvasState, const isLayerImage = canvasV2.layers.some((layer) =>
nodes: NodesState, layer.objects.some((obj) => obj.type === 'image' && obj.image.name === image_name)
controlAdapters: ControlAdaptersState,
controlLayers: CanvasV2State,
image_name: string
) => {
const isCanvasImage = canvas.layerState.objects.some((obj) => obj.kind === 'image' && obj.imageName === image_name);
const isNodesImage = nodes.nodes.filter(isInvocationNode).some((node) => {
return some(
node.data.inputs,
(input) => isImageFieldInputInstance(input) && input.value?.image_name === image_name
);
});
const isControlImage = selectControlAdapterAll(controlAdapters).some(
(ca) => ca.controlImage === image_name || (isControlNetOrT2IAdapter(ca) && ca.processedControlImage === image_name)
); );
const isControlLayerImage = controlLayers.layers.some((l) => { const isNodesImage = nodes.nodes
if (isRegionalGuidanceLayer(l)) { .filter(isInvocationNode)
return l.ipAdapters.some((ipa) => ipa.image?.name === image_name); .some((node) =>
} some(node.data.inputs, (input) => isImageFieldInputInstance(input) && input.value?.image_name === image_name)
if (isControlAdapterLayer(l)) { );
return l.controlAdapter.image?.name === image_name || l.controlAdapter.processedImage?.name === image_name;
} const isControlAdapterImage = canvasV2.controlAdapters.some(
if (isIPAdapterLayer(l)) { (ca) => ca.image?.name === image_name || ca.processedImage?.name === image_name
return l.ipAdapter.image?.name === image_name; );
}
if (isInitialImageLayer(l)) { const isIPAdapterImage = canvasV2.ipAdapters.some((ipa) => ipa.image?.name === image_name);
return l.image?.name === image_name;
}
return false;
});
const imageUsage: ImageUsage = { const imageUsage: ImageUsage = {
isCanvasImage, isLayerImage,
isNodesImage, isNodesImage,
isControlImage, isControlAdapterImage,
isControlLayerImage, isIPAdapterImage,
}; };
return imageUsage; return imageUsage;
@ -72,20 +39,16 @@ export const getImageUsage = (
export const selectImageUsage = createMemoizedSelector( export const selectImageUsage = createMemoizedSelector(
selectDeleteImageModalSlice, selectDeleteImageModalSlice,
selectCanvasSlice,
selectNodesSlice, selectNodesSlice,
selectControlAdaptersSlice,
selectCanvasV2Slice, selectCanvasV2Slice,
(deleteImageModal, canvas, nodes, controlAdapters, controlLayers) => { (deleteImageModal, nodes, canvasV2) => {
const { imagesToDelete } = deleteImageModal; const { imagesToDelete } = deleteImageModal;
if (!imagesToDelete.length) { if (!imagesToDelete.length) {
return []; return [];
} }
const imagesUsage = imagesToDelete.map((i) => const imagesUsage = imagesToDelete.map((i) => getImageUsage(nodes, canvasV2, i.image_name));
getImageUsage(canvas, nodes, controlAdapters, canvasV2, i.image_name)
);
return imagesUsage; return imagesUsage;
} }

View File

@ -6,8 +6,8 @@ export type DeleteImageState = {
}; };
export type ImageUsage = { export type ImageUsage = {
isCanvasImage: boolean;
isNodesImage: boolean; isNodesImage: boolean;
isControlImage: boolean; isControlAdapterImage: boolean;
isControlLayerImage: boolean; isIPAdapterImage: boolean;
isLayerImage: boolean;
}; };

View File

@ -13,8 +13,6 @@ import {
import { skipToken } from '@reduxjs/toolkit/query'; import { skipToken } from '@reduxjs/toolkit/query';
import { createMemoizedSelector } from 'app/store/createMemoizedSelector'; import { createMemoizedSelector } from 'app/store/createMemoizedSelector';
import { useAppSelector } from 'app/store/storeHooks'; import { useAppSelector } from 'app/store/storeHooks';
import { selectCanvasSlice } from 'features/canvas/store/canvasSlice';
import { selectControlAdaptersSlice } from 'features/controlAdapters/store/controlAdaptersSlice';
import { selectCanvasV2Slice } from 'features/controlLayers/store/canvasV2Slice'; import { selectCanvasV2Slice } from 'features/controlLayers/store/canvasV2Slice';
import ImageUsageMessage from 'features/deleteImageModal/components/ImageUsageMessage'; import ImageUsageMessage from 'features/deleteImageModal/components/ImageUsageMessage';
import { getImageUsage } from 'features/deleteImageModal/store/selectors'; import { getImageUsage } from 'features/deleteImageModal/store/selectors';
@ -41,23 +39,18 @@ const DeleteBoardModal = (props: Props) => {
const selectImageUsageSummary = useMemo( const selectImageUsageSummary = useMemo(
() => () =>
createMemoizedSelector( createMemoizedSelector([selectNodesSlice, selectCanvasV2Slice], (nodes, canvasV2) => {
[selectCanvasSlice, selectNodesSlice, selectControlAdaptersSlice, selectCanvasV2Slice], const allImageUsage = (boardImageNames ?? []).map((imageName) => getImageUsage(nodes, canvasV2, imageName));
(canvas, nodes, controlAdapters, controlLayers) => {
const allImageUsage = (boardImageNames ?? []).map((imageName) =>
getImageUsage(canvas, nodes, controlAdapters, canvasV2, imageName)
);
const imageUsageSummary: ImageUsage = { const imageUsageSummary: ImageUsage = {
isCanvasImage: some(allImageUsage, (i) => i.isCanvasImage), isLayerImage: some(allImageUsage, (i) => i.isLayerImage),
isNodesImage: some(allImageUsage, (i) => i.isNodesImage), isNodesImage: some(allImageUsage, (i) => i.isNodesImage),
isControlImage: some(allImageUsage, (i) => i.isControlImage), isControlAdapterImage: some(allImageUsage, (i) => i.isControlAdapterImage),
isControlLayerImage: some(allImageUsage, (i) => i.isControlLayerImage), isIPAdapterImage: some(allImageUsage, (i) => i.isIPAdapterImage),
}; };
return imageUsageSummary; return imageUsageSummary;
} }),
),
[boardImageNames] [boardImageNames]
); );

View File

@ -15,7 +15,6 @@ import { imageToCompareChanged } from 'features/gallery/store/gallerySlice';
import { $templates } from 'features/nodes/store/nodesSlice'; import { $templates } from 'features/nodes/store/nodesSlice';
import { selectOptimalDimension } from 'features/parameters/store/generationSlice'; import { selectOptimalDimension } from 'features/parameters/store/generationSlice';
import { upscaleInitialImageChanged } from 'features/parameters/store/upscaleSlice'; import { upscaleInitialImageChanged } from 'features/parameters/store/upscaleSlice';
import { useFeatureStatus } from 'features/system/hooks/useFeatureStatus';
import { toast } from 'features/toast/toast'; import { toast } from 'features/toast/toast';
import { setActiveTab } from 'features/ui/store/uiSlice'; import { setActiveTab } from 'features/ui/store/uiSlice';
import { useGetAndLoadEmbeddedWorkflow } from 'features/workflowLibrary/hooks/useGetAndLoadEmbeddedWorkflow'; import { useGetAndLoadEmbeddedWorkflow } from 'features/workflowLibrary/hooks/useGetAndLoadEmbeddedWorkflow';
@ -52,7 +51,6 @@ const SingleSelectionMenuItems = (props: SingleSelectionMenuItemsProps) => {
const maySelectForCompare = useAppSelector((s) => s.gallery.imageToCompare?.image_name !== imageDTO.image_name); const maySelectForCompare = useAppSelector((s) => s.gallery.imageToCompare?.image_name !== imageDTO.image_name);
const dispatch = useAppDispatch(); const dispatch = useAppDispatch();
const { t } = useTranslation(); const { t } = useTranslation();
const isCanvasEnabled = useFeatureStatus('canvas');
const customStarUi = useStore($customStarUI); const customStarUi = useStore($customStarUI);
const { downloadImage } = useDownloadImage(); const { downloadImage } = useDownloadImage();
const templates = useStore($templates); const templates = useStore($templates);