mirror of
https://github.com/invoke-ai/InvokeAI
synced 2024-08-30 20:32:17 +00:00
feat(ui): disable control adapter buttons if no models available
This commit is contained in:
parent
078c9b6964
commit
ed82bf6bb8
@ -49,9 +49,10 @@
|
||||
"cancel": "Cancel",
|
||||
"close": "Close",
|
||||
"communityLabel": "Community",
|
||||
"controlNet": "Controlnet",
|
||||
"controlNet": "ControlNet",
|
||||
"controlAdapter": "Control Adapter",
|
||||
"ipAdapter": "IP Adapter",
|
||||
"t2iAdapter": "T2I Adapter",
|
||||
"darkMode": "Dark Mode",
|
||||
"discordLabel": "Discord",
|
||||
"dontAskMeAgain": "Don't ask me again",
|
||||
@ -132,9 +133,12 @@
|
||||
},
|
||||
"controlnet": {
|
||||
"controlAdapter": "Control Adapter",
|
||||
"controlnet": "$t(controlnet.controlAdapter) #{{number}} (Control Net)",
|
||||
"ip_adapter": "$t(controlnet.controlAdapter) #{{number}} (IP Adapter)",
|
||||
"t2i_adapter": "$t(controlnet.controlAdapter) #{{number}} (T2I Adapter)",
|
||||
"controlnet": "$t(controlnet.controlAdapter) #{{number}} ($t(common.controlNet))",
|
||||
"ip_adapter": "$t(controlnet.controlAdapter) #{{number}} ($t(common.ipAdapter))",
|
||||
"t2i_adapter": "$t(controlnet.controlAdapter) #{{number}} ($t(common.t2iAdapter))",
|
||||
"addControlNet": "Add $t(common.controlNet)",
|
||||
"addIPAdapter": "Add $t(common.ipAdapter)",
|
||||
"addT2IAdapter": "Add $t(common.t2iAdapter)",
|
||||
"amult": "a_mult",
|
||||
"autoConfigure": "Auto configure processor",
|
||||
"balanced": "Balanced",
|
||||
|
@ -1,7 +1,7 @@
|
||||
import { logger } from 'app/logging/logger';
|
||||
import { setBoundingBoxDimensions } from 'features/canvas/store/canvasSlice';
|
||||
import {
|
||||
controlAdapterRemoved,
|
||||
controlAdapterModelCleared,
|
||||
selectControlAdapterAll,
|
||||
} from 'features/controlAdapters/store/controlAdaptersSlice';
|
||||
import { loraRemoved } from 'features/lora/store/loraSlice';
|
||||
@ -15,9 +15,9 @@ import {
|
||||
import { zMainOrOnnxModel } from 'features/parameters/types/parameterSchemas';
|
||||
import { addToast } from 'features/system/store/systemSlice';
|
||||
import { makeToast } from 'features/system/util/makeToast';
|
||||
import { t } from 'i18next';
|
||||
import { forEach } from 'lodash-es';
|
||||
import { startAppListening } from '..';
|
||||
import { t } from 'i18next';
|
||||
|
||||
export const addModelSelectedListener = () => {
|
||||
startAppListening({
|
||||
@ -62,7 +62,7 @@ export const addModelSelectedListener = () => {
|
||||
// handle incompatible controlnets
|
||||
selectControlAdapterAll(state.controlAdapters).forEach((ca) => {
|
||||
if (ca.model?.base_model !== base_model) {
|
||||
dispatch(controlAdapterRemoved({ id: ca.id }));
|
||||
dispatch(controlAdapterModelCleared({ id: ca.id }));
|
||||
modelsCleared += 1;
|
||||
}
|
||||
});
|
||||
|
@ -6,9 +6,6 @@ import { defaultSelectorOptions } from 'app/store/util/defaultMemoizeOptions';
|
||||
import IAIButton from 'common/components/IAIButton';
|
||||
import IAICollapse from 'common/components/IAICollapse';
|
||||
import ControlAdapterConfig from 'features/controlAdapters/components/ControlAdapterConfig';
|
||||
import { useAddControlNet } from 'features/controlAdapters/hooks/useAddControlNet';
|
||||
import { useAddIPAdapter } from 'features/controlAdapters/hooks/useAddIPAdapter';
|
||||
import { useAddT2IAdapter } from 'features/controlAdapters/hooks/useAddT2IAdapter';
|
||||
import {
|
||||
selectAllControlNets,
|
||||
selectAllIPAdapters,
|
||||
@ -18,6 +15,8 @@ import {
|
||||
import { useFeatureStatus } from 'features/system/hooks/useFeatureStatus';
|
||||
import { Fragment, memo } from 'react';
|
||||
import { FaPlus } from 'react-icons/fa';
|
||||
import { useAddControlAdapter } from '../hooks/useAddControlAdapter';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
|
||||
const selector = createSelector(
|
||||
[stateSelector],
|
||||
@ -50,12 +49,17 @@ const selector = createSelector(
|
||||
defaultSelectorOptions
|
||||
);
|
||||
|
||||
const ParamControlAdaptersCollapse = () => {
|
||||
const ControlAdaptersCollapse = () => {
|
||||
const { t } = useTranslation();
|
||||
const { controlAdapterIds, activeLabel } = useAppSelector(selector);
|
||||
const isControlNetDisabled = useFeatureStatus('controlNet').isFeatureDisabled;
|
||||
const { addControlNet } = useAddControlNet();
|
||||
const { addIPAdapter } = useAddIPAdapter();
|
||||
const { addT2IAdapter } = useAddT2IAdapter();
|
||||
|
||||
const [addControlNet, isAddControlNetDisabled] =
|
||||
useAddControlAdapter('controlnet');
|
||||
const [addIPAdapter, isAddIPAdapterDisabled] =
|
||||
useAddControlAdapter('ip_adapter');
|
||||
const [addT2IAdapter, isAddT2IAdapterDisabled] =
|
||||
useAddControlAdapter('t2i_adapter');
|
||||
|
||||
if (isControlNetDisabled) {
|
||||
return null;
|
||||
@ -66,28 +70,34 @@ const ParamControlAdaptersCollapse = () => {
|
||||
<Flex sx={{ flexDir: 'column', gap: 2 }}>
|
||||
<ButtonGroup size="sm" w="full" justifyContent="space-between">
|
||||
<IAIButton
|
||||
tooltip={t('controlnet.addControlNet')}
|
||||
leftIcon={<FaPlus />}
|
||||
onClick={addControlNet}
|
||||
data-testid="add controlnet"
|
||||
flexGrow={1}
|
||||
isDisabled={isAddControlNetDisabled}
|
||||
>
|
||||
ControlNet
|
||||
{t('common.controlNet')}
|
||||
</IAIButton>
|
||||
<IAIButton
|
||||
tooltip={t('controlnet.addIPAdapter')}
|
||||
leftIcon={<FaPlus />}
|
||||
onClick={addIPAdapter}
|
||||
data-testid="add ip adapter"
|
||||
flexGrow={1}
|
||||
isDisabled={isAddIPAdapterDisabled}
|
||||
>
|
||||
IP Adapter
|
||||
{t('common.ipAdapter')}
|
||||
</IAIButton>
|
||||
<IAIButton
|
||||
tooltip={t('controlnet.addT2IAdapter')}
|
||||
leftIcon={<FaPlus />}
|
||||
onClick={addT2IAdapter}
|
||||
data-testid="add t2i adapter"
|
||||
flexGrow={1}
|
||||
isDisabled={isAddT2IAdapterDisabled}
|
||||
>
|
||||
T2I Adapter
|
||||
{t('common.t2iAdapter')}
|
||||
</IAIButton>
|
||||
</ButtonGroup>
|
||||
{controlAdapterIds.map((id, i) => (
|
||||
@ -101,4 +111,4 @@ const ParamControlAdaptersCollapse = () => {
|
||||
);
|
||||
};
|
||||
|
||||
export default memo(ParamControlAdaptersCollapse);
|
||||
export default memo(ControlAdaptersCollapse);
|
@ -0,0 +1,43 @@
|
||||
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
|
||||
import { controlAdapterAdded } from 'features/controlAdapters/store/controlAdaptersSlice';
|
||||
import { useCallback, useMemo } from 'react';
|
||||
import { ControlAdapterType } from '../store/types';
|
||||
import { useControlAdapterModels } from './useControlAdapterModels';
|
||||
|
||||
export const useAddControlAdapter = (type: ControlAdapterType) => {
|
||||
const baseModel = useAppSelector(
|
||||
(state) => state.generation.model?.base_model
|
||||
);
|
||||
const dispatch = useAppDispatch();
|
||||
|
||||
const models = useControlAdapterModels(type);
|
||||
|
||||
const firstModel = useMemo(() => {
|
||||
// prefer to use a model that matches the base model
|
||||
const firstCompatibleModel = models.filter((m) =>
|
||||
baseModel ? m.base_model === baseModel : true
|
||||
)[0];
|
||||
|
||||
if (firstCompatibleModel) {
|
||||
return firstCompatibleModel;
|
||||
}
|
||||
|
||||
return models[0];
|
||||
}, [baseModel, models]);
|
||||
|
||||
const isDisabled = useMemo(() => !firstModel, [firstModel]);
|
||||
|
||||
const addControlAdapter = useCallback(() => {
|
||||
if (isDisabled) {
|
||||
return;
|
||||
}
|
||||
dispatch(
|
||||
controlAdapterAdded({
|
||||
type,
|
||||
overrides: { model: firstModel },
|
||||
})
|
||||
);
|
||||
}, [dispatch, firstModel, isDisabled, type]);
|
||||
|
||||
return [addControlAdapter, isDisabled] as const;
|
||||
};
|
@ -1,45 +0,0 @@
|
||||
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
|
||||
import { controlAdapterAdded } from 'features/controlAdapters/store/controlAdaptersSlice';
|
||||
import { useCallback, useMemo } from 'react';
|
||||
import {
|
||||
controlNetModelsAdapter,
|
||||
useGetControlNetModelsQuery,
|
||||
} from 'services/api/endpoints/models';
|
||||
|
||||
export const useAddControlNet = () => {
|
||||
const dispatch = useAppDispatch();
|
||||
const baseModel = useAppSelector(
|
||||
(state) => state.generation.model?.base_model
|
||||
);
|
||||
const { data: controlNetModels } = useGetControlNetModelsQuery();
|
||||
const firstControlNetModel = useMemo(
|
||||
() =>
|
||||
controlNetModels
|
||||
? controlNetModelsAdapter
|
||||
.getSelectors()
|
||||
.selectAll(controlNetModels)
|
||||
.filter((m) => (baseModel ? m.base_model === baseModel : true))[0]
|
||||
: undefined,
|
||||
[baseModel, controlNetModels]
|
||||
);
|
||||
const isDisabled = useMemo(
|
||||
() => !firstControlNetModel,
|
||||
[firstControlNetModel]
|
||||
);
|
||||
const addControlNet = useCallback(() => {
|
||||
if (isDisabled) {
|
||||
return;
|
||||
}
|
||||
dispatch(
|
||||
controlAdapterAdded({
|
||||
type: 'controlnet',
|
||||
overrides: { model: firstControlNetModel },
|
||||
})
|
||||
);
|
||||
}, [dispatch, firstControlNetModel, isDisabled]);
|
||||
|
||||
return {
|
||||
addControlNet,
|
||||
isDisabled,
|
||||
};
|
||||
};
|
@ -1,63 +0,0 @@
|
||||
import { createSelector } from '@reduxjs/toolkit';
|
||||
import { stateSelector } from 'app/store/store';
|
||||
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
|
||||
import { defaultSelectorOptions } from 'app/store/util/defaultMemoizeOptions';
|
||||
import {
|
||||
controlAdapterAdded,
|
||||
selectAllIPAdapters,
|
||||
} from 'features/controlAdapters/store/controlAdaptersSlice';
|
||||
import { useCallback, useMemo } from 'react';
|
||||
import {
|
||||
ipAdapterModelsAdapter,
|
||||
useGetIPAdapterModelsQuery,
|
||||
} from 'services/api/endpoints/models';
|
||||
|
||||
const selector = createSelector(
|
||||
[stateSelector],
|
||||
({ controlAdapters, generation }) => {
|
||||
const ipAdapterCount = selectAllIPAdapters(controlAdapters).length;
|
||||
const { model } = generation;
|
||||
return {
|
||||
ipAdapterCount,
|
||||
baseModel: model?.base_model,
|
||||
};
|
||||
},
|
||||
defaultSelectorOptions
|
||||
);
|
||||
|
||||
export const useAddIPAdapter = () => {
|
||||
const { ipAdapterCount, baseModel } = useAppSelector(selector);
|
||||
const dispatch = useAppDispatch();
|
||||
|
||||
const { data: ipAdapterModels } = useGetIPAdapterModelsQuery();
|
||||
const firstIPAdapterModel = useMemo(
|
||||
() =>
|
||||
ipAdapterModels
|
||||
? ipAdapterModelsAdapter
|
||||
.getSelectors()
|
||||
.selectAll(ipAdapterModels)
|
||||
.filter((m) => (baseModel ? m.base_model === baseModel : true))[0]
|
||||
: undefined,
|
||||
[baseModel, ipAdapterModels]
|
||||
);
|
||||
const isDisabled = useMemo(
|
||||
() => !firstIPAdapterModel && ipAdapterCount === 0,
|
||||
[firstIPAdapterModel, ipAdapterCount]
|
||||
);
|
||||
const addIPAdapter = useCallback(() => {
|
||||
if (isDisabled) {
|
||||
return;
|
||||
}
|
||||
dispatch(
|
||||
controlAdapterAdded({
|
||||
type: 'ip_adapter',
|
||||
overrides: { model: firstIPAdapterModel },
|
||||
})
|
||||
);
|
||||
}, [dispatch, firstIPAdapterModel, isDisabled]);
|
||||
|
||||
return {
|
||||
addIPAdapter,
|
||||
isDisabled,
|
||||
};
|
||||
};
|
@ -1,45 +0,0 @@
|
||||
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
|
||||
import { controlAdapterAdded } from 'features/controlAdapters/store/controlAdaptersSlice';
|
||||
import { useCallback, useMemo } from 'react';
|
||||
import {
|
||||
t2iAdapterModelsAdapter,
|
||||
useGetT2IAdapterModelsQuery,
|
||||
} from 'services/api/endpoints/models';
|
||||
|
||||
export const useAddT2IAdapter = () => {
|
||||
const dispatch = useAppDispatch();
|
||||
const baseModel = useAppSelector(
|
||||
(state) => state.generation.model?.base_model
|
||||
);
|
||||
const { data: t2iAdapterModels } = useGetT2IAdapterModelsQuery();
|
||||
const firstT2IAdapterModel = useMemo(
|
||||
() =>
|
||||
t2iAdapterModels
|
||||
? t2iAdapterModelsAdapter
|
||||
.getSelectors()
|
||||
.selectAll(t2iAdapterModels)
|
||||
.filter((m) => (baseModel ? m.base_model === baseModel : true))[0]
|
||||
: undefined,
|
||||
[baseModel, t2iAdapterModels]
|
||||
);
|
||||
const isDisabled = useMemo(
|
||||
() => !firstT2IAdapterModel,
|
||||
[firstT2IAdapterModel]
|
||||
);
|
||||
const addT2IAdapter = useCallback(() => {
|
||||
if (isDisabled) {
|
||||
return;
|
||||
}
|
||||
dispatch(
|
||||
controlAdapterAdded({
|
||||
type: 't2i_adapter',
|
||||
overrides: { model: firstT2IAdapterModel },
|
||||
})
|
||||
);
|
||||
}, [dispatch, firstT2IAdapterModel, isDisabled]);
|
||||
|
||||
return {
|
||||
addT2IAdapter,
|
||||
isDisabled,
|
||||
};
|
||||
};
|
@ -1,7 +1,7 @@
|
||||
import ParamDynamicPromptsCollapse from 'features/dynamicPrompts/components/ParamDynamicPromptsCollapse';
|
||||
import ParamLoraCollapse from 'features/lora/components/ParamLoraCollapse';
|
||||
import ParamAdvancedCollapse from 'features/parameters/components/Parameters/Advanced/ParamAdvancedCollapse';
|
||||
import ParamControlAdaptersCollapse from 'features/parameters/components/Parameters/ControlAdapters/ParamControlAdaptersCollapse';
|
||||
import ControlAdaptersCollapse from 'features/controlAdapters/components/ControlAdaptersCollapse';
|
||||
import { memo } from 'react';
|
||||
import ParamSDXLPromptArea from './ParamSDXLPromptArea';
|
||||
import ParamSDXLRefinerCollapse from './ParamSDXLRefinerCollapse';
|
||||
@ -13,7 +13,7 @@ const SDXLImageToImageTabParameters = () => {
|
||||
<ParamSDXLPromptArea />
|
||||
<SDXLImageToImageTabCoreParameters />
|
||||
<ParamSDXLRefinerCollapse />
|
||||
<ParamControlAdaptersCollapse />
|
||||
<ControlAdaptersCollapse />
|
||||
<ParamLoraCollapse />
|
||||
<ParamDynamicPromptsCollapse />
|
||||
<ParamAdvancedCollapse />
|
||||
|
@ -1,7 +1,7 @@
|
||||
import ParamDynamicPromptsCollapse from 'features/dynamicPrompts/components/ParamDynamicPromptsCollapse';
|
||||
import ParamLoraCollapse from 'features/lora/components/ParamLoraCollapse';
|
||||
import ParamAdvancedCollapse from 'features/parameters/components/Parameters/Advanced/ParamAdvancedCollapse';
|
||||
import ParamControlAdaptersCollapse from 'features/parameters/components/Parameters/ControlAdapters/ParamControlAdaptersCollapse';
|
||||
import ControlAdaptersCollapse from 'features/controlAdapters/components/ControlAdaptersCollapse';
|
||||
import TextToImageTabCoreParameters from 'features/ui/components/tabs/TextToImage/TextToImageTabCoreParameters';
|
||||
import { memo } from 'react';
|
||||
import ParamSDXLPromptArea from './ParamSDXLPromptArea';
|
||||
@ -13,7 +13,7 @@ const SDXLTextToImageTabParameters = () => {
|
||||
<ParamSDXLPromptArea />
|
||||
<TextToImageTabCoreParameters />
|
||||
<ParamSDXLRefinerCollapse />
|
||||
<ParamControlAdaptersCollapse />
|
||||
<ControlAdaptersCollapse />
|
||||
<ParamLoraCollapse />
|
||||
<ParamDynamicPromptsCollapse />
|
||||
<ParamAdvancedCollapse />
|
||||
|
@ -3,7 +3,7 @@ import ParamLoraCollapse from 'features/lora/components/ParamLoraCollapse';
|
||||
import ParamAdvancedCollapse from 'features/parameters/components/Parameters/Advanced/ParamAdvancedCollapse';
|
||||
import ParamCompositingSettingsCollapse from 'features/parameters/components/Parameters/Canvas/Compositing/ParamCompositingSettingsCollapse';
|
||||
import ParamInfillAndScalingCollapse from 'features/parameters/components/Parameters/Canvas/InfillAndScaling/ParamInfillAndScalingCollapse';
|
||||
import ParamControlAdaptersCollapse from 'features/parameters/components/Parameters/ControlAdapters/ParamControlAdaptersCollapse';
|
||||
import ControlAdaptersCollapse from 'features/controlAdapters/components/ControlAdaptersCollapse';
|
||||
import ParamSDXLPromptArea from './ParamSDXLPromptArea';
|
||||
import ParamSDXLRefinerCollapse from './ParamSDXLRefinerCollapse';
|
||||
import SDXLUnifiedCanvasTabCoreParameters from './SDXLUnifiedCanvasTabCoreParameters';
|
||||
@ -14,7 +14,7 @@ export default function SDXLUnifiedCanvasTabParameters() {
|
||||
<ParamSDXLPromptArea />
|
||||
<SDXLUnifiedCanvasTabCoreParameters />
|
||||
<ParamSDXLRefinerCollapse />
|
||||
<ParamControlAdaptersCollapse />
|
||||
<ControlAdaptersCollapse />
|
||||
<ParamLoraCollapse />
|
||||
<ParamDynamicPromptsCollapse />
|
||||
<ParamInfillAndScalingCollapse />
|
||||
|
@ -1,7 +1,7 @@
|
||||
import ParamDynamicPromptsCollapse from 'features/dynamicPrompts/components/ParamDynamicPromptsCollapse';
|
||||
import ParamLoraCollapse from 'features/lora/components/ParamLoraCollapse';
|
||||
import ParamAdvancedCollapse from 'features/parameters/components/Parameters/Advanced/ParamAdvancedCollapse';
|
||||
import ParamControlAdaptersCollapse from 'features/parameters/components/Parameters/ControlAdapters/ParamControlAdaptersCollapse';
|
||||
import ControlAdaptersCollapse from 'features/controlAdapters/components/ControlAdaptersCollapse';
|
||||
import ParamPromptArea from 'features/parameters/components/Parameters/Prompt/ParamPromptArea';
|
||||
import ParamSymmetryCollapse from 'features/parameters/components/Parameters/Symmetry/ParamSymmetryCollapse';
|
||||
import { memo } from 'react';
|
||||
@ -12,7 +12,7 @@ const ImageToImageTabParameters = () => {
|
||||
<>
|
||||
<ParamPromptArea />
|
||||
<ImageToImageTabCoreParameters />
|
||||
<ParamControlAdaptersCollapse />
|
||||
<ControlAdaptersCollapse />
|
||||
<ParamLoraCollapse />
|
||||
<ParamDynamicPromptsCollapse />
|
||||
<ParamSymmetryCollapse />
|
||||
|
@ -1,7 +1,7 @@
|
||||
import ParamDynamicPromptsCollapse from 'features/dynamicPrompts/components/ParamDynamicPromptsCollapse';
|
||||
import ParamLoraCollapse from 'features/lora/components/ParamLoraCollapse';
|
||||
import ParamAdvancedCollapse from 'features/parameters/components/Parameters/Advanced/ParamAdvancedCollapse';
|
||||
import ParamControlAdaptersCollapse from 'features/parameters/components/Parameters/ControlAdapters/ParamControlAdaptersCollapse';
|
||||
import ControlAdaptersCollapse from 'features/controlAdapters/components/ControlAdaptersCollapse';
|
||||
import ParamSymmetryCollapse from 'features/parameters/components/Parameters/Symmetry/ParamSymmetryCollapse';
|
||||
import { memo } from 'react';
|
||||
import ParamPromptArea from '../../../../parameters/components/Parameters/Prompt/ParamPromptArea';
|
||||
@ -12,7 +12,7 @@ const TextToImageTabParameters = () => {
|
||||
<>
|
||||
<ParamPromptArea />
|
||||
<TextToImageTabCoreParameters />
|
||||
<ParamControlAdaptersCollapse />
|
||||
<ControlAdaptersCollapse />
|
||||
<ParamLoraCollapse />
|
||||
<ParamDynamicPromptsCollapse />
|
||||
<ParamSymmetryCollapse />
|
||||
|
@ -3,7 +3,7 @@ import ParamLoraCollapse from 'features/lora/components/ParamLoraCollapse';
|
||||
import ParamAdvancedCollapse from 'features/parameters/components/Parameters/Advanced/ParamAdvancedCollapse';
|
||||
import ParamCompositingSettingsCollapse from 'features/parameters/components/Parameters/Canvas/Compositing/ParamCompositingSettingsCollapse';
|
||||
import ParamInfillAndScalingCollapse from 'features/parameters/components/Parameters/Canvas/InfillAndScaling/ParamInfillAndScalingCollapse';
|
||||
import ParamControlAdaptersCollapse from 'features/parameters/components/Parameters/ControlAdapters/ParamControlAdaptersCollapse';
|
||||
import ControlAdaptersCollapse from 'features/controlAdapters/components/ControlAdaptersCollapse';
|
||||
import ParamPromptArea from 'features/parameters/components/Parameters/Prompt/ParamPromptArea';
|
||||
import ParamSymmetryCollapse from 'features/parameters/components/Parameters/Symmetry/ParamSymmetryCollapse';
|
||||
import { memo } from 'react';
|
||||
@ -14,7 +14,7 @@ const UnifiedCanvasParameters = () => {
|
||||
<>
|
||||
<ParamPromptArea />
|
||||
<UnifiedCanvasCoreParameters />
|
||||
<ParamControlAdaptersCollapse />
|
||||
<ControlAdaptersCollapse />
|
||||
<ParamLoraCollapse />
|
||||
<ParamDynamicPromptsCollapse />
|
||||
<ParamSymmetryCollapse />
|
||||
|
2525
invokeai/frontend/web/src/services/api/schema.d.ts
vendored
2525
invokeai/frontend/web/src/services/api/schema.d.ts
vendored
File diff suppressed because one or more lines are too long
Loading…
Reference in New Issue
Block a user