Skip to content

Commit

Permalink
fix(ui): restore missing image paste handler
Browse files Browse the repository at this point in the history
Missed migrating this logic over during dnd migration.
  • Loading branch information
psychedelicious committed Nov 8, 2024
1 parent 2d08078 commit 5b3e159
Showing 1 changed file with 58 additions and 30 deletions.
88 changes: 58 additions & 30 deletions invokeai/frontend/web/src/features/dnd/FullscreenDropzone.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import type { DndTargetState } from 'features/dnd/types';
import { selectAutoAddBoardId } from 'features/gallery/store/gallerySelectors';
import { selectMaxImageUploadCount } from 'features/system/store/configSlice';
import { toast } from 'features/toast/toast';
import { memo, useEffect, useRef, useState } from 'react';
import { memo, useCallback, useEffect, useMemo, useRef, useState } from 'react';
import { useTranslation } from 'react-i18next';
import { type UploadImageArg, uploadImages } from 'services/api/endpoints/images';
import { useBoardName } from 'services/api/hooks/useBoardName';
Expand Down Expand Up @@ -71,46 +71,54 @@ export const FullscreenDropzone = memo(() => {
const maxImageUploadCount = useAppSelector(selectMaxImageUploadCount);
const [dndState, setDndState] = useState<DndTargetState>('idle');

const uploadFilesSchema = useMemo(() => getFilesSchema(maxImageUploadCount), [maxImageUploadCount]);

const validateAndUploadFiles = useCallback(
(files: File[]) => {
const { getState } = getStore();
const parseResult = uploadFilesSchema.safeParse(files);

if (!parseResult.success) {
const description =
maxImageUploadCount === undefined
? t('toast.uploadFailedInvalidUploadDesc')
: t('toast.uploadFailedInvalidUploadDesc_withCount', { count: maxImageUploadCount });

toast({
id: 'UPLOAD_FAILED',
title: t('toast.uploadFailed'),
description,
status: 'error',
});
return;
}
const autoAddBoardId = selectAutoAddBoardId(getState());

const uploadArgs: UploadImageArg[] = files.map((file) => ({
file,
image_category: 'user',
is_intermediate: false,
board_id: autoAddBoardId === 'none' ? undefined : autoAddBoardId,
}));

uploadImages(uploadArgs);
},
[maxImageUploadCount, t, uploadFilesSchema]
);

useEffect(() => {
const element = ref.current;
if (!element) {
return;
}
const { getState } = getStore();
const uploadFilesSchema = getFilesSchema(maxImageUploadCount);

return combine(
dropTargetForExternal({
element,
canDrop: containsFiles,
onDrop: ({ source }) => {
const files = getFiles({ source });
const parseResult = uploadFilesSchema.safeParse(files);

if (!parseResult.success) {
const description =
maxImageUploadCount === undefined
? t('toast.uploadFailedInvalidUploadDesc')
: t('toast.uploadFailedInvalidUploadDesc_withCount', { count: maxImageUploadCount });

toast({
id: 'UPLOAD_FAILED',
title: t('toast.uploadFailed'),
description,
status: 'error',
});
return;
}
const autoAddBoardId = selectAutoAddBoardId(getState());

const uploadArgs: UploadImageArg[] = files.map((file) => ({
file,
image_category: 'user',
is_intermediate: false,
board_id: autoAddBoardId === 'none' ? undefined : autoAddBoardId,
}));

uploadImages(uploadArgs);
validateAndUploadFiles(files);
},
onDragEnter: () => {
setDndState('over');
Expand All @@ -131,7 +139,27 @@ export const FullscreenDropzone = memo(() => {
},
})
);
}, [maxImageUploadCount, t]);
}, [validateAndUploadFiles]);

useEffect(() => {
const controller = new AbortController();

document.addEventListener(
'paste',
(e) => {
if (!e.clipboardData?.files) {
return;
}
const files = Array.from(e.clipboardData.files);
validateAndUploadFiles(files);
},
{ signal: controller.signal }
);

return () => {
controller.abort();
};
}, [validateAndUploadFiles]);

return (
<Box ref={ref} data-dnd-state={dndState} sx={sx}>
Expand Down

0 comments on commit 5b3e159

Please sign in to comment.