fix(ui): use isValidDrop in imageDropped listener

It was possible for a drop event to be invalid but still processed. Fixed by slightly changing the signature of isValidDrop.
This commit is contained in:
psychedelicious 2024-05-31 17:37:30 +10:00
parent 8f8ddd620b
commit 4ef8cbd9d0
4 changed files with 20 additions and 12 deletions

View File

@ -14,6 +14,7 @@ import {
rgLayerIPAdapterImageChanged, rgLayerIPAdapterImageChanged,
} from 'features/controlLayers/store/controlLayersSlice'; } from 'features/controlLayers/store/controlLayersSlice';
import type { TypesafeDraggableData, TypesafeDroppableData } from 'features/dnd/types'; import type { TypesafeDraggableData, TypesafeDroppableData } from 'features/dnd/types';
import { isValidDrop } from 'features/dnd/util/isValidDrop';
import { imageSelected, imageToCompareChanged } from 'features/gallery/store/gallerySlice'; import { imageSelected, imageToCompareChanged } from 'features/gallery/store/gallerySlice';
import { fieldImageValueChanged } from 'features/nodes/store/nodesSlice'; import { fieldImageValueChanged } from 'features/nodes/store/nodesSlice';
import { selectOptimalDimension } from 'features/parameters/store/generationSlice'; import { selectOptimalDimension } from 'features/parameters/store/generationSlice';
@ -30,6 +31,9 @@ export const addImageDroppedListener = (startAppListening: AppStartListening) =>
effect: async (action, { dispatch, getState }) => { effect: async (action, { dispatch, getState }) => {
const log = logger('dnd'); const log = logger('dnd');
const { activeData, overData } = action.payload; const { activeData, overData } = action.payload;
if (!isValidDrop(overData, activeData)) {
return;
}
if (activeData.payloadType === 'IMAGE_DTO') { if (activeData.payloadType === 'IMAGE_DTO') {
log.debug({ activeData, overData }, 'Image dropped'); log.debug({ activeData, overData }, 'Image dropped');

View File

@ -36,7 +36,7 @@ const IAIDroppable = (props: IAIDroppableProps) => {
pointerEvents={active ? 'auto' : 'none'} pointerEvents={active ? 'auto' : 'none'}
> >
<AnimatePresence> <AnimatePresence>
{isValidDrop(data, active) && <IAIDropOverlay isOver={isOver} label={dropLabel} />} {isValidDrop(data, active?.data.current) && <IAIDropOverlay isOver={isOver} label={dropLabel} />}
</AnimatePresence> </AnimatePresence>
</Box> </Box>
); );

View File

@ -1,14 +1,14 @@
import type { TypesafeActive, TypesafeDroppableData } from 'features/dnd/types'; import type { TypesafeDraggableData, TypesafeDroppableData } from 'features/dnd/types';
export const isValidDrop = (overData: TypesafeDroppableData | undefined, active: TypesafeActive | null) => { export const isValidDrop = (overData?: TypesafeDroppableData | null, activeData?: TypesafeDraggableData | null) => {
if (!overData || !active?.data.current) { if (!overData || !activeData) {
return false; return false;
} }
const { actionType } = overData; const { actionType } = overData;
const { payloadType } = active.data.current; const { payloadType } = activeData;
if (overData.id === active.data.current.id) { if (overData.id === activeData.id) {
return false; return false;
} }
@ -30,7 +30,11 @@ export const isValidDrop = (overData: TypesafeDroppableData | undefined, active:
case 'SET_NODES_IMAGE': case 'SET_NODES_IMAGE':
return payloadType === 'IMAGE_DTO'; return payloadType === 'IMAGE_DTO';
case 'SELECT_FOR_COMPARE': case 'SELECT_FOR_COMPARE':
return payloadType === 'IMAGE_DTO'; return (
payloadType === 'IMAGE_DTO' &&
activeData.id !== 'image-compare-first-image' &&
activeData.id !== 'image-compare-second-image'
);
case 'ADD_TO_BOARD': { case 'ADD_TO_BOARD': {
// If the board is the same, don't allow the drop // If the board is the same, don't allow the drop
@ -42,7 +46,7 @@ export const isValidDrop = (overData: TypesafeDroppableData | undefined, active:
// Check if the image's board is the board we are dragging onto // Check if the image's board is the board we are dragging onto
if (payloadType === 'IMAGE_DTO') { if (payloadType === 'IMAGE_DTO') {
const { imageDTO } = active.data.current.payload; const { imageDTO } = activeData.payload;
const currentBoard = imageDTO.board_id ?? 'none'; const currentBoard = imageDTO.board_id ?? 'none';
const destinationBoard = overData.context.boardId; const destinationBoard = overData.context.boardId;
@ -51,7 +55,7 @@ export const isValidDrop = (overData: TypesafeDroppableData | undefined, active:
if (payloadType === 'GALLERY_SELECTION') { if (payloadType === 'GALLERY_SELECTION') {
// Assume all images are on the same board - this is true for the moment // Assume all images are on the same board - this is true for the moment
const currentBoard = active.data.current.payload.boardId; const currentBoard = activeData.payload.boardId;
const destinationBoard = overData.context.boardId; const destinationBoard = overData.context.boardId;
return currentBoard !== destinationBoard; return currentBoard !== destinationBoard;
} }
@ -69,14 +73,14 @@ export const isValidDrop = (overData: TypesafeDroppableData | undefined, active:
// Check if the image's board is the board we are dragging onto // Check if the image's board is the board we are dragging onto
if (payloadType === 'IMAGE_DTO') { if (payloadType === 'IMAGE_DTO') {
const { imageDTO } = active.data.current.payload; const { imageDTO } = activeData.payload;
const currentBoard = imageDTO.board_id ?? 'none'; const currentBoard = imageDTO.board_id ?? 'none';
return currentBoard !== 'none'; return currentBoard !== 'none';
} }
if (payloadType === 'GALLERY_SELECTION') { if (payloadType === 'GALLERY_SELECTION') {
const currentBoard = active.data.current.payload.boardId; const currentBoard = activeData.payload.boardId;
return currentBoard !== 'none'; return currentBoard !== 'none';
} }

View File

@ -41,7 +41,7 @@ const UnifiedCanvasTab = () => {
> >
<IAICanvasToolbar /> <IAICanvasToolbar />
<IAICanvas /> <IAICanvas />
{isValidDrop(droppableData, active) && ( {isValidDrop(droppableData, active?.data.current) && (
<IAIDropOverlay isOver={isOver} label={t('toast.setCanvasInitialImage')} /> <IAIDropOverlay isOver={isOver} label={t('toast.setCanvasInitialImage')} />
)} )}
</Flex> </Flex>