feat(ui): add + buttons to entity categories

This commit is contained in:
psychedelicious 2024-08-29 10:15:35 +10:00
parent 0098c33f81
commit 085cc82926
7 changed files with 111 additions and 32 deletions

View File

@ -1684,27 +1684,34 @@
"addPositivePrompt": "Add $t(common.positivePrompt)",
"addNegativePrompt": "Add $t(common.negativePrompt)",
"addIPAdapter": "Add $t(common.ipAdapter)",
"addRasterLayer": "Add $t(controlLayers.rasterLayer)",
"addControlLayer": "Add $t(controlLayers.controlLayer)",
"addInpaintMask": "Add $t(controlLayers.inpaintMask)",
"addRegionalGuidance": "Add $t(controlLayers.regionalGuidance)",
"regionalGuidanceLayer": "$t(controlLayers.regionalGuidance) $t(unifiedCanvas.layer)",
"raster": "Raster",
"rasterLayer_one": "Raster Layer",
"controlLayer_one": "Control Layer",
"inpaintMask_one": "Inpaint Mask",
"regionalGuidance_one": "Regional Guidance",
"ipAdapter_one": "IP Adapter",
"rasterLayer_other": "Raster Layers",
"controlLayer_other": "Control Layers",
"inpaintMask_other": "Inpaint Masks",
"regionalGuidance_other": "Regional Guidance",
"ipAdapter_other": "IP Adapters",
"rasterLayer": "Raster Layer",
"controlLayer": "Control Layer",
"inpaintMask": "Inpaint Mask",
"regionalGuidance": "Regional Guidance",
"ipAdapter": "IP Adapter",
"rasterLayer_withCount_one": "$t(controlLayers.rasterLayer)",
"controlLayer_withCount_one": "$t(controlLayers.controlLayer)",
"inpaintMask_withCount_one": "$t(controlLayers.inpaintMask)",
"regionalGuidance_withCount_one": "$t(controlLayers.regionalGuidance)",
"ipAdapter_withCount_one": "$t(controlLayers.ipAdapter)",
"rasterLayer_withCount_other": "Raster Layers",
"controlLayer_withCount_other": "Control Layers",
"inpaintMask_withCount_other": "Inpaint Masks",
"regionalGuidance_withCount_other": "Regional Guidance",
"ipAdapter_withCount_other": "IP Adapters",
"opacity": "Opacity",
"regionalGuidance_withCount_hidden": "Regional Guidance ({{count}} hidden)",
"controlAdapters_withCount_hidden": "Control Adapters ({{count}} hidden)",
"controlLayers_withCount_hidden": "Control Layers ({{count}} hidden)",
"rasterLayers_withCount_hidden": "Raster Layers ({{count}} hidden)",
"ipAdapters_withCount_hidden": "IP Adapters ({{count}} hidden)",
"inpaintMasks_withCount_hidden": "Inpaint Masks ({{count}} hidden)",
"regionalGuidance_withCount_visible": "Regional Guidance ({{count}})",
"controlAdapters_withCount_visible": "Control Adapters ({{count}})",
"controlLayers_withCount_visible": "Control Layers ({{count}})",
"rasterLayers_withCount_visible": "Raster Layers ({{count}})",
"ipAdapters_withCount_visible": "IP Adapters ({{count}})",

View File

@ -34,19 +34,19 @@ export const CanvasAddEntityButtons = memo(() => {
<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 })}
{t('controlLayers.inpaintMask')}
</Button>
<Button variant="ghost" justifyContent="flex-start" leftIcon={<PiPlusBold />} onClick={addRegionalGuidance}>
{t('controlLayers.regionalGuidance', { count: 1 })}
{t('controlLayers.regionalGuidance')}
</Button>
<Button variant="ghost" justifyContent="flex-start" leftIcon={<PiPlusBold />} onClick={addRasterLayer}>
{t('controlLayers.rasterLayer', { count: 1 })}
{t('controlLayers.rasterLayer')}
</Button>
<Button variant="ghost" justifyContent="flex-start" leftIcon={<PiPlusBold />} onClick={addControlLayer}>
{t('controlLayers.controlLayer', { count: 1 })}
{t('controlLayers.controlLayer')}
</Button>
<Button variant="ghost" justifyContent="flex-start" leftIcon={<PiPlusBold />} onClick={addIPAdapter}>
{t('controlLayers.ipAdapter', { count: 1 })}
{t('controlLayers.ipAdapter')}
</Button>
</ButtonGroup>
</Flex>

View File

@ -33,19 +33,19 @@ export const CanvasEntityListMenuItems = memo(() => {
return (
<>
<MenuItem icon={<PiPlusBold />} onClick={addInpaintMask}>
{t('controlLayers.inpaintMask', { count: 1 })}
{t('controlLayers.inpaintMask')}
</MenuItem>
<MenuItem icon={<PiPlusBold />} onClick={addRegionalGuidance}>
{t('controlLayers.regionalGuidance', { count: 1 })}
{t('controlLayers.regionalGuidance')}
</MenuItem>
<MenuItem icon={<PiPlusBold />} onClick={addRasterLayer}>
{t('controlLayers.rasterLayer', { count: 1 })}
{t('controlLayers.rasterLayer')}
</MenuItem>
<MenuItem icon={<PiPlusBold />} onClick={addControlLayer}>
{t('controlLayers.controlLayer', { count: 1 })}
{t('controlLayers.controlLayer')}
</MenuItem>
<MenuItem icon={<PiPlusBold />} onClick={addIPAdapter}>
{t('controlLayers.ipAdapter', { count: 1 })}
{t('controlLayers.ipAdapter')}
</MenuItem>
</>
);

View File

@ -0,0 +1,70 @@
import { IconButton } from '@invoke-ai/ui-library';
import { useAppDispatch } from 'app/store/storeHooks';
import {
controlLayerAdded,
inpaintMaskAdded,
ipaAdded,
rasterLayerAdded,
rgAdded,
} from 'features/controlLayers/store/canvasSlice';
import type { CanvasEntityIdentifier } from 'features/controlLayers/store/types';
import { memo, useCallback, useMemo } from 'react';
import { useTranslation } from 'react-i18next';
import { PiPlusBold } from 'react-icons/pi';
type Props = {
type: CanvasEntityIdentifier['type'];
};
export const CanvasEntityAddOfTypeButton = memo(({ type }: Props) => {
const { t } = useTranslation();
const dispatch = useAppDispatch();
const onClick = useCallback(() => {
switch (type) {
case 'inpaint_mask':
dispatch(inpaintMaskAdded({ isSelected: true }));
break;
case 'regional_guidance':
dispatch(rgAdded({ isSelected: true }));
break;
case 'raster_layer':
dispatch(rasterLayerAdded({ isSelected: true }));
break;
case 'control_layer':
dispatch(controlLayerAdded({ isSelected: true }));
break;
case 'ip_adapter':
dispatch(ipaAdded({ isSelected: true }));
break;
}
}, [dispatch, type]);
const label = useMemo(() => {
switch (type) {
case 'inpaint_mask':
return t('controlLayers.addInpaintMask');
case 'regional_guidance':
return t('controlLayers.addRegionalGuidance');
case 'raster_layer':
return t('controlLayers.addRasterLayer');
case 'control_layer':
return t('controlLayers.addControlLayer');
case 'ip_adapter':
return t('controlLayers.addIPAdapter');
}
}, [type, t]);
return (
<IconButton
size="sm"
aria-label={label}
tooltip={label}
variant="link"
icon={<PiPlusBold />}
onClick={onClick}
alignSelf="stretch"
/>
);
});
CanvasEntityAddOfTypeButton.displayName = 'CanvasEntityAddOfTypeButton';

View File

@ -1,6 +1,7 @@
import type { SystemStyleObject } from '@invoke-ai/ui-library';
import { Button, Collapse, Flex, Icon, Spacer, Text } from '@invoke-ai/ui-library';
import { useBoolean } from 'common/hooks/useBoolean';
import { CanvasEntityAddOfTypeButton } from 'features/controlLayers/components/common/CanvasEntityAddOfTypeButton';
import { CanvasEntityTypeIsHiddenToggle } from 'features/controlLayers/components/common/CanvasEntityTypeIsHiddenToggle';
import { useEntityTypeTitle } from 'features/controlLayers/hooks/useEntityTypeTitle';
import type { CanvasEntityIdentifier } from 'features/controlLayers/store/types';
@ -53,6 +54,7 @@ export const CanvasEntityGroupList = memo(({ isSelected, type, children }: Props
</Text>
<Spacer />
</Flex>
<CanvasEntityAddOfTypeButton type={type} />
{type !== 'ip_adapter' && <CanvasEntityTypeIsHiddenToggle type={type} />}
</Flex>
<Collapse in={collapse.isTrue}>

View File

@ -29,15 +29,15 @@ export const useEntityTitle = (entityIdentifier: CanvasEntityIdentifier) => {
const parts: string[] = [];
if (entityIdentifier.type === 'inpaint_mask') {
parts.push(t('controlLayers.inpaintMask', { count: 1 }));
parts.push(t('controlLayers.inpaintMask'));
} else if (entityIdentifier.type === 'control_layer') {
parts.push(t('controlLayers.controlLayer', { count: 1 }));
parts.push(t('controlLayers.controlLayer'));
} else if (entityIdentifier.type === 'raster_layer') {
parts.push(t('controlLayers.rasterLayer', { count: 1 }));
parts.push(t('controlLayers.rasterLayer'));
} else if (entityIdentifier.type === 'ip_adapter') {
parts.push(t('common.ipAdapter', { count: 1 }));
parts.push(t('common.ipAdapter'));
} else if (entityIdentifier.type === 'regional_guidance') {
parts.push(t('controlLayers.regionalGuidance', { count: 1 }));
parts.push(t('controlLayers.regionalGuidance'));
} else {
assert(false, 'Unexpected entity type');
}

View File

@ -8,15 +8,15 @@ export const useEntityTypeString = (type: CanvasEntityIdentifier['type']): strin
const typeString = useMemo(() => {
switch (type) {
case 'control_layer':
return t('controlLayers.controlLayer', { count: 0 });
return t('controlLayers.controlLayer');
case 'raster_layer':
return t('controlLayers.rasterLayer', { count: 0 });
return t('controlLayers.rasterLayer');
case 'inpaint_mask':
return t('controlLayers.inpaintMask', { count: 0 });
return t('controlLayers.inpaintMask');
case 'regional_guidance':
return t('controlLayers.regionalGuidance', { count: 0 });
return t('controlLayers.regionalGuidance');
case 'ip_adapter':
return t('controlLayers.ipAdapter', { count: 0 });
return t('controlLayers.ipAdapter');
default:
return '';
}