diff --git a/invokeai/frontend/web/src/common/hooks/useImageUploadButton.tsx b/invokeai/frontend/web/src/common/hooks/useImageUploadButton.tsx index ff53b8ec79..9a06dab639 100644 --- a/invokeai/frontend/web/src/common/hooks/useImageUploadButton.tsx +++ b/invokeai/frontend/web/src/common/hooks/useImageUploadButton.tsx @@ -6,7 +6,7 @@ import { selectAutoAddBoardId } from 'features/gallery/store/gallerySelectors'; import { selectIsClientSideUploadEnabled } from 'features/system/store/configSlice'; import { toast } from 'features/toast/toast'; import { memo, useCallback } from 'react'; -import type { FileRejection } from 'react-dropzone'; +import type { Accept, FileRejection } from 'react-dropzone'; import { useDropzone } from 'react-dropzone'; import { useTranslation } from 'react-i18next'; import { PiUploadBold } from 'react-icons/pi'; @@ -15,6 +15,18 @@ import type { ImageDTO } from 'services/api/types'; import { assert } from 'tsafe'; import type { SetOptional } from 'type-fest'; +const addUpperCaseReducer = (acc: string[], ext: string) => { + acc.push(ext); + acc.push(ext.toUpperCase()); + return acc; +}; + +export const dropzoneAccept: Accept = { + 'image/png': ['.png'].reduce(addUpperCaseReducer, [] as string[]), + 'image/jpeg': ['.jpg', '.jpeg', '.png'].reduce(addUpperCaseReducer, [] as string[]), + 'image/webp': ['.webp'].reduce(addUpperCaseReducer, [] as string[]), +}; + import { useClientSideUpload } from './useClientSideUpload'; type UseImageUploadButtonArgs = | { @@ -164,11 +176,7 @@ export const useImageUploadButton = ({ getInputProps: getUploadInputProps, open: openUploader, } = useDropzone({ - accept: { - 'image/png': ['.png'], - 'image/jpeg': ['.jpg', '.jpeg', '.png'], - 'image/webp': ['.webp'], - }, + accept: dropzoneAccept, onDropAccepted, onDropRejected, disabled: isDisabled, diff --git a/invokeai/frontend/web/src/features/dnd/FullscreenDropzone.tsx b/invokeai/frontend/web/src/features/dnd/FullscreenDropzone.tsx index 0481a32251..bb890ed7eb 100644 --- a/invokeai/frontend/web/src/features/dnd/FullscreenDropzone.tsx +++ b/invokeai/frontend/web/src/features/dnd/FullscreenDropzone.tsx @@ -41,13 +41,13 @@ const zUploadFile = z // ) .refine( (file) => { - return ACCEPTED_IMAGE_TYPES.includes(file.type); + return ACCEPTED_IMAGE_TYPES.includes(file.type.toLowerCase()); }, { message: `File type is not supported` } ) .refine( (file) => { - return ACCEPTED_FILE_EXTENSIONS.some((ext) => file.name.endsWith(ext)); + return ACCEPTED_FILE_EXTENSIONS.some((ext) => file.name.toLowerCase().endsWith(ext)); }, { message: `File extension is not supported` } ); diff --git a/invokeai/frontend/web/src/features/modelManagerV2/subpanels/ModelPanel/Fields/ModelImageUpload.tsx b/invokeai/frontend/web/src/features/modelManagerV2/subpanels/ModelPanel/Fields/ModelImageUpload.tsx index d6ec53e33d..cde9955236 100644 --- a/invokeai/frontend/web/src/features/modelManagerV2/subpanels/ModelPanel/Fields/ModelImageUpload.tsx +++ b/invokeai/frontend/web/src/features/modelManagerV2/subpanels/ModelPanel/Fields/ModelImageUpload.tsx @@ -1,4 +1,5 @@ import { Box, IconButton, Image } from '@invoke-ai/ui-library'; +import { dropzoneAccept } from 'common/hooks/useImageUploadButton'; import { typedMemo } from 'common/util/typedMemo'; import { toast } from 'features/toast/toast'; import { useCallback, useState } from 'react'; @@ -72,11 +73,7 @@ const ModelImageUpload = ({ model_key, model_image }: Props) => { }, [model_key, t, deleteModelImage]); const { getInputProps, getRootProps } = useDropzone({ - accept: { - 'image/png': ['.png'], - 'image/jpeg': ['.jpg', '.jpeg', '.png'], - 'image/webp': ['.webp'], - }, + accept: dropzoneAccept, onDropAccepted, noDrag: true, multiple: false, diff --git a/invokeai/frontend/web/src/features/nodes/components/sidePanel/workflow/WorkflowThumbnail/WorkflowThumbnailField.tsx b/invokeai/frontend/web/src/features/nodes/components/sidePanel/workflow/WorkflowThumbnail/WorkflowThumbnailField.tsx index 3438084904..6416baf41f 100644 --- a/invokeai/frontend/web/src/features/nodes/components/sidePanel/workflow/WorkflowThumbnail/WorkflowThumbnailField.tsx +++ b/invokeai/frontend/web/src/features/nodes/components/sidePanel/workflow/WorkflowThumbnail/WorkflowThumbnailField.tsx @@ -1,4 +1,5 @@ import { Box, Button, Flex, Icon, IconButton, Image, Tooltip } from '@invoke-ai/ui-library'; +import { dropzoneAccept } from 'common/hooks/useImageUploadButton'; import { convertImageUrlToBlob } from 'common/util/convertImageUrlToBlob'; import { useCallback, useEffect, useState } from 'react'; import { useDropzone } from 'react-dropzone'; @@ -53,7 +54,7 @@ export const WorkflowThumbnailField = ({ }, [onChange]); const { getInputProps, getRootProps } = useDropzone({ - accept: { 'image/png': ['.png'], 'image/jpeg': ['.jpg', '.jpeg', '.png'] }, + accept: dropzoneAccept, onDropAccepted, noDrag: true, multiple: false, diff --git a/invokeai/frontend/web/src/features/stylePresets/components/StylePresetForm/StylePresetImageField.tsx b/invokeai/frontend/web/src/features/stylePresets/components/StylePresetForm/StylePresetImageField.tsx index 38eaac471a..089293d4e7 100644 --- a/invokeai/frontend/web/src/features/stylePresets/components/StylePresetForm/StylePresetImageField.tsx +++ b/invokeai/frontend/web/src/features/stylePresets/components/StylePresetForm/StylePresetImageField.tsx @@ -1,4 +1,5 @@ import { Box, Button, Flex, Icon, IconButton, Image, Tooltip } from '@invoke-ai/ui-library'; +import { dropzoneAccept } from 'common/hooks/useImageUploadButton'; import { useCallback } from 'react'; import { useDropzone } from 'react-dropzone'; import type { UseControllerProps } from 'react-hook-form'; @@ -26,7 +27,7 @@ export const StylePresetImageField = (props: UseControllerProps