diff --git a/invokeai/frontend/web/src/app/components/ImageDnd/ImageDndContext.tsx b/invokeai/frontend/web/src/app/components/ImageDnd/ImageDndContext.tsx index 9e8495aa63..6c76731d4c 100644 --- a/invokeai/frontend/web/src/app/components/ImageDnd/ImageDndContext.tsx +++ b/invokeai/frontend/web/src/app/components/ImageDnd/ImageDndContext.tsx @@ -3,6 +3,11 @@ import { DragEndEvent, DragOverlay, DragStartEvent, + KeyboardSensor, + MouseSensor, + TouchSensor, + useSensor, + useSensors, } from '@dnd-kit/core'; import { PropsWithChildren, memo, useCallback, useState } from 'react'; import OverlayDragImage from './OverlayDragImage'; @@ -32,8 +37,23 @@ const ImageDndContext = (props: ImageDndContextProps) => { [draggedImage] ); + const mouseSensor = useSensor(MouseSensor, { + activationConstraint: { distance: 15 }, + }); + + const touchSensor = useSensor(TouchSensor, { + activationConstraint: { distance: 15 }, + }); + const keyboardSensor = useSensor(KeyboardSensor); + + const sensors = useSensors(mouseSensor, touchSensor, keyboardSensor); + return ( - + {props.children} {draggedImage && } diff --git a/invokeai/frontend/web/src/app/components/ImageDnd/OverlayDragImage.tsx b/invokeai/frontend/web/src/app/components/ImageDnd/OverlayDragImage.tsx index 59fe6a7971..25a5fe2449 100644 --- a/invokeai/frontend/web/src/app/components/ImageDnd/OverlayDragImage.tsx +++ b/invokeai/frontend/web/src/app/components/ImageDnd/OverlayDragImage.tsx @@ -10,8 +10,8 @@ const OverlayDragImage = (props: OverlayDragImageProps) => { return ( { - const dispatch = useAppDispatch(); - const { t } = useTranslation(); - const { openUploader } = useImageUploader(); - - const handleResetInitialImage = useCallback(() => { - dispatch(clearInitialImage()); - }, [dispatch]); - - return ( - - - {t('parameters.initialImage')} - - - - } - aria-label={t('accessibility.reset')} - onClick={handleResetInitialImage} - /> - } - onClick={openUploader} - aria-label={t('common.upload')} - /> - - - ); -}; - -export default InitialImageButtons; diff --git a/invokeai/frontend/web/src/features/controlNet/components/parameters/IAISelectableImage.tsx b/invokeai/frontend/web/src/features/controlNet/components/parameters/IAISelectableImage.tsx index 25277269ed..635c192db1 100644 --- a/invokeai/frontend/web/src/features/controlNet/components/parameters/IAISelectableImage.tsx +++ b/invokeai/frontend/web/src/features/controlNet/components/parameters/IAISelectableImage.tsx @@ -14,7 +14,7 @@ import { useGetUrl } from 'common/util/getUrl'; import { AnimatePresence, motion } from 'framer-motion'; import { SyntheticEvent } from 'react'; import { memo, useRef } from 'react'; -import { FaImage, FaUndo } from 'react-icons/fa'; +import { FaImage, FaTimes } from 'react-icons/fa'; import { ImageDTO } from 'services/api'; import { v4 as uuidv4 } from 'uuid'; @@ -53,9 +53,8 @@ const IAISelectableImage = (props: IAISelectableImageProps) => { {image && ( { } + icon={} onClick={onReset} /> @@ -184,7 +183,7 @@ const DropOverlay = (props: DropOverlayProps) => { transitionDuration: '0.15s', }} > - + Drop Image diff --git a/invokeai/frontend/web/src/features/gallery/components/CurrentImageDisplay.tsx b/invokeai/frontend/web/src/features/gallery/components/CurrentImageDisplay.tsx index 5810c599c1..621ec8864b 100644 --- a/invokeai/frontend/web/src/features/gallery/components/CurrentImageDisplay.tsx +++ b/invokeai/frontend/web/src/features/gallery/components/CurrentImageDisplay.tsx @@ -1,4 +1,4 @@ -import { Flex, Icon } from '@chakra-ui/react'; +import { Box, Flex, Icon } from '@chakra-ui/react'; import { createSelector } from '@reduxjs/toolkit'; import { useAppSelector } from 'app/store/storeHooks'; import { systemSelector } from 'features/system/store/systemSelectors'; @@ -55,10 +55,7 @@ const CurrentImageDisplay = () => { }} > {hasAnImageToDisplay ? ( - <> - - - + ) : ( { /> )} + {hasAnImageToDisplay && ( + + + + )} ); }; diff --git a/invokeai/frontend/web/src/features/gallery/components/CurrentImagePreview.tsx b/invokeai/frontend/web/src/features/gallery/components/CurrentImagePreview.tsx index 280d859b87..f8194f5ad4 100644 --- a/invokeai/frontend/web/src/features/gallery/components/CurrentImagePreview.tsx +++ b/invokeai/frontend/web/src/features/gallery/components/CurrentImagePreview.tsx @@ -15,6 +15,7 @@ import ImageMetadataOverlay from 'common/components/ImageMetadataOverlay'; import { configSelector } from '../../system/store/configSelectors'; import { useAppToaster } from 'app/components/Toaster'; import { imageSelected } from '../store/gallerySlice'; +import { useDraggable } from '@dnd-kit/core'; export const imagesSelector = createSelector( [uiSelector, gallerySelector, systemSelector], @@ -46,7 +47,6 @@ const CurrentImagePreview = () => { const { shouldShowImageDetails, image, - shouldHidePreview, progressImage, shouldShowProgressInViewer, shouldAntialiasProgressImage, @@ -56,16 +56,12 @@ const CurrentImagePreview = () => { const toaster = useAppToaster(); const dispatch = useAppDispatch(); - const handleDragStart = useCallback( - (e: DragEvent) => { - if (!image) { - return; - } - e.dataTransfer.setData('invokeai/imageName', image.image_name); - e.dataTransfer.effectAllowed = 'move'; + const { attributes, listeners, setNodeRef } = useDraggable({ + id: `currentImage_${image?.image_name}`, + data: { + image, }, - [image] - ); + }); const handleError = useCallback(() => { dispatch(imageSelected()); @@ -105,24 +101,32 @@ const CurrentImagePreview = () => { /> ) : ( image && ( - <> + } - onDragStart={handleDragStart} sx={{ objectFit: 'contain', maxWidth: '100%', maxHeight: '100%', height: 'auto', - position: 'absolute', borderRadius: 'base', + touchAction: 'none', }} onError={handleError} /> - + ) )} {shouldShowImageDetails && image && 'metadata' in image && ( diff --git a/invokeai/frontend/web/src/features/gallery/components/HoverableImage.tsx b/invokeai/frontend/web/src/features/gallery/components/HoverableImage.tsx index c1fe2569e3..4dad27d4e8 100644 --- a/invokeai/frontend/web/src/features/gallery/components/HoverableImage.tsx +++ b/invokeai/frontend/web/src/features/gallery/components/HoverableImage.tsx @@ -40,7 +40,6 @@ import { import { useAppToaster } from 'app/components/Toaster'; import { ImageDTO } from 'services/api'; import { useDraggable } from '@dnd-kit/core'; -import { CSS } from '@dnd-kit/utilities'; export const selector = createSelector( [gallerySelector, systemSelector, lightboxSelector, activeTabNameSelector], @@ -120,7 +119,7 @@ const HoverableImage = memo((props: HoverableImageProps) => { useRecallParameters(); const { attributes, listeners, setNodeRef } = useDraggable({ - id: image_name, + id: `galleryImage_${image_name}`, data: { image, }, @@ -153,14 +152,6 @@ const HoverableImage = memo((props: HoverableImageProps) => { dispatch(imageSelected(image)); }, [image, dispatch]); - const handleDragStart = useCallback( - (e: DragEvent) => { - e.dataTransfer.setData('invokeai/imageName', image.image_name); - e.dataTransfer.effectAllowed = 'move'; - }, - [image] - ); - // Recall parameters handlers const handleRecallPrompt = useCallback(() => { recallBothPrompts( @@ -225,7 +216,7 @@ const HoverableImage = memo((props: HoverableImageProps) => { ref={setNodeRef} {...listeners} {...attributes} - sx={{ w: 'full', h: 'full' }} + sx={{ w: 'full', h: 'full', touchAction: 'none' }} > menuProps={{ size: 'sm', isLazy: true }} diff --git a/invokeai/frontend/web/src/features/nodes/components/fields/ImageInputFieldComponent.tsx b/invokeai/frontend/web/src/features/nodes/components/fields/ImageInputFieldComponent.tsx index 1232ff28e1..9889ade2f3 100644 --- a/invokeai/frontend/web/src/features/nodes/components/fields/ImageInputFieldComponent.tsx +++ b/invokeai/frontend/web/src/features/nodes/components/fields/ImageInputFieldComponent.tsx @@ -32,6 +32,16 @@ const ImageInputFieldComponent = ( [dispatch, field.name, nodeId] ); + const handleReset = useCallback(() => { + dispatch( + fieldValueChanged({ + nodeId, + fieldName: field.name, + value: undefined, + }) + ); + }, [dispatch, field.name, nodeId]); + return ( - + ); }; diff --git a/invokeai/frontend/web/src/features/parameters/components/Parameters/ImageToImage/InitialImageDisplay.tsx b/invokeai/frontend/web/src/features/parameters/components/Parameters/ImageToImage/InitialImageDisplay.tsx index 1746c9b592..64974f0d35 100644 --- a/invokeai/frontend/web/src/features/parameters/components/Parameters/ImageToImage/InitialImageDisplay.tsx +++ b/invokeai/frontend/web/src/features/parameters/components/Parameters/ImageToImage/InitialImageDisplay.tsx @@ -1,6 +1,5 @@ import { Flex } from '@chakra-ui/react'; import InitialImagePreview from './InitialImagePreview'; -import InitialImageButtons from 'common/components/InitialImageButtons'; const InitialImageDisplay = () => { return ( diff --git a/invokeai/frontend/web/src/features/parameters/components/Parameters/ImageToImage/InitialImagePreview.tsx b/invokeai/frontend/web/src/features/parameters/components/Parameters/ImageToImage/InitialImagePreview.tsx index 8cd7b99dc5..2a0ed4ab5d 100644 --- a/invokeai/frontend/web/src/features/parameters/components/Parameters/ImageToImage/InitialImagePreview.tsx +++ b/invokeai/frontend/web/src/features/parameters/components/Parameters/ImageToImage/InitialImagePreview.tsx @@ -1,4 +1,4 @@ -import { Flex, Icon, Image } from '@chakra-ui/react'; +import { Flex } from '@chakra-ui/react'; import { createSelector } from '@reduxjs/toolkit'; import { useAppDispatch, useAppSelector } from 'app/store/storeHooks'; import { useGetUrl } from 'common/util/getUrl'; @@ -6,14 +6,10 @@ import { clearInitialImage, initialImageChanged, } from 'features/parameters/store/generationSlice'; -import { DragEvent, useCallback } from 'react'; +import { useCallback } from 'react'; import { useTranslation } from 'react-i18next'; -import ImageMetadataOverlay from 'common/components/ImageMetadataOverlay'; import { generationSelector } from 'features/parameters/store/generationSelectors'; -import { initialImageSelected } from 'features/parameters/store/actions'; import { defaultSelectorOptions } from 'app/store/util/defaultMemoizeOptions'; -import ImageFallbackSpinner from 'features/gallery/components/ImageFallbackSpinner'; -import { FaImage } from 'react-icons/fa'; import { configSelector } from '../../../../system/store/configSelectors'; import { useAppToaster } from 'app/components/Toaster'; import IAISelectableImage from 'features/controlNet/components/parameters/IAISelectableImage'; @@ -76,41 +72,12 @@ const InitialImagePreview = () => { alignItems: 'center', justifyContent: 'center', }} - // onDrop={handleDrop} > - {/* {initialImage?.image_url && ( - <> - } - onError={handleError} - sx={{ - objectFit: 'contain', - maxWidth: '100%', - maxHeight: '100%', - height: 'auto', - position: 'absolute', - borderRadius: 'base', - }} - /> - - - )} - {!initialImage?.image_url && ( - - )} */} ); };