From e0906e8d50c4300df560206a39e9119b2db6d603 Mon Sep 17 00:00:00 2001 From: Mary Hipp Date: Tue, 17 Sep 2024 15:12:23 -0400 Subject: [PATCH 1/6] feat(ui): copy layer to clipboard --- invokeai/frontend/web/public/locales/en.json | 3 ++ ...nvasContextMenuSelectedEntityMenuItems.tsx | 2 + .../common/CanvasEntityCopyToClipboard.tsx | 34 ++++++++++++++ .../CanvasEntityHeaderCommonActions.tsx | 3 ++ .../common/CanvasEntityMenuItemsCopy.tsx | 28 ++++++++++++ .../hooks/useCopyLayerToClipboard.ts | 44 +++++++++++++++++++ .../src/features/controlLayers/store/types.ts | 8 ++-- 7 files changed, 118 insertions(+), 4 deletions(-) create mode 100644 invokeai/frontend/web/src/features/controlLayers/components/common/CanvasEntityCopyToClipboard.tsx create mode 100644 invokeai/frontend/web/src/features/controlLayers/components/common/CanvasEntityMenuItemsCopy.tsx create mode 100644 invokeai/frontend/web/src/features/controlLayers/hooks/useCopyLayerToClipboard.ts diff --git a/invokeai/frontend/web/public/locales/en.json b/invokeai/frontend/web/public/locales/en.json index f0ac55905e..4ed56fe1f1 100644 --- a/invokeai/frontend/web/public/locales/en.json +++ b/invokeai/frontend/web/public/locales/en.json @@ -1081,6 +1081,7 @@ "importFailed": "Import Failed", "importSuccessful": "Import Successful", "invalidUpload": "Invalid Upload", + "layerCopiedToClipboard": "Layer Copied to Clipboard", "loadedWithWarnings": "Workflow Loaded with Warnings", "maskSavedAssets": "Mask Saved to Assets", "maskSentControlnetAssets": "Mask Sent to ControlNet & Assets", @@ -1101,6 +1102,7 @@ "problemCopyingCanvas": "Problem Copying Canvas", "problemCopyingCanvasDesc": "Unable to export base layer", "problemCopyingImage": "Unable to Copy Image", + "problemCopyingLayer": "Unable to Copy Layer", "problemDownloadingImage": "Unable to Download Image", "problemDownloadingCanvas": "Problem Downloading Canvas", "problemDownloadingCanvasDesc": "Unable to export base layer", @@ -1669,6 +1671,7 @@ "sendToGallery": "Send To Gallery", "sendToGalleryDesc": "Pressing Invoke generates and saves a unique image to your gallery.", "sendToCanvas": "Send To Canvas", + "copyToClipboard": "Copy to Clipboard", "sendToCanvasDesc": "Pressing Invoke stages your work in progress on the canvas.", "viewProgressInViewer": "View progress and outputs in the Image Viewer.", "viewProgressOnCanvas": "View progress and stage outputs on the Canvas.", diff --git a/invokeai/frontend/web/src/features/controlLayers/components/CanvasContextMenu/CanvasContextMenuSelectedEntityMenuItems.tsx b/invokeai/frontend/web/src/features/controlLayers/components/CanvasContextMenu/CanvasContextMenuSelectedEntityMenuItems.tsx index 19c673fd69..4369a9925a 100644 --- a/invokeai/frontend/web/src/features/controlLayers/components/CanvasContextMenu/CanvasContextMenuSelectedEntityMenuItems.tsx +++ b/invokeai/frontend/web/src/features/controlLayers/components/CanvasContextMenu/CanvasContextMenuSelectedEntityMenuItems.tsx @@ -1,5 +1,6 @@ import { MenuGroup } from '@invoke-ai/ui-library'; import { useAppSelector } from 'app/store/storeHooks'; +import { CanvasEntityMenuItemsCopy } from 'features/controlLayers/components/common/CanvasEntityMenuItemsCopy'; import { CanvasEntityMenuItemsDelete } from 'features/controlLayers/components/common/CanvasEntityMenuItemsDelete'; import { CanvasEntityMenuItemsFilter } from 'features/controlLayers/components/common/CanvasEntityMenuItemsFilter'; import { CanvasEntityMenuItemsTransform } from 'features/controlLayers/components/common/CanvasEntityMenuItemsTransform'; @@ -20,6 +21,7 @@ const CanvasContextMenuSelectedEntityMenuItemsContent = memo(() => { {isFilterableEntityIdentifier(entityIdentifier) && } {isTransformableEntityIdentifier(entityIdentifier) && } + ); diff --git a/invokeai/frontend/web/src/features/controlLayers/components/common/CanvasEntityCopyToClipboard.tsx b/invokeai/frontend/web/src/features/controlLayers/components/common/CanvasEntityCopyToClipboard.tsx new file mode 100644 index 0000000000..1d4fc22fdd --- /dev/null +++ b/invokeai/frontend/web/src/features/controlLayers/components/common/CanvasEntityCopyToClipboard.tsx @@ -0,0 +1,34 @@ +import { IconButton } from '@invoke-ai/ui-library'; +import { useEntityAdapterSafe } from 'features/controlLayers/contexts/EntityAdapterContext'; +import { useEntityIdentifierContext } from 'features/controlLayers/contexts/EntityIdentifierContext'; +import { useCanvasIsBusy } from 'features/controlLayers/hooks/useCanvasIsBusy'; +import { useCopyLayerToClipboard } from 'features/controlLayers/hooks/useCopyLayerToClipboard'; +import { memo, useCallback } from 'react'; +import { useTranslation } from 'react-i18next'; +import { PiCopyBold } from 'react-icons/pi'; + +export const CanvasEntityCopyToClipboard = memo(() => { + const { t } = useTranslation(); + const entityIdentifier = useEntityIdentifierContext(); + const adapter = useEntityAdapterSafe(entityIdentifier); + const isBusy = useCanvasIsBusy(); + const copyLayerToClipboard = useCopyLayerToClipboard(); + const onClick = useCallback(() => { + copyLayerToClipboard(adapter); + }, [copyLayerToClipboard, adapter]); + + return ( + } + onClick={onClick} + isDisabled={isBusy} + /> + ); +}); + +CanvasEntityCopyToClipboard.displayName = 'CanvasEntityCopyToClipboard'; diff --git a/invokeai/frontend/web/src/features/controlLayers/components/common/CanvasEntityHeaderCommonActions.tsx b/invokeai/frontend/web/src/features/controlLayers/components/common/CanvasEntityHeaderCommonActions.tsx index cc89cb02f6..fd4771b895 100644 --- a/invokeai/frontend/web/src/features/controlLayers/components/common/CanvasEntityHeaderCommonActions.tsx +++ b/invokeai/frontend/web/src/features/controlLayers/components/common/CanvasEntityHeaderCommonActions.tsx @@ -6,11 +6,14 @@ import { CanvasEntityIsLockedToggle } from 'features/controlLayers/components/co import { useEntityIdentifierContext } from 'features/controlLayers/contexts/EntityIdentifierContext'; import { memo } from 'react'; +import { CanvasEntityCopyToClipboard } from './CanvasEntityCopyToClipboard'; + export const CanvasEntityHeaderCommonActions = memo(() => { const entityIdentifier = useEntityIdentifierContext(); return ( + {entityIdentifier.type !== 'reference_image' && } diff --git a/invokeai/frontend/web/src/features/controlLayers/components/common/CanvasEntityMenuItemsCopy.tsx b/invokeai/frontend/web/src/features/controlLayers/components/common/CanvasEntityMenuItemsCopy.tsx new file mode 100644 index 0000000000..040c439d87 --- /dev/null +++ b/invokeai/frontend/web/src/features/controlLayers/components/common/CanvasEntityMenuItemsCopy.tsx @@ -0,0 +1,28 @@ +import { MenuItem } from '@invoke-ai/ui-library'; +import { useEntityAdapterSafe } from 'features/controlLayers/contexts/EntityAdapterContext'; +import { useEntityIdentifierContext } from 'features/controlLayers/contexts/EntityIdentifierContext'; +import { useCopyLayerToClipboard } from 'features/controlLayers/hooks/useCopyLayerToClipboard'; +import { useIsEntityInteractable } from 'features/controlLayers/hooks/useEntityIsInteractable'; +import { memo, useCallback } from 'react'; +import { useTranslation } from 'react-i18next'; +import { PiCopyBold } from 'react-icons/pi'; + +export const CanvasEntityMenuItemsCopy = memo(() => { + const { t } = useTranslation(); + const entityIdentifier = useEntityIdentifierContext(); + const adapter = useEntityAdapterSafe(entityIdentifier); + const isInteractable = useIsEntityInteractable(entityIdentifier); + const copyLayerToClipboard = useCopyLayerToClipboard(); + + const onClick = useCallback(() => { + copyLayerToClipboard(adapter); + }, [copyLayerToClipboard, adapter]); + + return ( + } isDisabled={!isInteractable}> + {t('controlLayers.copyToClipboard')} + + ); +}); + +CanvasEntityMenuItemsCopy.displayName = 'CanvasEntityMenuItemsCopy'; diff --git a/invokeai/frontend/web/src/features/controlLayers/hooks/useCopyLayerToClipboard.ts b/invokeai/frontend/web/src/features/controlLayers/hooks/useCopyLayerToClipboard.ts new file mode 100644 index 0000000000..9221c3e2cb --- /dev/null +++ b/invokeai/frontend/web/src/features/controlLayers/hooks/useCopyLayerToClipboard.ts @@ -0,0 +1,44 @@ +import type { CanvasEntityAdapterControlLayer } from 'features/controlLayers/konva/CanvasEntity/CanvasEntityAdapterControlLayer'; +import type { CanvasEntityAdapterInpaintMask } from 'features/controlLayers/konva/CanvasEntity/CanvasEntityAdapterInpaintMask'; +import type { CanvasEntityAdapterRasterLayer } from 'features/controlLayers/konva/CanvasEntity/CanvasEntityAdapterRasterLayer'; +import type { CanvasEntityAdapterRegionalGuidance } from 'features/controlLayers/konva/CanvasEntity/CanvasEntityAdapterRegionalGuidance'; +import { canvasToBlob } from 'features/controlLayers/konva/util'; +import { copyBlobToClipboard } from 'features/system/util/copyBlobToClipboard'; +import { toast } from 'features/toast/toast'; +import { useCallback } from 'react'; +import { useTranslation } from 'react-i18next'; + +export const useCopyLayerToClipboard = () => { + const { t } = useTranslation(); + const copyLayerToCipboard = useCallback( + async ( + adapter: + | CanvasEntityAdapterRasterLayer + | CanvasEntityAdapterControlLayer + | CanvasEntityAdapterInpaintMask + | CanvasEntityAdapterRegionalGuidance + | null + ) => { + if (!adapter) { + return; + } + try { + const canvas = adapter.getCanvas(); + const blob = await canvasToBlob(canvas); + copyBlobToClipboard(blob); + toast({ + status: 'info', + title: t('toast.layerCopiedToClipboard'), + }); + } catch (error) { + toast({ + status: 'error', + title: t('toast.problemCopyingLayer'), + }); + } + }, + [t] + ); + + return copyLayerToCipboard; +}; diff --git a/invokeai/frontend/web/src/features/controlLayers/store/types.ts b/invokeai/frontend/web/src/features/controlLayers/store/types.ts index a6990a910a..944d8592e2 100644 --- a/invokeai/frontend/web/src/features/controlLayers/store/types.ts +++ b/invokeai/frontend/web/src/features/controlLayers/store/types.ts @@ -299,11 +299,11 @@ export type EntityIdentifierPayload< U extends CanvasEntityType = CanvasEntityType, > = T extends void ? { - entityIdentifier: CanvasEntityIdentifier; - } + entityIdentifier: CanvasEntityIdentifier; + } : { - entityIdentifier: CanvasEntityIdentifier; - } & T; + entityIdentifier: CanvasEntityIdentifier; + } & T; export type EntityMovedPayload = EntityIdentifierPayload<{ position: Coordinate }>; export type EntityBrushLineAddedPayload = EntityIdentifierPayload<{ brushLine: CanvasBrushLineState }>; From f73a5f71d7c4bc4aa09bb8a931f9de7088a8e6ab Mon Sep 17 00:00:00 2001 From: Mary Hipp Date: Tue, 17 Sep 2024 15:37:45 -0400 Subject: [PATCH 2/6] feat(ui): save layer to assets --- ...nvasContextMenuSelectedEntityMenuItems.tsx | 2 + .../CanvasEntityHeaderCommonActions.tsx | 2 + .../common/CanvasEntityMenuItemsSave.tsx | 27 +++++++++ .../common/CanvasEntitySaveToAssets.tsx | 34 +++++++++++ .../hooks/useSaveLayerToAssets.ts | 57 +++++++++++++++++++ .../src/features/controlLayers/store/types.ts | 8 +-- 6 files changed, 126 insertions(+), 4 deletions(-) create mode 100644 invokeai/frontend/web/src/features/controlLayers/components/common/CanvasEntityMenuItemsSave.tsx create mode 100644 invokeai/frontend/web/src/features/controlLayers/components/common/CanvasEntitySaveToAssets.tsx create mode 100644 invokeai/frontend/web/src/features/controlLayers/hooks/useSaveLayerToAssets.ts diff --git a/invokeai/frontend/web/src/features/controlLayers/components/CanvasContextMenu/CanvasContextMenuSelectedEntityMenuItems.tsx b/invokeai/frontend/web/src/features/controlLayers/components/CanvasContextMenu/CanvasContextMenuSelectedEntityMenuItems.tsx index 4369a9925a..f3a5d4e9d8 100644 --- a/invokeai/frontend/web/src/features/controlLayers/components/CanvasContextMenu/CanvasContextMenuSelectedEntityMenuItems.tsx +++ b/invokeai/frontend/web/src/features/controlLayers/components/CanvasContextMenu/CanvasContextMenuSelectedEntityMenuItems.tsx @@ -3,6 +3,7 @@ import { useAppSelector } from 'app/store/storeHooks'; import { CanvasEntityMenuItemsCopy } from 'features/controlLayers/components/common/CanvasEntityMenuItemsCopy'; import { CanvasEntityMenuItemsDelete } from 'features/controlLayers/components/common/CanvasEntityMenuItemsDelete'; import { CanvasEntityMenuItemsFilter } from 'features/controlLayers/components/common/CanvasEntityMenuItemsFilter'; +import { CanvasEntityMenuItemsSave } from 'features/controlLayers/components/common/CanvasEntityMenuItemsSave'; import { CanvasEntityMenuItemsTransform } from 'features/controlLayers/components/common/CanvasEntityMenuItemsTransform'; import { EntityIdentifierContext, @@ -22,6 +23,7 @@ const CanvasContextMenuSelectedEntityMenuItemsContent = memo(() => { {isFilterableEntityIdentifier(entityIdentifier) && } {isTransformableEntityIdentifier(entityIdentifier) && } + ); diff --git a/invokeai/frontend/web/src/features/controlLayers/components/common/CanvasEntityHeaderCommonActions.tsx b/invokeai/frontend/web/src/features/controlLayers/components/common/CanvasEntityHeaderCommonActions.tsx index fd4771b895..b2f7643a8a 100644 --- a/invokeai/frontend/web/src/features/controlLayers/components/common/CanvasEntityHeaderCommonActions.tsx +++ b/invokeai/frontend/web/src/features/controlLayers/components/common/CanvasEntityHeaderCommonActions.tsx @@ -7,12 +7,14 @@ import { useEntityIdentifierContext } from 'features/controlLayers/contexts/Enti import { memo } from 'react'; import { CanvasEntityCopyToClipboard } from './CanvasEntityCopyToClipboard'; +import { CanvasEntitySaveToAssets } from './CanvasEntitySaveToAssets'; export const CanvasEntityHeaderCommonActions = memo(() => { const entityIdentifier = useEntityIdentifierContext(); return ( + {entityIdentifier.type !== 'reference_image' && } diff --git a/invokeai/frontend/web/src/features/controlLayers/components/common/CanvasEntityMenuItemsSave.tsx b/invokeai/frontend/web/src/features/controlLayers/components/common/CanvasEntityMenuItemsSave.tsx new file mode 100644 index 0000000000..9aa3134de8 --- /dev/null +++ b/invokeai/frontend/web/src/features/controlLayers/components/common/CanvasEntityMenuItemsSave.tsx @@ -0,0 +1,27 @@ +import { MenuItem } from '@invoke-ai/ui-library'; +import { useEntityAdapterSafe } from 'features/controlLayers/contexts/EntityAdapterContext'; +import { useEntityIdentifierContext } from 'features/controlLayers/contexts/EntityIdentifierContext'; +import { useIsEntityInteractable } from 'features/controlLayers/hooks/useEntityIsInteractable'; +import { useSaveLayerToAssets } from 'features/controlLayers/hooks/useSaveLayerToAssets'; +import { memo, useCallback } from 'react'; +import { useTranslation } from 'react-i18next'; +import { PiFloppyDiskBold } from 'react-icons/pi'; + +export const CanvasEntityMenuItemsSave = memo(() => { + const { t } = useTranslation(); + const entityIdentifier = useEntityIdentifierContext(); + const adapter = useEntityAdapterSafe(entityIdentifier); + const isInteractable = useIsEntityInteractable(entityIdentifier); + const saveLayerToAssets = useSaveLayerToAssets(); + const onClick = useCallback(() => { + saveLayerToAssets(adapter); + }, [saveLayerToAssets, adapter]); + + return ( + } isDisabled={!isInteractable}> + {t('controlLayers.saveLayerToAssets')} + + ); +}); + +CanvasEntityMenuItemsSave.displayName = 'CanvasEntityMenuItemsSave'; diff --git a/invokeai/frontend/web/src/features/controlLayers/components/common/CanvasEntitySaveToAssets.tsx b/invokeai/frontend/web/src/features/controlLayers/components/common/CanvasEntitySaveToAssets.tsx new file mode 100644 index 0000000000..266e5c2d37 --- /dev/null +++ b/invokeai/frontend/web/src/features/controlLayers/components/common/CanvasEntitySaveToAssets.tsx @@ -0,0 +1,34 @@ +import { IconButton } from '@invoke-ai/ui-library'; +import { useEntityAdapterSafe } from 'features/controlLayers/contexts/EntityAdapterContext'; +import { useEntityIdentifierContext } from 'features/controlLayers/contexts/EntityIdentifierContext'; +import { useCanvasIsBusy } from 'features/controlLayers/hooks/useCanvasIsBusy'; +import { useSaveLayerToAssets } from 'features/controlLayers/hooks/useSaveLayerToAssets'; +import { memo, useCallback } from 'react'; +import { useTranslation } from 'react-i18next'; +import { PiFloppyDiskBold } from 'react-icons/pi'; + +export const CanvasEntitySaveToAssets = memo(() => { + const { t } = useTranslation(); + const entityIdentifier = useEntityIdentifierContext(); + const adapter = useEntityAdapterSafe(entityIdentifier); + const isBusy = useCanvasIsBusy(); + const saveLayerToAssets = useSaveLayerToAssets(); + const onClick = useCallback(() => { + saveLayerToAssets(adapter); + }, [saveLayerToAssets, adapter]); + + return ( + } + onClick={onClick} + isDisabled={isBusy} + /> + ); +}); + +CanvasEntitySaveToAssets.displayName = 'CanvasEntitySaveToAssets'; diff --git a/invokeai/frontend/web/src/features/controlLayers/hooks/useSaveLayerToAssets.ts b/invokeai/frontend/web/src/features/controlLayers/hooks/useSaveLayerToAssets.ts new file mode 100644 index 0000000000..44df26be64 --- /dev/null +++ b/invokeai/frontend/web/src/features/controlLayers/hooks/useSaveLayerToAssets.ts @@ -0,0 +1,57 @@ +import { useAppSelector } from 'app/store/storeHooks'; +import type { CanvasEntityAdapterControlLayer } from 'features/controlLayers/konva/CanvasEntity/CanvasEntityAdapterControlLayer'; +import type { CanvasEntityAdapterInpaintMask } from 'features/controlLayers/konva/CanvasEntity/CanvasEntityAdapterInpaintMask'; +import type { CanvasEntityAdapterRasterLayer } from 'features/controlLayers/konva/CanvasEntity/CanvasEntityAdapterRasterLayer'; +import type { CanvasEntityAdapterRegionalGuidance } from 'features/controlLayers/konva/CanvasEntity/CanvasEntityAdapterRegionalGuidance'; +import { canvasToBlob } from 'features/controlLayers/konva/util'; +import { selectAutoAddBoardId } from 'features/gallery/store/gallerySelectors'; +import { toast } from 'features/toast/toast'; +import { useCallback } from 'react'; +import { useTranslation } from 'react-i18next'; +import { useUploadImageMutation } from 'services/api/endpoints/images'; + +export const useSaveLayerToAssets = () => { + const { t } = useTranslation(); + const [uploadImage] = useUploadImageMutation(); + const autoAddBoardId = useAppSelector(selectAutoAddBoardId); + + const copyLayerToCipboard = useCallback( + async ( + adapter: + | CanvasEntityAdapterRasterLayer + | CanvasEntityAdapterControlLayer + | CanvasEntityAdapterInpaintMask + | CanvasEntityAdapterRegionalGuidance + | null + ) => { + if (!adapter) { + return; + } + try { + const canvas = adapter.getCanvas(); + const blob = await canvasToBlob(canvas); + const file = new File([blob], `layer-${adapter.id}.png`, { type: 'image/png' }); + await uploadImage({ + file, + image_category: 'user', + is_intermediate: false, + postUploadAction: { type: 'TOAST' }, + board_id: autoAddBoardId === 'none' ? undefined : autoAddBoardId, + }); + + toast({ + status: 'info', + title: t('toast.layerSavedToAssets'), + }); + } catch (error) { + toast({ + status: 'error', + title: t('toast.problemSavingLayer'), + }); + } + }, + [t, autoAddBoardId, uploadImage] + ); + + return copyLayerToCipboard; +}; diff --git a/invokeai/frontend/web/src/features/controlLayers/store/types.ts b/invokeai/frontend/web/src/features/controlLayers/store/types.ts index 944d8592e2..a6990a910a 100644 --- a/invokeai/frontend/web/src/features/controlLayers/store/types.ts +++ b/invokeai/frontend/web/src/features/controlLayers/store/types.ts @@ -299,11 +299,11 @@ export type EntityIdentifierPayload< U extends CanvasEntityType = CanvasEntityType, > = T extends void ? { - entityIdentifier: CanvasEntityIdentifier; - } + entityIdentifier: CanvasEntityIdentifier; + } : { - entityIdentifier: CanvasEntityIdentifier; - } & T; + entityIdentifier: CanvasEntityIdentifier; + } & T; export type EntityMovedPayload = EntityIdentifierPayload<{ position: Coordinate }>; export type EntityBrushLineAddedPayload = EntityIdentifierPayload<{ brushLine: CanvasBrushLineState }>; From 9e14388b0ddb8ee9b6b13409d728295adbdbec40 Mon Sep 17 00:00:00 2001 From: Mary Hipp Date: Tue, 17 Sep 2024 15:39:15 -0400 Subject: [PATCH 3/6] missed translation --- invokeai/frontend/web/public/locales/en.json | 3 +++ 1 file changed, 3 insertions(+) diff --git a/invokeai/frontend/web/public/locales/en.json b/invokeai/frontend/web/public/locales/en.json index 4ed56fe1f1..bc0f7861a3 100644 --- a/invokeai/frontend/web/public/locales/en.json +++ b/invokeai/frontend/web/public/locales/en.json @@ -1082,6 +1082,7 @@ "importSuccessful": "Import Successful", "invalidUpload": "Invalid Upload", "layerCopiedToClipboard": "Layer Copied to Clipboard", + "layerSavedToAssets": "Layer Saved to Assets", "loadedWithWarnings": "Workflow Loaded with Warnings", "maskSavedAssets": "Mask Saved to Assets", "maskSentControlnetAssets": "Mask Sent to ControlNet & Assets", @@ -1103,6 +1104,7 @@ "problemCopyingCanvasDesc": "Unable to export base layer", "problemCopyingImage": "Unable to Copy Image", "problemCopyingLayer": "Unable to Copy Layer", + "problemSavingLayer": "Unable to Save Layer", "problemDownloadingImage": "Unable to Download Image", "problemDownloadingCanvas": "Problem Downloading Canvas", "problemDownloadingCanvasDesc": "Unable to export base layer", @@ -1594,6 +1596,7 @@ "removeBookmark": "Remove Bookmark", "saveCanvasToGallery": "Save Canvas to Gallery", "saveBboxToGallery": "Save Bbox to Gallery", + "saveLayerToAssets": "Save Layer to Assets", "newControlLayerFromBbox": "New Control Layer from Bbox", "newRasterLayerFromBbox": "New Raster Layer from Bbox", "savedToGalleryOk": "Saved to Gallery", From a593178fbc970753cf1275eb88c9e3496e06903b Mon Sep 17 00:00:00 2001 From: Mary Hipp Date: Tue, 17 Sep 2024 15:41:15 -0400 Subject: [PATCH 4/6] fix variable name --- .../src/features/controlLayers/hooks/useSaveLayerToAssets.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/invokeai/frontend/web/src/features/controlLayers/hooks/useSaveLayerToAssets.ts b/invokeai/frontend/web/src/features/controlLayers/hooks/useSaveLayerToAssets.ts index 44df26be64..d4e64aa48d 100644 --- a/invokeai/frontend/web/src/features/controlLayers/hooks/useSaveLayerToAssets.ts +++ b/invokeai/frontend/web/src/features/controlLayers/hooks/useSaveLayerToAssets.ts @@ -15,7 +15,7 @@ export const useSaveLayerToAssets = () => { const [uploadImage] = useUploadImageMutation(); const autoAddBoardId = useAppSelector(selectAutoAddBoardId); - const copyLayerToCipboard = useCallback( + const saveLayerToAssets = useCallback( async ( adapter: | CanvasEntityAdapterRasterLayer @@ -53,5 +53,5 @@ export const useSaveLayerToAssets = () => { [t, autoAddBoardId, uploadImage] ); - return copyLayerToCipboard; + return saveLayerToAssets; }; From 2d106b7725d5de16b17bf090af5b125fec5fc95a Mon Sep 17 00:00:00 2001 From: Mary Hipp Date: Tue, 17 Sep 2024 18:58:53 -0400 Subject: [PATCH 5/6] remove copy/save from layer UX and add it to layer context menu and action bar where appropriate; remove copy/save from IP adapter layers --- ...nvasContextMenuSelectedEntityMenuItems.tsx | 12 ++++--- .../EntityListSelectedEntityActionBar.tsx | 3 ++ ...ctedEntityActionBarSaveToAssetsButton.tsx} | 28 ++++++++++----- .../ControlLayer/ControlLayerMenuItems.tsx | 4 +++ .../InpaintMask/InpaintMaskMenuItems.tsx | 4 +++ .../RasterLayer/RasterLayerMenuItems.tsx | 4 +++ .../RegionalGuidanceMenuItems.tsx | 4 +++ .../common/CanvasEntityCopyToClipboard.tsx | 34 ------------------- .../CanvasEntityHeaderCommonActions.tsx | 5 --- ... CanvasEntityMenuItemsCopyToClipboard.tsx} | 4 +-- .../src/features/controlLayers/store/types.ts | 15 ++++++++ 11 files changed, 63 insertions(+), 54 deletions(-) rename invokeai/frontend/web/src/features/controlLayers/components/{common/CanvasEntitySaveToAssets.tsx => CanvasEntityList/EntityListSelectedEntityActionBarSaveToAssetsButton.tsx} (55%) delete mode 100644 invokeai/frontend/web/src/features/controlLayers/components/common/CanvasEntityCopyToClipboard.tsx rename invokeai/frontend/web/src/features/controlLayers/components/common/{CanvasEntityMenuItemsCopy.tsx => CanvasEntityMenuItemsCopyToClipboard.tsx} (87%) diff --git a/invokeai/frontend/web/src/features/controlLayers/components/CanvasContextMenu/CanvasContextMenuSelectedEntityMenuItems.tsx b/invokeai/frontend/web/src/features/controlLayers/components/CanvasContextMenu/CanvasContextMenuSelectedEntityMenuItems.tsx index f3a5d4e9d8..cd244f5da6 100644 --- a/invokeai/frontend/web/src/features/controlLayers/components/CanvasContextMenu/CanvasContextMenuSelectedEntityMenuItems.tsx +++ b/invokeai/frontend/web/src/features/controlLayers/components/CanvasContextMenu/CanvasContextMenuSelectedEntityMenuItems.tsx @@ -1,6 +1,6 @@ import { MenuGroup } from '@invoke-ai/ui-library'; import { useAppSelector } from 'app/store/storeHooks'; -import { CanvasEntityMenuItemsCopy } from 'features/controlLayers/components/common/CanvasEntityMenuItemsCopy'; +import { CanvasEntityMenuItemsCopyToClipboard } from 'features/controlLayers/components/common/CanvasEntityMenuItemsCopyToClipboard'; import { CanvasEntityMenuItemsDelete } from 'features/controlLayers/components/common/CanvasEntityMenuItemsDelete'; import { CanvasEntityMenuItemsFilter } from 'features/controlLayers/components/common/CanvasEntityMenuItemsFilter'; import { CanvasEntityMenuItemsSave } from 'features/controlLayers/components/common/CanvasEntityMenuItemsSave'; @@ -11,7 +11,11 @@ import { } from 'features/controlLayers/contexts/EntityIdentifierContext'; import { useEntityTitle } from 'features/controlLayers/hooks/useEntityTitle'; import { selectSelectedEntityIdentifier } from 'features/controlLayers/store/selectors'; -import { isFilterableEntityIdentifier, isTransformableEntityIdentifier } from 'features/controlLayers/store/types'; +import { + isFilterableEntityIdentifier, + isSaveableEntityIdentifier, + isTransformableEntityIdentifier, +} from 'features/controlLayers/store/types'; import { memo } from 'react'; const CanvasContextMenuSelectedEntityMenuItemsContent = memo(() => { @@ -22,8 +26,8 @@ const CanvasContextMenuSelectedEntityMenuItemsContent = memo(() => { {isFilterableEntityIdentifier(entityIdentifier) && } {isTransformableEntityIdentifier(entityIdentifier) && } - - + {isSaveableEntityIdentifier(entityIdentifier) && } + {isSaveableEntityIdentifier(entityIdentifier) && } ); diff --git a/invokeai/frontend/web/src/features/controlLayers/components/CanvasEntityList/EntityListSelectedEntityActionBar.tsx b/invokeai/frontend/web/src/features/controlLayers/components/CanvasEntityList/EntityListSelectedEntityActionBar.tsx index a59270c6be..d5d2c3042d 100644 --- a/invokeai/frontend/web/src/features/controlLayers/components/CanvasEntityList/EntityListSelectedEntityActionBar.tsx +++ b/invokeai/frontend/web/src/features/controlLayers/components/CanvasEntityList/EntityListSelectedEntityActionBar.tsx @@ -7,6 +7,8 @@ import { EntityListSelectedEntityActionBarOpacity } from 'features/controlLayers import { EntityListSelectedEntityActionBarTransformButton } from 'features/controlLayers/components/CanvasEntityList/EntityListSelectedEntityActionBarTransformButton'; import { memo } from 'react'; +import { EntityListSelectedEntityActionBarSaveToAssetsButton } from './EntityListSelectedEntityActionBarSaveToAssetsButton'; + export const EntityListSelectedEntityActionBar = memo(() => { return ( @@ -16,6 +18,7 @@ export const EntityListSelectedEntityActionBar = memo(() => { + diff --git a/invokeai/frontend/web/src/features/controlLayers/components/common/CanvasEntitySaveToAssets.tsx b/invokeai/frontend/web/src/features/controlLayers/components/CanvasEntityList/EntityListSelectedEntityActionBarSaveToAssetsButton.tsx similarity index 55% rename from invokeai/frontend/web/src/features/controlLayers/components/common/CanvasEntitySaveToAssets.tsx rename to invokeai/frontend/web/src/features/controlLayers/components/CanvasEntityList/EntityListSelectedEntityActionBarSaveToAssetsButton.tsx index 266e5c2d37..eb4319f04b 100644 --- a/invokeai/frontend/web/src/features/controlLayers/components/common/CanvasEntitySaveToAssets.tsx +++ b/invokeai/frontend/web/src/features/controlLayers/components/CanvasEntityList/EntityListSelectedEntityActionBarSaveToAssetsButton.tsx @@ -1,34 +1,44 @@ import { IconButton } from '@invoke-ai/ui-library'; +import { useAppSelector } from 'app/store/storeHooks'; import { useEntityAdapterSafe } from 'features/controlLayers/contexts/EntityAdapterContext'; -import { useEntityIdentifierContext } from 'features/controlLayers/contexts/EntityIdentifierContext'; import { useCanvasIsBusy } from 'features/controlLayers/hooks/useCanvasIsBusy'; import { useSaveLayerToAssets } from 'features/controlLayers/hooks/useSaveLayerToAssets'; +import { selectSelectedEntityIdentifier } from 'features/controlLayers/store/selectors'; +import { isSaveableEntityIdentifier } from 'features/controlLayers/store/types'; import { memo, useCallback } from 'react'; import { useTranslation } from 'react-i18next'; import { PiFloppyDiskBold } from 'react-icons/pi'; -export const CanvasEntitySaveToAssets = memo(() => { +export const EntityListSelectedEntityActionBarSaveToAssetsButton = memo(() => { const { t } = useTranslation(); - const entityIdentifier = useEntityIdentifierContext(); - const adapter = useEntityAdapterSafe(entityIdentifier); const isBusy = useCanvasIsBusy(); + const selectedEntityIdentifier = useAppSelector(selectSelectedEntityIdentifier); + const adapter = useEntityAdapterSafe(selectedEntityIdentifier); const saveLayerToAssets = useSaveLayerToAssets(); const onClick = useCallback(() => { saveLayerToAssets(adapter); }, [saveLayerToAssets, adapter]); + if (!selectedEntityIdentifier) { + return null; + } + + if (!isSaveableEntityIdentifier(selectedEntityIdentifier)) { + return null; + } + return ( } - onClick={onClick} - isDisabled={isBusy} /> ); }); -CanvasEntitySaveToAssets.displayName = 'CanvasEntitySaveToAssets'; +EntityListSelectedEntityActionBarSaveToAssetsButton.displayName = 'EntityListSelectedEntityActionBarSaveToAssetsButton'; diff --git a/invokeai/frontend/web/src/features/controlLayers/components/ControlLayer/ControlLayerMenuItems.tsx b/invokeai/frontend/web/src/features/controlLayers/components/ControlLayer/ControlLayerMenuItems.tsx index c82cf23a3a..d3ac4717bf 100644 --- a/invokeai/frontend/web/src/features/controlLayers/components/ControlLayer/ControlLayerMenuItems.tsx +++ b/invokeai/frontend/web/src/features/controlLayers/components/ControlLayer/ControlLayerMenuItems.tsx @@ -1,8 +1,10 @@ import { MenuDivider } from '@invoke-ai/ui-library'; import { CanvasEntityMenuItemsArrange } from 'features/controlLayers/components/common/CanvasEntityMenuItemsArrange'; +import { CanvasEntityMenuItemsCopyToClipboard } from 'features/controlLayers/components/common/CanvasEntityMenuItemsCopyToClipboard'; import { CanvasEntityMenuItemsDelete } from 'features/controlLayers/components/common/CanvasEntityMenuItemsDelete'; import { CanvasEntityMenuItemsDuplicate } from 'features/controlLayers/components/common/CanvasEntityMenuItemsDuplicate'; import { CanvasEntityMenuItemsFilter } from 'features/controlLayers/components/common/CanvasEntityMenuItemsFilter'; +import { CanvasEntityMenuItemsSave } from 'features/controlLayers/components/common/CanvasEntityMenuItemsSave'; import { CanvasEntityMenuItemsTransform } from 'features/controlLayers/components/common/CanvasEntityMenuItemsTransform'; import { ControlLayerMenuItemsConvertControlToRaster } from 'features/controlLayers/components/ControlLayer/ControlLayerMenuItemsConvertControlToRaster'; import { ControlLayerMenuItemsTransparencyEffect } from 'features/controlLayers/components/ControlLayer/ControlLayerMenuItemsTransparencyEffect'; @@ -19,6 +21,8 @@ export const ControlLayerMenuItems = memo(() => { + + ); diff --git a/invokeai/frontend/web/src/features/controlLayers/components/InpaintMask/InpaintMaskMenuItems.tsx b/invokeai/frontend/web/src/features/controlLayers/components/InpaintMask/InpaintMaskMenuItems.tsx index 925ba30e35..a270d6c754 100644 --- a/invokeai/frontend/web/src/features/controlLayers/components/InpaintMask/InpaintMaskMenuItems.tsx +++ b/invokeai/frontend/web/src/features/controlLayers/components/InpaintMask/InpaintMaskMenuItems.tsx @@ -1,7 +1,9 @@ import { MenuDivider } from '@invoke-ai/ui-library'; import { CanvasEntityMenuItemsArrange } from 'features/controlLayers/components/common/CanvasEntityMenuItemsArrange'; +import { CanvasEntityMenuItemsCopyToClipboard } from 'features/controlLayers/components/common/CanvasEntityMenuItemsCopyToClipboard'; import { CanvasEntityMenuItemsDelete } from 'features/controlLayers/components/common/CanvasEntityMenuItemsDelete'; import { CanvasEntityMenuItemsDuplicate } from 'features/controlLayers/components/common/CanvasEntityMenuItemsDuplicate'; +import { CanvasEntityMenuItemsSave } from 'features/controlLayers/components/common/CanvasEntityMenuItemsSave'; import { CanvasEntityMenuItemsTransform } from 'features/controlLayers/components/common/CanvasEntityMenuItemsTransform'; import { memo } from 'react'; @@ -13,6 +15,8 @@ export const InpaintMaskMenuItems = memo(() => { + + ); diff --git a/invokeai/frontend/web/src/features/controlLayers/components/RasterLayer/RasterLayerMenuItems.tsx b/invokeai/frontend/web/src/features/controlLayers/components/RasterLayer/RasterLayerMenuItems.tsx index 2f387927ff..db4965474f 100644 --- a/invokeai/frontend/web/src/features/controlLayers/components/RasterLayer/RasterLayerMenuItems.tsx +++ b/invokeai/frontend/web/src/features/controlLayers/components/RasterLayer/RasterLayerMenuItems.tsx @@ -1,8 +1,10 @@ import { MenuDivider } from '@invoke-ai/ui-library'; import { CanvasEntityMenuItemsArrange } from 'features/controlLayers/components/common/CanvasEntityMenuItemsArrange'; +import { CanvasEntityMenuItemsCopyToClipboard } from 'features/controlLayers/components/common/CanvasEntityMenuItemsCopyToClipboard'; import { CanvasEntityMenuItemsDelete } from 'features/controlLayers/components/common/CanvasEntityMenuItemsDelete'; import { CanvasEntityMenuItemsDuplicate } from 'features/controlLayers/components/common/CanvasEntityMenuItemsDuplicate'; import { CanvasEntityMenuItemsFilter } from 'features/controlLayers/components/common/CanvasEntityMenuItemsFilter'; +import { CanvasEntityMenuItemsSave } from 'features/controlLayers/components/common/CanvasEntityMenuItemsSave'; import { CanvasEntityMenuItemsTransform } from 'features/controlLayers/components/common/CanvasEntityMenuItemsTransform'; import { RasterLayerMenuItemsConvertRasterToControl } from 'features/controlLayers/components/RasterLayer/RasterLayerMenuItemsConvertRasterToControl'; import { memo } from 'react'; @@ -17,6 +19,8 @@ export const RasterLayerMenuItems = memo(() => { + + ); diff --git a/invokeai/frontend/web/src/features/controlLayers/components/RegionalGuidance/RegionalGuidanceMenuItems.tsx b/invokeai/frontend/web/src/features/controlLayers/components/RegionalGuidance/RegionalGuidanceMenuItems.tsx index ac21fd6357..e89a41fa80 100644 --- a/invokeai/frontend/web/src/features/controlLayers/components/RegionalGuidance/RegionalGuidanceMenuItems.tsx +++ b/invokeai/frontend/web/src/features/controlLayers/components/RegionalGuidance/RegionalGuidanceMenuItems.tsx @@ -1,7 +1,9 @@ import { MenuDivider } from '@invoke-ai/ui-library'; import { CanvasEntityMenuItemsArrange } from 'features/controlLayers/components/common/CanvasEntityMenuItemsArrange'; +import { CanvasEntityMenuItemsCopyToClipboard } from 'features/controlLayers/components/common/CanvasEntityMenuItemsCopyToClipboard'; import { CanvasEntityMenuItemsDelete } from 'features/controlLayers/components/common/CanvasEntityMenuItemsDelete'; import { CanvasEntityMenuItemsDuplicate } from 'features/controlLayers/components/common/CanvasEntityMenuItemsDuplicate'; +import { CanvasEntityMenuItemsSave } from 'features/controlLayers/components/common/CanvasEntityMenuItemsSave'; import { CanvasEntityMenuItemsTransform } from 'features/controlLayers/components/common/CanvasEntityMenuItemsTransform'; import { RegionalGuidanceMenuItemsAddPromptsAndIPAdapter } from 'features/controlLayers/components/RegionalGuidance/RegionalGuidanceMenuItemsAddPromptsAndIPAdapter'; import { RegionalGuidanceMenuItemsAutoNegative } from 'features/controlLayers/components/RegionalGuidance/RegionalGuidanceMenuItemsAutoNegative'; @@ -18,6 +20,8 @@ export const RegionalGuidanceMenuItems = memo(() => { + + ); diff --git a/invokeai/frontend/web/src/features/controlLayers/components/common/CanvasEntityCopyToClipboard.tsx b/invokeai/frontend/web/src/features/controlLayers/components/common/CanvasEntityCopyToClipboard.tsx deleted file mode 100644 index 1d4fc22fdd..0000000000 --- a/invokeai/frontend/web/src/features/controlLayers/components/common/CanvasEntityCopyToClipboard.tsx +++ /dev/null @@ -1,34 +0,0 @@ -import { IconButton } from '@invoke-ai/ui-library'; -import { useEntityAdapterSafe } from 'features/controlLayers/contexts/EntityAdapterContext'; -import { useEntityIdentifierContext } from 'features/controlLayers/contexts/EntityIdentifierContext'; -import { useCanvasIsBusy } from 'features/controlLayers/hooks/useCanvasIsBusy'; -import { useCopyLayerToClipboard } from 'features/controlLayers/hooks/useCopyLayerToClipboard'; -import { memo, useCallback } from 'react'; -import { useTranslation } from 'react-i18next'; -import { PiCopyBold } from 'react-icons/pi'; - -export const CanvasEntityCopyToClipboard = memo(() => { - const { t } = useTranslation(); - const entityIdentifier = useEntityIdentifierContext(); - const adapter = useEntityAdapterSafe(entityIdentifier); - const isBusy = useCanvasIsBusy(); - const copyLayerToClipboard = useCopyLayerToClipboard(); - const onClick = useCallback(() => { - copyLayerToClipboard(adapter); - }, [copyLayerToClipboard, adapter]); - - return ( - } - onClick={onClick} - isDisabled={isBusy} - /> - ); -}); - -CanvasEntityCopyToClipboard.displayName = 'CanvasEntityCopyToClipboard'; diff --git a/invokeai/frontend/web/src/features/controlLayers/components/common/CanvasEntityHeaderCommonActions.tsx b/invokeai/frontend/web/src/features/controlLayers/components/common/CanvasEntityHeaderCommonActions.tsx index b2f7643a8a..cc89cb02f6 100644 --- a/invokeai/frontend/web/src/features/controlLayers/components/common/CanvasEntityHeaderCommonActions.tsx +++ b/invokeai/frontend/web/src/features/controlLayers/components/common/CanvasEntityHeaderCommonActions.tsx @@ -6,16 +6,11 @@ import { CanvasEntityIsLockedToggle } from 'features/controlLayers/components/co import { useEntityIdentifierContext } from 'features/controlLayers/contexts/EntityIdentifierContext'; import { memo } from 'react'; -import { CanvasEntityCopyToClipboard } from './CanvasEntityCopyToClipboard'; -import { CanvasEntitySaveToAssets } from './CanvasEntitySaveToAssets'; - export const CanvasEntityHeaderCommonActions = memo(() => { const entityIdentifier = useEntityIdentifierContext(); return ( - - {entityIdentifier.type !== 'reference_image' && } diff --git a/invokeai/frontend/web/src/features/controlLayers/components/common/CanvasEntityMenuItemsCopy.tsx b/invokeai/frontend/web/src/features/controlLayers/components/common/CanvasEntityMenuItemsCopyToClipboard.tsx similarity index 87% rename from invokeai/frontend/web/src/features/controlLayers/components/common/CanvasEntityMenuItemsCopy.tsx rename to invokeai/frontend/web/src/features/controlLayers/components/common/CanvasEntityMenuItemsCopyToClipboard.tsx index 040c439d87..9d9882399b 100644 --- a/invokeai/frontend/web/src/features/controlLayers/components/common/CanvasEntityMenuItemsCopy.tsx +++ b/invokeai/frontend/web/src/features/controlLayers/components/common/CanvasEntityMenuItemsCopyToClipboard.tsx @@ -7,7 +7,7 @@ import { memo, useCallback } from 'react'; import { useTranslation } from 'react-i18next'; import { PiCopyBold } from 'react-icons/pi'; -export const CanvasEntityMenuItemsCopy = memo(() => { +export const CanvasEntityMenuItemsCopyToClipboard = memo(() => { const { t } = useTranslation(); const entityIdentifier = useEntityIdentifierContext(); const adapter = useEntityAdapterSafe(entityIdentifier); @@ -25,4 +25,4 @@ export const CanvasEntityMenuItemsCopy = memo(() => { ); }); -CanvasEntityMenuItemsCopy.displayName = 'CanvasEntityMenuItemsCopy'; +CanvasEntityMenuItemsCopyToClipboard.displayName = 'CanvasEntityMenuItemsCopyToClipboard'; diff --git a/invokeai/frontend/web/src/features/controlLayers/store/types.ts b/invokeai/frontend/web/src/features/controlLayers/store/types.ts index a6990a910a..b24788f3ea 100644 --- a/invokeai/frontend/web/src/features/controlLayers/store/types.ts +++ b/invokeai/frontend/web/src/features/controlLayers/store/types.ts @@ -384,6 +384,21 @@ export function isTransformableEntityIdentifier( ); } +export function isSaveableEntityIdentifier( + entityIdentifier: CanvasEntityIdentifier +): entityIdentifier is + | CanvasEntityIdentifier<'raster_layer'> + | CanvasEntityIdentifier<'control_layer'> + | CanvasEntityIdentifier<'inpaint_mask'> + | CanvasEntityIdentifier<'regional_guidance'> { + return ( + isRasterLayerEntityIdentifier(entityIdentifier) || + isControlLayerEntityIdentifier(entityIdentifier) || + isInpaintMaskEntityIdentifier(entityIdentifier) || + isRegionalGuidanceEntityIdentifier(entityIdentifier) + ); +} + export function isRenderableEntity(entity: CanvasEntityState): entity is CanvasRenderableEntityState { return isRenderableEntityType(entity.type); } From aa3ca7a63353f365bcc724029aeb0d4516349937 Mon Sep 17 00:00:00 2001 From: psychedelicious <4822129+psychedelicious@users.noreply.github.com> Date: Wed, 18 Sep 2024 10:32:38 +1000 Subject: [PATCH 6/6] tidy(ui): remove save & copy functions for mask entities Not 100% sure that the format these are in is correct just yet. Will restore once we support importing image masks. --- .../components/InpaintMask/InpaintMaskMenuItems.tsx | 4 ---- .../RegionalGuidance/RegionalGuidanceMenuItems.tsx | 4 ---- .../web/src/features/controlLayers/store/types.ts | 13 ++----------- 3 files changed, 2 insertions(+), 19 deletions(-) diff --git a/invokeai/frontend/web/src/features/controlLayers/components/InpaintMask/InpaintMaskMenuItems.tsx b/invokeai/frontend/web/src/features/controlLayers/components/InpaintMask/InpaintMaskMenuItems.tsx index a270d6c754..925ba30e35 100644 --- a/invokeai/frontend/web/src/features/controlLayers/components/InpaintMask/InpaintMaskMenuItems.tsx +++ b/invokeai/frontend/web/src/features/controlLayers/components/InpaintMask/InpaintMaskMenuItems.tsx @@ -1,9 +1,7 @@ import { MenuDivider } from '@invoke-ai/ui-library'; import { CanvasEntityMenuItemsArrange } from 'features/controlLayers/components/common/CanvasEntityMenuItemsArrange'; -import { CanvasEntityMenuItemsCopyToClipboard } from 'features/controlLayers/components/common/CanvasEntityMenuItemsCopyToClipboard'; import { CanvasEntityMenuItemsDelete } from 'features/controlLayers/components/common/CanvasEntityMenuItemsDelete'; import { CanvasEntityMenuItemsDuplicate } from 'features/controlLayers/components/common/CanvasEntityMenuItemsDuplicate'; -import { CanvasEntityMenuItemsSave } from 'features/controlLayers/components/common/CanvasEntityMenuItemsSave'; import { CanvasEntityMenuItemsTransform } from 'features/controlLayers/components/common/CanvasEntityMenuItemsTransform'; import { memo } from 'react'; @@ -15,8 +13,6 @@ export const InpaintMaskMenuItems = memo(() => { - - ); diff --git a/invokeai/frontend/web/src/features/controlLayers/components/RegionalGuidance/RegionalGuidanceMenuItems.tsx b/invokeai/frontend/web/src/features/controlLayers/components/RegionalGuidance/RegionalGuidanceMenuItems.tsx index e89a41fa80..ac21fd6357 100644 --- a/invokeai/frontend/web/src/features/controlLayers/components/RegionalGuidance/RegionalGuidanceMenuItems.tsx +++ b/invokeai/frontend/web/src/features/controlLayers/components/RegionalGuidance/RegionalGuidanceMenuItems.tsx @@ -1,9 +1,7 @@ import { MenuDivider } from '@invoke-ai/ui-library'; import { CanvasEntityMenuItemsArrange } from 'features/controlLayers/components/common/CanvasEntityMenuItemsArrange'; -import { CanvasEntityMenuItemsCopyToClipboard } from 'features/controlLayers/components/common/CanvasEntityMenuItemsCopyToClipboard'; import { CanvasEntityMenuItemsDelete } from 'features/controlLayers/components/common/CanvasEntityMenuItemsDelete'; import { CanvasEntityMenuItemsDuplicate } from 'features/controlLayers/components/common/CanvasEntityMenuItemsDuplicate'; -import { CanvasEntityMenuItemsSave } from 'features/controlLayers/components/common/CanvasEntityMenuItemsSave'; import { CanvasEntityMenuItemsTransform } from 'features/controlLayers/components/common/CanvasEntityMenuItemsTransform'; import { RegionalGuidanceMenuItemsAddPromptsAndIPAdapter } from 'features/controlLayers/components/RegionalGuidance/RegionalGuidanceMenuItemsAddPromptsAndIPAdapter'; import { RegionalGuidanceMenuItemsAutoNegative } from 'features/controlLayers/components/RegionalGuidance/RegionalGuidanceMenuItemsAutoNegative'; @@ -20,8 +18,6 @@ export const RegionalGuidanceMenuItems = memo(() => { - - ); diff --git a/invokeai/frontend/web/src/features/controlLayers/store/types.ts b/invokeai/frontend/web/src/features/controlLayers/store/types.ts index b24788f3ea..bdddaeecbb 100644 --- a/invokeai/frontend/web/src/features/controlLayers/store/types.ts +++ b/invokeai/frontend/web/src/features/controlLayers/store/types.ts @@ -386,17 +386,8 @@ export function isTransformableEntityIdentifier( export function isSaveableEntityIdentifier( entityIdentifier: CanvasEntityIdentifier -): entityIdentifier is - | CanvasEntityIdentifier<'raster_layer'> - | CanvasEntityIdentifier<'control_layer'> - | CanvasEntityIdentifier<'inpaint_mask'> - | CanvasEntityIdentifier<'regional_guidance'> { - return ( - isRasterLayerEntityIdentifier(entityIdentifier) || - isControlLayerEntityIdentifier(entityIdentifier) || - isInpaintMaskEntityIdentifier(entityIdentifier) || - isRegionalGuidanceEntityIdentifier(entityIdentifier) - ); +): entityIdentifier is CanvasEntityIdentifier<'raster_layer'> | CanvasEntityIdentifier<'control_layer'> { + return isRasterLayerEntityIdentifier(entityIdentifier) || isControlLayerEntityIdentifier(entityIdentifier); } export function isRenderableEntity(entity: CanvasEntityState): entity is CanvasRenderableEntityState {