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}
/>
);
});