mirror of
https://github.com/invoke-ai/InvokeAI
synced 2024-08-30 20:32:17 +00:00
refactor(ui): fix delete image stuff
This commit is contained in:
parent
3f6cf638f9
commit
5e1a6ae334
@ -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;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
@ -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
|
||||||
|
@ -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));
|
||||||
|
@ -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,
|
||||||
|
@ -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);
|
||||||
|
@ -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;
|
||||||
|
@ -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);
|
||||||
|
@ -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;
|
||||||
|
@ -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 {
|
||||||
|
@ -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>
|
||||||
</>
|
</>
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
@ -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;
|
||||||
};
|
};
|
||||||
|
@ -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]
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -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);
|
||||||
|
Loading…
Reference in New Issue
Block a user