From fd457955bcfa1e4d8db3e7950a1c5ea58be09860 Mon Sep 17 00:00:00 2001 From: psychedelicious <4822129+psychedelicious@users.noreply.github.com> Date: Fri, 8 Mar 2024 20:22:37 +1100 Subject: [PATCH] feat(ui): update default settings for control adapters - Split out main model defaults - Add controlnet/t2i defaults (which includes only the preprocessor) --- .../listeners/setDefaultSettings.ts | 78 +++++----- .../controlAdapters/store/constants.ts | 20 --- .../controlAdapters/store/types.test.ts | 5 +- ...seControlNetOrT2IAdapterDefaultSettings.ts | 23 +++ .../ControlNetOrT2IAdapterDefaultSettings.tsx | 105 +++++++++++++ .../DefaultPreprocessor.tsx | 66 ++++++++ .../DefaultCfgRescaleMultiplier.tsx | 8 +- .../DefaultCfgScale.tsx | 8 +- .../DefaultScheduler.tsx | 8 +- .../DefaultSettingsForm.tsx | 141 ------------------ .../MainModelDefaultSettings/DefaultSteps.tsx | 8 +- .../MainModelDefaultSettings/DefaultVae.tsx | 8 +- .../DefaultVaePrecision.tsx | 8 +- .../MainModelDefaultSettings.tsx | 9 +- .../subpanels/ModelPanel/ModelView.tsx | 6 + .../SettingToggle.tsx | 4 +- 16 files changed, 273 insertions(+), 232 deletions(-) create mode 100644 invokeai/frontend/web/src/features/modelManagerV2/hooks/useControlNetOrT2IAdapterDefaultSettings.ts create mode 100644 invokeai/frontend/web/src/features/modelManagerV2/subpanels/ModelPanel/ControlNetOrT2IAdapterDefaultSettings/ControlNetOrT2IAdapterDefaultSettings.tsx create mode 100644 invokeai/frontend/web/src/features/modelManagerV2/subpanels/ModelPanel/ControlNetOrT2IAdapterDefaultSettings/DefaultPreprocessor.tsx delete mode 100644 invokeai/frontend/web/src/features/modelManagerV2/subpanels/ModelPanel/MainModelDefaultSettings/DefaultSettingsForm.tsx rename invokeai/frontend/web/src/features/modelManagerV2/subpanels/ModelPanel/{MainModelDefaultSettings => }/SettingToggle.tsx (79%) diff --git a/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/setDefaultSettings.ts b/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/setDefaultSettings.ts index da7cf6b6fe..e76f9de8f0 100644 --- a/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/setDefaultSettings.ts +++ b/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/setDefaultSettings.ts @@ -21,6 +21,7 @@ import { makeToast } from 'features/system/util/makeToast'; import { t } from 'i18next'; import { map } from 'lodash-es'; import { modelsApi } from 'services/api/endpoints/models'; +import { isNonRefinerMainModelConfig } from 'services/api/types'; export const addSetDefaultSettingsListener = (startAppListening: AppStartListening) => { startAppListening({ @@ -36,61 +37,64 @@ export const addSetDefaultSettingsListener = (startAppListening: AppStartListeni const modelConfig = await dispatch(modelsApi.endpoints.getModelConfig.initiate(currentModel.key)).unwrap(); - if (!modelConfig || !modelConfig.default_settings) { + if (!modelConfig) { return; } - const { vae, vae_precision, cfg_scale, cfg_rescale_multiplier, steps, scheduler } = modelConfig.default_settings; + if (isNonRefinerMainModelConfig(modelConfig) && modelConfig.default_settings) { + const { vae, vae_precision, cfg_scale, cfg_rescale_multiplier, steps, scheduler } = + modelConfig.default_settings; - if (vae) { - // we store this as "default" within default settings - // to distinguish it from no default set - if (vae === 'default') { - dispatch(vaeSelected(null)); - } else { - const { data } = modelsApi.endpoints.getVaeModels.select()(state); - const vaeArray = map(data?.entities); - const validVae = vaeArray.find((model) => model.key === vae); + if (vae) { + // we store this as "default" within default settings + // to distinguish it from no default set + if (vae === 'default') { + dispatch(vaeSelected(null)); + } else { + const { data } = modelsApi.endpoints.getVaeModels.select()(state); + const vaeArray = map(data?.entities); + const validVae = vaeArray.find((model) => model.key === vae); - const result = zParameterVAEModel.safeParse(validVae); - if (!result.success) { - return; + const result = zParameterVAEModel.safeParse(validVae); + if (!result.success) { + return; + } + dispatch(vaeSelected(result.data)); } - dispatch(vaeSelected(result.data)); } - } - if (vae_precision) { - if (isParameterPrecision(vae_precision)) { - dispatch(vaePrecisionChanged(vae_precision)); + if (vae_precision) { + if (isParameterPrecision(vae_precision)) { + dispatch(vaePrecisionChanged(vae_precision)); + } } - } - if (cfg_scale) { - if (isParameterCFGScale(cfg_scale)) { - dispatch(setCfgScale(cfg_scale)); + if (cfg_scale) { + if (isParameterCFGScale(cfg_scale)) { + dispatch(setCfgScale(cfg_scale)); + } } - } - if (cfg_rescale_multiplier) { - if (isParameterCFGRescaleMultiplier(cfg_rescale_multiplier)) { - dispatch(setCfgRescaleMultiplier(cfg_rescale_multiplier)); + if (cfg_rescale_multiplier) { + if (isParameterCFGRescaleMultiplier(cfg_rescale_multiplier)) { + dispatch(setCfgRescaleMultiplier(cfg_rescale_multiplier)); + } } - } - if (steps) { - if (isParameterSteps(steps)) { - dispatch(setSteps(steps)); + if (steps) { + if (isParameterSteps(steps)) { + dispatch(setSteps(steps)); + } } - } - if (scheduler) { - if (isParameterScheduler(scheduler)) { - dispatch(setScheduler(scheduler)); + if (scheduler) { + if (isParameterScheduler(scheduler)) { + dispatch(setScheduler(scheduler)); + } } - } - dispatch(addToast(makeToast({ title: t('toast.parameterSet', { parameter: 'Default settings' }) }))); + dispatch(addToast(makeToast({ title: t('toast.parameterSet', { parameter: 'Default settings' }) }))); + } }, }); }; diff --git a/invokeai/frontend/web/src/features/controlAdapters/store/constants.ts b/invokeai/frontend/web/src/features/controlAdapters/store/constants.ts index 01c7d4217f..91f792bf97 100644 --- a/invokeai/frontend/web/src/features/controlAdapters/store/constants.ts +++ b/invokeai/frontend/web/src/features/controlAdapters/store/constants.ts @@ -253,23 +253,3 @@ export const CONTROLNET_PROCESSORS: ControlNetProcessorsDict = { }, }, }; - -export const CONTROLNET_MODEL_DEFAULT_PROCESSORS: { - [key: string]: ControlAdapterProcessorType; -} = { - canny: 'canny_image_processor', - mlsd: 'mlsd_image_processor', - depth: 'depth_anything_image_processor', - bae: 'normalbae_image_processor', - sketch: 'pidi_image_processor', - scribble: 'lineart_image_processor', - lineart: 'lineart_image_processor', - lineart_anime: 'lineart_anime_image_processor', - softedge: 'hed_image_processor', - shuffle: 'content_shuffle_image_processor', - openpose: 'dw_openpose_image_processor', - mediapipe: 'mediapipe_face_processor', - pidi: 'pidi_image_processor', - zoe: 'zoe_depth_image_processor', - color: 'color_map_image_processor', -}; diff --git a/invokeai/frontend/web/src/features/controlAdapters/store/types.test.ts b/invokeai/frontend/web/src/features/controlAdapters/store/types.test.ts index 143f5ff3d4..3bde8bc6c6 100644 --- a/invokeai/frontend/web/src/features/controlAdapters/store/types.test.ts +++ b/invokeai/frontend/web/src/features/controlAdapters/store/types.test.ts @@ -1,7 +1,4 @@ -import type { - ControlAdapterProcessorType, - zControlAdapterProcessorType, -} from 'features/controlAdapters/store/types'; +import type { ControlAdapterProcessorType, zControlAdapterProcessorType } from 'features/controlAdapters/store/types'; import type { Equals } from 'tsafe'; import { assert } from 'tsafe'; import { describe, test } from 'vitest'; diff --git a/invokeai/frontend/web/src/features/modelManagerV2/hooks/useControlNetOrT2IAdapterDefaultSettings.ts b/invokeai/frontend/web/src/features/modelManagerV2/hooks/useControlNetOrT2IAdapterDefaultSettings.ts new file mode 100644 index 0000000000..826bec17b1 --- /dev/null +++ b/invokeai/frontend/web/src/features/modelManagerV2/hooks/useControlNetOrT2IAdapterDefaultSettings.ts @@ -0,0 +1,23 @@ +import { skipToken } from '@reduxjs/toolkit/query'; +import { isNil } from 'lodash-es'; +import { useMemo } from 'react'; +import { useGetModelConfigWithTypeGuard } from 'services/api/hooks/useGetModelConfigWithTypeGuard'; +import { isControlNetOrT2IAdapterModelConfig } from 'services/api/types'; + +export const useControlNetOrT2IAdapterDefaultSettings = (modelKey?: string | null) => { + const { modelConfig, isLoading } = useGetModelConfigWithTypeGuard( + modelKey ?? skipToken, + isControlNetOrT2IAdapterModelConfig + ); + + const defaultSettingsDefaults = useMemo(() => { + return { + preprocessor: { + isEnabled: !isNil(modelConfig?.default_settings?.preprocessor), + value: modelConfig?.default_settings?.preprocessor || 'none', + }, + }; + }, [modelConfig?.default_settings]); + + return { defaultSettingsDefaults, isLoading }; +}; diff --git a/invokeai/frontend/web/src/features/modelManagerV2/subpanels/ModelPanel/ControlNetOrT2IAdapterDefaultSettings/ControlNetOrT2IAdapterDefaultSettings.tsx b/invokeai/frontend/web/src/features/modelManagerV2/subpanels/ModelPanel/ControlNetOrT2IAdapterDefaultSettings/ControlNetOrT2IAdapterDefaultSettings.tsx new file mode 100644 index 0000000000..d54320b9dd --- /dev/null +++ b/invokeai/frontend/web/src/features/modelManagerV2/subpanels/ModelPanel/ControlNetOrT2IAdapterDefaultSettings/ControlNetOrT2IAdapterDefaultSettings.tsx @@ -0,0 +1,105 @@ +import { Button, Flex, Heading, Text } from '@invoke-ai/ui-library'; +import { useAppDispatch, useAppSelector } from 'app/store/storeHooks'; +import { useControlNetOrT2IAdapterDefaultSettings } from 'features/modelManagerV2/hooks/useControlNetOrT2IAdapterDefaultSettings'; +import { DefaultPreprocessor } from 'features/modelManagerV2/subpanels/ModelPanel/ControlNetOrT2IAdapterDefaultSettings/DefaultPreprocessor'; +import type { FormField } from 'features/modelManagerV2/subpanels/ModelPanel/MainModelDefaultSettings/MainModelDefaultSettings'; +import { addToast } from 'features/system/store/systemSlice'; +import { makeToast } from 'features/system/util/makeToast'; +import { useCallback } from 'react'; +import type { SubmitHandler } from 'react-hook-form'; +import { useForm } from 'react-hook-form'; +import { useTranslation } from 'react-i18next'; +import { PiCheckBold } from 'react-icons/pi'; +import { useUpdateModelMutation } from 'services/api/endpoints/models'; + +export type ControlNetOrT2IAdapterDefaultSettingsFormData = { + preprocessor: FormField; +}; + +export const ControlNetOrT2IAdapterDefaultSettings = () => { + const selectedModelKey = useAppSelector((s) => s.modelmanagerV2.selectedModelKey); + const { t } = useTranslation(); + const dispatch = useAppDispatch(); + + const { defaultSettingsDefaults, isLoading: isLoadingDefaultSettings } = + useControlNetOrT2IAdapterDefaultSettings(selectedModelKey); + + const [updateModel, { isLoading: isLoadingUpdateModel }] = useUpdateModelMutation(); + + const { handleSubmit, control, formState, reset } = useForm({ + defaultValues: defaultSettingsDefaults, + }); + + const onSubmit = useCallback>( + (data) => { + if (!selectedModelKey) { + return; + } + + const body = { + preprocessor: data.preprocessor.isEnabled ? data.preprocessor.value : null, + }; + + updateModel({ + key: selectedModelKey, + body: { default_settings: body }, + }) + .unwrap() + .then((_) => { + dispatch( + addToast( + makeToast({ + title: t('modelManager.defaultSettingsSaved'), + status: 'success', + }) + ) + ); + reset(data); + }) + .catch((error) => { + if (error) { + dispatch( + addToast( + makeToast({ + title: `${error.data.detail} `, + status: 'error', + }) + ) + ); + } + }); + }, + [selectedModelKey, dispatch, reset, updateModel, t] + ); + + if (isLoadingDefaultSettings) { + return {t('common.loading')}; + } + + return ( + <> + + {t('modelManager.defaultSettings')} + + + + + + + + + + + + ); +}; diff --git a/invokeai/frontend/web/src/features/modelManagerV2/subpanels/ModelPanel/ControlNetOrT2IAdapterDefaultSettings/DefaultPreprocessor.tsx b/invokeai/frontend/web/src/features/modelManagerV2/subpanels/ModelPanel/ControlNetOrT2IAdapterDefaultSettings/DefaultPreprocessor.tsx new file mode 100644 index 0000000000..b2284336bf --- /dev/null +++ b/invokeai/frontend/web/src/features/modelManagerV2/subpanels/ModelPanel/ControlNetOrT2IAdapterDefaultSettings/DefaultPreprocessor.tsx @@ -0,0 +1,66 @@ +import type { ComboboxOnChange } from '@invoke-ai/ui-library'; +import { Combobox, Flex, FormControl, FormLabel } from '@invoke-ai/ui-library'; +import { InformationalPopover } from 'common/components/InformationalPopover/InformationalPopover'; +import type { ControlNetOrT2IAdapterDefaultSettingsFormData } from 'features/modelManagerV2/subpanels/ModelPanel/ControlNetOrT2IAdapterDefaultSettings/ControlNetOrT2IAdapterDefaultSettings'; +import type { FormField } from 'features/modelManagerV2/subpanels/ModelPanel/MainModelDefaultSettings/MainModelDefaultSettings'; +import { SettingToggle } from 'features/modelManagerV2/subpanels/ModelPanel/SettingToggle'; +import { useCallback, useMemo } from 'react'; +import type { UseControllerProps } from 'react-hook-form'; +import { useController } from 'react-hook-form'; +import { useTranslation } from 'react-i18next'; + +const OPTIONS = [ + { label: 'Canny', value: 'canny_image_processor' }, + { label: 'MLSD', value: 'mlsd_image_processor' }, + { label: 'Depth Anything', value: 'depth_anything_image_processor' }, + { label: 'Normal BAE', value: 'normalbae_image_processor' }, + { label: 'Pidi', value: 'pidi_image_processor' }, + { label: 'Lineart', value: 'lineart_image_processor' }, + { label: 'Lineart Anime', value: 'lineart_anime_image_processor' }, + { label: 'HED', value: 'hed_image_processor' }, + { label: 'Content Shuffle', value: 'content_shuffle_image_processor' }, + { label: 'DW OpenPose', value: 'dw_openpose_image_processor' }, + { label: 'MediaPipe Face', value: 'mediapipe_face_processor' }, + { label: 'ZoeDepth', value: 'zoe_depth_image_processor' }, + { label: 'Color Map', value: 'color_map_image_processor' }, + { label: 'None', value: 'none' }, +] as const; + +type DefaultSchedulerType = ControlNetOrT2IAdapterDefaultSettingsFormData['preprocessor']; + +export function DefaultPreprocessor(props: UseControllerProps) { + const { t } = useTranslation(); + const { field } = useController(props); + + const onChange = useCallback( + (v) => { + if (!v) { + return; + } + const updatedValue = { + ...(field.value as FormField), + value: v.value, + }; + field.onChange(updatedValue); + }, + [field] + ); + + const value = useMemo(() => OPTIONS.find((o) => o.value === (field.value as FormField).value), [field]); + + const isDisabled = useMemo(() => { + return !(field.value as DefaultSchedulerType).isEnabled; + }, [field.value]); + + return ( + + + + {t('controlnet.processor')} + + + + + + ); +} diff --git a/invokeai/frontend/web/src/features/modelManagerV2/subpanels/ModelPanel/MainModelDefaultSettings/DefaultCfgRescaleMultiplier.tsx b/invokeai/frontend/web/src/features/modelManagerV2/subpanels/ModelPanel/MainModelDefaultSettings/DefaultCfgRescaleMultiplier.tsx index f27885aa81..d16ce1460c 100644 --- a/invokeai/frontend/web/src/features/modelManagerV2/subpanels/ModelPanel/MainModelDefaultSettings/DefaultCfgRescaleMultiplier.tsx +++ b/invokeai/frontend/web/src/features/modelManagerV2/subpanels/ModelPanel/MainModelDefaultSettings/DefaultCfgRescaleMultiplier.tsx @@ -1,17 +1,17 @@ import { CompositeNumberInput, CompositeSlider, Flex, FormControl, FormLabel } from '@invoke-ai/ui-library'; import { useAppSelector } from 'app/store/storeHooks'; import { InformationalPopover } from 'common/components/InformationalPopover/InformationalPopover'; -import { SettingToggle } from 'features/modelManagerV2/subpanels/ModelPanel/MainModelDefaultSettings/SettingToggle'; +import { SettingToggle } from 'features/modelManagerV2/subpanels/ModelPanel/SettingToggle'; import { useCallback, useMemo } from 'react'; import type { UseControllerProps } from 'react-hook-form'; import { useController } from 'react-hook-form'; import { useTranslation } from 'react-i18next'; -import type { DefaultSettingsFormData } from './DefaultSettingsForm'; +import type { MainModelDefaultSettingsFormData } from './MainModelDefaultSettings'; -type DefaultCfgRescaleMultiplierType = DefaultSettingsFormData['cfgRescaleMultiplier']; +type DefaultCfgRescaleMultiplierType = MainModelDefaultSettingsFormData['cfgRescaleMultiplier']; -export function DefaultCfgRescaleMultiplier(props: UseControllerProps) { +export function DefaultCfgRescaleMultiplier(props: UseControllerProps) { const { field } = useController(props); const sliderMin = useAppSelector((s) => s.config.sd.cfgRescaleMultiplier.sliderMin); diff --git a/invokeai/frontend/web/src/features/modelManagerV2/subpanels/ModelPanel/MainModelDefaultSettings/DefaultCfgScale.tsx b/invokeai/frontend/web/src/features/modelManagerV2/subpanels/ModelPanel/MainModelDefaultSettings/DefaultCfgScale.tsx index 131d85ac27..293261bc35 100644 --- a/invokeai/frontend/web/src/features/modelManagerV2/subpanels/ModelPanel/MainModelDefaultSettings/DefaultCfgScale.tsx +++ b/invokeai/frontend/web/src/features/modelManagerV2/subpanels/ModelPanel/MainModelDefaultSettings/DefaultCfgScale.tsx @@ -1,17 +1,17 @@ import { CompositeNumberInput, CompositeSlider, Flex, FormControl, FormLabel } from '@invoke-ai/ui-library'; import { useAppSelector } from 'app/store/storeHooks'; import { InformationalPopover } from 'common/components/InformationalPopover/InformationalPopover'; -import { SettingToggle } from 'features/modelManagerV2/subpanels/ModelPanel/MainModelDefaultSettings/SettingToggle'; +import { SettingToggle } from 'features/modelManagerV2/subpanels/ModelPanel/SettingToggle'; import { useCallback, useMemo } from 'react'; import type { UseControllerProps } from 'react-hook-form'; import { useController } from 'react-hook-form'; import { useTranslation } from 'react-i18next'; -import type { DefaultSettingsFormData } from './DefaultSettingsForm'; +import type { MainModelDefaultSettingsFormData } from './MainModelDefaultSettings'; -type DefaultCfgType = DefaultSettingsFormData['cfgScale']; +type DefaultCfgType = MainModelDefaultSettingsFormData['cfgScale']; -export function DefaultCfgScale(props: UseControllerProps) { +export function DefaultCfgScale(props: UseControllerProps) { const { field } = useController(props); const sliderMin = useAppSelector((s) => s.config.sd.guidance.sliderMin); diff --git a/invokeai/frontend/web/src/features/modelManagerV2/subpanels/ModelPanel/MainModelDefaultSettings/DefaultScheduler.tsx b/invokeai/frontend/web/src/features/modelManagerV2/subpanels/ModelPanel/MainModelDefaultSettings/DefaultScheduler.tsx index 145f670e54..4397e35a51 100644 --- a/invokeai/frontend/web/src/features/modelManagerV2/subpanels/ModelPanel/MainModelDefaultSettings/DefaultScheduler.tsx +++ b/invokeai/frontend/web/src/features/modelManagerV2/subpanels/ModelPanel/MainModelDefaultSettings/DefaultScheduler.tsx @@ -1,7 +1,7 @@ import type { ComboboxOnChange } from '@invoke-ai/ui-library'; import { Combobox, Flex, FormControl, FormLabel } from '@invoke-ai/ui-library'; import { InformationalPopover } from 'common/components/InformationalPopover/InformationalPopover'; -import { SettingToggle } from 'features/modelManagerV2/subpanels/ModelPanel/MainModelDefaultSettings/SettingToggle'; +import { SettingToggle } from 'features/modelManagerV2/subpanels/ModelPanel/SettingToggle'; import { SCHEDULER_OPTIONS } from 'features/parameters/types/constants'; import { isParameterScheduler } from 'features/parameters/types/parameterSchemas'; import { useCallback, useMemo } from 'react'; @@ -9,11 +9,11 @@ import type { UseControllerProps } from 'react-hook-form'; import { useController } from 'react-hook-form'; import { useTranslation } from 'react-i18next'; -import type { DefaultSettingsFormData } from './DefaultSettingsForm'; +import type { MainModelDefaultSettingsFormData } from './MainModelDefaultSettings'; -type DefaultSchedulerType = DefaultSettingsFormData['scheduler']; +type DefaultSchedulerType = MainModelDefaultSettingsFormData['scheduler']; -export function DefaultScheduler(props: UseControllerProps) { +export function DefaultScheduler(props: UseControllerProps) { const { t } = useTranslation(); const { field } = useController(props); diff --git a/invokeai/frontend/web/src/features/modelManagerV2/subpanels/ModelPanel/MainModelDefaultSettings/DefaultSettingsForm.tsx b/invokeai/frontend/web/src/features/modelManagerV2/subpanels/ModelPanel/MainModelDefaultSettings/DefaultSettingsForm.tsx deleted file mode 100644 index 3c8551a52f..0000000000 --- a/invokeai/frontend/web/src/features/modelManagerV2/subpanels/ModelPanel/MainModelDefaultSettings/DefaultSettingsForm.tsx +++ /dev/null @@ -1,141 +0,0 @@ -import { Button, Flex, Heading } from '@invoke-ai/ui-library'; -import { useAppDispatch, useAppSelector } from 'app/store/storeHooks'; -import type { ParameterScheduler } from 'features/parameters/types/parameterSchemas'; -import { addToast } from 'features/system/store/systemSlice'; -import { makeToast } from 'features/system/util/makeToast'; -import { useCallback } from 'react'; -import type { SubmitHandler } from 'react-hook-form'; -import { useForm } from 'react-hook-form'; -import { useTranslation } from 'react-i18next'; -import { PiCheckBold } from 'react-icons/pi'; -import { useUpdateModelMutation } from 'services/api/endpoints/models'; - -import { DefaultCfgRescaleMultiplier } from './DefaultCfgRescaleMultiplier'; -import { DefaultCfgScale } from './DefaultCfgScale'; -import { DefaultScheduler } from './DefaultScheduler'; -import { DefaultSteps } from './DefaultSteps'; -import { DefaultVae } from './DefaultVae'; -import { DefaultVaePrecision } from './DefaultVaePrecision'; - -export interface FormField { - value: T; - isEnabled: boolean; -} - -export type DefaultSettingsFormData = { - vae: FormField; - vaePrecision: FormField; - scheduler: FormField; - steps: FormField; - cfgScale: FormField; - cfgRescaleMultiplier: FormField; -}; - -export const DefaultSettingsForm = ({ - defaultSettingsDefaults, -}: { - defaultSettingsDefaults: DefaultSettingsFormData; -}) => { - const dispatch = useAppDispatch(); - const { t } = useTranslation(); - const selectedModelKey = useAppSelector((s) => s.modelmanagerV2.selectedModelKey); - - const [updateModel, { isLoading }] = useUpdateModelMutation(); - - const { handleSubmit, control, formState, reset } = useForm({ - defaultValues: defaultSettingsDefaults, - }); - - const onSubmit = useCallback>( - (data) => { - if (!selectedModelKey) { - return; - } - - const body = { - vae: data.vae.isEnabled ? data.vae.value : null, - vae_precision: data.vaePrecision.isEnabled ? data.vaePrecision.value : null, - cfg_scale: data.cfgScale.isEnabled ? data.cfgScale.value : null, - cfg_rescale_multiplier: data.cfgRescaleMultiplier.isEnabled ? data.cfgRescaleMultiplier.value : null, - steps: data.steps.isEnabled ? data.steps.value : null, - scheduler: data.scheduler.isEnabled ? data.scheduler.value : null, - }; - - updateModel({ - key: selectedModelKey, - body: { default_settings: body }, - }) - .unwrap() - .then((_) => { - dispatch( - addToast( - makeToast({ - title: t('modelManager.defaultSettingsSaved'), - status: 'success', - }) - ) - ); - reset(data); - }) - .catch((error) => { - if (error) { - dispatch( - addToast( - makeToast({ - title: `${error.data.detail} `, - status: 'error', - }) - ) - ); - } - }); - }, - [selectedModelKey, dispatch, reset, updateModel, t] - ); - - return ( - <> - - {t('modelManager.defaultSettings')} - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ); -}; diff --git a/invokeai/frontend/web/src/features/modelManagerV2/subpanels/ModelPanel/MainModelDefaultSettings/DefaultSteps.tsx b/invokeai/frontend/web/src/features/modelManagerV2/subpanels/ModelPanel/MainModelDefaultSettings/DefaultSteps.tsx index c366fe1237..9c1912a0f7 100644 --- a/invokeai/frontend/web/src/features/modelManagerV2/subpanels/ModelPanel/MainModelDefaultSettings/DefaultSteps.tsx +++ b/invokeai/frontend/web/src/features/modelManagerV2/subpanels/ModelPanel/MainModelDefaultSettings/DefaultSteps.tsx @@ -1,17 +1,17 @@ import { CompositeNumberInput, CompositeSlider, Flex, FormControl, FormLabel } from '@invoke-ai/ui-library'; import { useAppSelector } from 'app/store/storeHooks'; import { InformationalPopover } from 'common/components/InformationalPopover/InformationalPopover'; -import { SettingToggle } from 'features/modelManagerV2/subpanels/ModelPanel/MainModelDefaultSettings/SettingToggle'; +import { SettingToggle } from 'features/modelManagerV2/subpanels/ModelPanel/SettingToggle'; import { useCallback, useMemo } from 'react'; import type { UseControllerProps } from 'react-hook-form'; import { useController } from 'react-hook-form'; import { useTranslation } from 'react-i18next'; -import type { DefaultSettingsFormData } from './DefaultSettingsForm'; +import type { MainModelDefaultSettingsFormData } from './MainModelDefaultSettings'; -type DefaultSteps = DefaultSettingsFormData['steps']; +type DefaultSteps = MainModelDefaultSettingsFormData['steps']; -export function DefaultSteps(props: UseControllerProps) { +export function DefaultSteps(props: UseControllerProps) { const { field } = useController(props); const sliderMin = useAppSelector((s) => s.config.sd.steps.sliderMin); diff --git a/invokeai/frontend/web/src/features/modelManagerV2/subpanels/ModelPanel/MainModelDefaultSettings/DefaultVae.tsx b/invokeai/frontend/web/src/features/modelManagerV2/subpanels/ModelPanel/MainModelDefaultSettings/DefaultVae.tsx index 612ea32690..dcaab94377 100644 --- a/invokeai/frontend/web/src/features/modelManagerV2/subpanels/ModelPanel/MainModelDefaultSettings/DefaultVae.tsx +++ b/invokeai/frontend/web/src/features/modelManagerV2/subpanels/ModelPanel/MainModelDefaultSettings/DefaultVae.tsx @@ -3,7 +3,7 @@ import { Combobox, Flex, FormControl, FormLabel } from '@invoke-ai/ui-library'; import { skipToken } from '@reduxjs/toolkit/query'; import { useAppSelector } from 'app/store/storeHooks'; import { InformationalPopover } from 'common/components/InformationalPopover/InformationalPopover'; -import { SettingToggle } from 'features/modelManagerV2/subpanels/ModelPanel/MainModelDefaultSettings/SettingToggle'; +import { SettingToggle } from 'features/modelManagerV2/subpanels/ModelPanel/SettingToggle'; import { map } from 'lodash-es'; import { useCallback, useMemo } from 'react'; import type { UseControllerProps } from 'react-hook-form'; @@ -11,11 +11,11 @@ import { useController } from 'react-hook-form'; import { useTranslation } from 'react-i18next'; import { useGetModelConfigQuery, useGetVaeModelsQuery } from 'services/api/endpoints/models'; -import type { DefaultSettingsFormData } from './DefaultSettingsForm'; +import type { MainModelDefaultSettingsFormData } from './MainModelDefaultSettings'; -type DefaultVaeType = DefaultSettingsFormData['vae']; +type DefaultVaeType = MainModelDefaultSettingsFormData['vae']; -export function DefaultVae(props: UseControllerProps) { +export function DefaultVae(props: UseControllerProps) { const { t } = useTranslation(); const { field } = useController(props); const selectedModelKey = useAppSelector((s) => s.modelmanagerV2.selectedModelKey); diff --git a/invokeai/frontend/web/src/features/modelManagerV2/subpanels/ModelPanel/MainModelDefaultSettings/DefaultVaePrecision.tsx b/invokeai/frontend/web/src/features/modelManagerV2/subpanels/ModelPanel/MainModelDefaultSettings/DefaultVaePrecision.tsx index 9c7286540b..d33cf4e08d 100644 --- a/invokeai/frontend/web/src/features/modelManagerV2/subpanels/ModelPanel/MainModelDefaultSettings/DefaultVaePrecision.tsx +++ b/invokeai/frontend/web/src/features/modelManagerV2/subpanels/ModelPanel/MainModelDefaultSettings/DefaultVaePrecision.tsx @@ -1,23 +1,23 @@ import type { ComboboxOnChange } from '@invoke-ai/ui-library'; import { Combobox, Flex, FormControl, FormLabel } from '@invoke-ai/ui-library'; import { InformationalPopover } from 'common/components/InformationalPopover/InformationalPopover'; -import { SettingToggle } from 'features/modelManagerV2/subpanels/ModelPanel/MainModelDefaultSettings/SettingToggle'; +import { SettingToggle } from 'features/modelManagerV2/subpanels/ModelPanel/SettingToggle'; import { isParameterPrecision } from 'features/parameters/types/parameterSchemas'; import { useCallback, useMemo } from 'react'; import type { UseControllerProps } from 'react-hook-form'; import { useController } from 'react-hook-form'; import { useTranslation } from 'react-i18next'; -import type { DefaultSettingsFormData } from './DefaultSettingsForm'; +import type { MainModelDefaultSettingsFormData } from './MainModelDefaultSettings'; const options = [ { label: 'FP16', value: 'fp16' }, { label: 'FP32', value: 'fp32' }, ]; -type DefaultVaePrecisionType = DefaultSettingsFormData['vaePrecision']; +type DefaultVaePrecisionType = MainModelDefaultSettingsFormData['vaePrecision']; -export function DefaultVaePrecision(props: UseControllerProps) { +export function DefaultVaePrecision(props: UseControllerProps) { const { t } = useTranslation(); const { field } = useController(props); diff --git a/invokeai/frontend/web/src/features/modelManagerV2/subpanels/ModelPanel/MainModelDefaultSettings/MainModelDefaultSettings.tsx b/invokeai/frontend/web/src/features/modelManagerV2/subpanels/ModelPanel/MainModelDefaultSettings/MainModelDefaultSettings.tsx index 54563bf63f..9766fc1a14 100644 --- a/invokeai/frontend/web/src/features/modelManagerV2/subpanels/ModelPanel/MainModelDefaultSettings/MainModelDefaultSettings.tsx +++ b/invokeai/frontend/web/src/features/modelManagerV2/subpanels/ModelPanel/MainModelDefaultSettings/MainModelDefaultSettings.tsx @@ -17,12 +17,13 @@ import { DefaultScheduler } from './DefaultScheduler'; import { DefaultSteps } from './DefaultSteps'; import { DefaultVae } from './DefaultVae'; import { DefaultVaePrecision } from './DefaultVaePrecision'; -interface FormField { + +export interface FormField { value: T; isEnabled: boolean; } -type DefaultSettingsFormData = { +export type MainModelDefaultSettingsFormData = { vae: FormField; vaePrecision: FormField; scheduler: FormField; @@ -41,11 +42,11 @@ export const MainModelDefaultSettings = () => { const [updateModel, { isLoading: isLoadingUpdateModel }] = useUpdateModelMutation(); - const { handleSubmit, control, formState, reset } = useForm({ + const { handleSubmit, control, formState, reset } = useForm({ defaultValues: defaultSettingsDefaults, }); - const onSubmit = useCallback>( + const onSubmit = useCallback>( (data) => { if (!selectedModelKey) { return; diff --git a/invokeai/frontend/web/src/features/modelManagerV2/subpanels/ModelPanel/ModelView.tsx b/invokeai/frontend/web/src/features/modelManagerV2/subpanels/ModelPanel/ModelView.tsx index a8143f1c19..f7e2780fe1 100644 --- a/invokeai/frontend/web/src/features/modelManagerV2/subpanels/ModelPanel/ModelView.tsx +++ b/invokeai/frontend/web/src/features/modelManagerV2/subpanels/ModelPanel/ModelView.tsx @@ -1,6 +1,7 @@ import { Box, Flex, Text } from '@invoke-ai/ui-library'; import { skipToken } from '@reduxjs/toolkit/query'; import { useAppSelector } from 'app/store/storeHooks'; +import { ControlNetOrT2IAdapterDefaultSettings } from 'features/modelManagerV2/subpanels/ModelPanel/ControlNetOrT2IAdapterDefaultSettings/ControlNetOrT2IAdapterDefaultSettings'; import { TriggerPhrases } from 'features/modelManagerV2/subpanels/ModelPanel/TriggerPhrases'; import { useTranslation } from 'react-i18next'; import { useGetModelConfigQuery } from 'services/api/endpoints/models'; @@ -64,6 +65,11 @@ export const ModelView = () => { )} + {(data.type === 'controlnet' || data.type === 't2i_adapter') && ( + + + + )} {(data.type === 'main' || data.type === 'lora') && ( diff --git a/invokeai/frontend/web/src/features/modelManagerV2/subpanels/ModelPanel/MainModelDefaultSettings/SettingToggle.tsx b/invokeai/frontend/web/src/features/modelManagerV2/subpanels/ModelPanel/SettingToggle.tsx similarity index 79% rename from invokeai/frontend/web/src/features/modelManagerV2/subpanels/ModelPanel/MainModelDefaultSettings/SettingToggle.tsx rename to invokeai/frontend/web/src/features/modelManagerV2/subpanels/ModelPanel/SettingToggle.tsx index 7f5cd8efb9..15e4693c4f 100644 --- a/invokeai/frontend/web/src/features/modelManagerV2/subpanels/ModelPanel/MainModelDefaultSettings/SettingToggle.tsx +++ b/invokeai/frontend/web/src/features/modelManagerV2/subpanels/ModelPanel/SettingToggle.tsx @@ -4,9 +4,9 @@ import { useCallback, useMemo } from 'react'; import type { UseControllerProps } from 'react-hook-form'; import { useController } from 'react-hook-form'; -import type { DefaultSettingsFormData, FormField } from './DefaultSettingsForm'; +import type { FormField } from './MainModelDefaultSettings/MainModelDefaultSettings'; -export function SettingToggle(props: UseControllerProps) { +export function SettingToggle>>(props: UseControllerProps) { const { field } = useController(props); const value = useMemo(() => {