mirror of
https://github.com/invoke-ai/InvokeAI
synced 2024-08-30 20:32:17 +00:00
feat(ui): no entities fallback buttons
This commit is contained in:
parent
6d1edc330d
commit
fa48145cbc
@ -41,13 +41,14 @@ export const AddLayerButton = memo(() => {
|
|||||||
icon={<PiPlusBold />}
|
icon={<PiPlusBold />}
|
||||||
variant="link"
|
variant="link"
|
||||||
data-testid="control-layers-add-layer-menu-button"
|
data-testid="control-layers-add-layer-menu-button"
|
||||||
|
alignSelf="stretch"
|
||||||
/>
|
/>
|
||||||
<MenuList>
|
<MenuList>
|
||||||
<MenuItem onClick={addInpaintMask}>{t('controlLayers.inpaintMask')}</MenuItem>
|
<MenuItem onClick={addInpaintMask}>{t('controlLayers.inpaintMask', { count: 1 })}</MenuItem>
|
||||||
<MenuItem onClick={addRegionalGuidance}>{t('controlLayers.regionalGuidance')}</MenuItem>
|
<MenuItem onClick={addRegionalGuidance}>{t('controlLayers.regionalGuidance', { count: 1 })}</MenuItem>
|
||||||
<MenuItem onClick={addRasterLayer}>{t('controlLayers.rasterLayer')}</MenuItem>
|
<MenuItem onClick={addRasterLayer}>{t('controlLayers.rasterLayer', { count: 1 })}</MenuItem>
|
||||||
<MenuItem onClick={addControlLayer}>{t('controlLayers.controlLayer')}</MenuItem>
|
<MenuItem onClick={addControlLayer}>{t('controlLayers.controlLayer', { count: 1 })}</MenuItem>
|
||||||
<MenuItem onClick={addIPAdapter}>{t('controlLayers.globalIPAdapterLayer')}</MenuItem>
|
<MenuItem onClick={addIPAdapter}>{t('controlLayers.ipAdapter', { count: 1 })}</MenuItem>
|
||||||
</MenuList>
|
</MenuList>
|
||||||
</Menu>
|
</Menu>
|
||||||
);
|
);
|
||||||
|
@ -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';
|
@ -6,23 +6,20 @@ import { InpaintMaskList } from 'features/controlLayers/components/InpaintMask/I
|
|||||||
import { IPAdapterList } from 'features/controlLayers/components/IPAdapter/IPAdapterList';
|
import { IPAdapterList } from 'features/controlLayers/components/IPAdapter/IPAdapterList';
|
||||||
import { RasterLayerEntityList } from 'features/controlLayers/components/RasterLayer/RasterLayerEntityList';
|
import { RasterLayerEntityList } from 'features/controlLayers/components/RasterLayer/RasterLayerEntityList';
|
||||||
import { RegionalGuidanceEntityList } from 'features/controlLayers/components/RegionalGuidance/RegionalGuidanceEntityList';
|
import { RegionalGuidanceEntityList } from 'features/controlLayers/components/RegionalGuidance/RegionalGuidanceEntityList';
|
||||||
import { CanvasManagerProviderGate } from 'features/controlLayers/contexts/CanvasManagerProviderGate';
|
|
||||||
import { memo } from 'react';
|
import { memo } from 'react';
|
||||||
|
|
||||||
export const CanvasEntityList = memo(() => {
|
export const CanvasEntityList = memo(() => {
|
||||||
return (
|
return (
|
||||||
<CanvasManagerProviderGate>
|
<ScrollableContent>
|
||||||
<ScrollableContent>
|
<Flex flexDir="column" gap={4} pt={2} data-testid="control-layers-layer-list">
|
||||||
<Flex flexDir="column" gap={4} pt={2} data-testid="control-layers-layer-list">
|
<CanvasEntityOpacity />
|
||||||
<CanvasEntityOpacity />
|
<InpaintMaskList />
|
||||||
<InpaintMaskList />
|
<RegionalGuidanceEntityList />
|
||||||
<RegionalGuidanceEntityList />
|
<IPAdapterList />
|
||||||
<IPAdapterList />
|
<ControlLayerEntityList />
|
||||||
<ControlLayerEntityList />
|
<RasterLayerEntityList />
|
||||||
<RasterLayerEntityList />
|
</Flex>
|
||||||
</Flex>
|
</ScrollableContent>
|
||||||
</ScrollableContent>
|
|
||||||
</CanvasManagerProviderGate>
|
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -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';
|
@ -4,7 +4,7 @@ import { selectCanvasV2Slice } from 'features/controlLayers/store/canvasV2Slice'
|
|||||||
import type { CanvasEntityIdentifier } from 'features/controlLayers/store/types';
|
import type { CanvasEntityIdentifier } from 'features/controlLayers/store/types';
|
||||||
import { useMemo } from 'react';
|
import { useMemo } from 'react';
|
||||||
|
|
||||||
export const useEntityCount = (type: CanvasEntityIdentifier['type']): number => {
|
export const useEntityTypeCount = (type: CanvasEntityIdentifier['type']): number => {
|
||||||
const selectEntityCount = useMemo(
|
const selectEntityCount = useMemo(
|
||||||
() =>
|
() =>
|
||||||
createSelector(selectCanvasV2Slice, (canvasV2) => {
|
createSelector(selectCanvasV2Slice, (canvasV2) => {
|
@ -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 { useEntityTypeIsHidden } from 'features/controlLayers/hooks/useEntityTypeIsHidden';
|
||||||
import type { CanvasEntityIdentifier } from 'features/controlLayers/store/types';
|
import type { CanvasEntityIdentifier } from 'features/controlLayers/store/types';
|
||||||
import { useMemo } from 'react';
|
import { useMemo } from 'react';
|
||||||
@ -8,7 +8,7 @@ export const useEntityTypeTitle = (type: CanvasEntityIdentifier['type']): string
|
|||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
|
|
||||||
const isHidden = useEntityTypeIsHidden(type);
|
const isHidden = useEntityTypeIsHidden(type);
|
||||||
const count = useEntityCount(type);
|
const count = useEntityTypeCount(type);
|
||||||
|
|
||||||
const title = useMemo(() => {
|
const title = useMemo(() => {
|
||||||
const context = isHidden ? 'hidden' : 'visible';
|
const context = isHidden ? 'hidden' : 'visible';
|
||||||
|
@ -5,9 +5,10 @@ import { getOptimalDimension } from 'features/parameters/util/optimalDimension';
|
|||||||
export const selectEntityCount = createSelector(selectCanvasV2Slice, (canvasV2) => {
|
export const selectEntityCount = createSelector(selectCanvasV2Slice, (canvasV2) => {
|
||||||
return (
|
return (
|
||||||
canvasV2.regions.entities.length +
|
canvasV2.regions.entities.length +
|
||||||
// canvasV2.controlAdapters.entities.length +
|
|
||||||
canvasV2.ipAdapters.entities.length +
|
canvasV2.ipAdapters.entities.length +
|
||||||
canvasV2.rasterLayers.entities.length
|
canvasV2.rasterLayers.entities.length +
|
||||||
|
canvasV2.controlLayers.entities.length +
|
||||||
|
canvasV2.inpaintMasks.entities.length
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -4,7 +4,7 @@ import { useStore } from '@nanostores/react';
|
|||||||
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
|
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
|
||||||
import { overlayScrollbarsParams } from 'common/components/OverlayScrollbars/constants';
|
import { overlayScrollbarsParams } from 'common/components/OverlayScrollbars/constants';
|
||||||
import { AddLayerButton } from 'features/controlLayers/components/AddLayerButton';
|
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 { $isPreviewVisible } from 'features/controlLayers/store/canvasV2Slice';
|
||||||
import { selectEntityCount } from 'features/controlLayers/store/selectors';
|
import { selectEntityCount } from 'features/controlLayers/store/selectors';
|
||||||
import { isImageViewerOpenChanged } from 'features/gallery/store/gallerySlice';
|
import { isImageViewerOpenChanged } from 'features/gallery/store/gallerySlice';
|
||||||
@ -90,7 +90,7 @@ const ParametersPanelTextToImage = () => {
|
|||||||
gap={2}
|
gap={2}
|
||||||
onChange={onChangeTabs}
|
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">
|
<Tab sx={baseStyles} _selected={selectedStyles} data-testid="generation-tab-settings-tab-button">
|
||||||
{t('common.settingsLabel')}
|
{t('common.settingsLabel')}
|
||||||
</Tab>
|
</Tab>
|
||||||
@ -115,7 +115,7 @@ const ParametersPanelTextToImage = () => {
|
|||||||
</Flex>
|
</Flex>
|
||||||
</TabPanel>
|
</TabPanel>
|
||||||
<TabPanel p={0} w="full" h="full">
|
<TabPanel p={0} w="full" h="full">
|
||||||
<CanvasEntityList />
|
<CanvasPanelContent />
|
||||||
</TabPanel>
|
</TabPanel>
|
||||||
</TabPanels>
|
</TabPanels>
|
||||||
</Tabs>
|
</Tabs>
|
||||||
|
Loading…
Reference in New Issue
Block a user