mirror of
https://github.com/invoke-ai/InvokeAI.git
synced 2026-04-23 03:00:31 -04:00
fetching model image, still not working
This commit is contained in:
committed by
Kent Keirsey
parent
c1cdfd132b
commit
2f6964bfa5
@@ -0,0 +1,73 @@
|
||||
import { Box, IconButton, Image } from '@invoke-ai/ui-library';
|
||||
import { typedMemo } from 'common/util/typedMemo';
|
||||
import { useCallback } from 'react';
|
||||
import type { UseControllerProps } from 'react-hook-form';
|
||||
import { useController } from 'react-hook-form';
|
||||
import type { AnyModelConfig } from 'services/api/types';
|
||||
|
||||
import { Button } from '@invoke-ai/ui-library';
|
||||
import { useDropzone } from 'react-dropzone';
|
||||
import { PiArrowCounterClockwiseBold, PiUploadSimpleBold } from 'react-icons/pi';
|
||||
|
||||
const ModelImageUpload = (props: UseControllerProps<AnyModelConfig>) => {
|
||||
const { field } = useController(props);
|
||||
|
||||
const onDropAccepted = useCallback(
|
||||
(files: File[]) => {
|
||||
const file = files[0];
|
||||
|
||||
if (!file) {
|
||||
return;
|
||||
}
|
||||
|
||||
field.onChange(file);
|
||||
},
|
||||
[field]
|
||||
);
|
||||
|
||||
const handleResetControlImage = useCallback(() => {
|
||||
field.onChange(undefined);
|
||||
}, [field]);
|
||||
|
||||
console.log('field', field);
|
||||
|
||||
const { getInputProps, getRootProps } = useDropzone({
|
||||
accept: { 'image/png': ['.png'], 'image/jpeg': ['.jpg', '.jpeg', '.png'] },
|
||||
onDropAccepted,
|
||||
noDrag: true,
|
||||
multiple: false,
|
||||
});
|
||||
|
||||
if (field.value) {
|
||||
return (
|
||||
<Box>
|
||||
<Image
|
||||
src={field.value ? URL.createObjectURL(field.value) : 'http://localhost:5173/api/v2/models/i/6b8a6c0d68127ad8db5550f16d9a304b/image'}
|
||||
objectFit="contain"
|
||||
maxW="full"
|
||||
maxH="200px"
|
||||
borderRadius="base"
|
||||
/>
|
||||
<IconButton
|
||||
onClick={handleResetControlImage}
|
||||
aria-label="reset this image"
|
||||
tooltip="reset this image"
|
||||
icon={<PiArrowCounterClockwiseBold size={16} />}
|
||||
size="sm"
|
||||
variant="link"
|
||||
/>
|
||||
</Box>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
<Button leftIcon={<PiUploadSimpleBold />} {...getRootProps()} pointerEvents="auto">
|
||||
Upload Image
|
||||
</Button>
|
||||
<input {...getInputProps()} />
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default typedMemo(ModelImageUpload);
|
||||
@@ -1,18 +1,22 @@
|
||||
import { Box, IconButton, Image } from '@invoke-ai/ui-library';
|
||||
import { typedMemo } from 'common/util/typedMemo';
|
||||
import { useCallback } from 'react';
|
||||
import { useCallback, useEffect, useMemo } from 'react';
|
||||
import type { UseControllerProps } from 'react-hook-form';
|
||||
import { useController } from 'react-hook-form';
|
||||
import { useController, useWatch } from 'react-hook-form';
|
||||
import type { AnyModelConfig } from 'services/api/types';
|
||||
|
||||
import { Button } from '@invoke-ai/ui-library';
|
||||
import { useDropzone } from 'react-dropzone';
|
||||
import { PiArrowCounterClockwiseBold, PiUploadSimpleBold } from 'react-icons/pi';
|
||||
import IAIDndImageIcon from 'common/components/IAIDndImageIcon';
|
||||
import { useGetModelImageQuery } from 'services/api/endpoints/models';
|
||||
|
||||
const ModelImageUpload = (props: UseControllerProps<AnyModelConfig>) => {
|
||||
const { field } = useController(props);
|
||||
|
||||
const key = useWatch({ control: props.control, name: 'key' });
|
||||
|
||||
const { data } = useGetModelImageQuery(key);
|
||||
|
||||
const onDropAccepted = useCallback(
|
||||
(files: File[]) => {
|
||||
const file = files[0];
|
||||
@@ -30,8 +34,6 @@ const ModelImageUpload = (props: UseControllerProps<AnyModelConfig>) => {
|
||||
field.onChange(undefined);
|
||||
}, [field]);
|
||||
|
||||
console.log('field', field);
|
||||
|
||||
const { getInputProps, getRootProps } = useDropzone({
|
||||
accept: { 'image/png': ['.png'], 'image/jpeg': ['.jpg', '.jpeg', '.png'] },
|
||||
onDropAccepted,
|
||||
@@ -39,11 +41,20 @@ const ModelImageUpload = (props: UseControllerProps<AnyModelConfig>) => {
|
||||
multiple: false,
|
||||
});
|
||||
|
||||
if (field.value) {
|
||||
const image = useMemo(() => {
|
||||
console.log(field.value, 'asdf' );
|
||||
if (field.value) {
|
||||
return URL.createObjectURL(field.value);
|
||||
}
|
||||
|
||||
return data;
|
||||
}, [field.value, data]);
|
||||
|
||||
if (image) {
|
||||
return (
|
||||
<Box>
|
||||
<Image
|
||||
src={URL.createObjectURL(field.value)}
|
||||
src={image}
|
||||
objectFit="contain"
|
||||
maxW="full"
|
||||
maxH="200px"
|
||||
@@ -56,7 +67,6 @@ const ModelImageUpload = (props: UseControllerProps<AnyModelConfig>) => {
|
||||
icon={<PiArrowCounterClockwiseBold size={16} />}
|
||||
size="sm"
|
||||
variant="link"
|
||||
// sx={sx}
|
||||
/>
|
||||
</Box>
|
||||
);
|
||||
@@ -73,4 +83,3 @@ const ModelImageUpload = (props: UseControllerProps<AnyModelConfig>) => {
|
||||
};
|
||||
|
||||
export default typedMemo(ModelImageUpload);
|
||||
|
||||
|
||||
@@ -20,7 +20,11 @@ import type { SubmitHandler } from 'react-hook-form';
|
||||
import { useForm } from 'react-hook-form';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import type { UpdateModelArg } from 'services/api/endpoints/models';
|
||||
import { useGetModelConfigQuery, useUpdateModelMutation } from 'services/api/endpoints/models';
|
||||
import {
|
||||
useGetModelConfigQuery,
|
||||
useUpdateModelImageMutation,
|
||||
useUpdateModelsMutation,
|
||||
} from 'services/api/endpoints/models';
|
||||
|
||||
import BaseModelSelect from './Fields/BaseModelSelect';
|
||||
import ModelImageUpload from './Fields/ModelImageUpload';
|
||||
@@ -32,7 +36,8 @@ export const ModelEdit = () => {
|
||||
const selectedModelKey = useAppSelector((s) => s.modelmanagerV2.selectedModelKey);
|
||||
const { data, isLoading } = useGetModelConfigQuery(selectedModelKey ?? skipToken);
|
||||
|
||||
const [updateModel, { isLoading: isSubmitting }] = useUpdateModelMutation();
|
||||
const [updateModel, { isLoading: isSubmitting }] = useUpdateModelsMutation();
|
||||
const [updateModelImage] = useUpdateModelImageMutation();
|
||||
|
||||
const { t } = useTranslation();
|
||||
|
||||
@@ -55,11 +60,15 @@ export const ModelEdit = () => {
|
||||
return;
|
||||
}
|
||||
|
||||
// remove image from body
|
||||
const image = values.image;
|
||||
if (values.image) {
|
||||
delete values.image;
|
||||
}
|
||||
const responseBody: UpdateModelArg = {
|
||||
key: data.key,
|
||||
body: values,
|
||||
};
|
||||
console.log(responseBody, 'responseBody')
|
||||
|
||||
updateModel(responseBody)
|
||||
.unwrap()
|
||||
@@ -86,6 +95,33 @@ export const ModelEdit = () => {
|
||||
)
|
||||
);
|
||||
});
|
||||
if (image) {
|
||||
updateModelImage({ key: data.key, image: image })
|
||||
.unwrap()
|
||||
.then((payload) => {
|
||||
reset(payload, { keepDefaultValues: true });
|
||||
dispatch(setSelectedModelMode('view'));
|
||||
dispatch(
|
||||
addToast(
|
||||
makeToast({
|
||||
title: t('modelManager.modelUpdated'),
|
||||
status: 'success',
|
||||
})
|
||||
)
|
||||
);
|
||||
})
|
||||
.catch((_) => {
|
||||
reset();
|
||||
dispatch(
|
||||
addToast(
|
||||
makeToast({
|
||||
title: t('modelManager.modelUpdateFailed'),
|
||||
status: 'error',
|
||||
})
|
||||
)
|
||||
);
|
||||
});
|
||||
}
|
||||
},
|
||||
[dispatch, data?.key, reset, t, updateModel]
|
||||
);
|
||||
|
||||
@@ -23,7 +23,16 @@ export type UpdateModelArg = {
|
||||
body: paths['/api/v2/models/i/{key}']['patch']['requestBody']['content']['application/json'];
|
||||
};
|
||||
|
||||
export type UpdateModelImageArg = {
|
||||
key: paths['/api/v2/models/i/{key}/image']['patch']['parameters']['path']['key'];
|
||||
image: paths['/api/v2/models/i/{key}/image']['patch']['formData']['content']['multipart/form-data'];
|
||||
};
|
||||
|
||||
type UpdateModelResponse = paths['/api/v2/models/i/{key}']['patch']['responses']['200']['content']['application/json'];
|
||||
type UpdateModelImageResponse =
|
||||
paths['/api/v2/models/i/{key}/image']['patch']['responses']['200']['content']['application/json'];
|
||||
type GetModelImageResponse =
|
||||
paths['/api/v2/models/i/{key}/image']['get']['responses']['200']['content']['application/json'];
|
||||
|
||||
type GetModelConfigResponse = paths['/api/v2/models/i/{key}']['get']['responses']['200']['content']['application/json'];
|
||||
|
||||
@@ -144,6 +153,21 @@ export const modelsApi = api.injectEndpoints({
|
||||
},
|
||||
invalidatesTags: ['Model'],
|
||||
}),
|
||||
getModelImage: build.query<GetModelImageResponse, string>({
|
||||
query: (key) => buildModelsUrl(`i/${key}/image`),
|
||||
}),
|
||||
updateModelImage: build.mutation<UpdateModelImageResponse, UpdateModelImageArg>({
|
||||
query: ({ key, image }) => {
|
||||
const formData = new FormData();
|
||||
formData.append('image', image);
|
||||
return {
|
||||
url: buildModelsUrl(`i/${key}/image`),
|
||||
method: 'PATCH',
|
||||
body: formData,
|
||||
};
|
||||
},
|
||||
invalidatesTags: ['Model'],
|
||||
}),
|
||||
installModel: build.mutation<InstallModelResponse, InstallModelArg>({
|
||||
query: ({ source }) => {
|
||||
return {
|
||||
@@ -330,7 +354,9 @@ export const {
|
||||
useGetTextualInversionModelsQuery,
|
||||
useGetVaeModelsQuery,
|
||||
useDeleteModelsMutation,
|
||||
useUpdateModelMutation,
|
||||
useUpdateModelsMutation,
|
||||
useGetModelImageQuery,
|
||||
useUpdateModelImageMutation,
|
||||
useInstallModelMutation,
|
||||
useConvertModelMutation,
|
||||
useSyncModelsMutation,
|
||||
|
||||
File diff suppressed because one or more lines are too long
Reference in New Issue
Block a user