mirror of
https://github.com/invoke-ai/InvokeAI.git
synced 2026-04-23 03:00:31 -04:00
refactor(ui): async modal pattern; use for deleting images
This was needed for a canvas flow change which is currently paused, but the new API is much much nicer to use, so I am keeping it.
This commit is contained in:
@@ -1,98 +1,38 @@
|
||||
import { ConfirmationAlertDialog, Divider, Flex, FormControl, FormLabel, Switch, Text } from '@invoke-ai/ui-library';
|
||||
import { createSelector } from '@reduxjs/toolkit';
|
||||
import { createMemoizedSelector } from 'app/store/createMemoizedSelector';
|
||||
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
|
||||
import { useAssertSingleton } from 'common/hooks/useAssertSingleton';
|
||||
import { selectCanvasSlice } from 'features/controlLayers/store/selectors';
|
||||
import { imageDeletionConfirmed } from 'features/deleteImageModal/store/actions';
|
||||
import { getImageUsage, selectImageUsage } from 'features/deleteImageModal/store/selectors';
|
||||
import {
|
||||
imageDeletionCanceled,
|
||||
isModalOpenChanged,
|
||||
selectDeleteImageModalSlice,
|
||||
} from 'features/deleteImageModal/store/slice';
|
||||
import type { ImageUsage } from 'features/deleteImageModal/store/types';
|
||||
import { selectNodesSlice } from 'features/nodes/store/selectors';
|
||||
import { selectUpscaleSlice } from 'features/parameters/store/upscaleSlice';
|
||||
import { selectSystemSlice, setShouldConfirmOnDelete } from 'features/system/store/systemSlice';
|
||||
import { some } from 'lodash-es';
|
||||
import { useAppStore } from 'app/store/nanostores/store';
|
||||
import { useAppSelector } from 'app/store/storeHooks';
|
||||
import ImageUsageMessage from 'features/deleteImageModal/components/ImageUsageMessage';
|
||||
import { useDeleteImageModalApi, useDeleteImageModalState } from 'features/deleteImageModal/store/state';
|
||||
import { selectSystemShouldConfirmOnDelete, setShouldConfirmOnDelete } from 'features/system/store/systemSlice';
|
||||
import type { ChangeEvent } from 'react';
|
||||
import { memo, useCallback } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
|
||||
import ImageUsageMessage from './ImageUsageMessage';
|
||||
|
||||
const selectImageUsages = createMemoizedSelector(
|
||||
[selectDeleteImageModalSlice, selectNodesSlice, selectCanvasSlice, selectImageUsage, selectUpscaleSlice],
|
||||
(deleteImageModal, nodes, canvas, imagesUsage, upscale) => {
|
||||
const { imagesToDelete } = deleteImageModal;
|
||||
|
||||
const allImageUsage = (imagesToDelete ?? []).map(({ image_name }) =>
|
||||
getImageUsage(nodes, canvas, upscale, image_name)
|
||||
);
|
||||
|
||||
const imageUsageSummary: ImageUsage = {
|
||||
isUpscaleImage: some(allImageUsage, (i) => i.isUpscaleImage),
|
||||
isRasterLayerImage: some(allImageUsage, (i) => i.isRasterLayerImage),
|
||||
isInpaintMaskImage: some(allImageUsage, (i) => i.isInpaintMaskImage),
|
||||
isRegionalGuidanceImage: some(allImageUsage, (i) => i.isRegionalGuidanceImage),
|
||||
isNodesImage: some(allImageUsage, (i) => i.isNodesImage),
|
||||
isControlLayerImage: some(allImageUsage, (i) => i.isControlLayerImage),
|
||||
isReferenceImage: some(allImageUsage, (i) => i.isReferenceImage),
|
||||
};
|
||||
|
||||
return {
|
||||
imagesToDelete,
|
||||
imagesUsage,
|
||||
imageUsageSummary,
|
||||
};
|
||||
}
|
||||
);
|
||||
|
||||
const selectShouldConfirmOnDelete = createSelector(selectSystemSlice, (system) => system.shouldConfirmOnDelete);
|
||||
const selectIsModalOpen = createSelector(
|
||||
selectDeleteImageModalSlice,
|
||||
(deleteImageModal) => deleteImageModal.isModalOpen
|
||||
);
|
||||
|
||||
const DeleteImageModal = () => {
|
||||
useAssertSingleton('DeleteImageModal');
|
||||
const dispatch = useAppDispatch();
|
||||
export const DeleteImageModal = memo(() => {
|
||||
const state = useDeleteImageModalState();
|
||||
const api = useDeleteImageModalApi();
|
||||
const { dispatch } = useAppStore();
|
||||
const { t } = useTranslation();
|
||||
const shouldConfirmOnDelete = useAppSelector(selectShouldConfirmOnDelete);
|
||||
const isModalOpen = useAppSelector(selectIsModalOpen);
|
||||
const { imagesToDelete, imagesUsage, imageUsageSummary } = useAppSelector(selectImageUsages);
|
||||
const shouldConfirmOnDelete = useAppSelector(selectSystemShouldConfirmOnDelete);
|
||||
|
||||
const handleChangeShouldConfirmOnDelete = useCallback(
|
||||
(e: ChangeEvent<HTMLInputElement>) => dispatch(setShouldConfirmOnDelete(!e.target.checked)),
|
||||
[dispatch]
|
||||
);
|
||||
|
||||
const handleClose = useCallback(() => {
|
||||
dispatch(imageDeletionCanceled());
|
||||
dispatch(isModalOpenChanged(false));
|
||||
}, [dispatch]);
|
||||
|
||||
const handleDelete = useCallback(() => {
|
||||
if (!imagesToDelete.length || !imagesUsage.length) {
|
||||
return;
|
||||
}
|
||||
dispatch(imageDeletionCanceled());
|
||||
dispatch(imageDeletionConfirmed({ imageDTOs: imagesToDelete, imagesUsage }));
|
||||
}, [dispatch, imagesToDelete, imagesUsage]);
|
||||
|
||||
return (
|
||||
<ConfirmationAlertDialog
|
||||
title={t('gallery.deleteImage', { count: imagesToDelete.length })}
|
||||
isOpen={isModalOpen}
|
||||
onClose={handleClose}
|
||||
title={`${t('gallery.deleteImage', { count: state.imageDTOs.length })}2`}
|
||||
isOpen={state.isOpen}
|
||||
onClose={api.close}
|
||||
cancelButtonText={t('common.cancel')}
|
||||
acceptButtonText={t('common.delete')}
|
||||
acceptCallback={handleDelete}
|
||||
acceptCallback={api.confirm}
|
||||
cancelCallback={api.cancel}
|
||||
useInert={false}
|
||||
>
|
||||
<Flex direction="column" gap={3}>
|
||||
<ImageUsageMessage imageUsage={imageUsageSummary} />
|
||||
<ImageUsageMessage imageUsage={state.usageSummary} />
|
||||
<Divider />
|
||||
<Text>{t('gallery.deleteImagePermanent')}</Text>
|
||||
<Text>{t('common.areYouSure')}</Text>
|
||||
@@ -103,6 +43,5 @@ const DeleteImageModal = () => {
|
||||
</Flex>
|
||||
</ConfirmationAlertDialog>
|
||||
);
|
||||
};
|
||||
|
||||
export default memo(DeleteImageModal);
|
||||
});
|
||||
DeleteImageModal.displayName = 'DeleteImageModal';
|
||||
|
||||
Reference in New Issue
Block a user