feat(ui): add staging area toolbar to simple session

This commit is contained in:
psychedelicious
2025-06-05 19:58:50 +10:00
parent 3038a797a6
commit bf5ed61b84
7 changed files with 50 additions and 29 deletions

View File

@@ -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(() => {
<Flex position="relative" maxW="full" w="full" h={108} flexShrink={0}>
<StagingAreaItemsList />
</Flex>
<Flex gap={2} w="full" justifyContent="safe center">
<SimpleStagingAreaToolbar />
</Flex>
</>
);
});

View File

@@ -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 (
<>
<ButtonGroup borderRadius="base" shadow="dark-lg">
<StagingAreaToolbarPrevButton />
<StagingAreaToolbarImageCountButton />
<StagingAreaToolbarNextButton />
</ButtonGroup>
<ButtonGroup borderRadius="base" shadow="dark-lg">
<StagingAreaToolbarDiscardSelectedButton />
<StagingAreaToolbarDiscardAllButton />
</ButtonGroup>
</>
);
});
SimpleStagingAreaToolbar.displayName = 'SimpleStagingAreaToolbar';

View File

@@ -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 (
<>
<ButtonGroup borderRadius="base" shadow="dark-lg">
<StagingAreaToolbarPrevButton />
<StagingAreaToolbarPrevButton isDisabled={!shouldShowStagedImage} />
<StagingAreaToolbarImageCountButton />
<StagingAreaToolbarNextButton />
<StagingAreaToolbarNextButton isDisabled={!shouldShowStagedImage} />
</ButtonGroup>
<ButtonGroup borderRadius="base" shadow="dark-lg">
<StagingAreaToolbarAcceptButton />
<StagingAreaToolbarToggleShowResultsButton />
<StagingAreaToolbarSaveSelectedToGalleryButton />
<StagingAreaToolbarSaveAsMenu />
<StagingAreaToolbarDiscardSelectedButton />
<StagingAreaToolbarDiscardAllButton />
<StagingAreaToolbarDiscardSelectedButton isDisabled={!shouldShowStagedImage} />
<StagingAreaToolbarDiscardAllButton isDisabled={!shouldShowStagedImage} />
</ButtonGroup>
</>
);

View File

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

View File

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

View File

@@ -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={<PiArrowRightBold />}
onClick={selectNext}
colorScheme="invokeBlue"
isDisabled={itemCount <= 1 || !shouldShowStagedImage}
isDisabled={itemCount <= 1 || isDisabled}
/>
);
});

View File

@@ -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={<PiArrowLeftBold />}
onClick={selectPrev}
colorScheme="invokeBlue"
isDisabled={itemCount <= 1 || !shouldShowStagedImage}
isDisabled={itemCount <= 1 || isDisabled}
/>
);
});