refactor(ui): rejiggle enqueue actions to support api validation runs

This commit is contained in:
psychedelicious
2025-03-24 17:50:28 +10:00
parent afe088045f
commit b9ddf67853
8 changed files with 59 additions and 35 deletions

View File

@@ -1,7 +0,0 @@
import { createAction } from '@reduxjs/toolkit';
import type { TabName } from 'features/ui/store/uiTypes';
export const enqueueRequested = createAction<{
tabName: TabName;
prepend: boolean;
}>('app/enqueueRequested');

View File

@@ -1,5 +1,5 @@
import { createAction } from '@reduxjs/toolkit';
import { logger } from 'app/logging/logger';
import { enqueueRequested } from 'app/store/actions';
import type { AppStartListening } from 'app/store/middleware/listenerMiddleware';
import { extractMessageFromAssertionError } from 'common/util/extractMessageFromAssertionError';
import { withResult, withResultAsync } from 'common/util/result';
@@ -17,10 +17,11 @@ import { assert, AssertionError } from 'tsafe';
const log = logger('generation');
export const enqueueRequestedCanvas = createAction<{ prepend: boolean }>('app/enqueueRequestedCanvas');
export const addEnqueueRequestedLinear = (startAppListening: AppStartListening) => {
startAppListening({
predicate: (action): action is ReturnType<typeof enqueueRequested> =>
enqueueRequested.match(action) && action.payload.tabName === 'canvas',
actionCreator: enqueueRequestedCanvas,
effect: async (action, { getState, dispatch }) => {
log.debug('Enqueue requested');
const state = getState();

View File

@@ -1,5 +1,5 @@
import { createAction } from '@reduxjs/toolkit';
import { logger } from 'app/logging/logger';
import { enqueueRequested } from 'app/store/actions';
import type { AppStartListening } from 'app/store/middleware/listenerMiddleware';
import { parseify } from 'common/util/serialize';
import { $templates } from 'features/nodes/store/nodesSlice';
@@ -15,11 +15,15 @@ import type { Batch, EnqueueBatchArg } from 'services/api/types';
const log = logger('generation');
export const enqueueRequestedWorkflows = createAction<{ prepend: boolean; isApiValidationRun: boolean }>(
'app/enqueueRequestedWorkflows'
);
export const addEnqueueRequestedNodes = (startAppListening: AppStartListening) => {
startAppListening({
predicate: (action): action is ReturnType<typeof enqueueRequested> =>
enqueueRequested.match(action) && action.payload.tabName === 'workflows',
actionCreator: enqueueRequestedWorkflows,
effect: async (action, { getState, dispatch }) => {
const { prepend, isApiValidationRun } = action.payload;
const state = getState();
const nodesState = selectNodesSlice(state);
const workflow = state.workflow;
@@ -99,8 +103,9 @@ export const addEnqueueRequestedNodes = (startAppListening: AppStartListening) =
origin: 'workflows',
destination: 'gallery',
data,
is_api_validation_run: isApiValidationRun,
},
prepend: action.payload.prepend,
prepend,
};
const req = dispatch(queueApi.endpoints.enqueueBatch.initiate(batchConfig, enqueueMutationFixedCacheKeyOptions));

View File

@@ -1,5 +1,5 @@
import { createAction } from '@reduxjs/toolkit';
import { logger } from 'app/logging/logger';
import { enqueueRequested } from 'app/store/actions';
import type { AppStartListening } from 'app/store/middleware/listenerMiddleware';
import { parseify } from 'common/util/serialize';
import { prepareLinearUIBatch } from 'features/nodes/util/graph/buildLinearBatchConfig';
@@ -9,10 +9,11 @@ import { enqueueMutationFixedCacheKeyOptions, queueApi } from 'services/api/endp
const log = logger('generation');
export const enqueueRequestedUpscaling = createAction<{ prepend: boolean }>('app/enqueueRequestedUpscaling');
export const addEnqueueRequestedUpscale = (startAppListening: AppStartListening) => {
startAppListening({
predicate: (action): action is ReturnType<typeof enqueueRequested> =>
enqueueRequested.match(action) && action.payload.tabName === 'upscaling',
actionCreator: enqueueRequestedUpscaling,
effect: async (action, { getState, dispatch }) => {
const state = getState();
const { prepend } = action.payload;

View File

@@ -14,7 +14,7 @@ export const useGlobalHotkeys = () => {
useRegisteredHotkeys({
id: 'invoke',
category: 'app',
callback: queue.queueBack,
callback: queue.enqueueBack,
options: {
enabled: !queue.isDisabled && !queue.isLoading,
preventDefault: true,
@@ -26,7 +26,7 @@ export const useGlobalHotkeys = () => {
useRegisteredHotkeys({
id: 'invokeFront',
category: 'app',
callback: queue.queueFront,
callback: queue.enqueueFront,
options: {
enabled: !queue.isDisabled && !queue.isLoading,
preventDefault: true,

View File

@@ -20,7 +20,7 @@ export const InvokeButton = memo(() => {
<QueueIterationsNumberInput />
<InvokeButtonTooltip prepend={shift}>
<Button
onClick={shift ? queue.queueFront : queue.queueBack}
onClick={shift ? queue.enqueueFront : queue.enqueueBack}
isLoading={queue.isLoading || isLoadingDynamicPrompts}
loadingText={invoke}
isDisabled={queue.isDisabled}

View File

@@ -1,5 +1,7 @@
import { useStore } from '@nanostores/react';
import { enqueueRequested } from 'app/store/actions';
import { enqueueRequestedCanvas } from 'app/store/middleware/listenerMiddleware/listeners/enqueueRequestedLinear';
import { enqueueRequestedWorkflows } from 'app/store/middleware/listenerMiddleware/listeners/enqueueRequestedNodes';
import { enqueueRequestedUpscaling } from 'app/store/middleware/listenerMiddleware/listeners/enqueueRequestedUpscale';
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
import { $isReadyToEnqueue } from 'features/queue/store/readiness';
import { selectActiveTab } from 'features/ui/store/uiSelectors';
@@ -12,18 +14,40 @@ export const useInvoke = () => {
const isReady = useStore($isReadyToEnqueue);
const [_, { isLoading }] = useEnqueueBatchMutation(enqueueMutationFixedCacheKeyOptions);
const queueBack = useCallback(() => {
if (!isReady) {
return;
}
dispatch(enqueueRequested({ tabName, prepend: false }));
}, [dispatch, isReady, tabName]);
const queueFront = useCallback(() => {
if (!isReady) {
return;
}
dispatch(enqueueRequested({ tabName, prepend: true }));
}, [dispatch, isReady, tabName]);
return { queueBack, queueFront, isLoading, isDisabled: !isReady };
const enqueue = useCallback(
(prepend: boolean, isApiValidationRun: boolean) => {
if (!isReady) {
return;
}
if (tabName === 'workflows') {
dispatch(enqueueRequestedWorkflows({ prepend, isApiValidationRun }));
return;
}
if (tabName === 'upscaling') {
dispatch(enqueueRequestedUpscaling({ prepend }));
return;
}
if (tabName === 'canvas') {
dispatch(enqueueRequestedCanvas({ prepend }));
return;
}
// Else we are not on a generation tab and should not queue
},
[dispatch, isReady, tabName]
);
const enqueueBack = useCallback(() => {
enqueue(false, false);
}, [enqueue]);
const enqueueFront = useCallback(() => {
enqueue(true, false);
}, [enqueue]);
return { enqueueBack, enqueueFront, isLoading, isDisabled: !isReady };
};

View File

@@ -82,7 +82,7 @@ const InvokeIconButton = memo(() => {
<InvokeButtonTooltip prepend={shift} placement="end">
<IconButton
aria-label={t('queue.queueBack')}
onClick={shift ? queue.queueFront : queue.queueBack}
onClick={shift ? queue.enqueueFront : queue.enqueueBack}
isLoading={queue.isLoading}
isDisabled={queue.isDisabled}
icon={queueButtonIcon}