feat(ui): use dropzone for style preset upload

Easier to accept multiple file types and supper drag and drop in the future.
This commit is contained in:
psychedelicious 2024-08-15 14:40:42 +10:00 committed by Mary Hipp Rogers
parent 76b0380b5f
commit 15415c6d85

View File

@ -1,8 +1,8 @@
import type { SystemStyleObject } from '@invoke-ai/ui-library';
import { IconButton, spinAnimation, Text } from '@invoke-ai/ui-library';
import { toast } from 'features/toast/toast';
import type { ChangeEvent } from 'react';
import { useCallback, useRef } from 'react';
import { useCallback } from 'react';
import { useDropzone } from 'react-dropzone';
import { useTranslation } from 'react-i18next';
import { PiSpinner, PiUploadBold } from 'react-icons/pi';
import { useImportStylePresetsMutation } from 'services/api/endpoints/stylePresets';
@ -13,44 +13,39 @@ const loadingStyles: SystemStyleObject = {
export const StylePresetImport = () => {
const [importStylePresets, { isLoading }] = useImportStylePresetsMutation();
const fileInputRef = useRef<HTMLInputElement>(null);
const { t } = useTranslation();
const handleClickUpload = useCallback(() => {
if (fileInputRef.current) {
fileInputRef.current.click();
}
}, [fileInputRef]);
const handleFileChange = useCallback(
async (event: ChangeEvent<HTMLInputElement>) => {
if (event.target.files) {
const file = event.target.files[0];
if (!file) {
return;
}
try {
await importStylePresets(file).unwrap();
toast({
status: 'success',
title: t('toast.importSuccessful'),
});
} catch (error) {
toast({
status: 'error',
title: t('toast.importFailed'),
});
}
const onDropAccepted = useCallback(
async (files: File[]) => {
const file = files[0];
if (!file) {
return;
}
try {
await importStylePresets(file).unwrap();
toast({
status: 'success',
title: t('toast.importSuccessful'),
});
} catch (error) {
toast({
status: 'error',
title: t('toast.importFailed'),
});
}
},
[importStylePresets, t]
);
return (
<div>
<input type="file" accept=".csv" onChange={handleFileChange} hidden ref={fileInputRef} />
const { getInputProps, getRootProps } = useDropzone({
accept: { 'text/csv': ['.csv'], 'application/json': ['.json'] },
onDropAccepted,
noDrag: true,
multiple: false,
});
return (
<>
<IconButton
icon={!isLoading ? <PiUploadBold /> : <PiSpinner />}
tooltip={
@ -60,14 +55,15 @@ export const StylePresetImport = () => {
</>
}
aria-label={t('stylePresets.importTemplates')}
onClick={handleClickUpload}
size="md"
variant="link"
w={8}
h={8}
sx={isLoading ? loadingStyles : undefined}
isDisabled={isLoading}
{...getRootProps()}
/>
</div>
<input {...getInputProps()} />
</>
);
};