tidy(ui): remove extraneous metadata handlers

This commit is contained in:
psychedelicious 2024-05-08 10:12:57 +10:00 committed by Kent Keirsey
parent dfbd7eb1cf
commit 8b25c1a62e
10 changed files with 6 additions and 673 deletions

View File

@ -357,12 +357,6 @@ export const controlLayersSlice = createSlice({
const layer = selectCALayerOrThrow(state, layerId);
layer.controlAdapter.isProcessingImage = isProcessingImage;
},
caLayerControlNetsDeleted: (state) => {
state.layers = state.layers.filter((l) => !isControlAdapterLayer(l) || l.controlAdapter.type !== 'controlnet');
},
caLayerT2IAdaptersDeleted: (state) => {
state.layers = state.layers.filter((l) => !isControlAdapterLayer(l) || l.controlAdapter.type !== 't2i_adapter');
},
//#endregion
//#region IP Adapter Layers
@ -415,9 +409,6 @@ export const controlLayersSlice = createSlice({
const layer = selectIPALayerOrThrow(state, layerId);
layer.ipAdapter.clipVisionModel = clipVisionModel;
},
ipaLayersDeleted: (state) => {
state.layers = state.layers.filter((l) => !isIPAdapterLayer(l));
},
//#endregion
//#region CA or IPA Layers
@ -839,8 +830,6 @@ export const {
caLayerIsFilterEnabledChanged,
caLayerOpacityChanged,
caLayerIsProcessingImageChanged,
caLayerControlNetsDeleted,
caLayerT2IAdaptersDeleted,
// IPA Layers
ipaLayerAdded,
ipaLayerRecalled,
@ -848,7 +837,6 @@ export const {
ipaLayerMethodChanged,
ipaLayerModelChanged,
ipaLayerCLIPVisionModelChanged,
ipaLayersDeleted,
// CA or IPA Layers
caOrIPALayerWeightChanged,
caOrIPALayerBeginEndStepPctChanged,

View File

@ -1,13 +1,10 @@
import { useAppSelector } from 'app/store/storeHooks';
import { MetadataControlNets } from 'features/metadata/components/MetadataControlNets';
import { MetadataControlNetsV2 } from 'features/metadata/components/MetadataControlNetsV2';
import { MetadataIPAdapters } from 'features/metadata/components/MetadataIPAdapters';
import { MetadataIPAdaptersV2 } from 'features/metadata/components/MetadataIPAdaptersV2';
import { MetadataItem } from 'features/metadata/components/MetadataItem';
import { MetadataLayers } from 'features/metadata/components/MetadataLayers';
import { MetadataLoRAs } from 'features/metadata/components/MetadataLoRAs';
import { MetadataT2IAdapters } from 'features/metadata/components/MetadataT2IAdapters';
import { MetadataT2IAdaptersV2 } from 'features/metadata/components/MetadataT2IAdaptersV2';
import { handlers } from 'features/metadata/util/handlers';
import { activeTabNameSelector } from 'features/ui/store/uiSelectors';
import { memo } from 'react';
@ -40,7 +37,6 @@ const ImageMetadataActions = (props: Props) => {
<MetadataItem metadata={metadata} handlers={handlers.scheduler} />
<MetadataItem metadata={metadata} handlers={handlers.cfgScale} />
<MetadataItem metadata={metadata} handlers={handlers.cfgRescaleMultiplier} />
<MetadataItem metadata={metadata} handlers={handlers.initialImage} />
<MetadataItem metadata={metadata} handlers={handlers.strength} />
<MetadataItem metadata={metadata} handlers={handlers.hrfEnabled} />
<MetadataItem metadata={metadata} handlers={handlers.hrfMethod} />
@ -57,9 +53,6 @@ const ImageMetadataActions = (props: Props) => {
{activeTabName !== 'generation' && <MetadataControlNets metadata={metadata} />}
{activeTabName !== 'generation' && <MetadataT2IAdapters metadata={metadata} />}
{activeTabName !== 'generation' && <MetadataIPAdapters metadata={metadata} />}
{activeTabName === 'generation' && <MetadataControlNetsV2 metadata={metadata} />}
{activeTabName === 'generation' && <MetadataT2IAdaptersV2 metadata={metadata} />}
{activeTabName === 'generation' && <MetadataIPAdaptersV2 metadata={metadata} />}
</>
);
};

View File

@ -1,72 +0,0 @@
import { MetadataItemView } from 'features/metadata/components/MetadataItemView';
import type { ControlNetConfigV2Metadata, MetadataHandlers } from 'features/metadata/types';
import { handlers } from 'features/metadata/util/handlers';
import { useCallback, useEffect, useMemo, useState } from 'react';
type Props = {
metadata: unknown;
};
export const MetadataControlNetsV2 = ({ metadata }: Props) => {
const [controlNets, setControlNets] = useState<ControlNetConfigV2Metadata[]>([]);
useEffect(() => {
const parse = async () => {
try {
const parsed = await handlers.controlNetsV2.parse(metadata);
setControlNets(parsed);
} catch (e) {
setControlNets([]);
}
};
parse();
}, [metadata]);
const label = useMemo(() => handlers.controlNetsV2.getLabel(), []);
return (
<>
{controlNets.map((controlNet) => (
<MetadataViewControlNet
key={controlNet.id}
label={label}
controlNet={controlNet}
handlers={handlers.controlNetsV2}
/>
))}
</>
);
};
const MetadataViewControlNet = ({
label,
controlNet,
handlers,
}: {
label: string;
controlNet: ControlNetConfigV2Metadata;
handlers: MetadataHandlers<ControlNetConfigV2Metadata[], ControlNetConfigV2Metadata>;
}) => {
const onRecall = useCallback(() => {
if (!handlers.recallItem) {
return;
}
handlers.recallItem(controlNet, true);
}, [handlers, controlNet]);
const [renderedValue, setRenderedValue] = useState<React.ReactNode>(null);
useEffect(() => {
const _renderValue = async () => {
if (!handlers.renderItemValue) {
setRenderedValue(null);
return;
}
const rendered = await handlers.renderItemValue(controlNet);
setRenderedValue(rendered);
};
_renderValue();
}, [handlers, controlNet]);
return <MetadataItemView label={label} isDisabled={false} onRecall={onRecall} renderedValue={renderedValue} />;
};

View File

@ -1,72 +0,0 @@
import { MetadataItemView } from 'features/metadata/components/MetadataItemView';
import type { IPAdapterConfigV2Metadata, MetadataHandlers } from 'features/metadata/types';
import { handlers } from 'features/metadata/util/handlers';
import { useCallback, useEffect, useMemo, useState } from 'react';
type Props = {
metadata: unknown;
};
export const MetadataIPAdaptersV2 = ({ metadata }: Props) => {
const [ipAdapters, setIPAdapters] = useState<IPAdapterConfigV2Metadata[]>([]);
useEffect(() => {
const parse = async () => {
try {
const parsed = await handlers.ipAdaptersV2.parse(metadata);
setIPAdapters(parsed);
} catch (e) {
setIPAdapters([]);
}
};
parse();
}, [metadata]);
const label = useMemo(() => handlers.ipAdaptersV2.getLabel(), []);
return (
<>
{ipAdapters.map((ipAdapter) => (
<MetadataViewIPAdapter
key={ipAdapter.id}
label={label}
ipAdapter={ipAdapter}
handlers={handlers.ipAdaptersV2}
/>
))}
</>
);
};
const MetadataViewIPAdapter = ({
label,
ipAdapter,
handlers,
}: {
label: string;
ipAdapter: IPAdapterConfigV2Metadata;
handlers: MetadataHandlers<IPAdapterConfigV2Metadata[], IPAdapterConfigV2Metadata>;
}) => {
const onRecall = useCallback(() => {
if (!handlers.recallItem) {
return;
}
handlers.recallItem(ipAdapter, true);
}, [handlers, ipAdapter]);
const [renderedValue, setRenderedValue] = useState<React.ReactNode>(null);
useEffect(() => {
const _renderValue = async () => {
if (!handlers.renderItemValue) {
setRenderedValue(null);
return;
}
const rendered = await handlers.renderItemValue(ipAdapter);
setRenderedValue(rendered);
};
_renderValue();
}, [handlers, ipAdapter]);
return <MetadataItemView label={label} isDisabled={false} onRecall={onRecall} renderedValue={renderedValue} />;
};

View File

@ -1,72 +0,0 @@
import { MetadataItemView } from 'features/metadata/components/MetadataItemView';
import type { MetadataHandlers, T2IAdapterConfigV2Metadata } from 'features/metadata/types';
import { handlers } from 'features/metadata/util/handlers';
import { useCallback, useEffect, useMemo, useState } from 'react';
type Props = {
metadata: unknown;
};
export const MetadataT2IAdaptersV2 = ({ metadata }: Props) => {
const [t2iAdapters, setT2IAdapters] = useState<T2IAdapterConfigV2Metadata[]>([]);
useEffect(() => {
const parse = async () => {
try {
const parsed = await handlers.t2iAdaptersV2.parse(metadata);
setT2IAdapters(parsed);
} catch (e) {
setT2IAdapters([]);
}
};
parse();
}, [metadata]);
const label = useMemo(() => handlers.t2iAdaptersV2.getLabel(), []);
return (
<>
{t2iAdapters.map((t2iAdapter) => (
<MetadataViewT2IAdapter
key={t2iAdapter.id}
label={label}
t2iAdapter={t2iAdapter}
handlers={handlers.t2iAdaptersV2}
/>
))}
</>
);
};
const MetadataViewT2IAdapter = ({
label,
t2iAdapter,
handlers,
}: {
label: string;
t2iAdapter: T2IAdapterConfigV2Metadata;
handlers: MetadataHandlers<T2IAdapterConfigV2Metadata[], T2IAdapterConfigV2Metadata>;
}) => {
const onRecall = useCallback(() => {
if (!handlers.recallItem) {
return;
}
handlers.recallItem(t2iAdapter, true);
}, [handlers, t2iAdapter]);
const [renderedValue, setRenderedValue] = useState<React.ReactNode>(null);
useEffect(() => {
const _renderValue = async () => {
if (!handlers.renderItemValue) {
setRenderedValue(null);
return;
}
const rendered = await handlers.renderItemValue(t2iAdapter);
setRenderedValue(rendered);
};
_renderValue();
}, [handlers, t2iAdapter]);
return <MetadataItemView label={label} isDisabled={false} onRecall={onRecall} renderedValue={renderedValue} />;
};

View File

@ -1,9 +1,4 @@
import type { ControlNetConfig, IPAdapterConfig, T2IAdapterConfig } from 'features/controlAdapters/store/types';
import type {
ControlNetConfigV2,
IPAdapterConfigV2,
T2IAdapterConfigV2,
} from 'features/controlLayers/util/controlAdapters';
import type { O } from 'ts-toolbelt';
/**
@ -157,11 +152,3 @@ export type AnyControlAdapterConfigMetadata =
| ControlNetConfigMetadata
| T2IAdapterConfigMetadata
| IPAdapterConfigMetadata;
export type ControlNetConfigV2Metadata = O.NonNullable<ControlNetConfigV2, 'model'>;
export type T2IAdapterConfigV2Metadata = O.NonNullable<T2IAdapterConfigV2, 'model'>;
export type IPAdapterConfigV2Metadata = O.NonNullable<IPAdapterConfigV2, 'model'>;
export type AnyControlAdapterConfigV2Metadata =
| ControlNetConfigV2Metadata
| T2IAdapterConfigV2Metadata
| IPAdapterConfigV2Metadata;

View File

@ -4,7 +4,6 @@ import type { Layer } from 'features/controlLayers/store/types';
import type { LoRA } from 'features/lora/store/loraSlice';
import type {
AnyControlAdapterConfigMetadata,
AnyControlAdapterConfigV2Metadata,
BuildMetadataHandlers,
MetadataGetLabelFunc,
MetadataHandlers,
@ -46,14 +45,6 @@ const renderControlAdapterValue: MetadataRenderValueFunc<AnyControlAdapterConfig
return `${value.model.key} (${value.model.base.toUpperCase()}) - ${value.weight}`;
}
};
const renderControlAdapterValueV2: MetadataRenderValueFunc<AnyControlAdapterConfigV2Metadata> = async (value) => {
try {
const modelConfig = await fetchModelConfig(value.model.key ?? 'none');
return `${modelConfig.name} (${modelConfig.base.toUpperCase()}) - ${value.weight}`;
} catch {
return `${value.model.key} (${value.model.base.toUpperCase()}) - ${value.weight}`;
}
};
const renderLayerValue: MetadataRenderValueFunc<Layer> = async (layer) => {
if (layer.type === 'initial_image_layer') {
return t('controlLayers.initialImageLayer');
@ -93,26 +84,6 @@ const parameterNotSetToast = (parameter: string, description?: string) => {
});
};
// const allParameterSetToast = (description?: string) => {
// toast({
// title: t('toast.parametersSet'),
// status: 'info',
// description,
// duration: 2500,
// isClosable: true,
// });
// };
// const allParameterNotSetToast = (description?: string) => {
// toast({
// title: t('toast.parametersNotSet'),
// status: 'warning',
// description,
// duration: 2500,
// isClosable: true,
// });
// };
const buildParse =
<TValue, TItem>(arg: {
parser: MetadataParseFunc<TValue>;
@ -220,12 +191,6 @@ export const handlers = {
recaller: recallers.cfgScale,
}),
height: buildHandlers({ getLabel: () => t('metadata.height'), parser: parsers.height, recaller: recallers.height }),
initialImage: buildHandlers({
getLabel: () => t('metadata.initImage'),
parser: parsers.initialImage,
recaller: recallers.initialImage,
renderValue: async (imageDTO) => imageDTO.image_name,
}),
negativePrompt: buildHandlers({
getLabel: () => t('metadata.negativePrompt'),
parser: parsers.negativePrompt,
@ -372,36 +337,6 @@ export const handlers = {
itemValidator: validators.t2iAdapter,
renderItemValue: renderControlAdapterValue,
}),
controlNetsV2: buildHandlers({
getLabel: () => t('common.controlNet'),
parser: parsers.controlNetsV2,
itemParser: parsers.controlNetV2,
recaller: recallers.controlNetsV2,
itemRecaller: recallers.controlNetV2,
validator: validators.controlNetsV2,
itemValidator: validators.controlNetV2,
renderItemValue: renderControlAdapterValueV2,
}),
ipAdaptersV2: buildHandlers({
getLabel: () => t('common.ipAdapter'),
parser: parsers.ipAdaptersV2,
itemParser: parsers.ipAdapterV2,
recaller: recallers.ipAdaptersV2,
itemRecaller: recallers.ipAdapterV2,
validator: validators.ipAdaptersV2,
itemValidator: validators.ipAdapterV2,
renderItemValue: renderControlAdapterValueV2,
}),
t2iAdaptersV2: buildHandlers({
getLabel: () => t('common.t2iAdapter'),
parser: parsers.t2iAdaptersV2,
itemParser: parsers.t2iAdapterV2,
recaller: recallers.t2iAdaptersV2,
itemRecaller: recallers.t2iAdapterV2,
validator: validators.t2iAdaptersV2,
itemValidator: validators.t2iAdapterV2,
renderItemValue: renderControlAdapterValueV2,
}),
layers: buildHandlers({
getLabel: () => t('controlLayers.layers_other'),
parser: parsers.layers,
@ -469,22 +404,9 @@ export const parseAndRecallImageDimensions = async (metadata: unknown) => {
};
// These handlers should be omitted when recalling to control layers
const TO_CONTROL_LAYERS_SKIP_KEYS: (keyof typeof handlers)[] = [
'controlNets',
'ipAdapters',
't2iAdapters',
'controlNetsV2',
'ipAdaptersV2',
't2iAdaptersV2',
];
const TO_CONTROL_LAYERS_SKIP_KEYS: (keyof typeof handlers)[] = ['controlNets', 'ipAdapters', 't2iAdapters'];
// These handlers should be omitted when recalling to the rest of the app
const NOT_TO_CONTROL_LAYERS_SKIP_KEYS: (keyof typeof handlers)[] = [
'controlNetsV2',
'ipAdaptersV2',
't2iAdaptersV2',
'initialImage',
'layers',
];
const NOT_TO_CONTROL_LAYERS_SKIP_KEYS: (keyof typeof handlers)[] = ['layers'];
export const parseAndRecallAllMetadata = async (
metadata: unknown,

View File

@ -7,24 +7,13 @@ import {
import { buildControlAdapterProcessor } from 'features/controlAdapters/util/buildControlAdapterProcessor';
import type { Layer } from 'features/controlLayers/store/types';
import { zLayer } from 'features/controlLayers/store/types';
import {
CA_PROCESSOR_DATA,
imageDTOToImageWithDims,
initialControlNetV2,
initialIPAdapterV2,
initialT2IAdapterV2,
isProcessorTypeV2,
} from 'features/controlLayers/util/controlAdapters';
import type { LoRA } from 'features/lora/store/loraSlice';
import { defaultLoRAConfig } from 'features/lora/store/loraSlice';
import type {
ControlNetConfigMetadata,
ControlNetConfigV2Metadata,
IPAdapterConfigMetadata,
IPAdapterConfigV2Metadata,
MetadataParseFunc,
T2IAdapterConfigMetadata,
T2IAdapterConfigV2Metadata,
} from 'features/metadata/types';
import { fetchModelConfigWithTypeGuard, getModelKey } from 'features/metadata/util/modelFetchingHelpers';
import { zControlField, zIPAdapterField, zModelIdentifierField, zT2IAdapterField } from 'features/nodes/types/common';
@ -71,7 +60,7 @@ import {
isParameterWidth,
} from 'features/parameters/types/parameterSchemas';
import { get, isArray, isString } from 'lodash-es';
import { getImageDTO, imagesApi } from 'services/api/endpoints/images';
import { imagesApi } from 'services/api/endpoints/images';
import type { ImageDTO } from 'services/api/types';
import {
isControlNetModelConfig,
@ -441,203 +430,7 @@ const parseAllIPAdapters: MetadataParseFunc<IPAdapterConfigMetadata[]> = async (
}
};
//#region V2/Control Layers
const parseControlNetV2: MetadataParseFunc<ControlNetConfigV2Metadata> = async (metadataItem) => {
const control_model = await getProperty(metadataItem, 'control_model');
const key = await getModelKey(control_model, 'controlnet');
const controlNetModel = await fetchModelConfigWithTypeGuard(key, isControlNetModelConfig);
const image = zControlField.shape.image
.nullish()
.catch(null)
.parse(await getProperty(metadataItem, 'image'));
const processedImage = zControlField.shape.image
.nullish()
.catch(null)
.parse(await getProperty(metadataItem, 'processed_image'));
const control_weight = zControlField.shape.control_weight
.nullish()
.catch(null)
.parse(await getProperty(metadataItem, 'control_weight'));
const begin_step_percent = zControlField.shape.begin_step_percent
.nullish()
.catch(null)
.parse(await getProperty(metadataItem, 'begin_step_percent'));
const end_step_percent = zControlField.shape.end_step_percent
.nullish()
.catch(null)
.parse(await getProperty(metadataItem, 'end_step_percent'));
const control_mode = zControlField.shape.control_mode
.nullish()
.catch(null)
.parse(await getProperty(metadataItem, 'control_mode'));
const id = uuidv4();
const defaultPreprocessor = controlNetModel.default_settings?.preprocessor;
const processorConfig = isProcessorTypeV2(defaultPreprocessor)
? CA_PROCESSOR_DATA[defaultPreprocessor].buildDefaults()
: null;
const beginEndStepPct: [number, number] = [
begin_step_percent ?? initialControlNetV2.beginEndStepPct[0],
end_step_percent ?? initialControlNetV2.beginEndStepPct[1],
];
const imageDTO = image ? await getImageDTO(image.image_name) : null;
const processedImageDTO = processedImage ? await getImageDTO(processedImage.image_name) : null;
const controlNet: ControlNetConfigV2Metadata = {
id,
type: 'controlnet',
model: zModelIdentifierField.parse(controlNetModel),
weight: typeof control_weight === 'number' ? control_weight : initialControlNetV2.weight,
beginEndStepPct,
controlMode: control_mode ?? initialControlNetV2.controlMode,
image: imageDTO ? imageDTOToImageWithDims(imageDTO) : null,
processedImage: processedImageDTO ? imageDTOToImageWithDims(processedImageDTO) : null,
processorConfig,
isProcessingImage: false,
};
return controlNet;
};
const parseAllControlNetsV2: MetadataParseFunc<ControlNetConfigV2Metadata[]> = async (metadata) => {
try {
const controlNetsRaw = await getProperty(metadata, 'controlnets', isArray || undefined);
const parseResults = await Promise.allSettled(controlNetsRaw.map((cn) => parseControlNetV2(cn)));
const controlNets = parseResults
.filter((result): result is PromiseFulfilledResult<ControlNetConfigV2Metadata> => result.status === 'fulfilled')
.map((result) => result.value);
return controlNets;
} catch {
return [];
}
};
const parseT2IAdapterV2: MetadataParseFunc<T2IAdapterConfigV2Metadata> = async (metadataItem) => {
const t2i_adapter_model = await getProperty(metadataItem, 't2i_adapter_model');
const key = await getModelKey(t2i_adapter_model, 't2i_adapter');
const t2iAdapterModel = await fetchModelConfigWithTypeGuard(key, isT2IAdapterModelConfig);
const image = zT2IAdapterField.shape.image
.nullish()
.catch(null)
.parse(await getProperty(metadataItem, 'image'));
const processedImage = zT2IAdapterField.shape.image
.nullish()
.catch(null)
.parse(await getProperty(metadataItem, 'processed_image'));
const weight = zT2IAdapterField.shape.weight
.nullish()
.catch(null)
.parse(await getProperty(metadataItem, 'weight'));
const begin_step_percent = zT2IAdapterField.shape.begin_step_percent
.nullish()
.catch(null)
.parse(await getProperty(metadataItem, 'begin_step_percent'));
const end_step_percent = zT2IAdapterField.shape.end_step_percent
.nullish()
.catch(null)
.parse(await getProperty(metadataItem, 'end_step_percent'));
const id = uuidv4();
const defaultPreprocessor = t2iAdapterModel.default_settings?.preprocessor;
const processorConfig = isProcessorTypeV2(defaultPreprocessor)
? CA_PROCESSOR_DATA[defaultPreprocessor].buildDefaults()
: null;
const beginEndStepPct: [number, number] = [
begin_step_percent ?? initialT2IAdapterV2.beginEndStepPct[0],
end_step_percent ?? initialT2IAdapterV2.beginEndStepPct[1],
];
const imageDTO = image ? await getImageDTO(image.image_name) : null;
const processedImageDTO = processedImage ? await getImageDTO(processedImage.image_name) : null;
const t2iAdapter: T2IAdapterConfigV2Metadata = {
id,
type: 't2i_adapter',
model: zModelIdentifierField.parse(t2iAdapterModel),
weight: typeof weight === 'number' ? weight : initialT2IAdapterV2.weight,
beginEndStepPct,
image: imageDTO ? imageDTOToImageWithDims(imageDTO) : null,
processedImage: processedImageDTO ? imageDTOToImageWithDims(processedImageDTO) : null,
processorConfig,
isProcessingImage: false,
};
return t2iAdapter;
};
const parseAllT2IAdaptersV2: MetadataParseFunc<T2IAdapterConfigV2Metadata[]> = async (metadata) => {
try {
const t2iAdaptersRaw = await getProperty(metadata, 't2iAdapters', isArray);
const parseResults = await Promise.allSettled(t2iAdaptersRaw.map((t2iAdapter) => parseT2IAdapterV2(t2iAdapter)));
const t2iAdapters = parseResults
.filter((result): result is PromiseFulfilledResult<T2IAdapterConfigV2Metadata> => result.status === 'fulfilled')
.map((result) => result.value);
return t2iAdapters;
} catch {
return [];
}
};
const parseIPAdapterV2: MetadataParseFunc<IPAdapterConfigV2Metadata> = async (metadataItem) => {
const ip_adapter_model = await getProperty(metadataItem, 'ip_adapter_model');
const key = await getModelKey(ip_adapter_model, 'ip_adapter');
const ipAdapterModel = await fetchModelConfigWithTypeGuard(key, isIPAdapterModelConfig);
const image = zIPAdapterField.shape.image
.nullish()
.catch(null)
.parse(await getProperty(metadataItem, 'image'));
const weight = zIPAdapterField.shape.weight
.nullish()
.catch(null)
.parse(await getProperty(metadataItem, 'weight'));
const method = zIPAdapterField.shape.method
.nullish()
.catch(null)
.parse(await getProperty(metadataItem, 'method'));
const begin_step_percent = zIPAdapterField.shape.begin_step_percent
.nullish()
.catch(null)
.parse(await getProperty(metadataItem, 'begin_step_percent'));
const end_step_percent = zIPAdapterField.shape.end_step_percent
.nullish()
.catch(null)
.parse(await getProperty(metadataItem, 'end_step_percent'));
const id = uuidv4();
const beginEndStepPct: [number, number] = [
begin_step_percent ?? initialIPAdapterV2.beginEndStepPct[0],
end_step_percent ?? initialIPAdapterV2.beginEndStepPct[1],
];
const imageDTO = image ? await getImageDTO(image.image_name) : null;
const ipAdapter: IPAdapterConfigV2Metadata = {
id,
type: 'ip_adapter',
model: zModelIdentifierField.parse(ipAdapterModel),
weight: typeof weight === 'number' ? weight : initialIPAdapterV2.weight,
beginEndStepPct,
image: imageDTO ? imageDTOToImageWithDims(imageDTO) : null,
clipVisionModel: initialIPAdapterV2.clipVisionModel, // TODO: This needs to be added to the zIPAdapterField...
method: method ?? initialIPAdapterV2.method,
};
return ipAdapter;
};
const parseAllIPAdaptersV2: MetadataParseFunc<IPAdapterConfigV2Metadata[]> = async (metadata) => {
try {
const ipAdaptersRaw = await getProperty(metadata, 'ipAdapters', isArray);
const parseResults = await Promise.allSettled(ipAdaptersRaw.map((ipAdapter) => parseIPAdapterV2(ipAdapter)));
const ipAdapters = parseResults
.filter((result): result is PromiseFulfilledResult<IPAdapterConfigV2Metadata> => result.status === 'fulfilled')
.map((result) => result.value);
return ipAdapters;
} catch {
return [];
}
};
//#region Control Layers
const parseLayer: MetadataParseFunc<Layer> = async (metadataItem) => zLayer.parseAsync(metadataItem);
const parseLayers: MetadataParseFunc<Layer[]> = async (metadata) => {
@ -652,6 +445,7 @@ const parseLayers: MetadataParseFunc<Layer[]> = async (metadata) => {
return [];
}
};
//#endregion
export const parsers = {
createdBy: parseCreatedBy,
@ -689,12 +483,6 @@ export const parsers = {
t2iAdapters: parseAllT2IAdapters,
ipAdapter: parseIPAdapter,
ipAdapters: parseAllIPAdapters,
controlNetV2: parseControlNetV2,
controlNetsV2: parseAllControlNetsV2,
t2iAdapterV2: parseT2IAdapterV2,
t2iAdaptersV2: parseAllT2IAdaptersV2,
ipAdapterV2: parseIPAdapterV2,
ipAdaptersV2: parseAllIPAdaptersV2,
layer: parseLayer,
layers: parseLayers,
} as const;

View File

@ -7,16 +7,10 @@ import {
} from 'features/controlAdapters/store/controlAdaptersSlice';
import {
allLayersDeleted,
caLayerAdded,
caLayerControlNetsDeleted,
caLayerRecalled,
caLayerT2IAdaptersDeleted,
heightChanged,
iiLayerAdded,
iiLayerRecalled,
ipaLayerAdded,
ipaLayerRecalled,
ipaLayersDeleted,
negativePrompt2Changed,
negativePromptChanged,
positivePrompt2Changed,
@ -30,12 +24,9 @@ import type { LoRA } from 'features/lora/store/loraSlice';
import { loraRecalled, lorasReset } from 'features/lora/store/loraSlice';
import type {
ControlNetConfigMetadata,
ControlNetConfigV2Metadata,
IPAdapterConfigMetadata,
IPAdapterConfigV2Metadata,
MetadataRecallFunc,
T2IAdapterConfigMetadata,
T2IAdapterConfigV2Metadata,
} from 'features/metadata/types';
import { modelSelected } from 'features/parameters/store/actions';
import {
@ -78,7 +69,6 @@ import {
setRefinerStart,
setRefinerSteps,
} from 'features/sdxl/store/sdxlSlice';
import type { ImageDTO } from 'services/api/types';
const recallPositivePrompt: MetadataRecallFunc<ParameterPositivePrompt> = (positivePrompt) => {
getStore().dispatch(positivePromptChanged(positivePrompt));
@ -112,10 +102,6 @@ const recallScheduler: MetadataRecallFunc<ParameterScheduler> = (scheduler) => {
getStore().dispatch(setScheduler(scheduler));
};
const recallInitialImage: MetadataRecallFunc<ImageDTO> = async (imageDTO) => {
getStore().dispatch(iiLayerAdded(imageDTO));
};
const setSizeOptions = { updateAspectRatio: true, clamp: true };
const recallWidth: MetadataRecallFunc<ParameterWidth> = (width) => {
@ -250,52 +236,7 @@ const recallIPAdapters: MetadataRecallFunc<IPAdapterConfigMetadata[]> = (ipAdapt
});
};
//#region V2/Control Layer
const recallControlNetV2: MetadataRecallFunc<ControlNetConfigV2Metadata> = (controlNet) => {
getStore().dispatch(caLayerAdded(controlNet));
};
const recallControlNetsV2: MetadataRecallFunc<ControlNetConfigV2Metadata[]> = (controlNets) => {
const { dispatch } = getStore();
dispatch(caLayerControlNetsDeleted());
if (!controlNets.length) {
return;
}
controlNets.forEach((controlNet) => {
dispatch(caLayerAdded(controlNet));
});
};
const recallT2IAdapterV2: MetadataRecallFunc<T2IAdapterConfigV2Metadata> = (t2iAdapter) => {
getStore().dispatch(caLayerAdded(t2iAdapter));
};
const recallT2IAdaptersV2: MetadataRecallFunc<T2IAdapterConfigV2Metadata[]> = (t2iAdapters) => {
const { dispatch } = getStore();
dispatch(caLayerT2IAdaptersDeleted());
if (!t2iAdapters.length) {
return;
}
t2iAdapters.forEach((t2iAdapters) => {
dispatch(caLayerAdded(t2iAdapters));
});
};
const recallIPAdapterV2: MetadataRecallFunc<IPAdapterConfigV2Metadata> = (ipAdapter) => {
getStore().dispatch(ipaLayerAdded(ipAdapter));
};
const recallIPAdaptersV2: MetadataRecallFunc<IPAdapterConfigV2Metadata[]> = (ipAdapters) => {
const { dispatch } = getStore();
dispatch(ipaLayersDeleted());
if (!ipAdapters.length) {
return;
}
ipAdapters.forEach((ipAdapter) => {
dispatch(ipaLayerAdded(ipAdapter));
});
};
//#region Control Layers
const recallLayer: MetadataRecallFunc<Layer> = (layer) => {
const { dispatch } = getStore();
switch (layer.type) {
@ -331,7 +272,6 @@ export const recallers = {
cfgScale: recallCFGScale,
cfgRescaleMultiplier: recallCFGRescaleMultiplier,
scheduler: recallScheduler,
initialImage: recallInitialImage,
width: recallWidth,
height: recallHeight,
steps: recallSteps,
@ -356,12 +296,6 @@ export const recallers = {
t2iAdapter: recallT2IAdapter,
ipAdapters: recallIPAdapters,
ipAdapter: recallIPAdapter,
controlNetV2: recallControlNetV2,
controlNetsV2: recallControlNetsV2,
t2iAdapterV2: recallT2IAdapterV2,
t2iAdaptersV2: recallT2IAdaptersV2,
ipAdapterV2: recallIPAdapterV2,
ipAdaptersV2: recallIPAdaptersV2,
layer: recallLayer,
layers: recallLayers,
} as const;

View File

@ -3,12 +3,9 @@ import type { Layer } from 'features/controlLayers/store/types';
import type { LoRA } from 'features/lora/store/loraSlice';
import type {
ControlNetConfigMetadata,
ControlNetConfigV2Metadata,
IPAdapterConfigMetadata,
IPAdapterConfigV2Metadata,
MetadataValidateFunc,
T2IAdapterConfigMetadata,
T2IAdapterConfigV2Metadata,
} from 'features/metadata/types';
import { fetchModelConfigByIdentifier, InvalidModelConfigError } from 'features/metadata/util/modelFetchingHelpers';
import type { ParameterSDXLRefinerModel, ParameterVAEModel } from 'features/parameters/types/parameterSchemas';
@ -113,60 +110,6 @@ const validateIPAdapters: MetadataValidateFunc<IPAdapterConfigMetadata[]> = (ipA
return new Promise((resolve) => resolve(validatedIPAdapters));
};
const validateControlNetV2: MetadataValidateFunc<ControlNetConfigV2Metadata> = (controlNet) => {
validateBaseCompatibility(controlNet.model?.base, 'ControlNet incompatible with currently-selected model');
return new Promise((resolve) => resolve(controlNet));
};
const validateControlNetsV2: MetadataValidateFunc<ControlNetConfigV2Metadata[]> = (controlNets) => {
const validatedControlNets: ControlNetConfigV2Metadata[] = [];
controlNets.forEach((controlNet) => {
try {
validateBaseCompatibility(controlNet.model?.base, 'ControlNet incompatible with currently-selected model');
validatedControlNets.push(controlNet);
} catch {
// This is a no-op - we want to continue validating the rest of the ControlNets, and an empty list is valid.
}
});
return new Promise((resolve) => resolve(validatedControlNets));
};
const validateT2IAdapterV2: MetadataValidateFunc<T2IAdapterConfigV2Metadata> = (t2iAdapter) => {
validateBaseCompatibility(t2iAdapter.model?.base, 'T2I Adapter incompatible with currently-selected model');
return new Promise((resolve) => resolve(t2iAdapter));
};
const validateT2IAdaptersV2: MetadataValidateFunc<T2IAdapterConfigV2Metadata[]> = (t2iAdapters) => {
const validatedT2IAdapters: T2IAdapterConfigV2Metadata[] = [];
t2iAdapters.forEach((t2iAdapter) => {
try {
validateBaseCompatibility(t2iAdapter.model?.base, 'T2I Adapter incompatible with currently-selected model');
validatedT2IAdapters.push(t2iAdapter);
} catch {
// This is a no-op - we want to continue validating the rest of the T2I Adapters, and an empty list is valid.
}
});
return new Promise((resolve) => resolve(validatedT2IAdapters));
};
const validateIPAdapterV2: MetadataValidateFunc<IPAdapterConfigV2Metadata> = (ipAdapter) => {
validateBaseCompatibility(ipAdapter.model?.base, 'IP Adapter incompatible with currently-selected model');
return new Promise((resolve) => resolve(ipAdapter));
};
const validateIPAdaptersV2: MetadataValidateFunc<IPAdapterConfigV2Metadata[]> = (ipAdapters) => {
const validatedIPAdapters: IPAdapterConfigV2Metadata[] = [];
ipAdapters.forEach((ipAdapter) => {
try {
validateBaseCompatibility(ipAdapter.model?.base, 'IP Adapter incompatible with currently-selected model');
validatedIPAdapters.push(ipAdapter);
} catch {
// This is a no-op - we want to continue validating the rest of the IP Adapters, and an empty list is valid.
}
});
return new Promise((resolve) => resolve(validatedIPAdapters));
};
const validateLayer: MetadataValidateFunc<Layer> = async (layer) => {
if (layer.type === 'control_adapter_layer') {
const model = layer.controlAdapter.model;
@ -216,12 +159,6 @@ export const validators = {
t2iAdapters: validateT2IAdapters,
ipAdapter: validateIPAdapter,
ipAdapters: validateIPAdapters,
controlNetV2: validateControlNetV2,
controlNetsV2: validateControlNetsV2,
t2iAdapterV2: validateT2IAdapterV2,
t2iAdaptersV2: validateT2IAdaptersV2,
ipAdapterV2: validateIPAdapterV2,
ipAdaptersV2: validateIPAdaptersV2,
layer: validateLayer,
layers: validateLayers,
} as const;