import { CustomSizeConfig, ImageCountConfig, ImageSizeConfig, ImageconstExtraConfig, SizeOption, imageSizeOptions as imageSizeList } from '@/pages/playground/config/params-config'; import { generateRandomNumber } from '@/utils'; import { useSearchParams } from '@umijs/max'; import { useMemoizedFn } from 'ahooks'; import _ from 'lodash'; import React, { useEffect, useMemo, useRef, useState } from 'react'; import { ParamsSchema } from '../config/types'; import { IMG_METAKEYS, advancedFieldsDefaultValus, imgInitialValues, openaiCompatibleFieldsDefaultValus } from './config'; interface MessageProps { modelList: Global.BaseOption[]; model?: string; loaded?: boolean; isChat?: boolean; ref?: any; } export const useInitImageMeta = ( props: MessageProps, options: { type: string } ) => { const { modelList } = props; const ImageAdvancedParamsConfig: ParamsSchema[] = []; const form = useRef(null); const [searchParams] = useSearchParams(); const [modelMeta, setModelMeta] = useState({}); const [isOpenaiCompatible, setIsOpenaiCompatible] = useState(false); const [imageSizeOptions, setImageSizeOptions] = React.useState( [] ); const [basicParamsConfig, setBasicParamsConfig] = React.useState< ParamsSchema[] >([...ImageCountConfig, ...ImageSizeConfig]); const initialSeed = generateRandomNumber(); const [initialValues, setInitialValues] = useState({ ...imgInitialValues, ...advancedFieldsDefaultValus, seed: initialSeed, model: '' }); const [paramsConfig, setParamsConfig] = useState([ ...ImageCountConfig, ...ImageSizeConfig, ...ImageAdvancedParamsConfig ]); const [parameters, setParams] = useState({ ...imgInitialValues, ...advancedFieldsDefaultValus, seed: initialSeed, model: '' }); const defaultModel = useMemo(() => { return searchParams.get('model') || modelList?.[0]?.value || ''; }, [modelList]); const cacheFormData = React.useRef>({ ...imgInitialValues, ...openaiCompatibleFieldsDefaultValus, ...advancedFieldsDefaultValus }); const ensureSizeOption = ( options: SizeOption[], width?: number, height?: number ) => { if ( width && height && !options.find((item) => item.width === width && item.height === height) ) { options.push({ width, height, label: `${width}x${height}`, value: `${width}x${height}` }); } }; const getNewImageSizeOptions = (metaData: any) => { const { max_height, max_width, default_width, default_height } = metaData || {}; if (!max_height || !max_width) { const newImageSizeOptions = [...imageSizeList]; ensureSizeOption(newImageSizeOptions, default_width, default_height); return newImageSizeOptions; } const newImageSizeOptions = imageSizeList.filter((item) => { return ( (item.width <= max_width && item.height <= max_height) || item.value === 'custom' ); }); ensureSizeOption(newImageSizeOptions, max_width, max_height); ensureSizeOption(newImageSizeOptions, default_width, default_height); return newImageSizeOptions; }; const generateImageParamsConfig = ( currentModel: any, sizeOptions: SizeOption[] ) => { if (sizeOptions.length) { const sizeConfig = ImageSizeConfig.map((item) => { if (item.name === 'size') { return { ...item, options: sizeOptions }; } return item; }); return [...ImageCountConfig, ...sizeConfig]; } const { max_height, max_width } = currentModel.meta || {}; const customSizeConfig = _.cloneDeep(CustomSizeConfig).map((item: any) => { const max = item.name === 'height' ? max_height : max_width; return { ...item, attrs: { ...item.attrs, max: max || item.attrs.max } }; }); return [...ImageCountConfig, ...customSizeConfig]; }; const extractIMGMeta = (meta: any) => { const sizeOptions = getNewImageSizeOptions(meta); return { form: _.merge( {}, { ...imgInitialValues, ...advancedFieldsDefaultValus }, { ..._.pick(meta, IMG_METAKEYS), seed: meta?.seed === -1 ? null : meta?.seed, size: sizeOptions.length ? `${meta?.default_width || 512}x${meta?.default_height || 512}` : 'custom', width: meta?.default_width || 512, height: meta?.default_height || 512 } ), meta: meta, sizeOptions: sizeOptions }; }; const updateParamsConfig = (values: { size: string; isOpenaiCompatible: boolean; }) => { // update config if (values.size === 'custom') { return [ ...basicParamsConfig, ...CustomSizeConfig, ...(values.isOpenaiCompatible ? ImageconstExtraConfig : ImageAdvancedParamsConfig) ]; } return [ ...basicParamsConfig, ...(values.isOpenaiCompatible ? ImageconstExtraConfig : ImageAdvancedParamsConfig) ]; }; const updateCacheFormData = (values: Record) => { _.merge(cacheFormData.current, values); }; const handleToggleParamsStyle = () => { // update values let values: any = {}; if (!isOpenaiCompatible) { values = _.pick( cacheFormData.current, _.keys({ ...imgInitialValues, ...openaiCompatibleFieldsDefaultValus }) ); } else { values = _.pick( cacheFormData.current, _.keys({ ...imgInitialValues, ...advancedFieldsDefaultValus }) ); } // update config const newParamsConfig = updateParamsConfig({ size: values.size, isOpenaiCompatible: !isOpenaiCompatible }); form.current?.form?.setFieldsValue({ ...values, model: parameters.model }); setParamsConfig(newParamsConfig); setParams({ ...values, model: parameters.model }); setIsOpenaiCompatible(!isOpenaiCompatible); updateCacheFormData({ ...values, model: parameters }); }; const handleOnModelChange = useMemoizedFn((val: string) => { if (!val) return; const model = modelList.find((item) => item.value === val); const { form: initialData, sizeOptions } = extractIMGMeta(model?.meta); const newParamsConfig = generateImageParamsConfig(model, sizeOptions); if (!isOpenaiCompatible) { setParamsConfig([...newParamsConfig, ...ImageAdvancedParamsConfig]); } else { setParamsConfig(newParamsConfig); } setBasicParamsConfig(newParamsConfig); setImageSizeOptions(sizeOptions); setModelMeta(model?.meta || {}); setInitialValues({ ...initialData, seed: parameters.seed, model: val }); setParams({ ...initialData, seed: parameters.seed, model: val }); updateCacheFormData(initialData); }); const handleOnValuesChange = useMemoizedFn( (changeValues: Record, allValues: Record) => { console.log('changeValues', changeValues); // model change will reset all values if (changeValues.model) { handleOnModelChange(changeValues.model); return; } if (changeValues.size && changeValues.size === 'custom') { setParamsConfig([ ...basicParamsConfig, ...CustomSizeConfig, ...(!isOpenaiCompatible ? ImageAdvancedParamsConfig : ImageconstExtraConfig) ]); setParams({ ...allValues, width: modelMeta.default_width || 512, height: modelMeta.default_height || 512 }); form.current?.form?.setFieldsValue({ width: modelMeta.default_width || 512, height: modelMeta.default_height || 512 }); updateCacheFormData(changeValues); } else if (changeValues.size && parameters.size === 'custom') { setParamsConfig([ ...basicParamsConfig, ...(!isOpenaiCompatible ? ImageAdvancedParamsConfig : ImageconstExtraConfig) ]); setParams(allValues); updateCacheFormData(changeValues); } else if (_.isBoolean(changeValues.random_seed)) { const seed = changeValues.random_seed ? generateRandomNumber() : parameters.seed; setParams({ ...allValues, seed: seed }); form.current?.form?.setFieldsValue({ seed: seed }); updateCacheFormData(changeValues); } else { setParams(allValues); updateCacheFormData(changeValues); } } ); useEffect(() => { if (defaultModel && modelList.length) { handleOnModelChange(defaultModel); } }, [defaultModel, modelList.length]); return { extractIMGMeta, generateImageParamsConfig, setImageSizeOptions, setBasicParamsConfig, updateCacheFormData, handleOnValuesChange, handleToggleParamsStyle, setParams, setInitialValues, updateParamsConfig, setParamsConfig, form, modelMeta, paramsConfig, initialValues, parameters, isOpenaiCompatible, cacheFormData, basicParamsConfig, imageSizeOptions, openaiCompatibleFieldsDefaultValus, advancedFieldsDefaultValus, imgInitialValues, ImageCountConfig, ImageSizeConfig, CustomSizeConfig, ImageconstExtraConfig }; };