From 2d922a0a65b203d4ae27c00ba4a5b14d32b9b702 Mon Sep 17 00:00:00 2001
From: psychedelicious <4822129+psychedelicious@users.noreply.github.com>
Date: Thu, 4 Jan 2024 19:32:33 +1100
Subject: [PATCH] feat(ui): restore floating options and gallery buttons
---
...x => CancelCurrentQueueItemIconButton.tsx} | 14 +--
.../queue/components/ClearQueueButton.tsx | 45 +++-----
.../ClearQueueConfirmationAlertDialog.tsx | 32 ++++++
.../queue/components/ClearQueueIconButton.tsx | 35 ++++++
.../queue/components/QueueControls.tsx | 4 +-
.../ui/components/FloatingGalleryButton.tsx | 37 +++---
.../FloatingParametersPanelButtons.tsx | 57 +++++-----
.../src/features/ui/components/InvokeTabs.tsx | 106 +++++++++---------
8 files changed, 187 insertions(+), 143 deletions(-)
rename invokeai/frontend/web/src/features/queue/components/{CancelCurrentQueueItemButton.tsx => CancelCurrentQueueItemIconButton.tsx} (69%)
create mode 100644 invokeai/frontend/web/src/features/queue/components/ClearQueueConfirmationAlertDialog.tsx
create mode 100644 invokeai/frontend/web/src/features/queue/components/ClearQueueIconButton.tsx
diff --git a/invokeai/frontend/web/src/features/queue/components/CancelCurrentQueueItemButton.tsx b/invokeai/frontend/web/src/features/queue/components/CancelCurrentQueueItemIconButton.tsx
similarity index 69%
rename from invokeai/frontend/web/src/features/queue/components/CancelCurrentQueueItemButton.tsx
rename to invokeai/frontend/web/src/features/queue/components/CancelCurrentQueueItemIconButton.tsx
index 7fc6d89ff3..c921ca7ee6 100644
--- a/invokeai/frontend/web/src/features/queue/components/CancelCurrentQueueItemButton.tsx
+++ b/invokeai/frontend/web/src/features/queue/components/CancelCurrentQueueItemIconButton.tsx
@@ -1,27 +1,23 @@
import type { ChakraProps } from '@chakra-ui/react';
+import { InvIconButton } from 'common/components/InvIconButton/InvIconButton';
import { useCancelCurrentQueueItem } from 'features/queue/hooks/useCancelCurrentQueueItem';
import { memo } from 'react';
import { useTranslation } from 'react-i18next';
import { FaTimes } from 'react-icons/fa';
-
-import QueueButton from './common/QueueButton';
-
type Props = {
- asIconButton?: boolean;
sx?: ChakraProps['sx'];
};
-const CancelCurrentQueueItemButton = ({ asIconButton, sx }: Props) => {
+const CancelCurrentQueueItemIconButton = ({ sx }: Props) => {
const { t } = useTranslation();
const { cancelQueueItem, isLoading, isDisabled } =
useCancelCurrentQueueItem();
return (
- }
onClick={cancelQueueItem}
@@ -31,4 +27,4 @@ const CancelCurrentQueueItemButton = ({ asIconButton, sx }: Props) => {
);
};
-export default memo(CancelCurrentQueueItemButton);
+export default memo(CancelCurrentQueueItemIconButton);
diff --git a/invokeai/frontend/web/src/features/queue/components/ClearQueueButton.tsx b/invokeai/frontend/web/src/features/queue/components/ClearQueueButton.tsx
index 6c606893e9..e277a45c01 100644
--- a/invokeai/frontend/web/src/features/queue/components/ClearQueueButton.tsx
+++ b/invokeai/frontend/web/src/features/queue/components/ClearQueueButton.tsx
@@ -1,47 +1,34 @@
-import { type ChakraProps, useDisclosure } from '@chakra-ui/react';
-import { InvConfirmationAlertDialog } from 'common/components/InvConfirmationAlertDialog/InvConfirmationAlertDialog';
-import { InvText } from 'common/components/InvText/wrapper';
+import { useDisclosure } from '@chakra-ui/react';
+import { InvButton } from 'common/components/InvButton/InvButton';
+import type { InvButtonProps } from 'common/components/InvButton/types';
+import ClearQueueConfirmationAlertDialog from 'features/queue/components/ClearQueueConfirmationAlertDialog';
import { useClearQueue } from 'features/queue/hooks/useClearQueue';
import { memo } from 'react';
import { useTranslation } from 'react-i18next';
import { FaTrash } from 'react-icons/fa';
-import QueueButton from './common/QueueButton';
+type Props = InvButtonProps;
-type Props = {
- asIconButton?: boolean;
- sx?: ChakraProps['sx'];
-};
-
-const ClearQueueButton = ({ asIconButton, sx }: Props) => {
+const ClearQueueButton = (props: Props) => {
const { t } = useTranslation();
- const { isOpen, onClose, onOpen } = useDisclosure();
- const { clearQueue, isLoading, isDisabled } = useClearQueue();
+ const disclosure = useDisclosure();
+ const { isLoading, isDisabled } = useClearQueue();
return (
<>
- }
+ leftIcon={}
colorScheme="error"
- sx={sx}
- onClick={onOpen}
- />
-
- {t('queue.clearQueueAlertDialog')}
-
- {t('queue.clearQueueAlertDialog2')}
-
+ {t('queue.clear')}
+
+
>
);
};
diff --git a/invokeai/frontend/web/src/features/queue/components/ClearQueueConfirmationAlertDialog.tsx b/invokeai/frontend/web/src/features/queue/components/ClearQueueConfirmationAlertDialog.tsx
new file mode 100644
index 0000000000..abaa35276a
--- /dev/null
+++ b/invokeai/frontend/web/src/features/queue/components/ClearQueueConfirmationAlertDialog.tsx
@@ -0,0 +1,32 @@
+import type {
+ UseDisclosureReturn} from '@chakra-ui/react';
+import { InvConfirmationAlertDialog } from 'common/components/InvConfirmationAlertDialog/InvConfirmationAlertDialog';
+import { InvText } from 'common/components/InvText/wrapper';
+import { useClearQueue } from 'features/queue/hooks/useClearQueue';
+import { memo } from 'react';
+import { useTranslation } from 'react-i18next';
+
+type Props = {
+ disclosure: UseDisclosureReturn;
+};
+
+const ClearQueueButton = ({ disclosure }: Props) => {
+ const { t } = useTranslation();
+ const { clearQueue } = useClearQueue();
+
+ return (
+
+ {t('queue.clearQueueAlertDialog')}
+
+ {t('queue.clearQueueAlertDialog2')}
+
+ );
+};
+
+export default memo(ClearQueueButton);
diff --git a/invokeai/frontend/web/src/features/queue/components/ClearQueueIconButton.tsx b/invokeai/frontend/web/src/features/queue/components/ClearQueueIconButton.tsx
new file mode 100644
index 0000000000..02e795a466
--- /dev/null
+++ b/invokeai/frontend/web/src/features/queue/components/ClearQueueIconButton.tsx
@@ -0,0 +1,35 @@
+import { useDisclosure } from '@chakra-ui/react';
+import { InvIconButton } from 'common/components/InvIconButton/InvIconButton';
+import type { InvIconButtonProps } from 'common/components/InvIconButton/types';
+import ClearQueueConfirmationAlertDialog from 'features/queue/components/ClearQueueConfirmationAlertDialog';
+import { useClearQueue } from 'features/queue/hooks/useClearQueue';
+import { memo } from 'react';
+import { useTranslation } from 'react-i18next';
+import { FaTrash } from 'react-icons/fa';
+
+type Props = Omit;
+
+const ClearQueueIconButton = (props: Props) => {
+ const { t } = useTranslation();
+ const disclosure = useDisclosure();
+ const { isLoading, isDisabled } = useClearQueue();
+
+ return (
+ <>
+ }
+ colorScheme="error"
+ onClick={disclosure.onOpen}
+ data-testid={t('queue.clear')}
+ {...props}
+ />
+
+ >
+ );
+};
+
+export default memo(ClearQueueIconButton);
diff --git a/invokeai/frontend/web/src/features/queue/components/QueueControls.tsx b/invokeai/frontend/web/src/features/queue/components/QueueControls.tsx
index 61dd0f5473..0d0e707941 100644
--- a/invokeai/frontend/web/src/features/queue/components/QueueControls.tsx
+++ b/invokeai/frontend/web/src/features/queue/components/QueueControls.tsx
@@ -1,6 +1,6 @@
import { Flex, Spacer } from '@chakra-ui/react';
import { InvButtonGroup } from 'common/components/InvButtonGroup/InvButtonGroup';
-import ClearQueueButton from 'features/queue/components/ClearQueueButton';
+import ClearQueueIconButton from 'features/queue/components/ClearQueueIconButton';
import QueueFrontButton from 'features/queue/components/QueueFrontButton';
import ProgressBar from 'features/system/components/ProgressBar';
import { useFeatureStatus } from 'features/system/hooks/useFeatureStatus';
@@ -28,7 +28,7 @@ const QueueControls = () => {
{/*
{isResumeEnabled && }
{isPauseEnabled && } */}
-
+
diff --git a/invokeai/frontend/web/src/features/ui/components/FloatingGalleryButton.tsx b/invokeai/frontend/web/src/features/ui/components/FloatingGalleryButton.tsx
index df8087a498..fb5cbebbfb 100644
--- a/invokeai/frontend/web/src/features/ui/components/FloatingGalleryButton.tsx
+++ b/invokeai/frontend/web/src/features/ui/components/FloatingGalleryButton.tsx
@@ -1,22 +1,20 @@
import { Flex } from '@chakra-ui/layout';
import { Portal } from '@chakra-ui/portal';
import { InvIconButton } from 'common/components/InvIconButton/InvIconButton';
+import { InvTooltip } from 'common/components/InvTooltip/InvTooltip';
+import type { UsePanelReturn } from 'features/ui/hooks/usePanel';
import { memo } from 'react';
import { useTranslation } from 'react-i18next';
import { MdPhotoLibrary } from 'react-icons/md';
type Props = {
- isGalleryCollapsed: boolean;
- expandGallery: () => void;
+ panelApi: UsePanelReturn;
};
-const FloatingGalleryButton = ({
- isGalleryCollapsed,
- expandGallery,
-}: Props) => {
+const FloatingGalleryButton = (props: Props) => {
const { t } = useTranslation();
- if (!isGalleryCollapsed) {
+ if (!props.panelApi.isCollapsed) {
return null;
}
@@ -27,18 +25,21 @@ const FloatingGalleryButton = ({
transform="translate(0, -50%)"
minW={8}
top="50%"
- insetInlineEnd="1.63rem"
+ insetInlineEnd={0}
>
- }
- p={0}
- px={3}
- h={48}
- borderEndRadius={0}
- />
+
+ }
+ p={0}
+ h={48}
+ borderEndRadius={0}
+ />
+
);
diff --git a/invokeai/frontend/web/src/features/ui/components/FloatingParametersPanelButtons.tsx b/invokeai/frontend/web/src/features/ui/components/FloatingParametersPanelButtons.tsx
index 8cd6611cd6..3b99918323 100644
--- a/invokeai/frontend/web/src/features/ui/components/FloatingParametersPanelButtons.tsx
+++ b/invokeai/frontend/web/src/features/ui/components/FloatingParametersPanelButtons.tsx
@@ -1,40 +1,45 @@
-import type { ChakraProps } from '@chakra-ui/react';
+import { SpinnerIcon } from '@chakra-ui/icons';
+import type { SystemStyleObject } from '@chakra-ui/react';
import { Flex, Portal } from '@chakra-ui/react';
import { InvButtonGroup } from 'common/components/InvButtonGroup/InvButtonGroup';
import { InvIconButton } from 'common/components/InvIconButton/InvIconButton';
-import CancelCurrentQueueItemButton from 'features/queue/components/CancelCurrentQueueItemButton';
-import ClearQueueButton from 'features/queue/components/ClearQueueButton';
+import CancelCurrentQueueItemIconButton from 'features/queue/components/CancelCurrentQueueItemIconButton';
+import ClearQueueIconButton from 'features/queue/components/ClearQueueIconButton';
import { QueueButtonTooltip } from 'features/queue/components/QueueButtonTooltip';
import { useQueueBack } from 'features/queue/hooks/useQueueBack';
-import type { RefObject } from 'react';
-import { memo, useCallback } from 'react';
+import type { UsePanelReturn } from 'features/ui/hooks/usePanel';
+import { memo, useMemo } from 'react';
import { useTranslation } from 'react-i18next';
import { FaSlidersH } from 'react-icons/fa';
import { IoSparkles } from 'react-icons/io5';
-import type { ImperativePanelHandle } from 'react-resizable-panels';
+import { useGetQueueStatusQuery } from 'services/api/endpoints/queue';
+import { spinAnimationSlow } from 'theme/animations';
-const floatingButtonStyles: ChakraProps['sx'] = {
+const floatingButtonStyles: SystemStyleObject = {
borderStartRadius: 0,
flexGrow: 1,
};
type Props = {
- isSidePanelCollapsed: boolean;
- sidePanelRef: RefObject;
+ panelApi: UsePanelReturn;
};
-const FloatingSidePanelButtons = ({
- isSidePanelCollapsed,
- sidePanelRef,
-}: Props) => {
+const FloatingSidePanelButtons = (props: Props) => {
const { t } = useTranslation();
const { queueBack, isLoading, isDisabled } = useQueueBack();
+ const { data: queueStatus } = useGetQueueStatusQuery();
- const handleShowSidePanel = useCallback(() => {
- sidePanelRef.current?.expand();
- }, [sidePanelRef]);
+ const queueButtonIcon = useMemo(
+ () =>
+ queueStatus?.processor.is_processing ? (
+
+ ) : (
+
+ ),
+ [queueStatus?.processor.is_processing]
+ );
- if (!isSidePanelCollapsed) {
+ if (!props.panelApi.isCollapsed) {
return null;
}
@@ -45,7 +50,7 @@ const FloatingSidePanelButtons = ({
transform="translate(0, -50%)"
minW={8}
top="50%"
- insetInlineStart="5.13rem"
+ insetInlineStart="54px"
direction="column"
gap={2}
h={48}
@@ -54,29 +59,23 @@ const FloatingSidePanelButtons = ({
}
/>
}
- variant="solid"
- colorScheme="yellow"
+ icon={queueButtonIcon}
+ colorScheme="invokeYellow"
tooltip={}
sx={floatingButtonStyles}
/>
-
+
-
+
);
diff --git a/invokeai/frontend/web/src/features/ui/components/InvokeTabs.tsx b/invokeai/frontend/web/src/features/ui/components/InvokeTabs.tsx
index 07c4167709..3ee22260cf 100644
--- a/invokeai/frontend/web/src/features/ui/components/InvokeTabs.tsx
+++ b/invokeai/frontend/web/src/features/ui/components/InvokeTabs.tsx
@@ -16,6 +16,8 @@ import NodeEditorPanelGroup from 'features/nodes/components/sidePanel/NodeEditor
import InvokeAILogoComponent from 'features/system/components/InvokeAILogoComponent';
import SettingsMenu from 'features/system/components/SettingsModal/SettingsMenu';
import StatusIndicator from 'features/system/components/StatusIndicator';
+import FloatingGalleryButton from 'features/ui/components/FloatingGalleryButton';
+import FloatingParametersPanelButtons from 'features/ui/components/FloatingParametersPanelButtons';
import type { UsePanelOptions } from 'features/ui/hooks/usePanel';
import { usePanel } from 'features/ui/hooks/usePanel';
import { usePanelStorage } from 'features/ui/hooks/usePanelStorage';
@@ -99,8 +101,8 @@ const enabledTabsSelector = createMemoizedSelector(
}
);
-export const NO_GALLERY_TABS: InvokeTabName[] = ['modelManager', 'queue'];
-export const NO_SIDE_PANEL_TABS: InvokeTabName[] = ['modelManager', 'queue'];
+export const NO_GALLERY_PANEL_TABS: InvokeTabName[] = ['modelManager', 'queue'];
+export const NO_OPTIONS_PANEL_TABS: InvokeTabName[] = ['modelManager', 'queue'];
const panelStyles: CSSProperties = { height: '100%', width: '100%' };
const GALLERY_MIN_SIZE_PX = 310;
const GALLERY_MIN_SIZE_PCT = 20;
@@ -121,6 +123,14 @@ const InvokeTabs = () => {
e.target.blur();
}
}, []);
+ const shouldShowOptionsPanel = useMemo(
+ () => !NO_OPTIONS_PANEL_TABS.includes(activeTabName),
+ [activeTabName]
+ );
+ const shouldShowGalleryPanel = useMemo(
+ () => !NO_GALLERY_PANEL_TABS.includes(activeTabName),
+ [activeTabName]
+ );
const tabs = useMemo(
() =>
@@ -185,60 +195,38 @@ const InvokeTabs = () => {
const panelStorage = usePanelStorage();
- const {
- ref: optionsPanelRef,
- minSize: optionsPanelMinSize,
- isCollapsed: isOptionsPanelCollapsed,
- onCollapse: onCollapseOptionsPanel,
- onExpand: onExpandOptionsPanel,
- reset: resetOptionsPanel,
- expand: expandOptionsPanel,
- collapse: collapseOptionsPanel,
- toggle: toggleOptionsPanel,
- onDoubleClickHandle: onDoubleClickOptionsPanelHandle,
- } = usePanel(optionsPanelUsePanelOptions);
+ const optionsPanel = usePanel(optionsPanelUsePanelOptions);
- const {
- ref: galleryPanelRef,
- minSize: galleryPanelMinSize,
- isCollapsed: isGalleryPanelCollapsed,
- onCollapse: onCollapseGalleryPanel,
- onExpand: onExpandGalleryPanel,
- reset: resetGalleryPanel,
- expand: expandGalleryPanel,
- collapse: collapseGalleryPanel,
- toggle: toggleGalleryPanel,
- onDoubleClickHandle: onDoubleClickGalleryPanelHandle,
- } = usePanel(galleryPanelUsePanelOptions);
+ const galleryPanel = usePanel(galleryPanelUsePanelOptions);
- useHotkeys('g', toggleGalleryPanel, [toggleGalleryPanel]);
- useHotkeys(['t', 'o'], toggleOptionsPanel, [toggleOptionsPanel]);
+ useHotkeys('g', galleryPanel.toggle, [galleryPanel.toggle]);
+ useHotkeys(['t', 'o'], optionsPanel.toggle, [optionsPanel.toggle]);
useHotkeys(
'shift+r',
() => {
- resetOptionsPanel();
- resetGalleryPanel();
+ optionsPanel.reset();
+ galleryPanel.reset();
},
- [resetOptionsPanel, resetGalleryPanel]
+ [optionsPanel.reset, galleryPanel.reset]
);
useHotkeys(
'f',
() => {
- if (isOptionsPanelCollapsed || isGalleryPanelCollapsed) {
- expandOptionsPanel();
- expandGalleryPanel();
+ if (optionsPanel.isCollapsed || galleryPanel.isCollapsed) {
+ optionsPanel.expand();
+ galleryPanel.expand();
} else {
- collapseOptionsPanel();
- collapseGalleryPanel();
+ optionsPanel.collapse();
+ galleryPanel.collapse();
}
},
[
- isOptionsPanelCollapsed,
- isGalleryPanelCollapsed,
- expandOptionsPanel,
- expandGalleryPanel,
- collapseOptionsPanel,
- collapseGalleryPanel,
+ optionsPanel.isCollapsed,
+ galleryPanel.isCollapsed,
+ optionsPanel.expand,
+ galleryPanel.expand,
+ optionsPanel.collapse,
+ galleryPanel.collapse,
]
);
@@ -272,16 +260,16 @@ const InvokeTabs = () => {
style={panelStyles}
storage={panelStorage}
>
- {!NO_SIDE_PANEL_TABS.includes(activeTabName) && (
+ {shouldShowOptionsPanel && (
<>
{activeTabName === 'nodes' ? (
@@ -292,7 +280,7 @@ const InvokeTabs = () => {
>
@@ -302,21 +290,21 @@ const InvokeTabs = () => {
{tabPanels}
- {!NO_GALLERY_TABS.includes(activeTabName) && (
+ {shouldShowGalleryPanel && (
<>
@@ -324,6 +312,12 @@ const InvokeTabs = () => {
>
)}
+ {shouldShowOptionsPanel && (
+
+ )}
+ {shouldShowGalleryPanel && (
+
+ )}
);
};