mirror of
https://github.com/invoke-ai/InvokeAI.git
synced 2026-02-12 21:14:59 -05:00
feat(ui): simple session initial state
This commit is contained in:
@@ -1,6 +1,5 @@
|
||||
import { useAppSelector } from 'app/store/storeHooks';
|
||||
import { AdvancedSession } from 'features/controlLayers/components/AdvancedSession/AdvancedSession';
|
||||
import { NoSession } from 'features/controlLayers/components/NoSession/NoSession';
|
||||
import { SimpleSession } from 'features/controlLayers/components/SimpleSession/SimpleSession';
|
||||
import { selectCanvasSessionId, selectCanvasSessionType } from 'features/controlLayers/store/canvasStagingAreaSlice';
|
||||
import { memo } from 'react';
|
||||
@@ -12,11 +11,7 @@ export const CanvasMainPanelContent = memo(() => {
|
||||
const id = useAppSelector(selectCanvasSessionId);
|
||||
|
||||
if (type === 'simple') {
|
||||
if (id === null) {
|
||||
return <NoSession />;
|
||||
} else {
|
||||
return <SimpleSession id={id} />;
|
||||
}
|
||||
return <SimpleSession id={id} />;
|
||||
}
|
||||
|
||||
if (type === 'advanced') {
|
||||
|
||||
@@ -1,68 +0,0 @@
|
||||
/* eslint-disable i18next/no-literal-string */
|
||||
|
||||
import { Button, Flex, Text } from '@invoke-ai/ui-library';
|
||||
import { useAppStore } from 'app/store/nanostores/store';
|
||||
import { useImageUploadButton } from 'common/hooks/useImageUploadButton';
|
||||
import { newCanvasFromImageDndTarget } from 'features/dnd/dnd';
|
||||
import { DndDropTarget } from 'features/dnd/DndDropTarget';
|
||||
import { newCanvasFromImage } from 'features/imageActions/actions';
|
||||
import { memo, useMemo } from 'react';
|
||||
import { Trans } from 'react-i18next';
|
||||
import { PiUploadBold } from 'react-icons/pi';
|
||||
import type { ImageDTO } from 'services/api/types';
|
||||
import type { Param0 } from 'tsafe';
|
||||
|
||||
const generateWithControlImageDndTargetData = newCanvasFromImageDndTarget.getData({
|
||||
type: 'control_layer',
|
||||
withResize: true,
|
||||
});
|
||||
|
||||
export const GenerateWithControlImage = memo(() => {
|
||||
const { getState, dispatch } = useAppStore();
|
||||
const useImageUploadButtonOptions = useMemo<Param0<typeof useImageUploadButton>>(
|
||||
() => ({
|
||||
onUpload: (imageDTO: ImageDTO) => {
|
||||
newCanvasFromImage({ imageDTO, type: 'control_layer', withResize: true, getState, dispatch });
|
||||
},
|
||||
allowMultiple: false,
|
||||
}),
|
||||
[dispatch, getState]
|
||||
);
|
||||
const uploadApi = useImageUploadButton(useImageUploadButtonOptions);
|
||||
const components = useMemo(
|
||||
() => ({
|
||||
UploadButton: (
|
||||
<Button
|
||||
size="sm"
|
||||
variant="link"
|
||||
color="base.300"
|
||||
{...uploadApi.getUploadButtonProps()}
|
||||
rightIcon={<PiUploadBold />}
|
||||
/>
|
||||
),
|
||||
}),
|
||||
[uploadApi]
|
||||
);
|
||||
|
||||
return (
|
||||
<Flex position="relative" flexDir="column">
|
||||
<Text fontSize="lg" fontWeight="semibold">
|
||||
Generate with a Control Image
|
||||
</Text>
|
||||
<Text color="base.300">
|
||||
Generate a new image using the control image to guide the structure and composition (Text to Image with
|
||||
Control).
|
||||
</Text>
|
||||
<Text color="base.300">
|
||||
<Trans i18nKey="controlLayers.uploadOrDragAnImage" components={components} />
|
||||
<input {...uploadApi.getUploadInputProps()} />
|
||||
</Text>
|
||||
<DndDropTarget
|
||||
dndTarget={newCanvasFromImageDndTarget}
|
||||
dndTargetData={generateWithControlImageDndTargetData}
|
||||
label="Drop"
|
||||
/>
|
||||
</Flex>
|
||||
);
|
||||
});
|
||||
GenerateWithControlImage.displayName = 'GenerateWithControlImage';
|
||||
@@ -1,65 +0,0 @@
|
||||
/* eslint-disable i18next/no-literal-string */
|
||||
|
||||
import { Button, Flex, Text } from '@invoke-ai/ui-library';
|
||||
import { useAppStore } from 'app/store/nanostores/store';
|
||||
import { useImageUploadButton } from 'common/hooks/useImageUploadButton';
|
||||
import { newCanvasFromImageDndTarget } from 'features/dnd/dnd';
|
||||
import { DndDropTarget } from 'features/dnd/DndDropTarget';
|
||||
import { newCanvasFromImage } from 'features/imageActions/actions';
|
||||
import { memo, useMemo } from 'react';
|
||||
import { Trans } from 'react-i18next';
|
||||
import { PiUploadBold } from 'react-icons/pi';
|
||||
import type { ImageDTO } from 'services/api/types';
|
||||
import type { Param0 } from 'tsafe';
|
||||
|
||||
const generateWithStartingImageDndTargetData = newCanvasFromImageDndTarget.getData({
|
||||
type: 'raster_layer',
|
||||
withResize: true,
|
||||
});
|
||||
|
||||
export const GenerateWithStartingImage = memo(() => {
|
||||
const { getState, dispatch } = useAppStore();
|
||||
const useImageUploadButtonOptions = useMemo<Param0<typeof useImageUploadButton>>(
|
||||
() => ({
|
||||
onUpload: (imageDTO: ImageDTO) => {
|
||||
newCanvasFromImage({ imageDTO, type: 'raster_layer', withResize: true, getState, dispatch });
|
||||
},
|
||||
allowMultiple: false,
|
||||
}),
|
||||
[dispatch, getState]
|
||||
);
|
||||
const uploadApi = useImageUploadButton(useImageUploadButtonOptions);
|
||||
const components = useMemo(
|
||||
() => ({
|
||||
UploadButton: (
|
||||
<Button
|
||||
size="sm"
|
||||
variant="link"
|
||||
color="base.300"
|
||||
{...uploadApi.getUploadButtonProps()}
|
||||
rightIcon={<PiUploadBold />}
|
||||
/>
|
||||
),
|
||||
}),
|
||||
[uploadApi]
|
||||
);
|
||||
|
||||
return (
|
||||
<Flex position="relative" flexDir="column">
|
||||
<Text fontSize="lg" fontWeight="semibold">
|
||||
Generate with a Starting Image
|
||||
</Text>
|
||||
<Text color="base.300">Regenerate the starting image using the model (Image to Image).</Text>
|
||||
<Text color="base.300">
|
||||
<Trans i18nKey="controlLayers.uploadOrDragAnImage" components={components} />
|
||||
<input {...uploadApi.getUploadInputProps()} />
|
||||
</Text>
|
||||
<DndDropTarget
|
||||
dndTarget={newCanvasFromImageDndTarget}
|
||||
dndTargetData={generateWithStartingImageDndTargetData}
|
||||
label="Drop"
|
||||
/>
|
||||
</Flex>
|
||||
);
|
||||
});
|
||||
GenerateWithStartingImage.displayName = 'GenerateWithStartingImage';
|
||||
@@ -1,65 +0,0 @@
|
||||
/* eslint-disable i18next/no-literal-string */
|
||||
|
||||
import { Button, Flex, Text } from '@invoke-ai/ui-library';
|
||||
import { useAppStore } from 'app/store/nanostores/store';
|
||||
import { useImageUploadButton } from 'common/hooks/useImageUploadButton';
|
||||
import { newCanvasFromImageDndTarget } from 'features/dnd/dnd';
|
||||
import { DndDropTarget } from 'features/dnd/DndDropTarget';
|
||||
import { newCanvasFromImage } from 'features/imageActions/actions';
|
||||
import { memo, useMemo } from 'react';
|
||||
import { Trans } from 'react-i18next';
|
||||
import { PiUploadBold } from 'react-icons/pi';
|
||||
import type { ImageDTO } from 'services/api/types';
|
||||
import type { Param0 } from 'tsafe';
|
||||
|
||||
const generateWithStartingImageAndInpaintMaskDndTargetData = newCanvasFromImageDndTarget.getData({
|
||||
type: 'raster_layer',
|
||||
withInpaintMask: true,
|
||||
});
|
||||
|
||||
export const GenerateWithStartingImageAndInpaintMask = memo(() => {
|
||||
const { getState, dispatch } = useAppStore();
|
||||
const useImageUploadButtonOptions = useMemo<Param0<typeof useImageUploadButton>>(
|
||||
() => ({
|
||||
onUpload: (imageDTO: ImageDTO) => {
|
||||
newCanvasFromImage({ imageDTO, type: 'raster_layer', withInpaintMask: true, getState, dispatch });
|
||||
},
|
||||
allowMultiple: false,
|
||||
}),
|
||||
[dispatch, getState]
|
||||
);
|
||||
const uploadApi = useImageUploadButton(useImageUploadButtonOptions);
|
||||
const components = useMemo(
|
||||
() => ({
|
||||
UploadButton: (
|
||||
<Button
|
||||
size="sm"
|
||||
variant="link"
|
||||
color="base.300"
|
||||
{...uploadApi.getUploadButtonProps()}
|
||||
rightIcon={<PiUploadBold />}
|
||||
/>
|
||||
),
|
||||
}),
|
||||
[uploadApi]
|
||||
);
|
||||
|
||||
return (
|
||||
<Flex position="relative" flexDir="column">
|
||||
<Text fontSize="lg" fontWeight="semibold">
|
||||
Edit Image
|
||||
</Text>
|
||||
<Text color="base.300">Edit the image by regenerating parts of it (Inpaint).</Text>
|
||||
<Text color="base.300">
|
||||
<Trans i18nKey="controlLayers.uploadOrDragAnImage" components={components} />
|
||||
<input {...uploadApi.getUploadInputProps()} />
|
||||
</Text>
|
||||
<DndDropTarget
|
||||
dndTarget={newCanvasFromImageDndTarget}
|
||||
dndTargetData={generateWithStartingImageAndInpaintMaskDndTargetData}
|
||||
label="Drop"
|
||||
/>
|
||||
</Flex>
|
||||
);
|
||||
});
|
||||
GenerateWithStartingImageAndInpaintMask.displayName = 'GenerateWithStartingImageAndInpaintMask';
|
||||
@@ -1,32 +0,0 @@
|
||||
/* eslint-disable i18next/no-literal-string */
|
||||
|
||||
import { Button, Flex, Heading, Text } from '@invoke-ai/ui-library';
|
||||
import { useAppDispatch } from 'app/store/storeHooks';
|
||||
import { GenerateWithControlImage } from 'features/controlLayers/components/NoSession/GenerateWithControlImage';
|
||||
import { GenerateWithStartingImage } from 'features/controlLayers/components/NoSession/GenerateWithStartingImage';
|
||||
import { GenerateWithStartingImageAndInpaintMask } from 'features/controlLayers/components/NoSession/GenerateWithStartingImageAndInpaintMask';
|
||||
import { canvasSessionTypeChanged } from 'features/controlLayers/store/canvasStagingAreaSlice';
|
||||
import { memo, useCallback } from 'react';
|
||||
|
||||
export const NoSession = memo(() => {
|
||||
const dispatch = useAppDispatch();
|
||||
const newSesh = useCallback(() => {
|
||||
dispatch(canvasSessionTypeChanged({ type: 'advanced' }));
|
||||
}, [dispatch]);
|
||||
|
||||
return (
|
||||
<Flex flexDir="column" w="full" h="full" alignItems="center" justifyContent="center">
|
||||
<Heading>Get Started with Invoke</Heading>
|
||||
<Button variant="ghost" onClick={newSesh}>
|
||||
Start a new Canvas Session
|
||||
</Button>
|
||||
<Text>or</Text>
|
||||
<Flex flexDir="column" maxW={512}>
|
||||
<GenerateWithStartingImage />
|
||||
<GenerateWithControlImage />
|
||||
<GenerateWithStartingImageAndInpaintMask />
|
||||
</Flex>
|
||||
</Flex>
|
||||
);
|
||||
});
|
||||
NoSession.displayName = 'NoSession';
|
||||
@@ -0,0 +1,50 @@
|
||||
/* eslint-disable i18next/no-literal-string */
|
||||
|
||||
import { Button, Flex, Grid, Heading, Text } from '@invoke-ai/ui-library';
|
||||
import { useAppDispatch } from 'app/store/storeHooks';
|
||||
import { InitialStateAddAStyleReference } from 'features/controlLayers/components/SimpleSession/InitialStateAddAStyleReference';
|
||||
import { InitialStateCardGridItem } from 'features/controlLayers/components/SimpleSession/InitialStateCardGridItem';
|
||||
import { InitialStateEditImageCard } from 'features/controlLayers/components/SimpleSession/InitialStateEditImageCard';
|
||||
import { InitialStateGenerateFromText } from 'features/controlLayers/components/SimpleSession/InitialStateGenerateFromText';
|
||||
import { InitialStateUseALayoutImageCard } from 'features/controlLayers/components/SimpleSession/InitialStateUseALayoutImageCard';
|
||||
import { canvasSessionTypeChanged } from 'features/controlLayers/store/canvasStagingAreaSlice';
|
||||
import { memo, useCallback } from 'react';
|
||||
|
||||
export const InitialState = memo(() => {
|
||||
const dispatch = useAppDispatch();
|
||||
const newCanvasSession = useCallback(() => {
|
||||
dispatch(canvasSessionTypeChanged({ type: 'advanced' }));
|
||||
}, [dispatch]);
|
||||
|
||||
return (
|
||||
<Flex flexDir="column" h="full" justifyContent="center" mx={16}>
|
||||
<Heading mb={4}>Choose a starting method.</Heading>
|
||||
<Text fontSize="md" fontStyle="italic" mb={6}>
|
||||
Drag an image onto a card or click the upload icon.
|
||||
</Text>
|
||||
|
||||
<Grid gridTemplateColumns="1fr 1fr" gridTemplateRows="1fr 1fr" gap={4}>
|
||||
<InitialStateCardGridItem>
|
||||
<InitialStateGenerateFromText />
|
||||
</InitialStateCardGridItem>
|
||||
<InitialStateCardGridItem>
|
||||
<InitialStateAddAStyleReference />
|
||||
</InitialStateCardGridItem>
|
||||
<InitialStateCardGridItem>
|
||||
<InitialStateUseALayoutImageCard />
|
||||
</InitialStateCardGridItem>
|
||||
<InitialStateCardGridItem>
|
||||
<InitialStateEditImageCard />
|
||||
</InitialStateCardGridItem>
|
||||
</Grid>
|
||||
|
||||
<Text fontSize="md" color="base.300" alignSelf="center" mt={6}>
|
||||
or{' '}
|
||||
<Button variant="link" onClick={newCanvasSession}>
|
||||
start from a blank canvas.
|
||||
</Button>
|
||||
</Text>
|
||||
</Flex>
|
||||
);
|
||||
});
|
||||
InitialState.displayName = 'InitialState';
|
||||
@@ -0,0 +1,39 @@
|
||||
/* eslint-disable i18next/no-literal-string */
|
||||
|
||||
import { Flex, Heading, Icon, Text } from '@invoke-ai/ui-library';
|
||||
import { useAppStore } from 'app/store/nanostores/store';
|
||||
import { UploadImageIconButton } from 'common/hooks/useImageUploadButton';
|
||||
import { newCanvasFromImageDndTarget } from 'features/dnd/dnd';
|
||||
import { DndDropTarget } from 'features/dnd/DndDropTarget';
|
||||
import { newCanvasFromImage } from 'features/imageActions/actions';
|
||||
import { memo, useCallback } from 'react';
|
||||
import { PiUserCircleGearBold } from 'react-icons/pi';
|
||||
import type { ImageDTO } from 'services/api/types';
|
||||
|
||||
const NEW_CANVAS_OPTIONS = { type: 'reference_image' } as const;
|
||||
|
||||
const dndTargetData = newCanvasFromImageDndTarget.getData(NEW_CANVAS_OPTIONS);
|
||||
|
||||
export const InitialStateAddAStyleReference = memo(() => {
|
||||
const { getState, dispatch } = useAppStore();
|
||||
|
||||
const onUpload = useCallback(
|
||||
(imageDTO: ImageDTO) => {
|
||||
newCanvasFromImage({ imageDTO, getState, dispatch, ...NEW_CANVAS_OPTIONS });
|
||||
},
|
||||
[dispatch, getState]
|
||||
);
|
||||
|
||||
return (
|
||||
<>
|
||||
<Icon as={PiUserCircleGearBold} boxSize={8} color="base.500" />
|
||||
<Heading size="sm">Add a Style Reference</Heading>
|
||||
<Text color="base.300">Add an image to transfer its look.</Text>
|
||||
<Flex w="full" justifyContent="flex-end">
|
||||
<UploadImageIconButton onUpload={onUpload} variant="link" h={8} />
|
||||
</Flex>
|
||||
<DndDropTarget dndTarget={newCanvasFromImageDndTarget} dndTargetData={dndTargetData} label="Drop" />
|
||||
</>
|
||||
);
|
||||
});
|
||||
InitialStateAddAStyleReference.displayName = 'InitialStateAddAStyleReference';
|
||||
@@ -0,0 +1,24 @@
|
||||
import { GridItem } from '@invoke-ai/ui-library';
|
||||
import { memo, type PropsWithChildren } from 'react';
|
||||
|
||||
export const InitialStateCardGridItem = memo((props: PropsWithChildren) => {
|
||||
return (
|
||||
<GridItem
|
||||
display="flex"
|
||||
position="relative"
|
||||
flexDir="column"
|
||||
alignItems="center"
|
||||
borderWidth={1}
|
||||
borderRadius="base"
|
||||
p={2}
|
||||
pt={6}
|
||||
gap={2}
|
||||
w="full"
|
||||
h="full"
|
||||
>
|
||||
{props.children}
|
||||
</GridItem>
|
||||
);
|
||||
});
|
||||
|
||||
InitialStateCardGridItem.displayName = 'InitialStateCardGridItem';
|
||||
@@ -0,0 +1,39 @@
|
||||
/* eslint-disable i18next/no-literal-string */
|
||||
|
||||
import { Flex, Heading, Icon, Text } from '@invoke-ai/ui-library';
|
||||
import { useAppStore } from 'app/store/nanostores/store';
|
||||
import { UploadImageIconButton } from 'common/hooks/useImageUploadButton';
|
||||
import { newCanvasFromImageDndTarget } from 'features/dnd/dnd';
|
||||
import { DndDropTarget } from 'features/dnd/DndDropTarget';
|
||||
import { newCanvasFromImage } from 'features/imageActions/actions';
|
||||
import { memo, useCallback } from 'react';
|
||||
import { PiPencilBold } from 'react-icons/pi';
|
||||
import type { ImageDTO } from 'services/api/types';
|
||||
|
||||
const NEW_CANVAS_OPTIONS = { type: 'raster_layer', withInpaintMask: true } as const;
|
||||
|
||||
const dndTargetData = newCanvasFromImageDndTarget.getData(NEW_CANVAS_OPTIONS);
|
||||
|
||||
export const InitialStateEditImageCard = memo(() => {
|
||||
const { getState, dispatch } = useAppStore();
|
||||
|
||||
const onUpload = useCallback(
|
||||
(imageDTO: ImageDTO) => {
|
||||
newCanvasFromImage({ imageDTO, getState, dispatch, ...NEW_CANVAS_OPTIONS });
|
||||
},
|
||||
[dispatch, getState]
|
||||
);
|
||||
|
||||
return (
|
||||
<>
|
||||
<Icon as={PiPencilBold} boxSize={8} color="base.500" />
|
||||
<Heading size="sm">Edit Image</Heading>
|
||||
<Text color="base.300">Add an image to refine.</Text>
|
||||
<Flex w="full" justifyContent="flex-end">
|
||||
<UploadImageIconButton onUpload={onUpload} variant="link" h={8} />
|
||||
</Flex>
|
||||
<DndDropTarget dndTarget={newCanvasFromImageDndTarget} dndTargetData={dndTargetData} label="Drop" />
|
||||
</>
|
||||
);
|
||||
});
|
||||
InitialStateEditImageCard.displayName = 'InitialStateEditImageCard';
|
||||
@@ -0,0 +1,33 @@
|
||||
/* eslint-disable i18next/no-literal-string */
|
||||
|
||||
import { Flex, Heading, Icon, IconButton, Text } from '@invoke-ai/ui-library';
|
||||
import { memo } from 'react';
|
||||
import { PiCursorTextBold, PiTextAaBold } from 'react-icons/pi';
|
||||
|
||||
const focusOnPrompt = () => {
|
||||
const promptElement = document.getElementById('prompt');
|
||||
if (promptElement instanceof HTMLTextAreaElement) {
|
||||
promptElement.focus();
|
||||
promptElement.select();
|
||||
}
|
||||
};
|
||||
|
||||
export const InitialStateGenerateFromText = memo(() => {
|
||||
return (
|
||||
<>
|
||||
<Icon as={PiTextAaBold} boxSize={8} color="base.500" />
|
||||
<Heading size="sm">Generate from Text</Heading>
|
||||
<Text color="base.300">Enter a prompt and Invoke.</Text>
|
||||
<Flex w="full" justifyContent="flex-end">
|
||||
<IconButton
|
||||
onClick={focusOnPrompt}
|
||||
aria-label="Focus on prompt"
|
||||
icon={<PiCursorTextBold />}
|
||||
variant="link"
|
||||
h={8}
|
||||
/>
|
||||
</Flex>
|
||||
</>
|
||||
);
|
||||
});
|
||||
InitialStateGenerateFromText.displayName = 'InitialStateGenerateFromText';
|
||||
@@ -0,0 +1,39 @@
|
||||
/* eslint-disable i18next/no-literal-string */
|
||||
|
||||
import { Flex, Heading, Icon, Text } from '@invoke-ai/ui-library';
|
||||
import { useAppStore } from 'app/store/nanostores/store';
|
||||
import { UploadImageIconButton } from 'common/hooks/useImageUploadButton';
|
||||
import { newCanvasFromImageDndTarget } from 'features/dnd/dnd';
|
||||
import { DndDropTarget } from 'features/dnd/DndDropTarget';
|
||||
import { newCanvasFromImage } from 'features/imageActions/actions';
|
||||
import { memo, useCallback } from 'react';
|
||||
import { PiRectangleDashedBold } from 'react-icons/pi';
|
||||
import type { ImageDTO } from 'services/api/types';
|
||||
|
||||
const NEW_CANVAS_OPTIONS = { type: 'control_layer', withResize: true } as const;
|
||||
|
||||
const dndTargetData = newCanvasFromImageDndTarget.getData(NEW_CANVAS_OPTIONS);
|
||||
|
||||
export const InitialStateUseALayoutImageCard = memo(() => {
|
||||
const { getState, dispatch } = useAppStore();
|
||||
|
||||
const onUpload = useCallback(
|
||||
(imageDTO: ImageDTO) => {
|
||||
newCanvasFromImage({ imageDTO, getState, dispatch, ...NEW_CANVAS_OPTIONS });
|
||||
},
|
||||
[dispatch, getState]
|
||||
);
|
||||
|
||||
return (
|
||||
<>
|
||||
<Icon as={PiRectangleDashedBold} boxSize={8} color="base.500" />
|
||||
<Heading size="sm">Use a Layout Image</Heading>
|
||||
<Text color="base.300">Add an image to control composition.</Text>
|
||||
<Flex w="full" justifyContent="flex-end">
|
||||
<UploadImageIconButton onUpload={onUpload} variant="link" h={8} />
|
||||
</Flex>
|
||||
<DndDropTarget dndTarget={newCanvasFromImageDndTarget} dndTargetData={dndTargetData} label="Drop" />
|
||||
</>
|
||||
);
|
||||
});
|
||||
InitialStateUseALayoutImageCard.displayName = 'InitialStateUseALayoutImageCard';
|
||||
@@ -1,8 +1,12 @@
|
||||
import { CanvasSessionContextProvider } from 'features/controlLayers/components/SimpleSession/context';
|
||||
import { InitialState } from 'features/controlLayers/components/SimpleSession/InitialState';
|
||||
import { StagingArea } from 'features/controlLayers/components/SimpleSession/StagingArea';
|
||||
import { memo } from 'react';
|
||||
|
||||
export const SimpleSession = memo(({ id }: { id: string }) => {
|
||||
export const SimpleSession = memo(({ id }: { id: string | null }) => {
|
||||
if (id === null) {
|
||||
return <InitialState />;
|
||||
}
|
||||
return (
|
||||
<CanvasSessionContextProvider type="simple" id={id}>
|
||||
<StagingArea />
|
||||
|
||||
@@ -0,0 +1,32 @@
|
||||
import type { ButtonProps } from '@invoke-ai/ui-library';
|
||||
import { Button } from '@invoke-ai/ui-library';
|
||||
import { useDeleteAllExceptCurrentQueueItemDialog } from 'features/queue/components/DeleteAllExceptCurrentQueueItemConfirmationAlertDialog';
|
||||
import { memo } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { PiXCircle } from 'react-icons/pi';
|
||||
|
||||
type Props = ButtonProps;
|
||||
|
||||
export const DeleteAllExceptCurrentButton = memo((props: Props) => {
|
||||
const { t } = useTranslation();
|
||||
const deleteAllExceptCurrent = useDeleteAllExceptCurrentQueueItemDialog();
|
||||
|
||||
return (
|
||||
<>
|
||||
<Button
|
||||
onClick={deleteAllExceptCurrent.openDialog}
|
||||
isLoading={deleteAllExceptCurrent.isLoading}
|
||||
isDisabled={deleteAllExceptCurrent.isDisabled}
|
||||
tooltip={t('queue.cancelAllExceptCurrentTooltip')}
|
||||
leftIcon={<PiXCircle />}
|
||||
colorScheme="error"
|
||||
data-testid={t('queue.clear')}
|
||||
{...props}
|
||||
>
|
||||
{t('queue.clear')}
|
||||
</Button>
|
||||
</>
|
||||
);
|
||||
});
|
||||
|
||||
DeleteAllExceptCurrentButton.displayName = 'DeleteAllExceptCurrentButton';
|
||||
@@ -0,0 +1,25 @@
|
||||
import { IconButton } from '@invoke-ai/ui-library';
|
||||
import { useDeleteAllExceptCurrentQueueItemDialog } from 'features/queue/components/DeleteAllExceptCurrentQueueItemConfirmationAlertDialog';
|
||||
import { memo } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { PiXCircle } from 'react-icons/pi';
|
||||
|
||||
export const DeleteAllExceptCurrentIconButton = memo(() => {
|
||||
const { t } = useTranslation();
|
||||
const deleteAllExceptCurrent = useDeleteAllExceptCurrentQueueItemDialog();
|
||||
|
||||
return (
|
||||
<IconButton
|
||||
size="lg"
|
||||
isDisabled={deleteAllExceptCurrent.isDisabled}
|
||||
isLoading={deleteAllExceptCurrent.isLoading}
|
||||
aria-label={t('queue.clear')}
|
||||
tooltip={t('queue.cancelAllExceptCurrentTooltip')}
|
||||
icon={<PiXCircle />}
|
||||
colorScheme="error"
|
||||
onClick={deleteAllExceptCurrent.openDialog}
|
||||
/>
|
||||
);
|
||||
});
|
||||
|
||||
DeleteAllExceptCurrentIconButton.displayName = 'DeleteAllExceptCurrentIconButton';
|
||||
@@ -1,5 +1,5 @@
|
||||
import { Flex, Spacer, useShiftModifier } from '@invoke-ai/ui-library';
|
||||
import { DeleteAllExceptCurrentQueueItemConfirmationAlertDialog } from 'features/queue/components/DeleteAllExceptCurrentQueueItemConfirmationAlertDialog';
|
||||
import { DeleteAllExceptCurrentIconButton } from 'features/queue/components/DeleteAllExceptCurrentIconButton';
|
||||
import { DeleteCurrentQueueItemIconButton } from 'features/queue/components/DeleteCurrentQueueItemIconButton';
|
||||
import { QueueActionsMenuButton } from 'features/queue/components/QueueActionsMenuButton';
|
||||
import ProgressBar from 'features/system/components/ProgressBar';
|
||||
@@ -30,7 +30,7 @@ export const DeleteIconButton = memo(() => {
|
||||
return <DeleteCurrentQueueItemIconButton />;
|
||||
}
|
||||
|
||||
return <DeleteAllExceptCurrentQueueItemConfirmationAlertDialog />;
|
||||
return <DeleteAllExceptCurrentIconButton />;
|
||||
});
|
||||
|
||||
DeleteIconButton.displayName = 'DeleteIconButton';
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
/* eslint-disable i18next/no-literal-string */
|
||||
import { ButtonGroup, Flex } from '@invoke-ai/ui-library';
|
||||
import { DeleteAllExceptCurrentQueueItemConfirmationAlertDialog } from 'features/queue/components/DeleteAllExceptCurrentQueueItemConfirmationAlertDialog';
|
||||
import { DeleteAllExceptCurrentButton } from 'features/queue/components/DeleteAllExceptCurrentButton';
|
||||
import { useFeatureStatus } from 'features/system/hooks/useFeatureStatus';
|
||||
import { memo } from 'react';
|
||||
|
||||
@@ -24,7 +23,7 @@ const QueueTabQueueControls = () => {
|
||||
)}
|
||||
<ButtonGroup w={28} orientation="vertical" size="sm">
|
||||
<PruneQueueButton />
|
||||
<DeleteAllExceptCurrentQueueItemConfirmationAlertDialog />
|
||||
<DeleteAllExceptCurrentButton />
|
||||
</ButtonGroup>
|
||||
</Flex>
|
||||
<ClearModelCacheButton />
|
||||
|
||||
Reference in New Issue
Block a user