feat(ui): use stickyscrollable for models list

This commit is contained in:
psychedelicious 2024-03-07 14:12:55 +11:00
parent ed4e8624dd
commit b0add805c5
4 changed files with 55 additions and 27 deletions

View File

@ -0,0 +1,32 @@
import type { ButtonProps } from '@invoke-ai/ui-library';
import { Button } from '@invoke-ai/ui-library';
import { useFeatureStatus } from 'features/system/hooks/useFeatureStatus';
import { memo } from 'react';
import { useTranslation } from 'react-i18next';
import { PiArrowsClockwiseBold } from 'react-icons/pi';
import { useSyncModels } from './useSyncModels';
export const SyncModelsButton = memo((props: Omit<ButtonProps, 'aria-label'>) => {
const { t } = useTranslation();
const { syncModels, isLoading } = useSyncModels();
const isSyncModelEnabled = useFeatureStatus('syncModels').isFeatureEnabled;
if (!isSyncModelEnabled) {
return null;
}
return (
<Button
leftIcon={<PiArrowsClockwiseBold />}
isLoading={isLoading}
onClick={syncModels}
variant="ghost"
{...props}
>
{t('modelManager.syncModels')}
</Button>
);
});
SyncModelsButton.displayName = 'SyncModelsButton';

View File

@ -1,9 +1,10 @@
import { Box, Button, Flex, Heading } from '@invoke-ai/ui-library';
import { Button, Flex, Heading, Spacer } from '@invoke-ai/ui-library';
import { useAppDispatch } from 'app/store/storeHooks';
import { SyncModelsIconButton } from 'features/modelManagerV2/components/SyncModels/SyncModelsIconButton';
import { SyncModelsButton } from 'features/modelManagerV2/components/SyncModels/SyncModelsButton';
import { setSelectedModelKey } from 'features/modelManagerV2/store/modelManagerV2Slice';
import { useCallback } from 'react';
import { useTranslation } from 'react-i18next';
import { PiPlusBold } from 'react-icons/pi';
import ModelList from './ModelManagerPanel/ModelList';
import { ModelListNavigation } from './ModelManagerPanel/ModelListNavigation';
@ -16,20 +17,19 @@ export const ModelManager = () => {
}, [dispatch]);
return (
<Box layerStyle="first" p={3} borderRadius="base" w="50%" h="full">
<Flex w="full" p={3} justifyContent="space-between" alignItems="center">
<Flex gap={2}>
<Heading fontSize="xl">{t('common.modelManager')}</Heading>
<SyncModelsIconButton />
</Flex>
<Button colorScheme="invokeYellow" onClick={handleClickAddModel}>
<Flex flexDir="column" layerStyle="first" p={4} gap={4} borderRadius="base" w="50%" h="full">
<Flex w="full" gap={4} justifyContent="space-between" alignItems="center">
<Heading fontSize="xl">{t('common.modelManager')}</Heading>
<Spacer />
<SyncModelsButton />
<Button colorScheme="invokeYellow" leftIcon={<PiPlusBold />} onClick={handleClickAddModel}>
{t('modelManager.addModels')}
</Button>
</Flex>
<Box layerStyle="second" p={3} borderRadius="base" w="full" h="full">
<Flex flexDir="column" layerStyle="second" p={4} gap={4} borderRadius="base" w="full" h="full">
<ModelListNavigation />
<ModelList />
</Box>
</Box>
</Flex>
</Flex>
);
};

View File

@ -1,6 +1,7 @@
import { Flex, Spinner, Text } from '@invoke-ai/ui-library';
import type { EntityState } from '@reduxjs/toolkit';
import { useAppSelector } from 'app/store/storeHooks';
import ScrollableContent from 'common/components/OverlayScrollbars/ScrollableContent';
import { forEach } from 'lodash-es';
import { memo } from 'react';
import { ALL_BASE_MODELS } from 'services/api/constants';
@ -73,8 +74,8 @@ const ModelList = () => {
});
return (
<Flex flexDirection="column" p={4}>
<Flex flexDirection="column" maxHeight={window.innerHeight - 130} overflow="scroll">
<ScrollableContent>
<Flex flexDirection="column" w="full" h="full" gap={4}>
{/* Main Model List */}
{isLoadingMainModels && <FetchingModelsLoader loadingMessage="Loading Main..." />}
{!isLoadingMainModels && filteredMainModels.length > 0 && (
@ -118,7 +119,7 @@ const ModelList = () => {
<ModelListWrapper title="T2I Adapters" modelList={filteredT2iAdapterModels} key="t2i-adapters" />
)}
</Flex>
</Flex>
</ScrollableContent>
);
};
@ -148,7 +149,7 @@ const modelsFilter = <T extends AnyModelConfig>(
const FetchingModelsLoader = memo(({ loadingMessage }: { loadingMessage?: string }) => {
return (
<Flex flexDirection="column" gap={4} borderRadius={4} p={4} bg="base.800">
<Flex flexDirection="column" gap={4} borderRadius="base" p={4} bg="base.800">
<Flex justifyContent="center" alignItems="center" flexDirection="column" p={4} gap={8}>
<Spinner />
<Text variant="subtext">{loadingMessage ? loadingMessage : 'Fetching...'}</Text>

View File

@ -1,7 +1,6 @@
import { Flex } from '@invoke-ai/ui-library';
import { StickyScrollable } from 'features/system/components/StickyScrollable';
import type { AnyModelConfig } from 'services/api/types';
import { ModelListHeader } from './ModelListHeader';
import ModelListItem from './ModelListItem';
type ModelListWrapperProps = {
@ -12,14 +11,10 @@ type ModelListWrapperProps = {
export const ModelListWrapper = (props: ModelListWrapperProps) => {
const { title, modelList } = props;
return (
<Flex flexDirection="column" p="10px 0">
<Flex gap={2} flexDir="column">
<ModelListHeader title={title} />
{modelList.map((model) => (
<ModelListItem key={model.key} model={model} />
))}
</Flex>
</Flex>
<StickyScrollable title={title}>
{modelList.map((model) => (
<ModelListItem key={model.key} model={model} />
))}
</StickyScrollable>
);
};