diff --git a/invokeai/frontend/web/src/features/system/components/ModelManager/ModelList.tsx b/invokeai/frontend/web/src/features/system/components/ModelManager/ModelList.tsx index 4ef311e1d4..b090c2a07b 100644 --- a/invokeai/frontend/web/src/features/system/components/ModelManager/ModelList.tsx +++ b/invokeai/frontend/web/src/features/system/components/ModelManager/ModelList.tsx @@ -1,36 +1,16 @@ import { Box, Flex, Heading, Spacer, Spinner, Text } from '@chakra-ui/react'; -import IAIInput from 'common/components/IAIInput'; import IAIButton from 'common/components/IAIButton'; +import IAIInput from 'common/components/IAIInput'; import AddModel from './AddModel'; -import ModelListItem from './ModelListItem'; import MergeModels from './MergeModels'; +import ModelListItem from './ModelListItem'; -import { useAppSelector } from 'app/store/storeHooks'; import { useTranslation } from 'react-i18next'; -import { createSelector } from '@reduxjs/toolkit'; -import { systemSelector } from 'features/system/store/systemSelectors'; -import type { SystemState } from 'features/system/store/systemSlice'; -import { isEqual, map } from 'lodash-es'; - -import React, { useMemo, useState, useTransition } from 'react'; import type { ChangeEvent, ReactNode } from 'react'; - -const modelListSelector = createSelector( - systemSelector, - (system: SystemState) => { - const models = map(system.model_list, (model, key) => { - return { name: key, ...model }; - }); - return models; - }, - { - memoizeOptions: { - resultEqualityCheck: isEqual, - }, - } -); +import React, { useMemo, useState, useTransition } from 'react'; +import { useListModelsQuery } from 'services/api/endpoints/models'; function ModelFilterButton({ label, @@ -58,7 +38,9 @@ function ModelFilterButton({ } const ModelList = () => { - const models = useAppSelector(modelListSelector); + const { data: pipelineModels } = useListModelsQuery({ + model_type: 'pipeline', + }); const [renderModelList, setRenderModelList] = React.useState(false); @@ -90,43 +72,49 @@ const ModelList = () => { const filteredModelListItemsToRender: ReactNode[] = []; const localFilteredModelListItemsToRender: ReactNode[] = []; - models.forEach((model, i) => { - if (model.name.toLowerCase().includes(searchText.toLowerCase())) { + if (!pipelineModels) return; + + const modelList = pipelineModels.entities; + + Object.keys(modelList).forEach((model, i) => { + if ( + modelList[model].name.toLowerCase().includes(searchText.toLowerCase()) + ) { filteredModelListItemsToRender.push( ); - if (model.format === isSelectedFilter) { + if (modelList[model]?.model_format === isSelectedFilter) { localFilteredModelListItemsToRender.push( ); } } - if (model.format !== 'diffusers') { + if (modelList[model]?.model_format !== 'diffusers') { ckptModelListItemsToRender.push( ); } else { diffusersModelListItemsToRender.push( ); } @@ -142,6 +130,23 @@ const ModelList = () => { {isSelectedFilter === 'all' && ( <> + + + {t('modelManager.diffusersModels')} + + {diffusersModelListItemsToRender} + { {ckptModelListItemsToRender} - - - {t('modelManager.diffusersModels')} - - {diffusersModelListItemsToRender} - )} - {isSelectedFilter === 'ckpt' && ( - - {ckptModelListItemsToRender} - - )} - {isSelectedFilter === 'diffusers' && ( {diffusersModelListItemsToRender} )} + + {isSelectedFilter === 'ckpt' && ( + + {ckptModelListItemsToRender} + + )} ); - }, [models, searchText, t, isSelectedFilter]); + }, [pipelineModels, searchText, t, isSelectedFilter]); return ( @@ -211,7 +199,7 @@ const ModelList = () => { { onClick={() => setIsSelectedFilter('all')} isActive={isSelectedFilter === 'all'} /> - setIsSelectedFilter('ckpt')} - isActive={isSelectedFilter === 'ckpt'} - /> setIsSelectedFilter('diffusers')} isActive={isSelectedFilter === 'diffusers'} /> + setIsSelectedFilter('ckpt')} + isActive={isSelectedFilter === 'ckpt'} + /> {renderModelList ? ( diff --git a/invokeai/frontend/web/src/features/system/components/ModelManager/ModelListItem.tsx b/invokeai/frontend/web/src/features/system/components/ModelManager/ModelListItem.tsx index aa9f87816c..e1b3bbab1e 100644 --- a/invokeai/frontend/web/src/features/system/components/ModelManager/ModelListItem.tsx +++ b/invokeai/frontend/web/src/features/system/components/ModelManager/ModelListItem.tsx @@ -1,6 +1,6 @@ import { DeleteIcon, EditIcon } from '@chakra-ui/icons'; import { Box, Button, Flex, Spacer, Text, Tooltip } from '@chakra-ui/react'; -import { ModelStatus } from 'app/types/invokeai'; + // import { deleteModel, requestModelChange } from 'app/socketio/actions'; import { RootState } from 'app/store/store'; import { useAppDispatch, useAppSelector } from 'app/store/storeHooks'; @@ -10,9 +10,9 @@ import { setOpenModel } from 'features/system/store/systemSlice'; import { useTranslation } from 'react-i18next'; type ModelListItemProps = { + modelKey: string; name: string; - status: ModelStatus; - description: string; + description: string | undefined; }; export default function ModelListItem(props: ModelListItemProps) { @@ -28,18 +28,18 @@ export default function ModelListItem(props: ModelListItemProps) { const dispatch = useAppDispatch(); - const { name, status, description } = props; + const { modelKey, name, description } = props; const handleChangeModel = () => { - dispatch(requestModelChange(name)); + dispatch(requestModelChange(modelKey)); }; const openModelHandler = () => { - dispatch(setOpenModel(name)); + dispatch(setOpenModel(modelKey)); }; const handleModelDelete = () => { - dispatch(deleteModel(name)); + dispatch(deleteModel(modelKey)); dispatch(setOpenModel(null)); }; @@ -60,7 +60,7 @@ export default function ModelListItem(props: ModelListItemProps) { p={2} borderRadius="base" sx={ - name === openModel + modelKey === openModel ? { bg: 'accent.750', _hover: { @@ -81,7 +81,6 @@ export default function ModelListItem(props: ModelListItemProps) { - {status}