fix(ui): queue tab list of queue items

Reverted incomplete change to how queue items are listed. In the future
I think we should redo it to work like the gallery. For now, it is back
the way it was in v5.
This commit is contained in:
psychedelicious
2025-07-08 14:21:25 +10:00
committed by Kent Keirsey
parent db6af134b7
commit b1e2cb8401
9 changed files with 266 additions and 76 deletions

View File

@@ -0,0 +1,28 @@
import type { ButtonProps } from '@invoke-ai/ui-library';
import { Button } from '@invoke-ai/ui-library';
import { useCancelAllExceptCurrentQueueItemDialog } from 'features/queue/components/CancelAllExceptCurrentQueueItemConfirmationAlertDialog';
import { memo } from 'react';
import { useTranslation } from 'react-i18next';
import { PiXCircle } from 'react-icons/pi';
export const CancelAllExceptCurrentButton = memo((props: ButtonProps) => {
const { t } = useTranslation();
const api = useCancelAllExceptCurrentQueueItemDialog();
return (
<Button
isDisabled={api.isDisabled}
isLoading={api.isLoading}
aria-label={t('queue.clear')}
tooltip={t('queue.cancelAllExceptCurrentTooltip')}
leftIcon={<PiXCircle />}
colorScheme="error"
onClick={api.openDialog}
{...props}
>
{t('queue.clear')}
</Button>
);
});
CancelAllExceptCurrentButton.displayName = 'CancelAllExceptCurrentButton';

View File

@@ -1,32 +0,0 @@
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';

View File

@@ -3,7 +3,7 @@ import { Badge, ButtonGroup, Collapse, Flex, IconButton, Text } from '@invoke-ai
import QueueStatusBadge from 'features/queue/components/common/QueueStatusBadge';
import { useDestinationText } from 'features/queue/components/QueueList/useDestinationText';
import { useOriginText } from 'features/queue/components/QueueList/useOriginText';
import { useDeleteQueueItem } from 'features/queue/hooks/useDeleteQueueItem';
import { useCancelQueueItem } from 'features/queue/hooks/useCancelQueueItem';
import { useRetryQueueItem } from 'features/queue/hooks/useRetryQueueItem';
import { getSecondsFromTimestamps } from 'features/queue/util/getSecondsFromTimestamps';
import { useFeatureStatus } from 'features/system/hooks/useFeatureStatus';
@@ -38,13 +38,13 @@ const QueueItemComponent = ({ index, item, context }: InnerItemProps) => {
const handleToggle = useCallback(() => {
context.toggleQueueItem(item.item_id);
}, [context, item.item_id]);
const deleteQueueItem = useDeleteQueueItem();
const onClickDeleteQueueItem = useCallback(
const cancelQueueItem = useCancelQueueItem();
const onClickCancelQueueItem = useCallback(
(e: MouseEvent<HTMLButtonElement>) => {
e.stopPropagation();
deleteQueueItem.trigger(item.item_id);
cancelQueueItem.trigger(item.item_id);
},
[deleteQueueItem, item.item_id]
[cancelQueueItem, item.item_id]
);
const retryQueueItem = useRetryQueueItem();
const onClickRetryQueueItem = useCallback(
@@ -135,9 +135,9 @@ const QueueItemComponent = ({ index, item, context }: InnerItemProps) => {
<ButtonGroup size="xs" variant="ghost">
{(!isFailed || !isRetryEnabled || isValidationRun) && (
<IconButton
onClick={onClickDeleteQueueItem}
onClick={onClickCancelQueueItem}
isDisabled={isCanceled}
isLoading={deleteQueueItem.isLoading}
isLoading={cancelQueueItem.isLoading}
aria-label={t('queue.cancelItem')}
icon={<PiXBold />}
/>

View File

@@ -5,7 +5,7 @@ import { useDestinationText } from 'features/queue/components/QueueList/useDesti
import { useOriginText } from 'features/queue/components/QueueList/useOriginText';
import { useBatchIsCanceled } from 'features/queue/hooks/useBatchIsCanceled';
import { useCancelBatch } from 'features/queue/hooks/useCancelBatch';
import { useDeleteQueueItem } from 'features/queue/hooks/useDeleteQueueItem';
import { useCancelQueueItem } from 'features/queue/hooks/useCancelQueueItem';
import { useRetryQueueItem } from 'features/queue/hooks/useRetryQueueItem';
import { getSecondsFromTimestamps } from 'features/queue/util/getSecondsFromTimestamps';
import { useFeatureStatus } from 'features/system/hooks/useFeatureStatus';
@@ -13,20 +13,22 @@ import type { ReactNode } from 'react';
import { memo, useCallback, useMemo } from 'react';
import { useTranslation } from 'react-i18next';
import { PiArrowCounterClockwiseBold, PiXBold } from 'react-icons/pi';
import { useGetQueueItemQuery } from 'services/api/endpoints/queue';
import type { S } from 'services/api/types';
type Props = {
queueItem: S['SessionQueueItem'];
};
const QueueItemComponent = ({ queueItem }: Props) => {
const { session_id, batch_id, item_id, origin, destination } = queueItem;
const QueueItemComponent = ({ queueItem: queueItemDTO }: Props) => {
const { session_id, batch_id, item_id, origin, destination } = queueItemDTO;
const { t } = useTranslation();
const isRetryEnabled = useFeatureStatus('retryQueueItem');
const isBatchCanceled = useBatchIsCanceled(batch_id);
const cancelBatch = useCancelBatch();
const deleteQueueItem = useDeleteQueueItem();
const cancelQueueItem = useCancelQueueItem();
const retryQueueItem = useRetryQueueItem();
const { data: queueItem } = useGetQueueItemQuery(item_id);
const originText = useOriginText(origin);
const destinationText = useDestinationText(destination);
@@ -57,8 +59,8 @@ const QueueItemComponent = ({ queueItem }: Props) => {
}, [cancelBatch, batch_id]);
const onCancelQueueItem = useCallback(() => {
deleteQueueItem.trigger(item_id);
}, [deleteQueueItem, item_id]);
cancelQueueItem.trigger(item_id);
}, [cancelQueueItem, item_id]);
const onRetryQueueItem = useCallback(() => {
retryQueueItem.trigger(item_id);
@@ -85,8 +87,8 @@ const QueueItemComponent = ({ queueItem }: Props) => {
{(!isFailed || !isRetryEnabled) && (
<Button
onClick={onCancelQueueItem}
isLoading={deleteQueueItem.isLoading}
isDisabled={deleteQueueItem.isDisabled || queueItem ? isCanceled : true}
isLoading={cancelQueueItem.isLoading}
isDisabled={cancelQueueItem.isDisabled || queueItem ? isCanceled : true}
aria-label={t('queue.cancelItem')}
leftIcon={<PiXBold />}
colorScheme="error"

View File

@@ -13,7 +13,7 @@ import { memo, useCallback, useEffect, useMemo, useRef, useState } from 'react';
import { useTranslation } from 'react-i18next';
import type { Components, ItemContent } from 'react-virtuoso';
import { Virtuoso } from 'react-virtuoso';
import { useListQueueItemsQuery } from 'services/api/endpoints/queue';
import { queueItemsAdapterSelectors, useListQueueItemsQuery } from 'services/api/endpoints/queue';
import type { S } from 'services/api/types';
import QueueItemComponent from './QueueItemComponent';
@@ -70,7 +70,7 @@ const QueueList = () => {
if (!listQueueItemsData) {
return [];
}
return listQueueItemsData.items;
return queueItemsAdapterSelectors.selectAll(listQueueItemsData);
}, [listQueueItemsData]);
const handleLoadMore = useCallback(() => {

View File

@@ -1,8 +1,8 @@
import { ButtonGroup, Flex } from '@invoke-ai/ui-library';
import { DeleteAllExceptCurrentButton } from 'features/queue/components/DeleteAllExceptCurrentButton';
import { useFeatureStatus } from 'features/system/hooks/useFeatureStatus';
import { memo } from 'react';
import { CancelAllExceptCurrentButton } from './CancelAllExceptCurrentButton';
import ClearModelCacheButton from './ClearModelCacheButton';
import PauseProcessorButton from './PauseProcessorButton';
import PruneQueueButton from './PruneQueueButton';
@@ -23,7 +23,7 @@ const QueueTabQueueControls = () => {
)}
<ButtonGroup w={28} orientation="vertical" size="sm">
<PruneQueueButton />
<DeleteAllExceptCurrentButton />
<CancelAllExceptCurrentButton />
</ButtonGroup>
</Flex>
<ClearModelCacheButton />

View File

@@ -33,7 +33,7 @@ export const queueSlice = createSlice({
},
});
export const { listCursorChanged, listPriorityChanged } = queueSlice.actions;
export const { listCursorChanged, listPriorityChanged, listParamsReset } = queueSlice.actions;
const selectQueueSlice = (state: RootState) => state.queue;
const createQueueSelector = <T>(selector: Selector<QueueState, T>) => createSelector(selectQueueSlice, selector);