File size: 3,717 Bytes
8a37e0a | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 | import { Box, Combobox, Flex, FormControl, FormLabel, Icon, Spacer, Tooltip } from '@invoke-ai/ui-library';
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
import { InformationalPopover } from 'common/components/InformationalPopover/InformationalPopover';
import { useGroupedModelCombobox } from 'common/hooks/useGroupedModelCombobox';
import { selectModelKey } from 'features/controlLayers/store/paramsSlice';
import { zModelIdentifierField } from 'features/nodes/types/common';
import { modelSelected } from 'features/parameters/store/actions';
import { selectActiveTab } from 'features/ui/store/uiSelectors';
import { memo, useCallback, useMemo } from 'react';
import { useTranslation } from 'react-i18next';
import { MdMoneyOff } from 'react-icons/md';
import { useMainModels } from 'services/api/hooks/modelsByType';
import { type AnyModelConfig, isCheckpointMainModelConfig, type MainModelConfig } from 'services/api/types';
const ParamMainModelSelect = () => {
const dispatch = useAppDispatch();
const { t } = useTranslation();
const activeTabName = useAppSelector(selectActiveTab);
const selectedModelKey = useAppSelector(selectModelKey);
// const selectedModel = useAppSelector(selectModel);
const [modelConfigs, { isLoading }] = useMainModels();
const selectedModel = useMemo(() => {
if (!modelConfigs) {
return null;
}
if (selectedModelKey === null) {
return null;
}
const modelConfig = modelConfigs.find((model) => model.key === selectedModelKey);
if (!modelConfig) {
return null;
}
return modelConfig;
}, [modelConfigs, selectedModelKey]);
const tooltipLabel = useMemo(() => {
if (!modelConfigs.length || !selectedModel) {
return;
}
return modelConfigs.find((m) => m.key === selectedModel?.key)?.description;
}, [modelConfigs, selectedModel]);
const _onChange = useCallback(
(model: MainModelConfig | null) => {
if (!model) {
return;
}
try {
dispatch(modelSelected(zModelIdentifierField.parse(model)));
} catch {
// no-op
}
},
[dispatch]
);
const getIsDisabled = useCallback(
(model: AnyModelConfig): boolean => {
return activeTabName === 'upscaling' && model.base === 'flux';
},
[activeTabName]
);
const { options, value, onChange, placeholder, noOptionsMessage } = useGroupedModelCombobox({
modelConfigs,
selectedModel,
onChange: _onChange,
isLoading,
getIsDisabled,
});
const isFluxDevSelected = useMemo(() => {
return selectedModel && isCheckpointMainModelConfig(selectedModel) && selectedModel.config_path === 'flux-dev';
}, [selectedModel]);
return (
<FormControl isDisabled={!modelConfigs.length} isInvalid={!value || !modelConfigs.length}>
<Flex alignItems="center">
<InformationalPopover feature="paramModel">
<FormLabel>{t('modelManager.model')}</FormLabel>
</InformationalPopover>
{isFluxDevSelected ? (
<InformationalPopover feature="fluxDevLicense" hideDisable={true}>
<Flex justifyContent="flex-start">
<Icon as={MdMoneyOff} />
</Flex>
</InformationalPopover>
) : (
<Spacer />
)}
</Flex>
<Tooltip label={tooltipLabel}>
<Box w="full" minW={0}>
<Combobox
value={value}
placeholder={placeholder}
options={options}
onChange={onChange}
noOptionsMessage={noOptionsMessage}
isInvalid={value?.isDisabled}
/>
</Box>
</Tooltip>
</FormControl>
);
};
export default memo(ParamMainModelSelect);
|