feat(ui): no entities fallback buttons

This commit is contained in:
psychedelicious 2024-08-22 17:46:02 +10:00
parent 6d1edc330d
commit fa48145cbc
8 changed files with 102 additions and 26 deletions

View File

@ -41,13 +41,14 @@ export const AddLayerButton = memo(() => {
icon={<PiPlusBold />}
variant="link"
data-testid="control-layers-add-layer-menu-button"
alignSelf="stretch"
/>
<MenuList>
<MenuItem onClick={addInpaintMask}>{t('controlLayers.inpaintMask')}</MenuItem>
<MenuItem onClick={addRegionalGuidance}>{t('controlLayers.regionalGuidance')}</MenuItem>
<MenuItem onClick={addRasterLayer}>{t('controlLayers.rasterLayer')}</MenuItem>
<MenuItem onClick={addControlLayer}>{t('controlLayers.controlLayer')}</MenuItem>
<MenuItem onClick={addIPAdapter}>{t('controlLayers.globalIPAdapterLayer')}</MenuItem>
<MenuItem onClick={addInpaintMask}>{t('controlLayers.inpaintMask', { count: 1 })}</MenuItem>
<MenuItem onClick={addRegionalGuidance}>{t('controlLayers.regionalGuidance', { count: 1 })}</MenuItem>
<MenuItem onClick={addRasterLayer}>{t('controlLayers.rasterLayer', { count: 1 })}</MenuItem>
<MenuItem onClick={addControlLayer}>{t('controlLayers.controlLayer', { count: 1 })}</MenuItem>
<MenuItem onClick={addIPAdapter}>{t('controlLayers.ipAdapter', { count: 1 })}</MenuItem>
</MenuList>
</Menu>
);

View File

@ -0,0 +1,59 @@
import { Button, ButtonGroup, Flex } from '@invoke-ai/ui-library';
import { useAppDispatch } from 'app/store/storeHooks';
import { useDefaultControlAdapter, useDefaultIPAdapter } from 'features/controlLayers/hooks/useLayerControlAdapter';
import {
controlLayerAdded,
inpaintMaskAdded,
ipaAdded,
rasterLayerAdded,
rgAdded,
} from 'features/controlLayers/store/canvasV2Slice';
import { memo, useCallback } from 'react';
import { useTranslation } from 'react-i18next';
import { PiPlusBold } from 'react-icons/pi';
export const CanvasAddEntityButtons = memo(() => {
const { t } = useTranslation();
const dispatch = useAppDispatch();
const defaultControlAdapter = useDefaultControlAdapter();
const defaultIPAdapter = useDefaultIPAdapter();
const addInpaintMask = useCallback(() => {
dispatch(inpaintMaskAdded());
}, [dispatch]);
const addRegionalGuidance = useCallback(() => {
dispatch(rgAdded());
}, [dispatch]);
const addRasterLayer = useCallback(() => {
dispatch(rasterLayerAdded({ isSelected: true }));
}, [dispatch]);
const addControlLayer = useCallback(() => {
dispatch(controlLayerAdded({ isSelected: true, overrides: { controlAdapter: defaultControlAdapter } }));
}, [defaultControlAdapter, dispatch]);
const addIPAdapter = useCallback(() => {
dispatch(ipaAdded({ ipAdapter: defaultIPAdapter }));
}, [defaultIPAdapter, dispatch]);
return (
<Flex flexDir="column" w="full" h="full" alignItems="center" justifyContent="center">
<ButtonGroup orientation="vertical" isAttached={false}>
<Button variant="ghost" justifyContent="flex-start" leftIcon={<PiPlusBold />} onClick={addInpaintMask}>
{t('controlLayers.inpaintMask', { count: 1 })}
</Button>
<Button variant="ghost" justifyContent="flex-start" leftIcon={<PiPlusBold />} onClick={addRegionalGuidance}>
{t('controlLayers.regionalGuidance', { count: 1 })}
</Button>
<Button variant="ghost" justifyContent="flex-start" leftIcon={<PiPlusBold />} onClick={addRasterLayer}>
{t('controlLayers.rasterLayer', { count: 1 })}
</Button>
<Button variant="ghost" justifyContent="flex-start" leftIcon={<PiPlusBold />} onClick={addControlLayer}>
{t('controlLayers.controlLayer', { count: 1 })}
</Button>
<Button variant="ghost" justifyContent="flex-start" leftIcon={<PiPlusBold />} onClick={addIPAdapter}>
{t('controlLayers.ipAdapter', { count: 1 })}
</Button>
</ButtonGroup>
</Flex>
);
});
CanvasAddEntityButtons.displayName = 'CanvasAddEntityButtons';

View File

@ -6,12 +6,10 @@ import { InpaintMaskList } from 'features/controlLayers/components/InpaintMask/I
import { IPAdapterList } from 'features/controlLayers/components/IPAdapter/IPAdapterList';
import { RasterLayerEntityList } from 'features/controlLayers/components/RasterLayer/RasterLayerEntityList';
import { RegionalGuidanceEntityList } from 'features/controlLayers/components/RegionalGuidance/RegionalGuidanceEntityList';
import { CanvasManagerProviderGate } from 'features/controlLayers/contexts/CanvasManagerProviderGate';
import { memo } from 'react';
export const CanvasEntityList = memo(() => {
return (
<CanvasManagerProviderGate>
<ScrollableContent>
<Flex flexDir="column" gap={4} pt={2} data-testid="control-layers-layer-list">
<CanvasEntityOpacity />
@ -22,7 +20,6 @@ export const CanvasEntityList = memo(() => {
<RasterLayerEntityList />
</Flex>
</ScrollableContent>
</CanvasManagerProviderGate>
);
});

View File

@ -0,0 +1,18 @@
import { useAppSelector } from 'app/store/storeHooks';
import { CanvasAddEntityButtons } from 'features/controlLayers/components/CanvasAddEntityButtons';
import { CanvasEntityList } from 'features/controlLayers/components/CanvasEntityList';
import { CanvasManagerProviderGate } from 'features/controlLayers/contexts/CanvasManagerProviderGate';
import { selectEntityCount } from 'features/controlLayers/store/selectors';
import { memo } from 'react';
export const CanvasPanelContent = memo(() => {
const hasEntities = useAppSelector((s) => selectEntityCount(s) > 0);
return (
<CanvasManagerProviderGate>
{!hasEntities && <CanvasAddEntityButtons />}
{hasEntities && <CanvasEntityList />}
</CanvasManagerProviderGate>
);
});
CanvasPanelContent.displayName = 'CanvasPanelContent';

View File

@ -4,7 +4,7 @@ import { selectCanvasV2Slice } from 'features/controlLayers/store/canvasV2Slice'
import type { CanvasEntityIdentifier } from 'features/controlLayers/store/types';
import { useMemo } from 'react';
export const useEntityCount = (type: CanvasEntityIdentifier['type']): number => {
export const useEntityTypeCount = (type: CanvasEntityIdentifier['type']): number => {
const selectEntityCount = useMemo(
() =>
createSelector(selectCanvasV2Slice, (canvasV2) => {

View File

@ -1,4 +1,4 @@
import { useEntityCount } from 'features/controlLayers/hooks/useEntityCount';
import { useEntityTypeCount } from 'features/controlLayers/hooks/useEntityTypeCount';
import { useEntityTypeIsHidden } from 'features/controlLayers/hooks/useEntityTypeIsHidden';
import type { CanvasEntityIdentifier } from 'features/controlLayers/store/types';
import { useMemo } from 'react';
@ -8,7 +8,7 @@ export const useEntityTypeTitle = (type: CanvasEntityIdentifier['type']): string
const { t } = useTranslation();
const isHidden = useEntityTypeIsHidden(type);
const count = useEntityCount(type);
const count = useEntityTypeCount(type);
const title = useMemo(() => {
const context = isHidden ? 'hidden' : 'visible';

View File

@ -5,9 +5,10 @@ import { getOptimalDimension } from 'features/parameters/util/optimalDimension';
export const selectEntityCount = createSelector(selectCanvasV2Slice, (canvasV2) => {
return (
canvasV2.regions.entities.length +
// canvasV2.controlAdapters.entities.length +
canvasV2.ipAdapters.entities.length +
canvasV2.rasterLayers.entities.length
canvasV2.rasterLayers.entities.length +
canvasV2.controlLayers.entities.length +
canvasV2.inpaintMasks.entities.length
);
});

View File

@ -4,7 +4,7 @@ import { useStore } from '@nanostores/react';
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
import { overlayScrollbarsParams } from 'common/components/OverlayScrollbars/constants';
import { AddLayerButton } from 'features/controlLayers/components/AddLayerButton';
import { CanvasEntityList } from 'features/controlLayers/components/CanvasEntityList';
import { CanvasPanelContent } from 'features/controlLayers/components/CanvasPanelContent';
import { $isPreviewVisible } from 'features/controlLayers/store/canvasV2Slice';
import { selectEntityCount } from 'features/controlLayers/store/selectors';
import { isImageViewerOpenChanged } from 'features/gallery/store/gallerySlice';
@ -90,7 +90,7 @@ const ParametersPanelTextToImage = () => {
gap={2}
onChange={onChangeTabs}
>
<TabList gap={2} fontSize="sm" borderColor="base.800" alignItems="center" w="full">
<TabList gap={2} fontSize="sm" borderColor="base.800" alignItems="center" w="full" pe={1}>
<Tab sx={baseStyles} _selected={selectedStyles} data-testid="generation-tab-settings-tab-button">
{t('common.settingsLabel')}
</Tab>
@ -115,7 +115,7 @@ const ParametersPanelTextToImage = () => {
</Flex>
</TabPanel>
<TabPanel p={0} w="full" h="full">
<CanvasEntityList />
<CanvasPanelContent />
</TabPanel>
</TabPanels>
</Tabs>