mirror of
https://github.com/invoke-ai/InvokeAI
synced 2024-08-30 20:32:17 +00:00
got model images displaying, still need to clean up types and unused code
This commit is contained in:
parent
86aef9f31d
commit
8a68355926
@ -374,11 +374,6 @@ AnyModelConfig = Annotated[
|
||||
|
||||
AnyModelConfigValidator = TypeAdapter(AnyModelConfig)
|
||||
|
||||
|
||||
class ModelImage(str, Enum):
|
||||
path: str
|
||||
|
||||
|
||||
class ModelConfigFactory(object):
|
||||
"""Class for parsing config dicts into StableDiffusion Config obects."""
|
||||
|
||||
|
6
invokeai/frontend/package-lock.json
generated
Normal file
6
invokeai/frontend/package-lock.json
generated
Normal file
@ -0,0 +1,6 @@
|
||||
{
|
||||
"name": "frontend",
|
||||
"lockfileVersion": 2,
|
||||
"requires": true,
|
||||
"packages": {}
|
||||
}
|
12557
invokeai/frontend/web/package-lock.json
generated
Normal file
12557
invokeai/frontend/web/package-lock.json
generated
Normal file
File diff suppressed because it is too large
Load Diff
@ -829,6 +829,7 @@
|
||||
"repo_id": "Repo ID",
|
||||
"repoIDValidationMsg": "Online repository of your model",
|
||||
"repoVariant": "Repo Variant",
|
||||
"resetImage": "Reset This Image",
|
||||
"safetensorModels": "SafeTensors",
|
||||
"sameFolder": "Same folder",
|
||||
"scan": "Scan",
|
||||
@ -853,6 +854,7 @@
|
||||
"triggerPhrases": "Trigger Phrases",
|
||||
"typePhraseHere": "Type phrase here",
|
||||
"upcastAttention": "Upcast Attention",
|
||||
"uploadImage":"Upload Image",
|
||||
"updateModel": "Update Model",
|
||||
"useCustomConfig": "Use Custom Config",
|
||||
"useDefaultSettings": "Use Default Settings",
|
||||
|
@ -0,0 +1,29 @@
|
||||
import { Box, Image } from '@invoke-ai/ui-library';
|
||||
import { typedMemo } from 'common/util/typedMemo';
|
||||
import { useState } from 'react';
|
||||
|
||||
import { buildModelsUrl } from 'services/api/endpoints/models';
|
||||
|
||||
type Props = {
|
||||
model_key: string;
|
||||
};
|
||||
|
||||
const ModelImage = ({ model_key }: Props) => {
|
||||
const [image, setImage] = useState<string | undefined>(buildModelsUrl(`i/${model_key}/image`));
|
||||
|
||||
if (!image) return <Box height="50px" width="50px"></Box>;
|
||||
|
||||
return (
|
||||
<Image
|
||||
onError={() => setImage(undefined)}
|
||||
src={image}
|
||||
objectFit="cover"
|
||||
objectPosition="50% 50%"
|
||||
height="50px"
|
||||
width="50px"
|
||||
borderRadius="base"
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
export default typedMemo(ModelImage);
|
@ -21,6 +21,7 @@ import { IoWarning } from 'react-icons/io5';
|
||||
import { PiTrashSimpleBold } from 'react-icons/pi';
|
||||
import { useDeleteModelsMutation } from 'services/api/endpoints/models';
|
||||
import type { AnyModelConfig } from 'services/api/types';
|
||||
import ModelImage from './ModelImage';
|
||||
|
||||
type ModelListItemProps = {
|
||||
model: AnyModelConfig;
|
||||
@ -73,6 +74,7 @@ const ModelListItem = (props: ModelListItemProps) => {
|
||||
|
||||
return (
|
||||
<Flex gap={2} alignItems="center" w="full">
|
||||
<ModelImage model_key={model.key} />
|
||||
<Flex
|
||||
as={Button}
|
||||
isChecked={isSelected}
|
||||
|
@ -1,21 +1,24 @@
|
||||
import { Box, IconButton, Image } from '@invoke-ai/ui-library';
|
||||
import { typedMemo } from 'common/util/typedMemo';
|
||||
import { useCallback, useEffect, useMemo } from 'react';
|
||||
import type { UseControllerProps } from 'react-hook-form';
|
||||
import { useCallback, useState } from 'react';
|
||||
import type { Control } 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 { useGetModelImageQuery } from 'services/api/endpoints/models';
|
||||
import { UpdateModelArg, buildModelsUrl } from 'services/api/endpoints/models';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
|
||||
const ModelImageUpload = (props: UseControllerProps<AnyModelConfig>) => {
|
||||
const { field } = useController(props);
|
||||
type Props = {
|
||||
control: Control<UpdateModelArg['body']>;
|
||||
};
|
||||
|
||||
const key = useWatch({ control: props.control, name: 'key' });
|
||||
|
||||
const { data } = useGetModelImageQuery(key);
|
||||
const ModelImageUpload = ({ control }: Props) => {
|
||||
const key = useWatch({ control, name: 'key' });
|
||||
const [image, setImage] = useState<string | undefined>(buildModelsUrl(`i/${key}/image`));
|
||||
const { field } = useController({ control, name: 'image' });
|
||||
const { t } = useTranslation();
|
||||
|
||||
const onDropAccepted = useCallback(
|
||||
(files: File[]) => {
|
||||
@ -26,12 +29,14 @@ const ModelImageUpload = (props: UseControllerProps<AnyModelConfig>) => {
|
||||
}
|
||||
|
||||
field.onChange(file);
|
||||
setImage(URL.createObjectURL(file));
|
||||
},
|
||||
[field]
|
||||
);
|
||||
|
||||
const handleResetControlImage = useCallback(() => {
|
||||
const handleResetImage = useCallback(() => {
|
||||
field.onChange(undefined);
|
||||
setImage(undefined);
|
||||
}, [field]);
|
||||
|
||||
const { getInputProps, getRootProps } = useDropzone({
|
||||
@ -41,29 +46,28 @@ const ModelImageUpload = (props: UseControllerProps<AnyModelConfig>) => {
|
||||
multiple: false,
|
||||
});
|
||||
|
||||
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>
|
||||
<Box
|
||||
position="relative"
|
||||
_hover={{ filter: 'brightness(50%)' }}
|
||||
transition="filter ease 0.2s"
|
||||
>
|
||||
<Image
|
||||
onError={() => setImage(undefined)}
|
||||
src={image}
|
||||
objectFit="contain"
|
||||
maxW="full"
|
||||
maxH="200px"
|
||||
maxH="100px"
|
||||
borderRadius="base"
|
||||
/>
|
||||
<IconButton
|
||||
onClick={handleResetControlImage}
|
||||
aria-label="reset this image"
|
||||
tooltip="reset this image"
|
||||
position="absolute"
|
||||
top="1"
|
||||
right="1"
|
||||
onClick={handleResetImage}
|
||||
aria-label={t('modelManager.resetImage')}
|
||||
tooltip={t('modelManager.resetImage')}
|
||||
icon={<PiArrowCounterClockwiseBold size={16} />}
|
||||
size="sm"
|
||||
variant="link"
|
||||
@ -75,7 +79,7 @@ const ModelImageUpload = (props: UseControllerProps<AnyModelConfig>) => {
|
||||
return (
|
||||
<>
|
||||
<Button leftIcon={<PiUploadSimpleBold />} {...getRootProps()} pointerEvents="auto">
|
||||
Upload Image
|
||||
{t('modelManager.uploadImage')}
|
||||
</Button>
|
||||
<input {...getInputProps()} />
|
||||
</>
|
||||
|
@ -168,7 +168,7 @@ export const ModelEdit = () => {
|
||||
|
||||
<Flex flexDir="column" gap={3} mt="4">
|
||||
<Flex gap="4" alignItems="center">
|
||||
<ModelImageUpload control={control} name="image" />
|
||||
<ModelImageUpload control={control} />
|
||||
<FormControl flexDir="column" alignItems="flex-start" gap={1}>
|
||||
<FormLabel>{t('modelManager.description')}</FormLabel>
|
||||
<Textarea fontSize="md" resize="none" {...register('description')} />
|
||||
|
@ -25,14 +25,12 @@ export type UpdateModelArg = {
|
||||
|
||||
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'];
|
||||
image: paths['/api/v2/models/i/{key}/image']['patch']['requestBody']['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'];
|
||||
|
||||
@ -139,7 +137,7 @@ const buildTransformResponse =
|
||||
* buildModelsUrl('some-path')
|
||||
* // '/api/v1/models/some-path'
|
||||
*/
|
||||
const buildModelsUrl = (path: string = '') => buildV2Url(`models/${path}`);
|
||||
export const buildModelsUrl = (path: string = '') => buildV2Url(`models/${path}`);
|
||||
|
||||
export const modelsApi = api.injectEndpoints({
|
||||
endpoints: (build) => ({
|
||||
@ -153,13 +151,10 @@ 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);
|
||||
formData.append('image', image.image);
|
||||
return {
|
||||
url: buildModelsUrl(`i/${key}/image`),
|
||||
method: 'PATCH',
|
||||
@ -354,8 +349,7 @@ export const {
|
||||
useGetTextualInversionModelsQuery,
|
||||
useGetVaeModelsQuery,
|
||||
useDeleteModelsMutation,
|
||||
useUpdateModelsMutation,
|
||||
useGetModelImageQuery,
|
||||
useUpdateModelMutation,
|
||||
useUpdateModelImageMutation,
|
||||
useInstallModelMutation,
|
||||
useConvertModelMutation,
|
||||
|
Loading…
Reference in New Issue
Block a user