From bf5ed61b84f4cfd8b898474be9d3a74e62f6389e Mon Sep 17 00:00:00 2001 From: psychedelicious <4822129+psychedelicious@users.noreply.github.com> Date: Thu, 5 Jun 2025 19:58:50 +1000 Subject: [PATCH] feat(ui): add staging area toolbar to simple session --- .../SimpleSession/StagingAreaContent.tsx | 4 +++ .../StagingArea/SimpleStagingAreaToolbar.tsx | 25 +++++++++++++++++++ .../StagingArea/StagingAreaToolbar.tsx | 13 +++++++--- .../StagingAreaToolbarDiscardAllButton.tsx | 8 ++---- ...tagingAreaToolbarDiscardSelectedButton.tsx | 7 ++---- .../StagingAreaToolbarNextButton.tsx | 11 +++----- .../StagingAreaToolbarPrevButton.tsx | 11 +++----- 7 files changed, 50 insertions(+), 29 deletions(-) create mode 100644 invokeai/frontend/web/src/features/controlLayers/components/StagingArea/SimpleStagingAreaToolbar.tsx diff --git a/invokeai/frontend/web/src/features/controlLayers/components/SimpleSession/StagingAreaContent.tsx b/invokeai/frontend/web/src/features/controlLayers/components/SimpleSession/StagingAreaContent.tsx index 0f60379962..0e5c230204 100644 --- a/invokeai/frontend/web/src/features/controlLayers/components/SimpleSession/StagingAreaContent.tsx +++ b/invokeai/frontend/web/src/features/controlLayers/components/SimpleSession/StagingAreaContent.tsx @@ -2,6 +2,7 @@ import { Divider, Flex } from '@invoke-ai/ui-library'; import { StagingAreaItemsList } from 'features/controlLayers/components/SimpleSession/StagingAreaItemsList'; import { StagingAreaSelectedItem } from 'features/controlLayers/components/SimpleSession/StagingAreaSelectedItem'; +import { SimpleStagingAreaToolbar } from 'features/controlLayers/components/StagingArea/SimpleStagingAreaToolbar'; import { memo } from 'react'; export const StagingAreaContent = memo(() => { @@ -14,6 +15,9 @@ export const StagingAreaContent = memo(() => { + + + ); }); diff --git a/invokeai/frontend/web/src/features/controlLayers/components/StagingArea/SimpleStagingAreaToolbar.tsx b/invokeai/frontend/web/src/features/controlLayers/components/StagingArea/SimpleStagingAreaToolbar.tsx new file mode 100644 index 0000000000..26511981f3 --- /dev/null +++ b/invokeai/frontend/web/src/features/controlLayers/components/StagingArea/SimpleStagingAreaToolbar.tsx @@ -0,0 +1,25 @@ +import { ButtonGroup } from '@invoke-ai/ui-library'; +import { StagingAreaToolbarDiscardAllButton } from 'features/controlLayers/components/StagingArea/StagingAreaToolbarDiscardAllButton'; +import { StagingAreaToolbarDiscardSelectedButton } from 'features/controlLayers/components/StagingArea/StagingAreaToolbarDiscardSelectedButton'; +import { StagingAreaToolbarImageCountButton } from 'features/controlLayers/components/StagingArea/StagingAreaToolbarImageCountButton'; +import { StagingAreaToolbarNextButton } from 'features/controlLayers/components/StagingArea/StagingAreaToolbarNextButton'; +import { StagingAreaToolbarPrevButton } from 'features/controlLayers/components/StagingArea/StagingAreaToolbarPrevButton'; +import { memo } from 'react'; + +export const SimpleStagingAreaToolbar = memo(() => { + return ( + <> + + + + + + + + + + + ); +}); + +SimpleStagingAreaToolbar.displayName = 'SimpleStagingAreaToolbar'; diff --git a/invokeai/frontend/web/src/features/controlLayers/components/StagingArea/StagingAreaToolbar.tsx b/invokeai/frontend/web/src/features/controlLayers/components/StagingArea/StagingAreaToolbar.tsx index 4ac13e74a3..63926e766d 100644 --- a/invokeai/frontend/web/src/features/controlLayers/components/StagingArea/StagingAreaToolbar.tsx +++ b/invokeai/frontend/web/src/features/controlLayers/components/StagingArea/StagingAreaToolbar.tsx @@ -1,4 +1,5 @@ import { ButtonGroup } from '@invoke-ai/ui-library'; +import { useStore } from '@nanostores/react'; import { useCanvasSessionContext } from 'features/controlLayers/components/SimpleSession/context'; import { getQueueItemElementId } from 'features/controlLayers/components/SimpleSession/shared'; import { StagingAreaToolbarAcceptButton } from 'features/controlLayers/components/StagingArea/StagingAreaToolbarAcceptButton'; @@ -10,10 +11,14 @@ import { StagingAreaToolbarPrevButton } from 'features/controlLayers/components/ import { StagingAreaToolbarSaveAsMenu } from 'features/controlLayers/components/StagingArea/StagingAreaToolbarSaveAsMenu'; import { StagingAreaToolbarSaveSelectedToGalleryButton } from 'features/controlLayers/components/StagingArea/StagingAreaToolbarSaveSelectedToGalleryButton'; import { StagingAreaToolbarToggleShowResultsButton } from 'features/controlLayers/components/StagingArea/StagingAreaToolbarToggleShowResultsButton'; +import { useCanvasManager } from 'features/controlLayers/contexts/CanvasManagerProviderGate'; import { memo, useEffect } from 'react'; import { useHotkeys } from 'react-hotkeys-hook'; export const StagingAreaToolbar = memo(() => { + const canvasManager = useCanvasManager(); + const shouldShowStagedImage = useStore(canvasManager.stagingArea.$shouldShowStagedImage); + const ctx = useCanvasSessionContext(); useEffect(() => { @@ -29,17 +34,17 @@ export const StagingAreaToolbar = memo(() => { return ( <> - + - + - - + + ); diff --git a/invokeai/frontend/web/src/features/controlLayers/components/StagingArea/StagingAreaToolbarDiscardAllButton.tsx b/invokeai/frontend/web/src/features/controlLayers/components/StagingArea/StagingAreaToolbarDiscardAllButton.tsx index 99514b2b96..d3cc4b20e4 100644 --- a/invokeai/frontend/web/src/features/controlLayers/components/StagingArea/StagingAreaToolbarDiscardAllButton.tsx +++ b/invokeai/frontend/web/src/features/controlLayers/components/StagingArea/StagingAreaToolbarDiscardAllButton.tsx @@ -1,21 +1,17 @@ import { IconButton } from '@invoke-ai/ui-library'; -import { useStore } from '@nanostores/react'; import { useAppDispatch } from 'app/store/storeHooks'; import { useCanvasSessionContext } from 'features/controlLayers/components/SimpleSession/context'; -import { useCanvasManager } from 'features/controlLayers/contexts/CanvasManagerProviderGate'; import { canvasSessionGenerationFinished } from 'features/controlLayers/store/canvasStagingAreaSlice'; import { memo, useCallback } from 'react'; import { useTranslation } from 'react-i18next'; import { PiTrashSimpleBold } from 'react-icons/pi'; import { useDeleteQueueItemsByDestinationMutation } from 'services/api/endpoints/queue'; -export const StagingAreaToolbarDiscardAllButton = memo(() => { - const canvasManager = useCanvasManager(); +export const StagingAreaToolbarDiscardAllButton = memo(({ isDisabled }: { isDisabled?: boolean }) => { const ctx = useCanvasSessionContext(); const dispatch = useAppDispatch(); const { t } = useTranslation(); const [deleteByDestination] = useDeleteQueueItemsByDestinationMutation(); - const shouldShowStagedImage = useStore(canvasManager.stagingArea.$shouldShowStagedImage); const discardAll = useCallback(() => { deleteByDestination({ destination: ctx.session.id }); @@ -30,7 +26,7 @@ export const StagingAreaToolbarDiscardAllButton = memo(() => { onClick={discardAll} colorScheme="error" fontSize={16} - isDisabled={!shouldShowStagedImage} + isDisabled={isDisabled} /> ); }); diff --git a/invokeai/frontend/web/src/features/controlLayers/components/StagingArea/StagingAreaToolbarDiscardSelectedButton.tsx b/invokeai/frontend/web/src/features/controlLayers/components/StagingArea/StagingAreaToolbarDiscardSelectedButton.tsx index f6608672b5..7006a30aa3 100644 --- a/invokeai/frontend/web/src/features/controlLayers/components/StagingArea/StagingAreaToolbarDiscardSelectedButton.tsx +++ b/invokeai/frontend/web/src/features/controlLayers/components/StagingArea/StagingAreaToolbarDiscardSelectedButton.tsx @@ -1,18 +1,15 @@ import { IconButton } from '@invoke-ai/ui-library'; import { useStore } from '@nanostores/react'; import { useCanvasSessionContext } from 'features/controlLayers/components/SimpleSession/context'; -import { useCanvasManager } from 'features/controlLayers/contexts/CanvasManagerProviderGate'; import { memo, useCallback } from 'react'; import { useTranslation } from 'react-i18next'; import { PiXBold } from 'react-icons/pi'; import { useDeleteQueueItemMutation } from 'services/api/endpoints/queue'; -export const StagingAreaToolbarDiscardSelectedButton = memo(() => { - const canvasManager = useCanvasManager(); +export const StagingAreaToolbarDiscardSelectedButton = memo(({ isDisabled }: { isDisabled?: boolean }) => { const ctx = useCanvasSessionContext(); const [deleteQueueItem] = useDeleteQueueItemMutation(); const selectedItemId = useStore(ctx.$selectedItemId); - const shouldShowStagedImage = useStore(canvasManager.stagingArea.$shouldShowStagedImage); const { t } = useTranslation(); @@ -31,7 +28,7 @@ export const StagingAreaToolbarDiscardSelectedButton = memo(() => { onClick={discardSelected} colorScheme="invokeBlue" fontSize={16} - isDisabled={selectedItemId === null || !shouldShowStagedImage} + isDisabled={selectedItemId === null || isDisabled} /> ); }); diff --git a/invokeai/frontend/web/src/features/controlLayers/components/StagingArea/StagingAreaToolbarNextButton.tsx b/invokeai/frontend/web/src/features/controlLayers/components/StagingArea/StagingAreaToolbarNextButton.tsx index 0a5b5e50de..91eec2f6de 100644 --- a/invokeai/frontend/web/src/features/controlLayers/components/StagingArea/StagingAreaToolbarNextButton.tsx +++ b/invokeai/frontend/web/src/features/controlLayers/components/StagingArea/StagingAreaToolbarNextButton.tsx @@ -2,17 +2,14 @@ import { IconButton } from '@invoke-ai/ui-library'; import { useStore } from '@nanostores/react'; import { useIsRegionFocused } from 'common/hooks/focus'; import { useCanvasSessionContext } from 'features/controlLayers/components/SimpleSession/context'; -import { useCanvasManager } from 'features/controlLayers/contexts/CanvasManagerProviderGate'; import { memo, useCallback } from 'react'; import { useHotkeys } from 'react-hotkeys-hook'; import { useTranslation } from 'react-i18next'; import { PiArrowRightBold } from 'react-icons/pi'; -export const StagingAreaToolbarNextButton = memo(() => { +export const StagingAreaToolbarNextButton = memo(({ isDisabled }: { isDisabled?: boolean }) => { const ctx = useCanvasSessionContext(); const itemCount = useStore(ctx.$itemCount); - const canvasManager = useCanvasManager(); - const shouldShowStagedImage = useStore(canvasManager.stagingArea.$shouldShowStagedImage); const isCanvasFocused = useIsRegionFocused('canvas'); const { t } = useTranslation(); @@ -26,9 +23,9 @@ export const StagingAreaToolbarNextButton = memo(() => { ctx.selectNext, { preventDefault: true, - enabled: isCanvasFocused && shouldShowStagedImage && itemCount > 1, + enabled: isCanvasFocused && !isDisabled && itemCount > 1, }, - [isCanvasFocused, shouldShowStagedImage, itemCount, ctx.selectNext] + [isCanvasFocused, isDisabled, itemCount, ctx.selectNext] ); return ( @@ -38,7 +35,7 @@ export const StagingAreaToolbarNextButton = memo(() => { icon={} onClick={selectNext} colorScheme="invokeBlue" - isDisabled={itemCount <= 1 || !shouldShowStagedImage} + isDisabled={itemCount <= 1 || isDisabled} /> ); }); diff --git a/invokeai/frontend/web/src/features/controlLayers/components/StagingArea/StagingAreaToolbarPrevButton.tsx b/invokeai/frontend/web/src/features/controlLayers/components/StagingArea/StagingAreaToolbarPrevButton.tsx index 430fdf9629..cbed5ab675 100644 --- a/invokeai/frontend/web/src/features/controlLayers/components/StagingArea/StagingAreaToolbarPrevButton.tsx +++ b/invokeai/frontend/web/src/features/controlLayers/components/StagingArea/StagingAreaToolbarPrevButton.tsx @@ -2,17 +2,14 @@ import { IconButton } from '@invoke-ai/ui-library'; import { useStore } from '@nanostores/react'; import { useIsRegionFocused } from 'common/hooks/focus'; import { useCanvasSessionContext } from 'features/controlLayers/components/SimpleSession/context'; -import { useCanvasManager } from 'features/controlLayers/contexts/CanvasManagerProviderGate'; import { memo, useCallback } from 'react'; import { useHotkeys } from 'react-hotkeys-hook'; import { useTranslation } from 'react-i18next'; import { PiArrowLeftBold } from 'react-icons/pi'; -export const StagingAreaToolbarPrevButton = memo(() => { +export const StagingAreaToolbarPrevButton = memo(({ isDisabled }: { isDisabled?: boolean }) => { const ctx = useCanvasSessionContext(); const itemCount = useStore(ctx.$itemCount); - const canvasManager = useCanvasManager(); - const shouldShowStagedImage = useStore(canvasManager.stagingArea.$shouldShowStagedImage); const isCanvasFocused = useIsRegionFocused('canvas'); const { t } = useTranslation(); @@ -26,9 +23,9 @@ export const StagingAreaToolbarPrevButton = memo(() => { ctx.selectPrev, { preventDefault: true, - enabled: isCanvasFocused && shouldShowStagedImage && itemCount > 1, + enabled: isCanvasFocused && !isDisabled && itemCount > 1, }, - [isCanvasFocused, shouldShowStagedImage, itemCount, ctx.selectPrev] + [isCanvasFocused, isDisabled, itemCount, ctx.selectPrev] ); return ( @@ -38,7 +35,7 @@ export const StagingAreaToolbarPrevButton = memo(() => { icon={} onClick={selectPrev} colorScheme="invokeBlue" - isDisabled={itemCount <= 1 || !shouldShowStagedImage} + isDisabled={itemCount <= 1 || isDisabled} /> ); });