Add toggle for non-raster layers with hotkey and UI button

This commit is contained in:
Cursor Agent
2025-06-23 16:02:08 +00:00
committed by psychedelicious
parent adf4cc750a
commit 7a7a2e147c
8 changed files with 104 additions and 0 deletions

View File

@@ -579,6 +579,10 @@
"cancelTransform": {
"title": "Cancel Transform",
"desc": "Cancel the pending transform."
},
"toggleNonRasterLayers": {
"title": "Toggle Non-Raster Layers",
"desc": "Show or hide all non-raster layer categories (Control Layers, Inpaint Masks, Regional Guidance)."
}
},
"workflows": {
@@ -1994,6 +1998,8 @@
"disableTransparencyEffect": "Disable Transparency Effect",
"hidingType": "Hiding {{type}}",
"showingType": "Showing {{type}}",
"showNonRasterLayers": "Show Non-Raster Layers",
"hideNonRasterLayers": "Hide Non-Raster Layers",
"dynamicGrid": "Dynamic Grid",
"logDebugInfo": "Log Debug Info",
"locked": "Locked",

View File

@@ -1,4 +1,5 @@
import { Flex, Spacer } from '@invoke-ai/ui-library';
import { CanvasNonRasterLayersIsHiddenToggle } from 'features/controlLayers/components/common/CanvasNonRasterLayersIsHiddenToggle';
import { EntityListGlobalActionBarAddLayerMenu } from 'features/controlLayers/components/CanvasEntityList/EntityListGlobalActionBarAddLayerMenu';
import { EntityListSelectedEntityActionBarDuplicateButton } from 'features/controlLayers/components/CanvasEntityList/EntityListSelectedEntityActionBarDuplicateButton';
import { EntityListSelectedEntityActionBarFill } from 'features/controlLayers/components/CanvasEntityList/EntityListSelectedEntityActionBarFill';
@@ -22,6 +23,7 @@ export const EntityListSelectedEntityActionBar = memo(() => {
<EntityListSelectedEntityActionBarTransformButton />
<EntityListSelectedEntityActionBarSaveToAssetsButton />
<EntityListSelectedEntityActionBarDuplicateButton />
<CanvasNonRasterLayersIsHiddenToggle />
<EntityListGlobalActionBarAddLayerMenu />
</Flex>
</Flex>

View File

@@ -4,6 +4,7 @@ import { CanvasAddEntityButtons } from 'features/controlLayers/components/Canvas
import { CanvasEntityList } from 'features/controlLayers/components/CanvasEntityList/CanvasEntityList';
import { EntityListSelectedEntityActionBar } from 'features/controlLayers/components/CanvasEntityList/EntityListSelectedEntityActionBar';
import { CanvasManagerProviderGate } from 'features/controlLayers/contexts/CanvasManagerProviderGate';
import { useCanvasToggleNonRasterLayersHotkey } from 'features/controlLayers/hooks/useCanvasToggleNonRasterLayersHotkey';
import { selectHasEntities } from 'features/controlLayers/store/selectors';
import { memo } from 'react';
@@ -11,6 +12,7 @@ import { ParamDenoisingStrength } from './ParamDenoisingStrength';
export const CanvasLayersPanel = memo(() => {
const hasEntities = useAppSelector(selectHasEntities);
useCanvasToggleNonRasterLayersHotkey();
return (
<CanvasManagerProviderGate>

View File

@@ -0,0 +1,36 @@
import { IconButton } from '@invoke-ai/ui-library';
import { useAppDispatch } from 'app/store/storeHooks';
import { useNonRasterLayersIsHidden } from 'features/controlLayers/hooks/useNonRasterLayersIsHidden';
import { allNonRasterLayersIsHiddenToggled } from 'features/controlLayers/store/canvasSlice';
import type { MouseEventHandler } from 'react';
import { memo, useCallback } from 'react';
import { useTranslation } from 'react-i18next';
import { PiEyeBold, PiEyeClosedBold } from 'react-icons/pi';
export const CanvasNonRasterLayersIsHiddenToggle = memo(() => {
const { t } = useTranslation();
const dispatch = useAppDispatch();
const isHidden = useNonRasterLayersIsHidden();
const onClick = useCallback<MouseEventHandler>(
(e) => {
e.stopPropagation();
dispatch(allNonRasterLayersIsHiddenToggled());
},
[dispatch]
);
return (
<IconButton
size="sm"
aria-label={t(isHidden ? 'controlLayers.showNonRasterLayers' : 'controlLayers.hideNonRasterLayers')}
tooltip={t(isHidden ? 'controlLayers.showNonRasterLayers' : 'controlLayers.hideNonRasterLayers')}
variant="link"
icon={isHidden ? <PiEyeClosedBold /> : <PiEyeBold />}
onClick={onClick}
alignSelf="stretch"
/>
);
});
CanvasNonRasterLayersIsHiddenToggle.displayName = 'CanvasNonRasterLayersIsHiddenToggle';

View File

@@ -0,0 +1,19 @@
import { useAppDispatch } from 'app/store/storeHooks';
import { allNonRasterLayersIsHiddenToggled } from 'features/controlLayers/store/canvasSlice';
import { useRegisteredHotkeys } from 'features/system/components/HotkeysModal/useHotkeyData';
import { useCallback } from 'react';
export const useCanvasToggleNonRasterLayersHotkey = () => {
const dispatch = useAppDispatch();
const handleToggleNonRasterLayers = useCallback(() => {
dispatch(allNonRasterLayersIsHiddenToggled());
}, [dispatch]);
useRegisteredHotkeys({
id: 'toggleNonRasterLayers',
category: 'canvas',
callback: handleToggleNonRasterLayers,
dependencies: [handleToggleNonRasterLayers],
});
};

View File

@@ -0,0 +1,21 @@
import { createSelector } from '@reduxjs/toolkit';
import { useAppSelector } from 'app/store/storeHooks';
import { selectCanvasSlice } from 'features/controlLayers/store/selectors';
import { useMemo } from 'react';
export const useNonRasterLayersIsHidden = (): boolean => {
const selectNonRasterLayersIsHidden = useMemo(
() =>
createSelector(selectCanvasSlice, (canvas) => {
// Check if all non-raster layer categories are hidden
return (
canvas.controlLayers.isHidden &&
canvas.inpaintMasks.isHidden &&
canvas.regionalGuidance.isHidden
);
}),
[]
);
const isHidden = useAppSelector(selectNonRasterLayersIsHidden);
return isHidden;
};

View File

@@ -1539,6 +1539,22 @@ export const canvasSlice = createSlice({
break;
}
},
allNonRasterLayersIsHiddenToggled: (state) => {
// Toggle visibility for all non-raster layer categories
// Check if any non-raster layers are currently visible
const hasVisibleNonRasterLayers =
!state.controlLayers.isHidden ||
!state.inpaintMasks.isHidden ||
!state.regionalGuidance.isHidden;
// If any are visible, hide all; if all are hidden, show all
const shouldHide = hasVisibleNonRasterLayers;
state.controlLayers.isHidden = shouldHide;
state.inpaintMasks.isHidden = shouldHide;
state.regionalGuidance.isHidden = shouldHide;
// Note: reference_image doesn't have isHidden property, so it's not included
},
allEntitiesDeleted: (state) => {
// Deleting all entities is equivalent to resetting the state for each entity type
const initialState = getInitialCanvasState();
@@ -1648,6 +1664,7 @@ export const {
entitiesReordered,
allEntitiesDeleted,
allEntitiesOfTypeIsHiddenToggled,
allNonRasterLayersIsHiddenToggled,
// bbox
bboxChangedFromCanvas,
bboxScaledWidthChanged,

View File

@@ -122,6 +122,7 @@ export const useHotkeyData = (): HotkeysData => {
addHotkey('canvas', 'cancelTransform', ['esc']);
addHotkey('canvas', 'applySegmentAnything', ['enter']);
addHotkey('canvas', 'cancelSegmentAnything', ['esc']);
addHotkey('canvas', 'toggleNonRasterLayers', ['shift+h']);
// Workflows
addHotkey('workflows', 'addNode', ['shift+a', 'space']);