From ccbe1b233de42ccb9c196c042f89e17ffa9c322d Mon Sep 17 00:00:00 2001 From: psychedelicious <4822129+psychedelicious@users.noreply.github.com> Date: Tue, 17 Sep 2024 19:19:21 +1000 Subject: [PATCH] feat(ui): rework queue controls - Remove queue front button. Hold shift while clicking `Invoke` button to queue front. - Restore queue menu actions w/ the reclaimed space. - Simplify queue interaction hooks. --- .../frontend/web/src/app/types/invokeai.ts | 1 - .../web/src/common/hooks/useGlobalHotkeys.ts | 19 ++--- .../queue/components/ClearQueueIconButton.tsx | 31 +++---- .../components/InvokeQueueBackButton.tsx | 23 +++--- .../components/QueueActionsMenuButton.tsx | 80 +++++++++++++++++++ .../queue/components/QueueControls.tsx | 10 +-- .../queue/components/QueueFrontButton.tsx | 26 ------ .../hooks/{useQueueBack.ts => useInvoke.ts} | 17 ++-- .../src/features/queue/hooks/useQueueFront.ts | 30 ------- .../FloatingParametersPanelButtons.tsx | 30 ++++--- 10 files changed, 147 insertions(+), 120 deletions(-) create mode 100644 invokeai/frontend/web/src/features/queue/components/QueueActionsMenuButton.tsx delete mode 100644 invokeai/frontend/web/src/features/queue/components/QueueFrontButton.tsx rename invokeai/frontend/web/src/features/queue/hooks/{useQueueBack.ts => useInvoke.ts} (68%) delete mode 100644 invokeai/frontend/web/src/features/queue/hooks/useQueueFront.ts diff --git a/invokeai/frontend/web/src/app/types/invokeai.ts b/invokeai/frontend/web/src/app/types/invokeai.ts index 0b7c5c9440..952dd04e3a 100644 --- a/invokeai/frontend/web/src/app/types/invokeai.ts +++ b/invokeai/frontend/web/src/app/types/invokeai.ts @@ -22,7 +22,6 @@ export type AppFeature = | 'multiselect' | 'pauseQueue' | 'resumeQueue' - | 'prependQueue' | 'invocationCache' | 'bulkDownload' | 'starterModels' diff --git a/invokeai/frontend/web/src/common/hooks/useGlobalHotkeys.ts b/invokeai/frontend/web/src/common/hooks/useGlobalHotkeys.ts index 167c60d758..6715f53d8e 100644 --- a/invokeai/frontend/web/src/common/hooks/useGlobalHotkeys.ts +++ b/invokeai/frontend/web/src/common/hooks/useGlobalHotkeys.ts @@ -2,8 +2,7 @@ import { useAppDispatch } from 'app/store/storeHooks'; import { addScope, removeScope, setScopes } from 'common/hooks/interactionScopes'; import { useClearQueue } from 'features/queue/components/ClearQueueConfirmationAlertDialog'; import { useCancelCurrentQueueItem } from 'features/queue/hooks/useCancelCurrentQueueItem'; -import { useQueueBack } from 'features/queue/hooks/useQueueBack'; -import { useQueueFront } from 'features/queue/hooks/useQueueFront'; +import { useInvoke } from 'features/queue/hooks/useInvoke'; import { useFeatureStatus } from 'features/system/hooks/useFeatureStatus'; import { setActiveTab } from 'features/ui/store/uiSlice'; import { useHotkeys } from 'react-hotkeys-hook'; @@ -11,30 +10,28 @@ import { useHotkeys } from 'react-hotkeys-hook'; export const useGlobalHotkeys = () => { const dispatch = useAppDispatch(); const isModelManagerEnabled = useFeatureStatus('modelManager'); - const { queueBack, isDisabled: isDisabledQueueBack, isLoading: isLoadingQueueBack } = useQueueBack(); + const queue = useInvoke(); useHotkeys( ['ctrl+enter', 'meta+enter'], - queueBack, + queue.queueBack, { - enabled: !isDisabledQueueBack && !isLoadingQueueBack, + enabled: !queue.isDisabled && !queue.isLoading, preventDefault: true, enableOnFormTags: ['input', 'textarea', 'select'], }, - [queueBack, isDisabledQueueBack, isLoadingQueueBack] + [queue] ); - const { queueFront, isDisabled: isDisabledQueueFront, isLoading: isLoadingQueueFront } = useQueueFront(); - useHotkeys( ['ctrl+shift+enter', 'meta+shift+enter'], - queueFront, + queue.queueFront, { - enabled: !isDisabledQueueFront && !isLoadingQueueFront, + enabled: !queue.isDisabled && !queue.isLoading, preventDefault: true, enableOnFormTags: ['input', 'textarea', 'select'], }, - [queueFront, isDisabledQueueFront, isLoadingQueueFront] + [queue] ); const { diff --git a/invokeai/frontend/web/src/features/queue/components/ClearQueueIconButton.tsx b/invokeai/frontend/web/src/features/queue/components/ClearQueueIconButton.tsx index 0174db0bcb..9d9ccc0b49 100644 --- a/invokeai/frontend/web/src/features/queue/components/ClearQueueIconButton.tsx +++ b/invokeai/frontend/web/src/features/queue/components/ClearQueueIconButton.tsx @@ -1,14 +1,12 @@ import { IconButton, useShiftModifier } from '@invoke-ai/ui-library'; -import { QueueCountBadge } from 'features/queue/components/QueueCountBadge'; import { useCancelCurrentQueueItem } from 'features/queue/hooks/useCancelCurrentQueueItem'; -import { memo, useRef } from 'react'; +import { memo } from 'react'; import { useTranslation } from 'react-i18next'; import { PiTrashSimpleBold, PiXBold } from 'react-icons/pi'; import { useClearQueue } from './ClearQueueConfirmationAlertDialog'; export const ClearQueueIconButton = memo((_) => { - const ref = useRef(null); const { t } = useTranslation(); const clearQueue = useClearQueue(); const cancelCurrentQueueItem = useCancelCurrentQueueItem(); @@ -18,22 +16,17 @@ export const ClearQueueIconButton = memo((_) => { const shift = useShiftModifier(); return ( - <> - : } - colorScheme="error" - onClick={shift ? clearQueue.openDialog : cancelCurrentQueueItem.cancelQueueItem} - data-testid={shift ? t('queue.clear') : t('queue.cancel')} - /> - {/* The badge is dynamically positioned, needs a ref to the target element */} - - + : } + colorScheme="error" + onClick={shift ? clearQueue.openDialog : cancelCurrentQueueItem.cancelQueueItem} + data-testid={shift ? t('queue.clear') : t('queue.cancel')} + /> ); }); diff --git a/invokeai/frontend/web/src/features/queue/components/InvokeQueueBackButton.tsx b/invokeai/frontend/web/src/features/queue/components/InvokeQueueBackButton.tsx index 9bfe7025bb..54b076bee9 100644 --- a/invokeai/frontend/web/src/features/queue/components/InvokeQueueBackButton.tsx +++ b/invokeai/frontend/web/src/features/queue/components/InvokeQueueBackButton.tsx @@ -1,29 +1,30 @@ -import { Button, Flex, Spacer } from '@invoke-ai/ui-library'; +import { Button, Flex, Spacer, useShiftModifier } from '@invoke-ai/ui-library'; import { useAppSelector } from 'app/store/storeHooks'; import { selectDynamicPromptsIsLoading } from 'features/dynamicPrompts/store/dynamicPromptsSlice'; import { QueueIterationsNumberInput } from 'features/queue/components/QueueIterationsNumberInput'; -import { useQueueBack } from 'features/queue/hooks/useQueueBack'; +import { useInvoke } from 'features/queue/hooks/useInvoke'; import { memo } from 'react'; -import { PiSparkleFill } from 'react-icons/pi'; +import { PiLightningFill, PiSparkleFill } from 'react-icons/pi'; import { QueueButtonTooltip } from './QueueButtonTooltip'; const invoke = 'Invoke'; -export const InvokeQueueBackButton = memo(() => { - const { queueBack, isLoading, isDisabled } = useQueueBack(); +export const InvokeButton = memo(() => { + const queue = useInvoke(); + const shift = useShiftModifier(); const isLoadingDynamicPrompts = useAppSelector(selectDynamicPromptsIsLoading); return ( - +